我有一个全速USB设备,用于发送报告描述符,其相关端点描述符声明bInterval
为8,表示8ms。
当设备的驱动程序为HidUsb时,以下报告摘录是从USB描述符转储程序获得的:
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我曾经见过“ for”度量等于18ms,总和恰好等于24ms。使用URB跟踪器(在我的情况下为Microsoft Message Analyzer),Complete URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER
消息之间的时间差也是8ms的倍数-通常为8ms。简而言之,它们与“求和”度量相匹配。
因此,很明显,两次“ libusb中断传输调用”返回之间的时间是8ms的倍数,我认为这与bInterval值8有关(FullSpeed-> * 1ms-> 8ms)。
但是,现在我希望我已经明确了我在说什么-强制执行在哪里?尽管进行了研究,但我找不到关于bInterval值如何影响事物的清晰解释。
显然,这是由驱动程序强制执行的。
因此,是:
驱动程序禁止触发请求,直到经过8ms。对我来说,这听起来似乎是最合理的选择,但是从我的URB跟踪中,Dispatch message
事件在请求返回之前被引发了几毫秒。这将意味着对主机/消息分析器隐藏的实时离开主机的数据。
驱动程序对我和分析器隐藏了响应,直到上次响应以来已过去8毫秒。
如果确实由驾驶员处理,则在交换消息日志中显示给我的内容中有一个谎言。请求后应立即做出响应,但实际情况并非如此。因此,要么在显示的时间之后发送请求,要么响应早于显示的时间。
我的最终目标是不理会bInterval值并以8ms以上的频率更频繁地轮询设备(我有充分的理由相信它可以每2ms轮询一次,使用8ms的时间是不可接受的),但首先我想知道它当前的局限性是如何工作的,如果我所寻求的完全可行,那么我就能理解下一步要学习的内容(例如,编写自定义WinUSB驱动程序)
答案 0 :(得分:1)
我有一个FullSpeed USB设备
注意:您是否对此进行了验证? 8ms是低速度USB设备的限制-许多常见的鼠标或键盘可能仍在使用。
8ms调度是在USB主机驱动程序(ehci / xhci)AFAIK中完成的。您可以尝试通过释放和回收接口来赌博(不过未经测试)。 (编辑:将不起作用,请参阅评论)。
USB设备无法自行讲话,因此必须延迟请求。请注意,当没有新数据可用时,设备也可以NAK任何中断IN请求。这只是在时间上增加了bInterval
毫秒。
编写自定义WinUSB驱动程序
不推荐-更换Windows提供的驱动程序很麻烦。我们的USB CDC设备的libusb-win32替换程序在所有大型Windows 10升级中均告失败-升级完成后,该设备将使用COM端口而不是libusb。