Partilhar via


Melhores práticas: utilização dos URBs

Este tópico descreve as práticas recomendadas para um driver de cliente para alocação, criação e envio de um URB para a pilha de drivers USB incluída no Windows 8.

O Windows 8 inclui uma nova pilha de drivers USB para suportar dispositivos USB (Universal Serial Bus) 3.0. A nova pilha de drivers USB 3.0 implementa vários novos recursos, de acordo com a especificação USB 3.0. Além disso, a pilha de drivers inclui outros recursos que permitem que um driver cliente execute tarefas comuns de forma eficiente. Por exemplo, a nova pilha de drivers aceita MDLs encadeadas que permitem que o driver cliente envie um buffer de transferência em páginas descontíguas na memória física.

Antes que um driver de cliente possa usar as novas funcionalidades da pilha de drivers USB para o Windows 8, o driver deve registar-se na pilha de drivers USB subjacente que o Windows carrega para o dispositivo. Para registrar o driver do cliente, ligue para USBD_CreateHandle e especifique uma versão do contrato. Se o driver do cliente se destinar a criar, executar e usar as melhorias e os novos recursos no Windows 8, a versão do contrato do cliente será USBD_CLIENT_CONTRACT_VERSION_602.

Para um driver de cliente da versão USBD_CLIENT_CONTRACT_VERSION_602, a pilha de controladores USB assume que o driver do cliente está em conformidade com o seguinte conjunto de regras:

A pilha de controladores de USB realiza validações nas solicitações recebidas e resolve as violações sempre que possível. Não fazer isso pode levar a um comportamento indefinido.

Não envie solicitações de E/S usando alças de tubo obsoletas ou inválidas

O driver do cliente não deve usar alças de tubo obsoletas para enviar solicitações de E/S para a pilha de drivers USB. Uma alça de tubo obsoleta refere-se a uma alça de tubo que foi obtida em uma solicitação para selecionar uma configuração, uma interface ou uma configuração alternativa que não está mais selecionada no dispositivo. Para evitar alças de pipe obsoletas, sempre que o driver cliente seleciona uma configuração ou uma interface, o driver deve atualizar seu cache de alças de pipe (geralmente armazenadas no contexto do dispositivo). Certas condições de corrida também podem resultar em alças de tubos obsoletas. Por exemplo, o driver do cliente envia uma solicitação de E/S usando uma alça de pipe na interface selecionada. Antes da conclusão da solicitação, o driver do cliente seleciona uma configuração alternativa que não usa o mesmo ponto de extremidade associado à alça de pipe em uso. Ambas as solicitações pendentes podem causar uma condição de corrida tornando a alça do tubo inválida.

Alocar URBs chamando rotinas de alocação no Windows 8

O Windows 8 fornece novas rotinas para alocação, criação e liberação de URBs (Blocos de Solicitação USB). Para alocar URBs, um driver de cliente WDM (Windows Driver Model) sempre deve usar as novas rotinas mostradas na lista a seguir:

As rotinas da lista anterior podem anexar um contexto URB opaco ao URB atribuído, a fim de melhorar o acompanhamento e o processamento. O driver do cliente não pode exibir ou modificar o conteúdo do contexto URB. Para obter mais informações sobre alocação de URB no Windows 8, consulte Alocação e criação de URBs.

Se um driver de cliente do Windows Driver Framework (WDF) que identifica sua versão como USBD_CLIENT_CONTRACT_VERSION_602 durante o registro (consulte WdfUsbTargetDeviceCreateWithParameters), a pilha de driver USB espera que o driver do cliente aloque memória para o URB chamando o novo WdfUsbTargetDeviceCreateUrb.

Não reutilize URBs ativos associados a solicitações pendentes

A pilha de drivers USB verifica deliberadamente bugs se detetar que um URB ativo que foi reenviado antes da solicitação associada ao URB. Um URB está ativo enquanto a solicitação estiver pendente e a rotina de conclusão do IRP do motorista do cliente não tiver sido chamada. Não execute as seguintes tarefas em um URB ativo.

  • Não reenvie um URB ativo para outra solicitação (associe o URB a outro IRP).
  • Não modifique o conteúdo de uma URB ativa.
  • Não liberte uma URB ativa.

