Поделиться через


Работа с USB-каналами

Фреймворк представляет каждый канал в USB-интерфейсе в виде объекта USB-канала. Когда драйвер настраивает USB-устройство, платформа создает объект USB-канала платформы для каждого канала в каждом выбранном интерфейсе. Методы объекта канала позволяют драйверу выполнять следующие операции:

Получение сведений о трубе

После вызова WdfUsbInterfaceGetConfiguredPipe для получения дескриптора объекта канала USB в рамках драйвера, ваш драйвер может вызвать следующие методы, которые объект канала USB определяет для получения сведений о канале USB:

WdfUsbTargetPipeGetIoTarget
Возвращает дескриптор целевого объекта ввода-вывода, связанного с USB-каналом. Драйвер может передать этот дескриптор в WdfRequestSend.

WdfUsbTargetPipeGetInformation
Извлекает сведения о USB-канале и его конечной точке.

WdfUsbTargetPipeGetType
Возвращает тип USB-канала.

WdfUsbTargetPipeIsInEndpoint
Определяет, подключен ли USB-канал к входной конечной точке.

WdfUsbTargetPipeIsOutEndpoint
Определяет, подключен ли USB-канал к выходной конечной точке.

WDF_USB_PIPE_DIRECTION_IN
Определяет, является ли конечная точка USB входной конечной точкой.

WDF_USB_PIPE_DIRECTION_OUT
Определяет, является ли конечная точка USB выходной конечной точкой.

Дополнительные сведения см. в разделе "Перечисление USB-каналов".

Чтение из канала

Чтобы считывать данные из USB-канала ввода, драйвер может использовать любой (или все) из следующих трех методов:

  • Синхронно считывать данные

    Для синхронного чтения данных из USB-канала ввода драйвер может вызвать метод WdfUsbTargetPipeReadSynchronous. Этот метод создает и отправляет запрос на чтение и возвращается после завершения операции ввода-вывода.

  • Асинхронное чтение данных

    Чтобы асинхронно считывать данные из USB-канала ввода, драйвер может вызвать метод WdfUsbTargetPipeFormatRequestForRead для создания запроса на чтение. Затем драйвер может вызвать WdfRequestSend , чтобы отправить запрос асинхронно (или синхронно).

  • Асинхронное и непрерывное чтение данных

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

    Чтобы настроить непрерывное средство чтения для входного канала, функция обратного вызова EvtDevicePrepareHardware должна вызвать метод WdfUsbTargetPipeConfigContinuousReader . Этот метод помещает в очередь набор запросов на чтение в целевой объект устройства ввода-вывода.

    Кроме того, функция обратного вызова EvtDeviceD0Entry драйвера должна вызвать WdfIoTargetStart , чтобы запустить непрерывное средство чтения, а функция обратного вызова EvtDeviceD0Exit должна вызвать WdfIoTargetStop , чтобы остановить непрерывное средство чтения.

    Каждый раз, когда данные доступны на устройстве, целевой объект ввода-вывода завершит запрос на чтение, и платформа вызовет одну из двух функций обратного вызова: EvtUsbTargetPipeReadComplete, если целевой объект ввода-вывода успешно считывает данные или EvtUsbTargetPipeReadersFailed, если целевой объект ввода-вывода сообщает об ошибке.

    Если вы не предоставляете необязательный обратный вызов EvtUsbTargetPipeReadersFailed, фреймворк реагирует на неудачную попытку чтения, отправляя новый запрос на чтение. Таким образом, если шина находится в состоянии, в котором она не принимает операции чтения, платформа постоянно отправляет новые запросы на восстановление после неудачного чтения.

    После вызова драйвера WdfUsbTargetPipeConfigContinuousReader драйвер не может использовать WdfUsbTargetPipeReadSynchronously или WdfRequestSend для отправки запросов ввода-вывода в канал, если функция обратного вызова EvtUsbTargetPipeReadersFailed не вызывается и возвращает FALSE.

По умолчанию фреймворк сообщает об ошибке, если драйвер задает буфер чтения, который не является кратным максимальному размеру пакета канала. Драйвер может вызвать WdfUsbTargetPipeSetNoMaximumPacketSizeCheck , чтобы отключить этот тест размера буфера чтения.

Для получения дополнительной информации см.:

Запись в канал

