Libusb interrupt passing

I need to reverse engineer the driver for a specially configured HID USB device (some buttons and LEDs on the control panel). The driver is only available on Windows, and we need a * nix implementation.

The device is apparently a HID device, although not for a specific class. It provides two interfaces, each with one endpoint breakpoint.

My installation currently includes a Windows-based VirtualBox on the Ubuntu host to capture USB traffic through Wireshark. The protocol is pretty simple, and I already got a pretty good understanding.

I use libusb-1.0 in a simple C ++ console program for prototyping. I have already managed to switch the LEDs by releasing the SET_REPORT control transfer, but struggle with pressing the button by pressing the interrupt in the transfers.

In fact, the following call blocks are forever:

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

When checking the received URB in Wireshark, it looks exactly the same as the equivalent received in a Windows session. However, I never get a response from a device.

I fell, I am missing some settings. Please note that the device is correctly opened, and both interfaces provided by the device have been successfully announced. Input reports via pilot transfers come in, even in my Linux application.

Thanks for any pointer! Arne

Addendum I: I wonder how I should indicate which report identifier I want when using libusb_interrupt_transfer() ?

Appendix II: When comparing requests made by the Windows driver with the one created by the above code in Wireshark, I don’t see the difference (the same values ​​in URB). But still, only when issued by the Windows driver does the interrupt transmission return.

When checking the connection of the Windows driver in Wireshark, I do not see any control transfers, except for various GET_DESCRIPTOR(...) . Most important: no SET_INTERFACE or SET_CONFIGURATION Thus, I suspect that the problem is with the library or how I use it and is not related to the device.

+4
source share
2 answers

There is a problem with the code you posted. The syntax you wrote to define bytes will not result in an 8-byte array, but you are requesting libusb to write 8 bytes to this address so you can get an error or memory corruption. Try 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 have specified the endpoint 1 IN (0x81). Are you sure the endpoint is defined in the device descriptors? Perhaps you should get the descriptors (from lsusb -v on Ubuntu) and post them here so we can check them out.

+1
source

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

In my case, I wrote 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 needs the code passed before reading the data,
and requires a size of 64 buffers, although the output of lsusb -v 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); 

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

Hope this helps.

0
source

All Articles