Рекомендации. Использование универсальных кодов ресурса (URB)

В этом разделе описаны рекомендации по выделению, созданию и отправке URB в стек драйверов USB, входящий в состав Windows 8.

Windows 8 включает новый стек драйверов USB для поддержки устройств универсальной последовательной шины (USB) 3.0. Новый стек драйверов USB 3.0 реализует несколько новых возможностей в спецификации USB 3.0. Кроме того, стек драйверов включает другие возможности, позволяющие драйверу клиента эффективно выполнять распространенные задачи. Например, новый стек драйверов принимает цепочки многомерных выражений, которые позволяют драйверу клиента отправлять буфер передачи в несогласованных страницах в физической памяти.

Прежде чем драйвер клиента сможет использовать новые возможности стека драйверов USB для Windows 8, драйвер должен зарегистрировать себя в базовом стеке USB-драйверов, загруженном Windows для устройства. Чтобы зарегистрировать драйвер клиента, вызовите USBD_CreateHandle и укажите версию контракта. Если драйвер клиента предназначен для сборки, запуска и использования улучшений и новых возможностей в Windows 8, версия контракта клиента USBD_CLIENT_CONTRACT_VERSION_602.

Для драйвера клиента USBD_CLIENT_CONTRACT_VERSION_602 версии стек драйверов USB предполагает, что драйвер клиента соответствует следующему набору правил:

Стек драйверов USB выполняет проверку полученных запросов и по возможности обрабатывает нарушения. Невыполнение этого действия может привести к неопределенному поведению.

Не отправлять запросы ввода-вывода с помощью устаревших или недопустимых дескрипторов канала

Драйвер клиента не должен использовать устаревшие дескрипторы канала для отправки запросов ввода-вывода в стек драйверов USB. Устаревший дескриптор канала — это дескриптор канала, полученный в запросе на выбор конфигурации, интерфейса или альтернативного параметра, который больше не выбран на устройстве. Чтобы избежать устаревших дескрипторов канала, каждый раз, когда драйвер клиента выбирает конфигурацию или интерфейс, драйвер должен обновлять кэш дескрипторов канала (обычно хранящихся в контексте устройства). Некоторые условия гонки также могут привести к устареть ручки трубы. Например, драйвер клиента отправляет запрос ввода-вывода с помощью дескриптора канала в выбранном интерфейсе. Перед выполнением запроса драйвер клиента выбирает альтернативный параметр, который не использует ту же конечную точку, связанную с используемым дескриптором канала. Оба этих ожидающих запроса могут привести к тому, что состояние гонки делает дескриптор канала недопустимым.

Выделение URI путем вызова процедур выделения в Windows 8

Windows 8 предоставляет новые процедуры для выделения, создания и освобождения блоков запросов USB (URB). Чтобы выделить URB, драйвер клиента модели драйвера Windows (WDM) должен всегда использовать новые подпрограммы, показанные в следующем списке:

Подпрограммы из предыдущего списка могут прикреплять непрозрачный контекст URB к выделенной urb для улучшения отслеживания и обработки. Драйвер клиента не может просматривать или изменять содержимое контекста URB. Дополнительные сведения о выделении urb в Windows 8 см. в разделе Выделение и создание urb.

Если драйвер клиента Windows Driver Framework (WDF), который определяет свою версию как USBD_CLIENT_CONTRACT_VERSION_602 во время регистрации (см. WdfUsbTargetDeviceCreateWithParameters), стек драйверов USB ожидает, что драйвер клиента будет выделять память для URB, вызвав новый WdfUsbTargetDeviceCreateUrb.

Не используйте повторно активные URI, связанные с ожидающих запросов

Стек драйверов USB намеренно проверяет ошибки, если обнаруживает, что активная URB, которая была повторно предоставлена перед запросом, связанным с URB. URB активна до тех пор, пока запрос находится в ожидании, а подпрограмма завершения IRP драйвера клиента не была вызвана. Не выполняйте следующие задачи на активной urb.

  • Не пересылайте активную urb для другого запроса (свяжите URB с другим IRP).
  • Не изменяйте содержимое активной urb.
  • Не освобождайте активную urb.

