USB外围设备如何';强制执行宾特伐?

USB外围设备如何';强制执行宾特伐?,usb,polling,libusb,peripherals,Usb,Polling,Libusb,Peripherals,我有一个全速USB设备,它发送一个报告描述符,它的相关端点描述符声明了一个8的bInterval,意思是8毫秒 当设备的驱动程序为HidUsb时,从USB描述符转储程序获取以下报告摘录: Interface Descriptor: // +several attributes ------------------------------ 0x04 bDescriptorType 0x03 bInterfaceClass (Human Interface Device Cla

我有一个全速USB设备,它发送一个报告描述符,它的相关端点描述符声明了一个8的
bInterval
,意思是8毫秒

当设备的驱动程序为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重复查询中断传输,并使用以下脚本计算两次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;
}
总和值始终保持非常接近8毫秒,除非在启动新的中断传输调用之前经过的时间太长(对于我的特定情况,阈值似乎在6和6.5之间),在这种情况下,它等于16。我曾经看到一个“for”度量值等于18ms,其和正好等于24ms。使用URB跟踪器(在我的例子中是Microsoft Message Analyzer),完整URB功能、批量或中断传输之间的时间差也是8ms的倍数,通常是8ms。简言之,它们符合“总和”指标

因此,很明显,“libusb中断传输调用”的两次返回之间经过的时间是8ms的倍数,我假设这与bInterval值8(全速->*1ms->8ms)有关

但现在,我希望,我已经清楚地表明了我在说什么——这是在哪里实施的?尽管进行了研究,我还是找不到一个关于bInterval值如何影响事物的清晰解释

显然,这是由司机强制执行的

因此,是否:

  • 驾驶员禁止请求在8毫秒后触发。对我来说,这似乎是最合理的选择,但从我的URB跟踪来看,
    Dispatch message
    事件是在请求返回前几毫秒引发的。这意味着离开主机的实时数据对我/消息分析器是隐藏的

  • 驱动程序对我和分析器隐藏响应,直到距离上次响应8毫秒

如果它确实是由司机处理的,那么在交换信息的日志中显示给我的东西在某个地方是谎言。响应应该在请求之后立即出现,但事实并非如此。因此,要么请求在显示的时间之后发送,要么响应早于显示的时间

如何执行对bInterval的尊重? 我的最终目标是忽略bInterval值,并以超过8ms的频率轮询设备(我有充分的理由相信它可以每2ms轮询一次,8ms的使用周期是不可接受的),但首先我想知道它当前的限制是如何工作的,如果我所寻求的是可能的,所以我可以理解下一步要学习什么(例如编写自定义WinUSB驱动程序)

我有一个全速USB设备

小心:你核实了吗?8ms是低速USB设备的极限,许多普通鼠标或键盘可能仍在使用

8ms调度在USB主机驱动程序(ehci/xhci)AFAIK中完成。您可以尝试通过释放和回收接口来赌一把——尽管没有经过测试。(编辑:不起作用,请参见注释)

USB设备无法单独通话,因此它必须是延迟的请求。请注意,当没有新数据可用时,设备也可以NAK请求中的任何中断。这只是将另一个
bInterval
ms添加到计时中

编写自定义WinUSB驱动程序


不推荐-更换windows提供的驱动程序相当麻烦。我们的USB CDC设备的libusb-win32替换程序在所有大型windows 10升级中都会中断-升级完成后,该设备将使用COM端口而不是libusb。

感谢您的输入。一个USB设备描述符声称它是全速的。您知道是请求还是响应被USB主机驱动程序延迟了吗?如果设备中没有完成8ms调度,URB消息分析器向我显示的“响应和请求之间约3ms,请求和响应之间平均约5ms”必须错误地反映实际发生的情况。我尝试过在每个请求之间释放/声明接口,这种行为非常令人惊讶。响应时间(发布/索赔之间的时间)+8毫秒,在之前的响应之后。例如:1.73毫秒的释放/索赔时间=>9.73毫秒。
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