Atribuição e criação de URB
Um driver de cliente USB pode usar rotinas de driver WDM (Windows Driver Model) para alocar e formatar um URB antes de enviar a solicitação à pilha de drivers USB fornecida pela Microsoft.
O driver cliente usa um URB para empacotar todas as informações exigidas pelos drivers inferiores na pilha de drivers USB para processar a solicitação. No sistema operacional Windows, um URB é descrito em uma estrutura URB.
A Microsoft fornece uma biblioteca de rotinas para drivers cliente USB. Usando essas rotinas, os drivers cliente USB podem criar solicitações URB para determinadas operações especificadas e encaminhá-las para a pilha USB. Se preferir, projete o driver cliente para chamar as rotinas da biblioteca para as operações compatíveis em vez de criar suas próprias solicitações URB.
Alocação URB no Windows 7 e versões anteriores
Para enviar uma solicitação USB usando rotinas incluídas no Kit de Driver do Windows (WDK) para Windows 7 e versões anteriores, um driver cliente normalmente aloca e preenche uma estrutura URB, associa-a a um novo IRP e envia o IRP à pilha de drivers USB.
Para determinados tipos de solicitação, a Microsoft fornece rotinas auxiliares (exportadas por Usbd.sys) que alocam e formatam a estrutura URB. Por exemplo, a estrutura USBD_CreateConfigurationRequestEx aloca memória para uma estrutura URB, formata o URB para uma solicitação de configuração de seleção e retorna o endereço da estrutura URB para o driver cliente. No entanto, as rotinas auxiliares não podem ser usadas para todos os tipos de solicitação.
A Microsoft também fornece macros que formatam URBs para alguns tipos de solicitação. Para essas macros, o driver cliente deve alocar a estrutura URB chamando ExAllocatePoolWithTag ou alocar a estrutura na pilha. Por exemplo, depois que o driver cliente aloca um URB, o driver pode chamar UsbBuildSelectConfigurationRequest para formatar o URB para uma solicitação de configuração de seleção ou limpar a configuração.
Para outras solicitações, o driver cliente deve alocar e formatar o URB manualmente, definindo vários membros da estrutura URB, dependendo do tipo de solicitação.
Quando uma solicitação USB é concluída, o driver cliente deve liberar a estrutura URB. Se o URB estiver alocado na pilha, ele será liberado quando sair do escopo. Se o URB estiver alocado em um pool não paginado, o driver cliente deverá chamar ExFreePool para liberar o URB.
Alocação de URB no Windows 8
O WDK para Windows 8 fornece uma nova biblioteca estática, Usbdex.lib, que exporta rotinas para alocação, formatação e liberação de URBs. Além disso, há uma nova forma de associar um URB a um IRP. As novas rotinas podem ser chamadas por um driver cliente destinado ao Windows Vista e a versões posteriores do Windows.
Um driver cliente em execução no Windows Vista e posterior deve usar as novas rotinas para que a pilha de drivers USB subjacente possa utilizar determinados aprimoramentos de desempenho e confiabilidade. Essas melhorias se aplicam à nova pilha de drivers USB introduzida no Windows 8 para oferecer suporte a dispositivos USB 3.0 e controladores de host. Para controladores de host USB 2.0, o Windows carrega uma versão anterior da pilha de drivers que não oferece suporte às melhorias. Independentemente da versão da pilha de drivers subjacente ou da versão do protocolo compatível com o controlador de host, você sempre deve chamar as novas rotinas URB.
Antes de chamar qualquer uma das novas rotinas, verifique se tem um identificador USBD para o registro do driver cliente na pilha de drivers USB. Para obter um identificador USBD, chame USBD_CreateHandle.
As rotinas a seguir estão disponíveis com o WDK para Windows 8. Essas rotinas são definidas em Usbdlib.h.
- USBD_UrbAllocate
- USBD_IsochUrbAllocate
- USBD_SelectConfigUrbAllocateAndBuild
- USBD_SelectInterfaceUrbAllocateAndBuild
- USBD_UrbFree
- USBD_AssignUrbToIoStackLocation
As rotinas de alocação na lista anterior retornam um ponteiro para uma nova estrutura URB, que é alocada pela pilha de drivers USB. Dependendo da versão da pilha de drivers USB carregada pelo Windows, a estrutura URB pode ser emparelhada com um contexto de URB opaco. Contexto de URB é um bloco de informações sobre o URB. Não é possível exibir o conteúdo do cabeçalho URB; as informações devem ser usadas internamente pela pilha de drivers USB para melhorar o rastreamento e o processamento do URB. O contexto de URB é usado apenas pela pilha de drivers USB para Windows 8. Se o contexto de URB estiver disponível, a pilha de drivers USB o usará para tornar o processamento de URB mais seguro e eficiente. Por exemplo, a pilha de drivers USB deve garantir que o driver cliente não envie um URB e, em seguida, tente reutilizar esse mesmo URB antes que a primeira solicitação seja concluída. Para detectar esse tipo de erro, a pilha de drivers USB armazena informações de estado no contexto de URB. Sem as informações de estado, a pilha de drivers USB precisaria comparar o URB de entrada com todos os URBs em andamento no momento. As informações de estado também são usadas pela pilha de drivers USB quando o driver cliente tenta liberar o URB. Antes de liberar o URB, a pilha de drivers USB verifica o estado para garantir que o URB não esteja pendente.
O contexto de URB fornece um mecanismo oficial para armazenar informações extras sobre o URB. O uso do contexto de URB é preferível à alocação de memória extra conforme necessário ou ao armazenamento de informações extras em membros reservados da estrutura URB. A pilha de drivers USB aloca URBs e seu contexto de URB associado em pool não paginado, de modo que, no futuro, se um contexto de URB maior for necessário, o único ajuste necessário será o tamanho de uma alocação de pool.
Migração de rotinas URB
A tabela a seguir resume as alterações nas rotinas URB.
Caso de uso | Disponível no WDK para Windows 7 e versões anteriores | Disponível no WDK para Windows 8 e versões posteriores |
---|---|---|
Destina-se ao Windows 7 e versões anteriores do sistema operacional | Destina-se ao Windows 8 e versões posteriores do sistema operacional | |
Para criar um URB… | O driver cliente aloca uma estrutura URB e formata a estrutura dependendo da solicitação. O driver cliente aloca a estrutura URB na pilha ou o driver aloca a estrutura no pool não paginado chamando ExAllocatePoolWithTag. |
O driver cliente chama USBD_UrbAllocate e recebe um ponteiro para a nova estrutura URB, que é alocada pela pilha de drivers USB. O URB pode estar associado a um contexto de URB, dependendo da versão da interface USBD da pilha de drivers USB subjacente. |
Para criar um URB para uma solicitação de configuração de seleção... | O driver cliente chama a rotina USBD_CreateConfigurationRequestEx que retorna um ponteiro para o novo URB que é criado e formatado pela pilha de drivers USB. | O driver cliente chama USBD_SelectConfigUrbAllocateAndBuild e recebe um ponteiro para a nova estrutura URB, que é alocado e formatado (para a solicitação de configuração de seleção) pela pilha de drivers USB. O URB pode estar associado a um contexto de URB, dependendo da versão da interface USBD da pilha de drivers USB subjacente. |
Para criar um URB para uma solicitação de interface de seleção... | O driver cliente aloca uma estrutura URB e usa a estrutura _URB_SELECT_INTERFACE para definir o formato de um comando de interface de seleção para um dispositivo USB. | O driver cliente chama USBD_SelectInterfaceUrbAllocateAndBuild e recebe um ponteiro para a nova estrutura URB, que é alocado e formatado (para a solicitação de interface de seleção) pela pilha de drivers USB. O URB pode estar associado a um contexto de URB, dependendo da versão da interface USBD da pilha de drivers USB subjacente. |
Para associar um URB a um IRP... | O driver cliente obtém um ponteiro para o próximo local da pilha IRP chamando IoGetNextIrpStackLocation. Em seguida, o driver cliente define manualmente o membro Parameters.Others.Argument1 do local da pilha para o endereço da estrutura URB. | O driver cliente obtém um ponteiro para o próximo local da pilha IRP chamando IoGetNextIrpStackLocation. Em seguida, o driver cliente chama USBD_AssignUrbToIoStackLocation para associar o URB ao local da pilha. |
Para liberar um URB... | Se o driver cliente alocar um URB na pilha, a variável sairá do escopo após a conclusão da solicitação. Para liberar uma estrutura URB que o driver cliente ou a pilha de drivers USB alocou no pool não paginado, o driver cliente chama ExFreePool. |
O driver cliente chama USBD_UrbFree. |