【问题标题】:libusb interrupt transferlibusb 中断传输
【发布时间】:2011-06-25 00:15:22
【问题描述】:

我需要对定制 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 会话中捕获的等效 URB 完全相同。我仍然没有收到设备的回复。

我觉得我错过了一些设置。请注意,设备已正确打开,并且设备提供的两个接口均已成功声明。即使在我的 linux 应用程序中,通过控制传输的输入报告也即将到来。

感谢您的指点! 阿恩

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

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

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

【问题讨论】:

  • @david:我现在无法发布描述符,因为设备位于我的办公室。无论如何,描述符中肯定有两个端点 - 在两个接口中的每一个上都有一个。两个界面都提供至少一个包含设备按钮状态的输出报告。至少那些报告定义了Usage Buttons
  • 我认为 libusb_interrupt_transfer 会永远阻塞,即使我已将超时设置为 500 毫秒。但是当我注释掉那条线后,我的简单驱动程序挂断了;所以我在这里和那里插入了一些调试打印,发现libusb_open 永远锁定,无论我在哪个设备上发布它。该死,从数位板获取int x,y,pressure,button_state; 真的需要这么难吗?说真的,这是矫枉过正:)

标签: c++ c linux usb libusb


【解决方案1】:

您发布的代码有问题。您为定义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)并将它们发布在这里以便我们检查它们。

【讨论】:

  • 缺少的括号是一个错字。实际代码为unsigned char buffer[8]。无论如何,谢谢你的提示。
【解决方案2】:

我遇到了同样的问题,libusb_interrupt_transfer() 永远阻塞了读取端点(bEndpointAddress: 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} 取决于设备规格。

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-07
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    相关资源
    最近更新 更多