使用libftdi或libusb按名称打开设备

时间:2015-06-29 14:59:42

标签: c++ c ubuntu-14.04 libusb

我正在使用带有多个ftdi设备的libftdi来运行在Ubuntu 14.04上运行的程序。我有一个udev规则,它根据自定义制造商字符串检测设备,并在dev目录中为它们提供符号链接。它看起来与/dev/my-device类似。我想使用libftdi来使用此字符串而不是pid / vid /序列号打开设备。

我没有看到这个功能在libftdi中可用,所以我检查了libusb并且没有看到该功能。

1 个答案:

答案 0 :(得分:0)

你可以试试这个:

static int usbGetDescriptorString(usb_dev_handle *dev, int index, int langid, char *buf, int buflen) {
    char buffer[256];
    int rval, i;

    // make standard request GET_DESCRIPTOR, type string and given index 
    // (e.g. dev->iProduct)
    rval = usb_control_msg(dev,
        USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_ENDPOINT_IN,
        USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, langid,
        buffer, sizeof(buffer), 1000);

    if (rval < 0) // error
        return rval;

    // rval should be bytes read, but buffer[0] contains the actual response size
    if ((unsigned char)buffer[0] < rval)
        rval = (unsigned char)buffer[0]; // string is shorter than bytes read

    if (buffer[1] != USB_DT_STRING) // second byte is the data type
        return 0; // invalid return type

                  // we're dealing with UTF-16LE here so actual chars is half of rval,
                  // and index 0 doesn't count
    rval /= 2;

    /* lossy conversion to ISO Latin1 */
    for (i = 1; i < rval && i < buflen; i++) {
        if (buffer[2 * i + 1] == 0)
            buf[i - 1] = buffer[2 * i];
        else
            buf[i - 1] = '?'; /* outside of ISO Latin1 range */
    }
    buf[i - 1] = 0;

    return i - 1;
}

static usb_dev_handle * usbOpenDevice(int vendor, char *vendorName, int product, char *productName) {
    struct usb_bus *bus;
    struct usb_device *dev;
    char devVendor[256], devProduct[256];

    usb_dev_handle * handle = NULL;

    usb_init();
    usb_find_busses();
    usb_find_devices();

    for (bus = usb_get_busses(); bus; bus = bus->next) {
        for (dev = bus->devices; dev; dev = dev->next) {
            if (dev->descriptor.idVendor != vendor ||
                dev->descriptor.idProduct != product)
                continue;

            /* we need to open the device in order to query strings */
            if (!(handle = usb_open(dev))) {
                fprintf(stderr, "Warning: cannot open USB device: %sn",
                    usb_strerror());
                continue;
            }

            /* get vendor name */
            if (usbGetDescriptorString(handle, dev->descriptor.iManufacturer, 0x0409, devVendor, sizeof(devVendor)) < 0) {
                fprintf(stderr,
                    "Warning: cannot query manufacturer for device: %sn",
                    usb_strerror());
                usb_close(handle);
                continue;
            }

            /* get product name */
            if (usbGetDescriptorString(handle, dev->descriptor.iProduct, 0x0409, devProduct, sizeof(devVendor)) < 0) {
                fprintf(stderr,
                    "Warning: cannot query product for device: %sn",
                    usb_strerror());
                usb_close(handle);
                continue;
            }

            if (strcmp(devVendor, vendorName) == 0 &&
                strcmp(devProduct, productName) == 0)
                return handle;
            else
                usb_close(handle);
        }
    }

    return NULL;
}