После вызова подпрограммы завершения драйвера клиента драйверы могут повторно отправить URI для определенных типов запросов в рамках процедуры завершения. При повторном выполнении действуют следующие правила:

  • Драйвер клиента не должен повторно использовать urb, выделенный USBD_SelectConfigUrbAllocateAndBuild для любого типа запроса, кроме запроса на выбор конфигурации, чтобы выбрать ту же конфигурацию.

  • Драйвер клиента не должен повторно использовать urb, выделенный USBD_SelectInterfaceUrbAllocateAndBuild для любого типа запроса, кроме запроса интерфейса выбора, чтобы выбрать тот же альтернативный параметр в интерфейсе. Пример см. в разделе Примечания в USBD_SelectInterfaceUrbAllocateAndBuild.

  • UrB, выделенный USBD_IsochUrbAllocate , необходимо повторно использовать только для изохронных запросов на передачу. И наоборот, urb, выделенный для других типов запросов ввода-вывода (управление, массовые операции или прерывания), не следует использовать для изохронного запроса.

    Например, драйвер клиента выделяет и создает структуру URB для запроса на массовую передачу. Драйвер клиента также хочет отправлять данные в изохронные конечные точки на устройстве. После завершения запроса на массовую передачу драйвер клиента не должен переформатировать и отправлять URB для изохронного запроса. Это связано с тем, что URB, связанный с изохронным запросом, имеет переменную длину в зависимости от количества пакетов. Кроме того, пакеты должны начинаться и заканчиваться на границе кадра. Выделенная URB (для массовой передачи) может не соответствовать макету буфера, необходимому для изохронной передачи, и запрос может завершиться ошибкой.

  • UrB, выделенный USBD_UrbAllocate , не должен повторно использоваться для изохронного запроса, запроса select-configuration или select-interface. UrB можно повторно использовать для выбора конфигурации NULL, чтобы отключить выбранную конфигурацию на устройстве. UrB не должна быть активной, и драйвер клиента должен переформатировать URB путем вызова макроса UsbBuildSelectConfigurationRequest и передачи NULL в параметре ConfigurationDescriptor .

  • Перед повторной отправкой URB драйвер клиента должен переформатировать URB с помощью соответствующего макроса UsbBuildXxx, определенного для типа запроса. Важно, чтобы драйвер отформатировал URB, так как стек USB мог изменить часть его содержимого.

    Например, предположим, что драйвер вызывает UsbBuildInterruptOrBulkTransferRequest для инициализации URB для запроса на массовую передачу (см . _URB_BULK_OR_INTERRUPT_TRANSFER). Если драйвер инициализирует элемент TransferBufferMDL структуры URB со значением NULL, стек драйверов USB использует буфер передачи, указанный TransferBuffer, в для обмена данными с устройством вместо MDL. Однако внутренне стек драйверов USB может создать MDL, сохранить указатель на MDL в TransferBufferMDL и использовать MDL для передачи данных в стек. Несмотря на то, что стек USB-драйверов освобождает память MDL, функция TransferBufferMDL может не иметь значение NULL, если драйвер клиента обрабатывает URB в процедуре завершения. Чтобы убедиться, что элементы URB правильно отформатированы, драйвер должен снова вызвать UsbBuildInterruptOrBulkTransferRequest , чтобы переформатировать URB перед отправкой запроса.

Не используйте период опроса больше 8 для высокоскоростных и изохронных передач SuperSpeed

Стек драйверов USB поддерживает высокоскоростные и изохронные трубы SuperSpeed с номерами периода опроса 1, 2, 4 или 8. Драйвер клиента не должен отправлять операции ввода-вывода в конечную точку с периодом больше 8. Это может привести к ошибке.

Убедитесь, что количество изохронных пакетов кратно количеству пакетов на кадр.

Для высокоскоростных и изохронных передач SuperSpeed количество изохронных пакетов на кадр вычисляется как 8 / период опроса. Драйвер клиента должен убедиться, что значение NumberOfPackets , указанное в URB (см . _URB_ISOCH_TRANSFER), кратно количеству пакетов на кадр.

Стек драйверов USB не поддерживает изохронную передачу URI, в которой numberOfPackets не кратно количеству пакетов на кадр.

Вызов подпрограммы на задокументированном уровне IRQL

Если вы регистрируете драйвер клиента с USBD_CLIENT_CONTRACT_VERSION_602 в качестве версии контракта, стек драйверов USB предполагает, что драйвер клиента отправил запрос на соответствующем уровне IRQL. Если драйвер клиента отправляет запрос в DISPATCH_LEVEL, который должен быть отправлен в PASSIVE_LEVEL. При получении запроса в некоторых случаях стек usb-драйвера проверяет значение IRQL и завершает запрос неудачно. Однако в других случаях стек драйверов USB может создать проверку ошибок.

Отправка запросов на USB-устройство