Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

libusb_open returns 'LIBUSB_ERROR_NOT_SUPPORTED' on Windows 7

Tags:

libusb

I have been developing USB drivers using LibUSB on Linux, but now I want to have one of my drivers compiled for Windows (this is the first time I am doing it).

My environment

I am working on Windows 7 using the MinGW compiler (also using Dev-cpp IDE), and I am using a pre-compiled libusb library downloaded from this link.

My device: It's a HID touch device. So no drivers are required for Windows. I have an additional endpoint to get certain debug data.

My code:

I have compiled code to list all the devices and USB devices connected to my machine, and the code works. Now I add code to open the device so that I get a device handle and start communication. But the function returns -12 That is, LIBUSB_ERROR_NOT_SUPPORTED.

How can I fix this problem?

I searched through the Internet and did not find a definite solution for this problem. While it's code which works beautifully on Linux.

P.S.: I have added the whole code below. The DoList(); function works fine, but the GetTRSDevice(); function fails at libusb_open(dev, &handle);.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libusb.h>


libusb_device_handle* deviceHandle = NULL;

int DoList();
libusb_device_handle* GetTRSDevice(void);

int main()
{
    int ret = libusb_init(NULL);
    if (ret < 0) {
        printf("Failed to init libusb");
        return ret;
    }

    DoList();
    deviceHandle = GetTRSDevice();
    if(!deviceHandle) {
        printf("Failed to locate device");
        goto fail_dev_open;
    }

    printf("Device opened");

    libusb_close(deviceHandle);
    fail_dev_open:
        libusb_exit(NULL);

    return(ret);
}

int DoList()
{
    libusb_device **devs;
    ssize_t cnt;


    cnt = libusb_get_device_list(NULL, &devs);
    if (cnt < 0)
        return (int) cnt;

    libusb_device *dev;
    int i = 0;

    while ((dev = devs[i++]) != NULL) {
        struct libusb_device_descriptor desc;
        int r = libusb_get_device_descriptor(dev, &desc);
        if (r < 0) {
            fprintf(stderr, "failed to get device descriptor");
            return(-1);
        }

        printf("%04x:%04x (bus %d, device %d)\n",
               desc.idVendor, desc.idProduct,
               libusb_get_bus_number(dev), libusb_get_device_address(dev));
    }
    libusb_free_device_list(devs, 1);
    return 0;
}

libusb_device_handle* GetTRSDevice(void)
{
    int i = 0;
    ssize_t cnt;
    libusb_device *dev;
    libusb_device **devs;
    libusb_device_handle* handle = NULL;

    cnt = libusb_get_device_list(NULL, &devs);
    if (cnt < 0) {
        printf("Failed libusb_get_device_list");
        return(0);
    }

    while ((dev = devs[i++]) != NULL) {
        struct libusb_device_descriptor desc;
        int ret = libusb_get_device_descriptor(dev, &desc);
        if (ret < 0) {
            printf("Failed libusb_get_device_descriptor");
            continue;
        }
        if(desc.idVendor == 0X238f && desc.idProduct == 1) {
            int ret = libusb_open(dev, &handle);
            if (ret < 0) {
                printf("Failed libusb_open: %d\n\r",ret);
                break;
            }
            #ifndef WIN32
                libusb_detach_kernel_driver(handle, 0);
            #endif
            ret = libusb_claim_interface(handle,0);
            if (ret < 0) {
                libusb_close(handle);
                handle=NULL;
                break;
            }
            break;
        }
    }
    libusb_free_device_list(devs, 1);
    return(handle);
}
like image 360
Prajosh Premdas Avatar asked Jun 27 '13 18:06

Prajosh Premdas


2 Answers

You can easily install the WinUSB driver or the other drivers which libusb supports (libusb-win32 and libusbK) through the use of Zadig, an application that was developed just to solve this problem. See https://zadig.akeo.ie.

One thing to keep in mind, though, is that if you replace a Mass Storage driver or HID driver (which Windows installs automatically) with WinUSB, you will only be able to access your device through libusb and won't be able to access your device as Mass Storage or HID until you uninstall the WinUSB driver.

Finally, if you have control of the firmware for your device, it is also possible to create devices that will automatically install the WinUSB driver on Vista or later, so that users don't have to go through a manual driver installation (this may require a connection to Windows Update for Windows 7 or earlier, but should work even without an internet connection for Windows 8 or later). See https://github.com/pbatard/libwdi/wiki/WCID-Devices.

[DISCLAIMER] I am the author of Zadig/libwi, the WCID wiki pages as well as a contributor to the libusb Windows backend.

like image 143
Akeo Avatar answered Nov 15 '22 18:11

Akeo


It seems you need to install the winusb driver - libusb can get information about devices without this driver, but it cannot open them.

http://libusb.6.n5.nabble.com/LIBUSB-ERROR-NOT-SUPPORTED-td5617169.html:

On Wed, Apr 4, 2012 at 11:52 PM, Quân Phạm Minh <[hidden email]> wrote:

although I never install winusb driver but I use libusb to get information of my usb (kingston usb, and already recognize by system)

Yes that is possible. But you can not open the device and do further things. That is the confusing part for new users with regard to libusb Windows backend, and similarly for Mac OS X as well. libusb can get some basic information for device with a non-proper driver (e.g.: USB mass storage device), but will not be able to open the device without changing the driver to a supported one.

-- Xiaofan

like image 43
antiduh Avatar answered Nov 15 '22 18:11

antiduh