libusb interrupt transfer

15,559

Solution 1

There is a problem with the code you posted. The syntax you wrote for defining bytes will not result in an 8-byte array, but you are requesting that libusb write 8 bytes in to that address so you might get an error or memory corruption. Try this instead:

unsigned char buffer[8];
int len = 0;
int ret = libusb_interrupt_transfer(handle, 0x81, buffer, sizeof(buffer), &len, 0);

Each HID report has its own endpoint, so you specify which report you want to receive by specifying the correct endpoint. You specified Endpoint 1 IN (0x81). Are you sure that endpoint is defined in the device's descriptors? Maybe you should get the descriptors (with lsusb -v in Ubuntu) and post them here so we can check them.

Solution 2

I had the same issue, libusb_interrupt_transfer() blocks forever for read endpoint (bEndpoinntAddress: 0x81 EP 1 IN (output of lsusb -v)), but solved.

In my case, I have written like this.

#define ENDPOINT_IN 0x81
unsigned char buffer[8];
int len = 0;
int ret = libusb_interrupt_transfer(handle, ENDPOINT_IN, buffer, sizeof(buffer), &len, 0);

But, my device requires some code sent before reading data,
and requires sizeof 64 buffer although lsusb -v's output bLength is 7.

#define ENDPOINT_OUT 0x01
#define ENDPOINT_IN 0x81
unsigned char buffer[64] = {0x20, 0x01, 0x03, 0x02, 0x07};
int len = 0;
int send_ret = libusb_interrupt_transfer(handle, ENDPOINT_OUT, buffer, sizeof(buffer), &len, 0);
int recv_ret = libusb_interrupt_transfer(handle, ENDPOINT_IN, buffer, sizeof(buffer), &len, 0);

the buffer[64] = {0x20, 0x01, 0x03, 0x02, 0x07} depends on the device specification.

Hope this helps.

Share:
15,559
Arne
Author by

Arne

Updated on June 29, 2022

Comments

  • Arne
    Arne almost 2 years

    I need to reverse engineer a driver for custom made HID USB device (some buttons and leds on an control panel). The driver is only available on Windows and we need a *nix implementation.

    The device apparently is a HID device although not of a particular class. It provides two interfaces each with a single interrupt endpoint.

    My setup currently involves a VirtualBox running Windows on a Ubuntu host to capture the USB traffic via Wireshark. The protocol is rather simple and I already gained a rather good understanding.

    I am using libusb-1.0 in a simple C++ console program for prototyping. I already managed to toggle LEDs by issuing a SET_REPORT control transfer but struggle in receiving button presses via interrupt in transfers.

    In fact the following call blocks forever:

    unsigned char bytes[8] = { 0 };
    int len = 0;
    int ret = libusb_interrupt_transfer(handle, 0x81, bytes, 8, &len, 0); 
    

    When inspecting the resulting URB in Wireshark it looks exactly like the equivalent captured at the Windows session. Still I never get a reply from the device.

    I fell I am missing some setting. Note that the device is properly opened and both interfaces provided by the device have been sucessfully claimed. Input reports by means of control transfers are coming trough, even in my linux application.

    Thanks for any pointer! Arne

    Addendum I: I am wondering how am I supposed to specify which report id I want to receive when using libusb_interrupt_transfer()?

    Addendum II: When comparing the requests made by the windows driver to the one generated by the above code in Wireshark I don't see any difference (same values in URB). But still, only when issued by the Windows driver the interrupt transfer returns.

    When inspecting the Windows driver communication in Wireshark I dont see any control transfers other than various GET_DESCRIPTOR(...). Most important: no SET_INTERFACE or SET_CONFIGURATION Thus I suspect the problem is related to the library or how I use it and is not related to the device.

  • Arne
    Arne almost 13 years
    the missing brackets are a typo. The actual code reads unsigned char buffer[8]. Thanks for the hint, anyway.