18

I'm learning to use libusb v1.0.0 for the first time on Ubuntu 12.10. Here is some small test code I'm using to try and understand how to use this API:

#include <libusb-1.0/libusb.h>
...
libusb_device **list;
libusb_get_device_list(ctx, &list); // Returns 11 USB devices which is correct.
for (size_t idx = 0; list[idx] != NULL; idx ++)
{
    libusb_device *dev = list[idx];
    libusb_device_descriptor desc = {0};
    int rc = libusb_get_device_descriptor(dev, &desc);

At this point, rc == 0, meaning it should have completed successfully. Source: documentation for *libusb_get_device_descriptor()*.

But the structure desc is always empty. None of the fields ever get set. If I change the last two lines above to this:

    libusb_device_descriptor desc = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int rc = libusb_get_device_descriptor(dev, &desc);

...then when libusb_get_device_descriptor() returns, I see desc remains unchanged, confirming for me that I'm not getting what I expect from this API.

I've also tried to run a.out as root just in case this requires elevated privileges. Doing a Google search on libusb_get_device_descriptor hasn't gotten me anywhere.

Relevant commands I ran to try this code:

sudo apt-get install libusb-1.0.0-dev
g++ -ggdb test.cpp -lusb-1.0
./a.out 

Ah! Crazy user error! sharth's code helped me figure it out. Here is the code I was actually using -- see if you can spot the error:

std::cout << "rc == " << libusb_get_device_descriptor(dev, &desc) << std::endl
          << "vendor == " << desc.idVendor << std::endl;

I guess the way the compiler evaluates this, it is free to evaluate desc.idVendor before the call to libusb_get_device_descriptor() has actually been made. My bad.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
Stéphane
  • 19,459
  • 24
  • 95
  • 136
  • [Your cout was actually undefined behavior.](http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points) Glad to help though! – Bill Lynch Feb 06 '13 at 14:56

3 Answers3

37

You didn't include a full, compilable test case. So I built one. This works for me on CentOS 6 x64. I'm also running this as a normal user account.

Source

#include <cassert>
#include <cstdio>
#include <libusb-1.0/libusb.h>

int main() {
    libusb_context *context = NULL;
    libusb_device **list = NULL;
    int rc = 0;
    ssize_t count = 0;

    rc = libusb_init(&context);
    assert(rc == 0);

    count = libusb_get_device_list(context, &list);
    assert(count > 0);

    for (size_t idx = 0; idx < count; ++idx) {
        libusb_device *device = list[idx];
        libusb_device_descriptor desc = {0};

        rc = libusb_get_device_descriptor(device, &desc);
        assert(rc == 0);

        printf("Vendor:Device = %04x:%04x\n", desc.idVendor, desc.idProduct);
    }

    libusb_free_device_list(list, 1);
    libusb_exit(context);
}

Output

Vendor:Device = 1d6b:0002
Vendor:Device = 1d6b:0002
Vendor:Device = 8087:0020
Vendor:Device = 8087:0020
Vendor:Device = 0424:2514
Vendor:Device = 10c4:ea60
Vendor:Device = 051d:0002
Vendor:Device = 0624:0248
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • 1
    libusb_free_device_list(list, count); void libusb_free_device_list(libusb_device **list, int unref_devices) Free the list of devices discovered by libusb_get_device_list. If unref_device is set to 1 all devices in the list have their reference counter decremented once. you have unref_devices wrong – Brandon Ros Aug 05 '20 at 22:45
  • why i can't pass `libusb_device_descriptor *desc;` to the method as `.., desc)` ? what i did for now is `libusb_device_descriptor desc;` to the method `..., &desc)` – obeid salem Jul 31 '23 at 00:11
3

This is not an standalone answer, it's more a comment to Bill Lynch's post. I'm not able to add a comment to Bill Lynch's post (missing reputation) so I decided to do it this way ;-).

There's a little detail missing in the code above:

you have to free the list you got filled from libusb_get_device_list by hand.

From the libusb docu:

You are expected to unreference all the devices when you are done with them, and then free the list with libusb_free_device_list(). Note that libusb_free_device_list() can unref all the devices for you. Be careful not to unreference a device you are about to open until after you have opened it.

lexXxel
  • 111
  • 2
  • 14
3

Just to add to Bill's answer, to avoid the multiple warnings you will likely recieve from this line

libusb_device_descriptor desc = {0};

Simply remove the assignment.

libusb_device_descriptor desc;

Not a huge deal, but these things bother me.

Goddard
  • 2,863
  • 31
  • 37