Чтобы записать данные в usb-канал вывода, драйвер может использовать один (или оба) из следующих методов:

  • Синхронная запись данных

    Для синхронной записи данных в usb-канал вывода драйвер может вызвать метод WdfUsbTargetPipeWriteSynchronously . Этот метод создает и отправляет запрос на запись и возвращается после завершения операции ввода-вывода.

  • Асинхронная запись данных

    Чтобы асинхронно записывать данные в usb-канал ввода, драйвер может вызвать метод WdfUsbTargetPipeFormatRequestForWrite для создания запроса на запись. Затем драйвер может вызвать WdfRequestSend , чтобы отправить запрос асинхронно.

Дополнительные сведения см. в разделе "Как отправлять запросы на массовую передачу USB".

Остановка и сброс трубы

Ваш драйвер может вызвать следующие методы, чтобы остановить или перезапустить USB-канал:

WdfUsbTargetPipeAbortSynchronously
Синхронно отправляет запрос на остановку USB-канала.

WdfUsbTargetPipeFormatRequestForAbort
Форматирует запрос, чтобы остановить USB-канал. Драйвер может вызывать WdfRequestSend, чтобы отправить запрос синхронно или асинхронно.

WdfUsbTargetPipeResetSynchronously
Синхронно отправляет запрос на сброс USB трубки.

WdfUsbTargetPipeFormatRequestForReset
Форматирует запрос для сброса USB-канала. Драйвер должен вызывать WdfRequestSend, чтобы отправить запрос синхронно или асинхронно.

Если usb-целевой объект драйвера завершает запрос ввода-вывода со значением состояния ошибки, драйвер должен выполнить следующее:

  1. Остановите канал и отмените все дополнительные запросы ввода-вывода, отправленные драйверу в USB-целевой объект, если целевой объект не завершил запросы.

    Вызовите WdfIoTargetStop с установленным флагом WdfIoTargetCancelSentIo.

  2. Синхронно отправьте запрос прерывания в канал.

    Вызовите WdfUsbTargetPipeAbortSynchronously, или вызовите WdfUsbTargetPipeFormatRequestForAbort, а затем WdfRequestSend, установив флаг WDF_REQUEST_SEND_OPTION_SYNCHRONOUS.

  3. Синхронно отправьте запрос на сброс в канал.

    Вызовите WdfUsbTargetPipeResetSynchronously или вызовите WdfUsbTargetPipeFormatRequestForReset, а затем WdfRequestSend с флагом WDF_REQUEST_SEND_OPTION_SYNCHRONOUS.

  4. Перезапустите трубу.

    Вызовите WdfIoTargetStart.

  5. Повторно отправьте запрос ввода-вывода, который завершился ошибкой, и все запросы ввода-вывода, которые последовали за неудачным запросом.

После значительного числа сбоев драйверу следует попытаться сбросить USB-порт, выполнив следующие действия:

  1. Остановите все активные каналы и отмените все дополнительные запросы ввода-вывода, отправленные драйверу на USB-объект каждого канала, если целевой объект не завершил их.

    Для каждого активного трубопровода вызовите WdfIoTargetStop с установленным флагом WdfIoTargetCancelSentIo.

  2. Синхронно отправить запрос на сброс USB-порта.

    Вызовите WdfUsbTargetDeviceResetPortSynchronously.

  3. Перезапустите трубы.

    Вызовите WdfIoTargetStart для каждого канала, остановленного драйвером.

  4. Повторно отправьте последний запрос ввода-вывода, который завершился ошибкой, и все запросы ввода-вывода, которые последовали за неудачным запросом.

Для получения дополнительной информации см. Как устранить ошибки USB-канала.

Отправка URB в трубопровод

Если драйвер KMDF взаимодействует с USB-каналом, отправляя запросы ввода-вывода, содержащие URI, драйвер может вызвать следующие методы:

WdfUsbTargetPipeSendUrbSynchronously (лишь для KMDF)
Синхронно отправляет запрос ввода-вывода, содержащий URB.

WdfUsbTargetPipeFormatRequestForUrb (только KMDF)
Форматирует запрос ввода-вывода, содержащий URB. Драйвер может вызывать WdfRequestSend, чтобы отправить запрос синхронно или асинхронно.

WdfUsbTargetPipeWdmGetPipeHandle (только KMDF)
Возвращает дескриптор канала USBD устройства. Для некоторых URB требуется этот хэндл.