Linux libusb中断传输
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6474949/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
libusb interrupt transfer
提问by Arne
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.
我需要对定制的 HID USB 设备(控制面板上的一些按钮和 LED)驱动程序进行逆向工程。该驱动程序仅在 Windows 上可用,我们需要一个 *nix 实现。
The device apparently is a HID device although not of a particular class. It provides two interfaces each with a single interrupt endpoint.
该设备显然是 HID 设备,尽管不是特定类别。它提供了两个接口,每个接口都有一个中断端点。
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.
我的设置目前涉及在 Ubuntu 主机上运行 Windows 的 VirtualBox,以通过 Wireshark 捕获 USB 流量。该协议相当简单,我已经获得了相当好的理解。
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.
我在一个简单的 C++ 控制台程序中使用 libusb-1.0 进行原型设计。我已经设法通过发出 SET_REPORT 控制传输来切换 LED,但在通过传输中断接收按钮按下时遇到了困难。
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.
在 Wireshark 中检查生成的 URB 时,它看起来与在 Windows 会话中捕获的等效项完全相同。我仍然没有收到设备的回复。
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.
我觉得我错过了一些设置。请注意,设备已正确打开,并且设备提供的两个接口均已成功声明。即使在我的 linux 应用程序中,通过控制传输的输入报告也即将到来。
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()
?
附录 I:我想知道我应该如何指定使用时要接收的报告 ID 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.
附录 II:将 Windows 驱动程序发出的请求与 Wireshark 中上述代码生成的请求进行比较时,我没有看到任何区别(URB 中的值相同)。但是,只有在由 Windows 驱动程序发出时,中断传输才会返回。
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 notrelated to the device.
在 Wireshark 中检查 Windows 驱动程序通信时,除了各种GET_DESCRIPTOR(...)
. 最重要的是:没有SET_INTERFACE
或SET_CONFIGURATION
因此我怀疑问题是关系到图书馆或如何我使用它,并没有相关的设备。
回答by David Grayson
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:
您发布的代码有问题。您为定义编写的语法bytes
不会产生 8 字节数组,但您请求 libusb 将 8 个字节写入该地址,因此您可能会收到错误或内存损坏。试试这个:
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.
每个 HID 报告都有自己的端点,因此您可以通过指定正确的端点来指定要接收的报告。您指定了端点 1 IN (0x81)。您确定端点是在设备的描述符中定义的吗?也许您应该获取描述符(lsusb -v
在 Ubuntu 中)并将它们张贴在这里,以便我们可以检查它们。
回答by jacob
I had the same issue, libusb_interrupt_transfer()
blocks forever for read endpoint (bEndpoinntAddress: 0x81 EP 1 IN (output of lsusb -v
)), but solved.
我遇到了同样的问题,libusb_interrupt_transfer()
永远阻止读取端点(bEndpointAddress:0x81 EP 1 IN(输出lsusb -v
)),但已解决。
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.
但是,我的设备需要在读取数据之前发送一些代码,
并且需要 sizeof 64 的缓冲区,尽管lsusb -v
的输出bLength
是 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.
这buffer[64] = {0x20, 0x01, 0x03, 0x02, 0x07}
取决于设备规格。
Hope this helps.
希望这可以帮助。