Após a rotina de conclusão do driver cliente ser chamada, os drivers podem reenviar URBs para determinados tipos de solicitação dentro da rotina de conclusão. Aplicam-se as seguintes regras aos reenvios:

  • O driver do cliente não deve reutilizar um URB alocado por USBD_SelectConfigUrbAllocateAndBuild para qualquer tipo de solicitação que não seja uma solicitação de configuração selecionada para selecionar a mesma configuração.

  • O driver do cliente não deve reutilizar um URB alocado por USBD_SelectInterfaceUrbAllocateAndBuild para qualquer tipo de solicitação que não seja uma solicitação de interface selecionada para selecionar a mesma configuração alternativa em uma interface. Para obter um exemplo, consulte Comentários no USBD_SelectInterfaceUrbAllocateAndBuild.

  • Um URB atribuído por USBD_IsochUrbAllocate deve ser reutilizado apenas para pedidos de transferência isócronos. Por outro lado, um URB alocado para outros tipos de solicitações de E/S (controle, volume ou interrupção) não deve ser usado para uma solicitação isócrona.

    Por exemplo, um driver cliente aloca e constrói uma estrutura URB para uma solicitação de transferência em massa. O driver do cliente também deseja enviar dados para pontos finais isócronos no dispositivo. Após a conclusão de uma solicitação de transferência em massa, o driver do cliente não deve reformatar e enviar o URB para uma solicitação isócrona. Isso porque um URB associado a uma solicitação isócrona, tem um comprimento variável dependendo do número de pacotes. Além disso, os pacotes devem iniciar e terminar num limite de quadro. O URB alocado (para a transferência em massa) pode não se encaixar no layout do buffer necessário para uma transferência isócrona e a solicitação pode falhar.

  • Um URB alocado por USBD_UrbAllocate não deve ser reutilizado para uma solicitação isócrona, uma configuração selecionada ou uma solicitação de interface selecionada. O URB pode ser reutilizado para selecionar uma configuração NULL para desativar a configuração selecionada no dispositivo. O URB não deve estar ativo e o driver do cliente deve reformatar o URB chamando a macro UsbBuildSelectConfigurationRequest e passando NULL no parâmetro ConfigurationDescritor .

  • Antes de reenviar um URB, o driver do cliente deve reformatar o URB usando a macro UsbBuildXxx apropriada definida para o tipo de solicitação. É importante para o driver formatar o URB, porque a pilha USB pode ter alterado alguns dos seus conteúdos.

    Por exemplo, suponha que um driver chame UsbBuildInterruptOrBulkTransferRequest para inicializar um URB para uma solicitação de transferência em massa (consulte _URB_BULK_OR_INTERRUPT_TRANSFER). Se o driver inicializa o membro TransferBufferMDL da estrutura URB para NULL, a pilha de driver USB usa o buffer de transferência, especificado TransferBuffer, para trocar dados com o dispositivo em vez de um MDL. No entanto, internamente, a pilha de driver USB pode criar um MDL, armazenar um ponteiro para o MDL em TransferBufferMDL e usar o MDL para passar dados para baixo da pilha. Mesmo que a pilha de drivers USB libere a memória MDL, TransferBufferMDL pode não ser NULL quando o driver do cliente está processando o URB na rotina de conclusão. Para garantir que os membros do URB estejam formatados corretamente, o driver deve chamar UsbBuildInterruptOrBulkTransferRequest novamente para reformatar o URB antes de enviar a solicitação,

Não utilize um período de sondagem superior a 8 para transferências isócronas de alta velocidade e SuperSpeed

A pilha de drivers USB suporta tubos isócronos de alta velocidade e SuperSpeed com números de período de sondagem de 1, 2, 4 ou 8. Um driver de cliente não deve enviar E/S para um ponto de extremidade que tenha um período maior que 8. Fazer isso pode levar a uma verificação de bugs.

Certifique-se de que o número de pacotes isócronos seja um múltiplo do número de pacotes por quadro.

Para as transferências isócronas de alta velocidade e SuperSpeed, o número de pacotes isócronos por quadro é calculado como 8 / período de sondagem. O driver do cliente deve certificar-se de que o valor NumberOfPackets especificado no URB (consulte _URB_ISOCH_TRANSFER) é um múltiplo do número de pacotes por quadro.

A pilha de drivers USB não suporta URBs de transferência isócrona em que o NumberOfPackets não é um múltiplo do número de pacotes por quadro.

Chame a rotina no nível IRQL especificado na documentação

Se você registrar seu driver de cliente com USBD_CLIENT_CONTRACT_VERSION_602 como a versão do contrato, a pilha de drivers USB pressupõe que o driver do cliente enviou a solicitação no nível IRQL apropriado. Se um driver cliente envia uma solicitação em DISPATCH_LEVEL, que deve ser enviada em PASSIVE_LEVEL. Ao receber a solicitação, a pilha de drivers USB, em alguns casos, valida o valor IRQL e rejeita a solicitação. No entanto, em outros casos, a pilha de drivers USB pode gerar uma verificação de bugs.

Enviar pedidos para um dispositivo USB