libusb中断传输

发布于 2024-11-17 00:08:00 字数 1048 浏览 0 评论 0原文

我需要对定制 HID USB 设备(控制面板上的一些按钮和 LED)驱动程序进行逆向工程。该驱动程序仅在 Windows 上可用,我们需要 *nix 实现。

该设备显然是 HID 设备,尽管不属于特定类别。它提供两个接口,每个接口都有一个中断端点。

我的设置当前涉及在 Ubuntu 主机上运行 Windows 的 VirtualBox,以通过 Wireshark 捕获 USB 流量。该协议相当简单,我已经有了很好的理解。

我在一个简单的 C++ 控制台程序中使用 libusb-1.0 进行原型设计。我已经成功地通过发出 SET_REPORT 控制传输来切换 LED,但在通过传输中断接收按钮按下时遇到了困难。

事实上,以下调用将永远阻塞:

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

在 Wireshark 中检查生成的 URB 时,它看起来与在 Windows 会话中捕获的等效内容完全相同。但我仍然没有收到设备的回复。

我觉得我缺少一些设置。请注意,设备已正确打开,并且设备提供的两个接口已成功声明。即使在我的 Linux 应用程序中,通过控制传输的输入报告也会出现。

感谢您的指点! 阿恩

附录一: 我想知道在使用 libusb_interrupt_transfer() 时如何指定我想要接收的报告 ID?

附录二: 将 Windows 驱动程序发出的请求与上述代码在 Wireshark 中生成的请求进行比较时,我没有看到任何差异(URB 中的值相同)。但是,只有当 Windows 驱动程序发出中断传输时才会返回。

在 Wireshark 中检查 Windows 驱动程序通信时,除了各种 GET_DESCRIPTOR(...) 之外,我没有看到任何控制传输。最重要的是:没有 SET_INTERFACESET_CONFIGURATION 因此,我怀疑问题与库或我使用它的方式有关,与设备无关。 。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

扬花落满肩 2024-11-24 00:08:00

我遇到了同样的问题,libusb_interrupt_transfer() 永远阻止读取端点(bEndpointntAddress:0x81 EP 1 IN(lsusb -v 的输出)),但已解决。

就我而言,我是这样写的。

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

但是,我的设备需要在读取数据之前发送一些代码,
并且需要 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);

buffer[64] = {0x20, 0x01, 0x03, 0x02, 0x07} 取决于设备规格。

希望这有帮助。

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.

半边脸i 2024-11-24 00:08:00

您发布的代码有问题。您为定义 bytes 编写的语法不会生成 8 字节数组,但您请求 libusb 将 8 个字节写入该地址,因此可能会出现错误或内存损坏。请尝试以下操作:

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

每个 HID 报告都有其自己的端点,因此您可以通过指定正确的端点来指定要接收的报告。您指定了端点 1 IN (0x81)。您确定端点已在设备描述符中定义吗?也许您应该获取描述符(在 Ubuntu 中使用 lsusb -v)并将它们发布到此处,以便我们可以检查它们。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文