2

I'm trying to get the usb device serial number from a C code application in a embedded Linux platform (petalinux) using libusb.

I've seen a few similar questions which helped me to get some direction but unfortunately I didn't manage to solve it yet.

First I'll show what I'm trying to read, this is the dmesg of the device when is plugged in:

[    9.632965] usb 1-1.4: New USB device found, idVendor=0403, idProduct=de37
[    9.639837] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[    9.647146] usb 1-1.4: Product: PI CAM
[    9.651153] usb 1-1.4: Manufacturer: MANUF
[    9.655326] usb 1-1.4: SerialNumber: 20102130
[    9.688519] uvcvideo: Found UVC 1.00 device PI IMAGER (0403:de37)
[    9.695084] uvcvideo 1-1.4:1.0: Entity type for entity Processing 3 was not initialized!
[    9.703177] uvcvideo 1-1.4:1.0: Entity type for entity Camera 1 was not initialized!
[    9.711098] input: PI CAM: PI CAM as /devices/platform/amba/ff9d0000.usb0/fe200000.dwc3/xhci-hcd.0.auto/usb1/1-1/1-1.4/1-1.4:1.0/input/input0

What I'm trying to read is the serial number: 20102130

I've tried the next code:

    libusb_device*** list=NULL;
    libusb_context *context = NULL;
    libusb_init(&context);

        unsigned char serial[200];
        int status = libusb_get_string_descriptor_ascii(device,desc.iSerialNumber, serial,200);
        if(status < 0)
        {
            printf("Index: %d Error: %d\n",desc.iSerialNumber, status);
        }else{
            printf("Themal camera serial: %s\n",serial);
        }

But it gives a -1 error, it prints: "Index: 3 Error: -1" . If I remove the error checking I've got the serial: bA6` which it doesn't make any sense...

Does anyone know how could I retrieve/read that serial number from my application?

Thanks in advance.

joe
  • 309
  • 4
  • 16
  • If I recall correctly you need to call libusb_init before any usage of that descriptor. And looking in the documentation for `libusb_init()` it indeed states: `Initialize libusb. This function must be called before calling any other libusb function.` – Tony Tannous Jan 07 '21 at 18:05
  • You also need root priviliges to access usb peripherals with libusb. I suggest you look for the error code to understand what went wrong. There's iSerialNumber field in the descriptor – Tony Tannous Jan 07 '21 at 18:11
  • yes that's right but I'm already calling to libusb_init() and using other libusb functions successfully in the code, sorry for simplicity I only included the code snippet of that part. I edit the question to add more code info but we can assume that the libusb initialization and setup is right in this case. Got root privileges and the error code is LIBUSB_ERROR_IO any idea what it means? – joe Jan 07 '21 at 18:14
  • I've done this in the past but I am not near my computer to check if I still have the code or try it out my self now again. But you should be able to use open_device_with_vid_pid then call get_descriptor and then you can simply print `d.iSerialNumber` – Tony Tannous Jan 07 '21 at 18:20
  • Libusb error code list doesn't say much on error code LIBUSB_ERROR_IO besides its an input output error. Try taking out the usb and re plug it in. Maybe different usb port this time. Sorry I missed some of the code where you do access `.iSerial...` it is not convenient to read code on my phone... – Tony Tannous Jan 07 '21 at 18:29
  • I've done all of that and called get_descriptor but if I print the d.iSerialNumber I've got only 3 which is the Index of string descriptor containing device serial number. So what I need is the device serial number which in theory calling to get_string_descriptor functions and passing the d.iSerialNumber should give me that...any idea how to read the serial number? – joe Jan 08 '21 at 08:54

1 Answers1

1
#include <iostream>
#include <libusb-1.0/libusb.h>
#include <cstdio>
#include <unordered_map>

using namespace std;

int main() {
    libusb_device **devs;
    libusb_context *ctx = nullptr; // libusb session context
    int r; // for results
    ssize_t cnt; // number of usb devices found
    r = libusb_init(&ctx); // open session
    if (r < 0) {
        cerr << "Error: initialization failed: " << r << endl;
        return 1;
    }
    // set the verbosity level of debug messages
    libusb_set_debug(ctx, 3);
    // get a list of all found USB devices
    cnt = libusb_get_device_list(ctx, &devs);
    if (cnt < 0) {
        cerr << "Error: USB device list not received." << endl;
        return 1;
    }
    libusb_device_descriptor desc{};
    for (int i = 0; i < cnt; i++) {
        libusb_device_handle *handle;
        auto *data = new uint8_t[33]();
        r = libusb_get_device_descriptor(devs[i], &desc);
        if (r < 0) {
            cerr << "Error: Device handle not received, code: " << r << endl;
        }
        printf("%02X:%02X  \t", desc.idVendor, desc.idProduct);
        try {
            libusb_open(devs[i], &handle);
            if (handle != nullptr) {
                if (libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, data, 31) >= 0) {
                    data[32] = '\0';
                    cout << "Serial Number: \"" << data << "\"";
                }
            }
            libusb_close(handle);
        } catch (libusb_error &e) {
            cerr << e << endl;
        }
        cout << endl;
    }
    // release the memory allocated by the get device list function
    libusb_free_device_list(devs, 1);
    libusb_exit(ctx); // close session,
    return 0;
}

// https://www.keil.com/pack/doc/mw/USB/html/_u_s_b__interface__descriptor.html
// https://libusb.sourceforge.io/api-1.0

Gives me an output:

...
1D6B:02     Serial Number: "0000:05:00.3"
...
RedRainbowGuy
  • 170
  • 1
  • 8