Trabalhando com pipes USB
A estrutura representa cada pipe em uma interface USB como um objeto de pipe USB da estrutura. Quando um driver configura um dispositivo USB, a estrutura cria um objeto de pipe USB de estrutura para cada pipe em cada interface selecionada. Os métodos de objeto pipe permitem que um driver execute as seguintes operações:
Obtendo informações de pipe
Depois de chamar WdfUsbInterfaceGetConfiguredPipe para obter um identificador para um objeto de pipe USB da estrutura, o driver pode chamar os seguintes métodos que o objeto de pipe USB define para obter informações sobre o pipe USB:
WdfUsbTargetPipeGetIoTarget
Retorna um identificador para o objeto de destino de E/S associado a um pipe USB. O driver pode passar esse identificador para WdfRequestSend.
WdfUsbTargetPipeGetInformation
Recupera informações sobre um pipe USB e seu ponto de extremidade.
WdfUsbTargetPipeGetType
Retorna o tipo de um pipe USB.
WdfUsbTargetPipeIsInEndpoint
Determina se um pipe USB está conectado a um ponto de extremidade de entrada.
WdfUsbTargetPipeIsOutEndpoint
Determina se um pipe USB está conectado a um ponto de extremidade de saída.
WDF_USB_PIPE_DIRECTION_IN
Determina se um ponto de extremidade USB é um ponto de extremidade de entrada.
WDF_USB_PIPE_DIRECTION_OUT
Determina se um ponto de extremidade USB é um ponto de extremidade de saída.
Para obter informações relacionadas, consulte Como enumerar pipes USB.
Lendo de um pipe
Para ler dados de um pipe de entrada USB, o driver pode usar qualquer (ou todas) das três técnicas a seguir:
Ler dados de forma síncrona
Para ler dados de forma síncrona de um pipe de entrada USB, o driver pode chamar o método WdfUsbTargetPipeReadSynchronously . Esse método compila e envia uma solicitação de leitura e retorna após a conclusão da operação de E/S.
Ler dados de forma assíncrona
Para ler dados de forma assíncrona de um pipe de entrada USB, o driver pode chamar o método WdfUsbTargetPipeFormatRequestForRead para criar uma solicitação de leitura. Em seguida, o driver pode chamar WdfRequestSend para enviar a solicitação de forma assíncrona (ou síncrona).
Ler dados de forma assíncrona e contínua
Um leitor contínuo é um mecanismo fornecido pela estrutura para garantir que uma solicitação de leitura esteja sempre disponível para um pipe USB. Esse mecanismo garante que o driver sempre estará pronto para receber dados de um dispositivo que fornece um fluxo de entrada assíncrono e não solicitado. Por exemplo, um driver para uma NIC (cartão de interface de rede) pode usar um leitor contínuo para receber dados de entrada.
Para configurar um leitor contínuo para um pipe de entrada, a função de retorno de chamada EvtDevicePrepareHardware do driver deve chamar o método WdfUsbTargetPipeConfigContinuousReader . Esse método enfileira um conjunto de solicitações de leitura para o destino de E/S do dispositivo.
Além disso, a função de retorno de chamada EvtDeviceD0Entry do driver deve chamar WdfIoTargetStart para iniciar o leitor contínuo e a função de retorno de chamada EvtDeviceD0Exit do driver deve chamar WdfIoTargetStop para interromper o leitor contínuo.
Sempre que os dados estiverem disponíveis no dispositivo, o destino de E/S concluirá uma solicitação de leitura e a estrutura chamará uma das duas funções de retorno de chamada: EvtUsbTargetPipeReadComplete, se o destino de E/S ler os dados com êxito ou EvtUsbTargetPipeReadersFailed, se o destino de E/S relatar um erro.
Se você não fornecer o retorno de chamada opcional EvtUsbTargetPipeReadersFailed , a estrutura responderá a uma tentativa de leitura com falha enviando outra solicitação de leitura. Portanto, se o barramento estiver em um estado em que não está aceitando leituras, a estrutura enviará continuamente novas solicitações para se recuperar de uma leitura com falha.
Depois que um driver tiver chamado WdfUsbTargetPipeConfigContinuousReader, o driver não poderá usar WdfUsbTargetPipeReadSynchronously ou WdfRequestSend para enviar solicitações de E/S para o pipe, a menos que a função de retorno de chamada EvtUsbTargetPipeReadersFailed do driver seja chamada e retorne FALSE.
Por padrão, a estrutura relatará um erro se o driver especificar um buffer de leitura que não seja um múltiplo do tamanho máximo do pacote do pipe. Seu driver pode chamar WdfUsbTargetPipeSetNoMaximumPacketSizeCheck para desabilitar esse teste de tamanhos de buffer de leitura.
Para obter informações relacionadas. consulte:
- Como enviar solicitações de transferência em massa USB
- Como transferir dados para pontos de extremidade isócronos USB
- Como usar o leitor contínuo para ler dados de um pipe USB
Gravando em um pipe
Para gravar dados em um pipe de saída USB, o driver pode usar uma (ou ambas) das seguintes técnicas:
Gravar dados de forma síncrona
Para gravar dados de forma síncrona em um pipe de saída USB, o driver pode chamar o método WdfUsbTargetPipeWriteSynchronously . Esse método compila e envia uma solicitação de gravação e retorna após a conclusão da operação de E/S.
Gravar dados de forma assíncrona
Para gravar dados de forma assíncrona em um pipe de entrada USB, o driver pode chamar o método WdfUsbTargetPipeFormatRequestForWrite para criar uma solicitação de gravação. Em seguida, o driver pode chamar WdfRequestSend para enviar a solicitação de forma assíncrona.
Para obter informações relacionadas, consulte Como enviar solicitações de transferência em massa usb.
Parando e redefinindo um pipe
O driver pode chamar os seguintes métodos para parar ou redefinir um pipe USB:
WdfUsbTargetPipeAbortSynchronously
Envia de forma síncrona uma solicitação para interromper um pipe USB.
WdfUsbTargetPipeFormatRequestForAbort
Formata uma solicitação para interromper um pipe USB. O driver pode chamar WdfRequestSend para enviar a solicitação de forma síncrona ou assíncrona.
WdfUsbTargetPipeResetSynchronously
Envia de forma síncrona uma solicitação para redefinir um pipe USB.
WdfUsbTargetPipeFormatRequestForReset
Formata uma solicitação para redefinir um pipe USB. O driver deve chamar WdfRequestSend para enviar a solicitação de forma síncrona ou assíncrona.
Se o destino USB do driver concluir uma solicitação de E/S com um erro status valor, o driver deverá fazer o seguinte:
Pare o pipe e cancele as solicitações de E/S adicionais que o driver enviou para o destino USB, se o destino não tiver concluído as solicitações.
Chame WdfIoTargetStop com o sinalizador WdfIoTargetCancelSentIo definido.
Envie de forma síncrona uma solicitação de anulação para o pipe.
Chame WdfUsbTargetPipeAbortSynchronously ou chame WdfUsbTargetPipeFormatRequestForAbort seguido por WdfRequestSend com o sinalizador WDF_REQUEST_SEND_OPTION_SYNCHRONOUS definido.
Envie de forma síncrona uma solicitação de redefinição para o pipe.
Chame WdfUsbTargetPipeResetSynchronously ou chame WdfUsbTargetPipeFormatRequestForReset seguido por WdfRequestSend com o sinalizador WDF_REQUEST_SEND_OPTION_SYNCHRONOUS definido.
Reinicie o pipe.
Chame WdfIoTargetStart.
Reenviar a solicitação de E/S que falhou e todas as solicitações de E/S que seguiram a solicitação com falha.
Após um número significativo de várias falhas, o driver deve tentar redefinir a porta USB fazendo o seguinte:
Interrompa todos os pipes ativos e cancele quaisquer solicitações de E/S adicionais que o driver enviou para o destino USB de cada pipe, se o destino não tiver concluído.
Para cada pipe ativo, chame WdfIoTargetStop com o sinalizador WdfIoTargetCancelSentIo definido.
Envie uma solicitação de forma síncrona para redefinir a porta USB.
Reinicie os pipes.
Chame WdfIoTargetStart para cada pipe que o driver parou.
Reenviar a última solicitação de E/S que falhou e todas as solicitações de E/S que seguiram a solicitação com falha.
Para obter informações relacionadas, consulte Como se recuperar de erros de pipe USB.
Enviando um URB para um pipe
Se o driver KMDF se comunicar com um pipe USB enviando solicitações de E/S que contenham URBs, o driver poderá chamar os seguintes métodos:
WdfUsbTargetPipeSendUrbSynchronously (somente KMDF)
Envia de forma síncrona uma solicitação de E/S que contém um URB.
WdfUsbTargetPipeFormatRequestForUrb (somente KMDF)
Formata uma solicitação de E/S que contém um URB. O driver pode chamar WdfRequestSend para enviar a solicitação de forma síncrona ou assíncrona.
WdfUsbTargetPipeWdmGetPipeHandle (somente KMDF)
Retorna o identificador de pipe USBD de um dispositivo. Alguns URBs exigem esse identificador.