我有一个FullSpeed USB设备发送一个报告描述符,其相关的端点描述符声明一个8的bInterval
,意思是8ms。
当设备的驱动程序为HidUsb时,从USB Descriptor Dumper获取以下报告摘录:
Interface Descriptor: // +several attributes
------------------------------
0x04 bDescriptorType
0x03 bInterfaceClass (Human Interface Device Class)
0x00 bInterfaceSubClass
0x00 bInterfaceProtocol
0x00 iInterface
HID Descriptor: // +bLength, bCountryCode
------------------------------
0x21 bDescriptorType
0x0110 bcdHID
0x01 bNumDescriptors
0x22 bDescriptorType (Report descriptor)
0x00D6 bDescriptorLength
Endpoint Descriptor: // + bLength, bEndpointAddress, wMaxPacketSize
------------------------------
0x05 bDescriptorType
0x03 bmAttributes (Transfer: Interrupt / Synch: None / Usage: Data)
0x08 bInterval (8 frames)
在将驱动程序切换到WinUSB以便能够使用它之后,如果我使用libusb重复查询IN中断传输,并使用此脚本在libusb调用和libusb调用期间花费实时时间:
for (int i = 0; i < n; i++) {
start = std::chrono::high_resolution_clock::now();
forTime = (double)((start - end).count()) / 1000000;
<libusb_interrupt_transfer on IN interrupt endpoint>
end = std::chrono::high_resolution_clock::now();
std::cout << "for " << forTime << std::endl;
transferTime = (double)((end - start).count()) / 1000000;
std::cout << "transfer " << transferTime << std::endl;
std::cout << "sum " << transferTime + forTime << std::endl << std::endl;
}
以下是获得值的示例:
for 2.60266
transfer 5.41087
sum 8.04307 //~8
for 3.04287
transfer 5.41087
sum 8.01353 //~8
for 6.42174
transfer 9.65907
sum 16.0808 //~16
for 2.27422
transfer 5.13271
sum 7.87691 //~8
for 3.29928
transfer 4.68676
sum 7.98604 //~8
总和值始终保持非常接近8ms,除非在启动新的中断传输调用之前经过的时间太长(对于我的特定情况,阈值似乎在6到6.5之间),在这种情况下它等于16.我有曾经看到一个等于18ms的“for”度量,总和精确等于24ms。使用URB跟踪器(在我的情况下是Microsoft Message Analyzer),Complete URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
消息之间的时间差也是8ms的倍数 - 通常是8ms。简而言之,它们与“总和”措施相匹配。
因此,很明显两次返回“libusb中断传输调用”之间经过的时间是8ms的倍数,我假设它与bInterval值为8(FullSpeed - > * 1ms - > 8ms)有关。
但是现在,我希望,我已经说清楚我在说什么 - 强制执行的地方在哪里?尽管有研究,但我无法找到bInterval值如何影响事物的明确解释。
显然,这是由司机强制执行的。
因此,它是:
Dispatch message
事件在请求回来之前几毫秒被提升。这意味着数据离开主机的实时时间对我/消息分析器是隐藏的。如果它确实由驱动程序处理,那么在交换消息的日志中向我显示的内容存在谎言。在请求之后应立即响应,但事实并非如此。因此,请求在显示的时间之后发送,或者响应早于显示的时间。
我的最终目标是忽略bInterval值并且比8ms更频繁地轮询设备(我有充分的理由相信它可以被轮询到每2ms,并且8ms的时间段对于它的使用是不可接受的),但首先我想要知道它当前的限制是如何工作的,如果我正在寻找什么是可能的,那么我可以理解下一步要学习什么(例如编写一个自定义的WinUSB驱动程序)
我有一个FullSpeed USB设备
小心:你确认了吗? 8ms是低速USB设备的限制 - 许多常见的鼠标或键盘可能仍在使用。
8ms调度在USB主机驱动程序(ehci / xhci)AFAIK内完成。您可以尝试通过释放和回收接口来赌博 - 但未经过测试。 (编辑:不起作用,请参阅评论)。
USB设备无法自行通话,因此必须是延迟的请求。请注意,当没有可用的新数据时,设备也可以NAK任何中断IN请求。这只是为时间增加了另一个bInterval
ms。
编写自定义WinUSB驱动程序
不推荐 - 更换Windows提供的驱动程序是一件非常麻烦的事。我们用于USB CDC设备的libusb-win32替换器在所有大型Windows 10升级中破坏 - 升级完成后,设备使用COM端口而不是libusb。