Как применяются bIntervals периферийных устройств USB? - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть устройство USB FullSpeed, которое отправляет дескриптор отчета, соответствующий дескриптор конечной точки которого объявляет bInterval из 8, что означает 8 мс.

Следующая выдержка отчета получается из дампера дескриптора USB, когда устройстводрайвер HidUsb:

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, чтобы иметь возможность его использовать, если я неоднократно запрашиваю передачу прерываний IN, используя libusb, и время реального времени, потраченное между 2 вызовами 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

Значения суммы постоянно остаются очень близкими к 8 мс, за исключением времени, прошедшего до инициации нового прерывания.Переадресация слишком длинная (пороговое значение, по-видимому, находится между 6 и 6,5 для моего конкретного случая), в этом случае оно равно 16. Я однажды видел меру «для», равную 18 мс, а сумма точно равна 24 мс.Используя трекер URB (в моем случае Microsoft Message Analyzer), разница во времени между сообщениями Complete URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER также кратна 8 мс - обычно 8 мс.Короче говоря, они соответствуют мерам «суммы».

Итак, ясно, что время, прошедшее между двумя возвратами «вызовов передачи прерываний libusb», кратно 8 мсам, что, я полагаю, связано с bIntervalзначение 8 (FullSpeed ​​-> * 1ms -> 8ms).

Но теперь, когда я, я надеюсь, дал понять, о чем я говорю - где это применяется?Несмотря на исследования, я не могу найти четкого объяснения того, как значение bInterval влияет на вещи.

Очевидно, это обеспечивается драйвером.

Следовательно, это:

  • Водитель запрещает запуск запроса до истечения 8 мс.Звучит как наиболее разумный вариант для меня, но из моего URB Trace события Dispatch message были вызваны за несколько миллисекунд до того, как запрос вернулся.Это будет означать, что в реальном времени данные, оставленные хостом, скрыты от меня / анализатора сообщений.

  • Драйвер скрывает ответ от меня и анализатора до тех пор, пока не пройдет 8 мс с момента последнего ответа.

Если это действительно обработано драйвером, то где-то ложь с тем, что показано мне в журнале обмена сообщениями.Ответ должен прийти сразу после запроса, но это не так.Итак, либо запрос отправляется после указанного времени, либо ответ приходит раньше, чем отображается.

Как работает соблюдение принципа уважения bInterval?

Моя конечная цель состоит в том, чтобыне обращайте внимания на значение bInterval и опрашивайте устройство чаще, чем за 8 мс (у меня есть веские основания полагать, что оно может опрашиваться каждые 2 мс, а период 8 мс неприемлем для его использования), но сначала я бы хотел узнать, как его текущееограничение работает, если то, что я ищу, вообще возможно, поэтому я могу понять, что изучать дальше (например, написание собственного драйвера WinUSB)

1 Ответ

0 голосов
/ 13 февраля 2019

У меня есть USB-устройство FullSpeed ​​

Осторожно: Вы убедились в этом?8 мс - это предел для низко скоростных USB-устройств, которые все еще могут использовать многие обычные мыши или клавиатуры.

Планирование 8 мс выполняется внутри хост-драйвера USB (ehci / xhci) AFAIK,Вы можете попытаться сыграть в эту игру, выпустив и восстановив интерфейс - но не проверено.(Изменить: не будет работать, см. Комментарий).

USB-устройство не может разговаривать самостоятельно, поэтому запрос должен быть отложен.Обратите внимание, что устройство может также принимать любые запросы IN прерывания, когда нет новых доступных данных.Это просто добавляет еще одну bInterval мс к времени.

написание пользовательского драйвера WinUSB

Не рекомендуется - замена драйвера, поставляемого с Windows, довольно хлопотна.Наш заменитель libusb-win32 для устройства USB CDC ломается на всех больших обновлениях Windows 10 - устройство использует COM-порт вместо libusb после завершения обновления.

...