USB外围设备的bIntervals是如何实施的?

问题描述 投票:0回答:1

我有一个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值如何影响事物的明确解释。

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

因此,它是:

  • 驱动程序禁止触发请求,直到8ms过去。听起来对我来说是最合理的选择,但是从我的URB Trace中,Dispatch message事件在请求回来之前几毫秒被提升。这意味着数据离开主机的实时时间对我/消息分析器是隐藏的。
  • 驱动程序隐藏了我和分析仪的响应,直到最后一次响应后已经过了8ms。

如果它确实由驱动程序处理,那么在交换消息的日志中向我显示的内容存在谎言。在请求之后应立即响应,但事实并非如此。因此,请求在显示的时间之后发送,或者响应早于显示的时间。

如何执行对bInterval的尊重?

我的最终目标是忽略bInterval值并且比8ms更频繁地轮询设备(我有充分的理由相信它可以被轮询到每2ms,并且8ms的时间段对于它的使用是不可接受的),但首先我想要知道它当前的限制是如何工作的,如果我正在寻找什么是可能的,那么我可以理解下一步要学习什么(例如编写一个自定义的WinUSB驱动程序)

usb polling libusb peripherals
1个回答
1
投票

我有一个FullSpeed USB设备

小心:你确认了吗? 8ms是低速USB设备的限制 - 许多常见的鼠标或键盘可能仍在使用。

8ms调度在USB主机驱动程序(ehci / xhci)AFAIK内完成。您可以尝试通过释放和回收接口来赌博 - 但未经过测试。 (编辑:不起作用,请参阅评论)。

USB设备无法自行通话,因此必须是延迟的请求。请注意,当没有可用的新数据时,设备也可以NAK任何中断IN请求。这只是为时间增加了另一个bInterval ms。

编写自定义WinUSB驱动程序

不推荐 - 更换Windows提供的驱动程序是一件非常麻烦的事。我们用于USB CDC设备的libusb-win32替换器在所有大型Windows 10升级中破坏 - 升级完成后,设备使用COM端口而不是libusb。

© www.soinside.com 2019 - 2024. All rights reserved.