Como escrever seu primeiro driver de cliente para USB (UMDF)
Neste artigo, você usará o modelo Driver de modo de usuário, USB (UMDF V2) fornecido com o Microsoft Visual Studio 2022 para escrever um driver do cliente baseado em UMDF (estrutura de driver do modo de usuário). Depois de criar e instalar o driver do cliente, você exibirá o driver do cliente no Gerenciador de Dispositivos e exibirá a saída do driver em um depurador.
O UMDF (conhecido como a estrutura neste artigo) é baseado no COM (Component Object Model). Cada objeto de estrutura deve implementar IUnknown e seus métodos, QueryInterface, AddRef e Release, por padrão. Os métodos AddRef e Release gerenciam o tempo de vida do objeto, para que o driver do cliente não precise manter a contagem de referência. O método QueryInterface permite que o driver do cliente obtenha ponteiros de interface para outros objetos de estrutura no modelo de objeto WDF (Windows Driver Frameworks). Os objetos de estrutura executam tarefas complicadas de driver e interagem com o Windows. Determinados objetos de estrutura expõem interfaces que permitem que um driver do cliente interaja com a estrutura.
Um driver do cliente baseado em UMDF é implementado como um DLL do servidor COM em andamento e C++ é a linguagem preferencial para escrever um driver do cliente para um dispositivo USB. Normalmente, o driver do cliente implementa várias interfaces expostas pela estrutura. Este artigo refere-se a uma classe definida pelo driver do cliente que implementa interfaces de estrutura como uma classe de retorno de chamada. Depois que essas classes são instanciadas, os objetos de retorno de chamada resultantes são associados a objetos de estrutura específicos. Essa parceria dá ao driver do cliente a oportunidade de responder a eventos relacionados ao dispositivo ou ao sistema relatados pela estrutura. Sempre que Windows notifica a estrutura sobre determinados eventos, a estrutura invoca o retorno de chamada do driver do cliente, se houver um disponível. Caso contrário, a estrutura continuará com o processamento padrão do evento. O código do modelo define classes de retorno de chamada de driver, dispositivo e fila.
Para obter uma explicação sobre o código-fonte gerado pelo modelo, consulte Noções básicas sobre o código do modelo UMDF para driver do cliente USB.
Antes de começar
Para desenvolver, depurar e instalar um driver de modo de usuário, você precisa de dois computadores:
- Um computador host executando o Windows 10 ou uma versão posterior do sistema operacional Windows. O computador host é o ambiente de desenvolvimento, onde você escreve e depura o driver.
- Um computador de destino que executa a versão do sistema operacional no qual você deseja testar o driver, por exemplo, Windows 11, versão 22H2. O computador de destino tem o driver de modo de usuário que você deseja depurar e um dos depuradores.
Em alguns casos, em que os computadores host e de destino estão executando a mesma versão do Windows, você pode ter apenas um computador que executa o Windows 10 ou uma versão posterior do Windows. Este artigo pressupõe que você esteja usando dois computadores para desenvolver, depurar e instalar o driver de modo de usuário.
Antes de começar, certifique-se de que você atende aos seguintes requisitos:
Requisitos de software
Seu computador host tem o Visual Studio 2022.
Seu computador host tem o WDK (Windows Driver Kit) mais recente para Windows 11, versão 22H2.
O kit inclui cabeçalhos, bibliotecas, ferramentas, documentação e as ferramentas de depuração necessárias para desenvolver, compilar e depurar um driver do cliente USB. Você pode obter a versão mais recente do WDK em Como obter o WDK.
Seu computador host tem a versão mais recente das ferramentas de depuração para Windows. Você pode obter a versão mais recente do WDK ou Baixar e instalar ferramentas de depuração para Windows.
Se você estiver usando dois computadores, deverá configurar os computadores host e de destino para depuração no modo de usuário. Para obter mais informações, consulte Configurando a depuração do modo de usuário no Visual Studio.
Requisitos de hardware
Obtenha um dispositivo USB para o qual você escreverá o driver do cliente. Na maioria dos casos, você recebe um dispositivo USB e sua especificação de hardware. A especificação descreve os recursos do dispositivo e os comandos do fornecedor suportados. Use a especificação para determinar a funcionalidade do driver USB e as decisões de design relacionadas.
Se você não estiver familiarizado com o desenvolvimento de driver USB, use o kit de aprendizado OSR USB FX2 para estudar exemplos de USB incluídos no WDK. Ele contém o dispositivo USB FX2 e todas as especificações de hardware necessárias para implementar um driver do cliente.
Leitura recomendada
- Conceitos para todos os desenvolvedores de drivers
- Nós de dispositivo e pilhas de dispositivos
- Introdução a drivers no Windows
- User-Mode Driver Framework
- Como desenvolver drivers com o Windows Driver Foundation escrito por Penny Orwick e Guy Smith. Para obter mais informações, consulte Como desenvolver drivers com o WDF.
Etapa 1: gerar o código do driver
Para obter detalhes sobre como escrever o código de driver UMDF, consulte Criar um driver UMDF com base em um modelo.
Para código específico de USB, selecione as seguintes opções no Visual Studio 2022
- Na caixa de diálogo Novo Projeto, na caixa de pesquisa na parte superior, digite USB.
- No painel do meio, selecione Driver de Modo de Usuário, USB (UMDF V2).
- Selecione Avançar.
- Digite um nome de projeto, escolha um local de gravação e selecione Criar.
As capturas de tela a seguir mostram a caixa de diálogo Novo Projeto para o modelo de Driver de Modo de Usuário USB.
Este artigo pressupõe que o nome do projeto é MyUSBDriver_UMDF_. Ele contém os seguintes arquivos:
Arquivos | Descrição |
---|---|
Driver.h; Driver.c | Contém a implementação do ponto de entrada do módulo do driver. DriverEntry e WDFDRIVER relacionados à funcionalidade e retornos de chamada. |
Device.h; Device.c | Funcionalidade e retornos de chamada relacionados ao WDFDEVICE e ao WDFUSBDEVICE. |
Queue.h; Queue.c | Funcionalidade e retornos de chamada relacionados ao WDFQUEUE. |
Trace.h | Define o GUID da interface do dispositivo. Ele também declara funções de rastreamento e macros. |
<Nome do projeto>.inf | Arquivo INF necessário para instalar o driver do cliente no computador de destino. |
Etapa 2: adicionar informações sobre o dispositivo
Antes de criar o driver, você deve adicionar informações sobre seu dispositivo, especificamente a ID de hardware. Para fornecer a ID do hardware:
- Na janela Gerenciador de Soluções, Clique com o botão direito do mouse em MyUSBDriver_UMDF_, e escolha Propriedades.
- Na janela MyUSBDriver_UMDF_ Property Pages, acesse Propriedades de Configuração > Instalação do Driver > Implantação, conforme mostrado aqui.
- Marque a caixa Remover versões anteriores do driver antes da implantação.
- Para Nome do Dispositivo de Destino, selecione o nome do computador que você configurou para teste e depuração.
- Selecione Atualização de driver de ID de hardware e insira a ID de hardware do driver. Neste exercício, a ID de hardware é Root\MyUSBDriver_UMDF_. Selecione OK.
Observação
Neste exercício, a ID de hardware não identifica uma parte real do hardware. Ela identifica um dispositivo imaginário que receberá um lugar na árvore de dispositivos como filho do nó raiz. Para hardware real, não selecione Atualização de driver de ID de hardware. Em vez disso, selecione Instalar e verificar. Você pode ver a ID de hardware no arquivo INF (informações do driver). Na janela Gerenciador de Soluções, acesse MyUSBDriver_UMDF_ > Arquivos de Driver e clique duas vezes em MyUSBDriver_UMDF_.inf. A ID do hardware está em [Standard.NT$ARCH$].
Todos os drivers de cliente USB baseados em UMDF exigem dois drivers fornecidos pela Microsoft, o refletor e o WinUSB.
Refletor: se o driver for carregado com êxito, o refletor será carregado como o driver mais alto na pilha do modo kernel. O refletor deve ser o driver superior na pilha do modo kernel. Para atender a esse requisito, o arquivo INF do modelo especifica o refletor como um serviço e o WinUSB como um driver de filtro inferior no INF:
[MyDevice_Install.NT.Services] AddService=WUDFRd,0x000001fa,WUDFRD_ServiceInstall ; flag 0x2 sets this as the service for the device AddService=WinUsb,0x000001f8,WinUsb_ServiceInstall ; this service is installed because its a filter.
WinUSB: o pacote de instalação deve conter co-instaladores para Winusb.sys porque, para o driver do cliente, o WinUSB é o gateway para a pilha de driver USB no modo kernel. Outro componente que é carregado é uma DLL no modo de usuário, chamada WinUsb.dll, no processo de host do driver do cliente (Wudfhost.exe). Winusb.dll expõe as funções do WinUSB que simplificam o processo de comunicação entre o driver do cliente e o WinUSB.
Etapa 3: criar o código do driver do cliente USB
Para criar seu driver:
- Abra o projeto de driver ou uma solução no Visual Studio 2022.
- Clique com o botão direito do mouse no Gerenciador de Soluções e selecione Gerenciador de Configurações.
- No Gerenciador de Configurações, selecione sua Configuração da Solução Ativa (por exemplo, Depurar ou Liberar) e sua Plataforma de Solução Ativa (por exemplo, x64) que corresponde ao tipo de build em que você está interessado.
- Verifique se o GUID da interface do dispositivo é necessário em todo o projeto.
- O GUID da interface do dispositivo é definido em Trace.h e é referenciado
MyUSBDriverUMDFCreateDevice
em Device.c. Quando você cria seu projeto com o nome MyUSBDriver_UMDF_, o Visual Studio 2022 define o GUID da interface do dispositivo com o nomeGUID_DEVINTERFACE_MyUSBDriver_UMDF_
, mas chamaWdfDeviceCreateDeviceInterface
com o parâmetro&GUID_DEVINTERFACE_MyUSBDriverUMDF
incorreto. Substitua o parâmetro incorreto pelo nome definido em Trace.h para garantir que o driver seja compilado corretamente.
- O GUID da interface do dispositivo é definido em Trace.h e é referenciado
- No menu Compilar, selecione Compilar Solução.
Para obter mais informações, consulte Como criar um Driver.
Etapa 4: configurar um computador para teste e depuração
Para testar e depurar um driver, execute o depurador no computador host e o driver no computador de destino. Até agora, você usou o Visual Studio no computador host para criar um driver. Em seguida, você precisa configurar um computador de destino. Para configurar um computador de destino, siga as instruções em Provisionar um computador para implantação e teste de driver.
Etapa 5: habilitar o rastreamento para depuração de kernel
O código do modelo contém várias mensagens de rastreamento (TraceEvents) que podem ajudar você a rastrear chamadas de função. Todas as funções no código-fonte contêm mensagens de rastreamento que marcam a entrada e a saída de uma rotina. Para erros, a mensagem de rastreamento contém o código de erro e uma cadeia de caracteres significativa. Como o rastreamento de WPP está habilitado para seu projeto de driver, o arquivo de símbolo PDB criado durante o processo de build contém instruções de formatação de mensagem de rastreamento. Se você configurar os computadores host e de destino para rastreamento WPP, o driver poderá enviar mensagens de rastreamento para um arquivo ou para o depurador.
Para configurar seu computador host para rastreamento de WPP
Crie arquivos de formato de mensagem de rastreamento (TMF) extraindo instruções de formatação de mensagem de rastreamento do arquivo de símbolo PDB.
Você pode usar Tracepdb.exe para criar arquivos TMF. A ferramenta está localizada na <pasta de instalação>Windows Kits\10\bin\<architecture> do WDK. O comando a seguir cria arquivos TMF para o projeto de driver.
tracepdb -f <PDBFiles> -p <TMFDirectory>
A opção -f especifica o local e o nome do arquivo de símbolo PDB. A opção -p especifica o local dos arquivos TMF criados pelo Tracepdb. Para obter mais informações, consulte Comandos Tracepdb.
Há três arquivos no local especificado, um por arquivo de código C no projeto. Eles recebem nomes de arquivo GUID.
No depurador, digite os seguintes comandos:
.load Wmitrace .chain !wmitrace.searchpath + <TMF file location>
Estes comandos:
- Carregue a extensão Wmitrace.dll.
- Verifica se a extensão do depurador está carregada.
- Adiciona o local dos arquivos TMF ao caminho de pesquisa da extensão do depurador.
A saída será semelhante a esta:
Trace Format search path is: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE;c:\drivers\tmf
Para configurar seu computador de destino para rastreamento de WPP
Verifique se você tem a ferramenta Tracelog no computador de destino. A ferramenta está localizada em <install_folder>Windows Kits\10\Tools\<arch> do WDK. Para obter mais informações, consulte Sintaxe do comando Tracelog.
Abra uma Janela de Comando e execute como administrador.
Digite o seguinte comando:
tracelog -start MyTrace -guid \#c918ee71-68c7-4140-8f7d-c907abbcb05d -flag 0xFFFF -level 7-rt -kd
O comando inicia uma sessão de rastreamento chamada MyTrace.
O argumento guid especifica o GUID do provedor de rastreamento, que é o driver do cliente. Você pode obter o GUID de Trace.h no projeto do Visual Studio 2022. Como outra opção, você pode digitar o comando a seguir e especificar o GUID em um arquivo .guid. O arquivo contém o GUID no formato de hífen:
tracelog -start MyTrace -guid c:\\drivers\\Provider.guid -flag 0xFFFF -level 7-rt -kd
Você pode interromper a sessão de rastreamento digitando o seguinte comando:
tracelog -stop MyTrace
Etapa 6: implantar o driver no computador de destino
- Na janela Gerenciador de Soluções clique com o botão direito do mouse no nome do projeto (MyUSBDriver_UMDF_) e escolha Propriedades.
- No painel esquerdo, navegue até Propriedades de Configuração > Instalação do Driver > Implantação.
- Em Nome do Dispositivo de Destino, especifique o nome do computador de destino.
- Selecione Instalar/Reinstalar e Verificar.
- Selecione Ok.
- No menu Depurar, escolha Iniciar Depuração ou pressione F5 no teclado.
Observação
Não especifique a ID de hardware do seu dispositivo em Atualização de driver de ID de hardware. A ID de hardware deve ser especificada apenas no arquivo INF de informações do driver.
Etapa 7: visualizar o driver no Gerenciador de dispositivos
Digite o seguinte comando para abrir o Gerenciador de Dispositivos.
devmgmt
Verifique se o Gerenciador de Dispositivos mostra o nó a seguir.
Dispositivo USB
MyUSBDriver_UMDF_Device
Etapa 8: exibir a saída no depurador
Verifique se as mensagens de rastreamento aparecem na Janela Imediata do Depurador no computador host.
A saída deve ser semelhante ao seguinte:
[0]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::OnPrepareHardware Entry
[0]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::OnPrepareHardware Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::CreateInstanceAndInitialize Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::Initialize Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::Initialize Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::CreateInstanceAndInitialize Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::Configure Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyIoQueue::CreateInstanceAndInitialize Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyIoQueue::Initialize Entry
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyIoQueue::Initialize Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyIoQueue::CreateInstanceAndInitialize Exit
[1]0744.05F0::00/00/0000-00:00:00.000 [MyUSBDriver_UMDF_]CMyDevice::Configure Exit
Comentários
Vamos dar uma olhada em como a estrutura e o driver do cliente trabalham juntos para interagir com o Windows e lidar com solicitações enviadas ao dispositivo USB. Esta ilustração mostra os módulos carregados no sistema para um driver do cliente USB baseado em UMDF.
O objetivo de cada módulo é descrito aqui:
- Aplicativo - um processo de modo de usuário que emite solicitações de E/S para se comunicar com o dispositivo USB.
- Gerenciador de E/S - um componente do Windows que cria pacotes de solicitação de E/S (IRPs) para representar as solicitações de aplicativo recebidas e os encaminha para o topo da pilha de dispositivos no modo kernel para o dispositivo de destino.
- Refletor - um driver de modo kernel fornecido pela Microsoft instalado na parte superior da pilha de dispositivos do modo kernel (WUDFRd.sys). O refletor redireciona os IRPs recebidos do gerenciador de E/S para o processo de host do driver do cliente. Ao receber a solicitação, a estrutura e o driver do cliente lidam com a solicitação.
- Processo de host - o processo no qual o driver do modo de usuário é executado (Wudfhost.exe). Ele também hospeda a estrutura e o dispatcher de E/S.
- Driver do cliente - o driver de função do modo de usuário para o dispositivo USB.
- UMDF - o módulo de estrutura que lida com a maioria das interações com o Windows em nome do driver do cliente. Ele expõe as DDIs (interfaces de driver de dispositivo) do modo de usuário que o driver do cliente pode usar para executar tarefas comuns de driver.
- Dispatcher - mecanismo que é executado no processo do host. Determina como encaminhar uma solicitação para o modo kernel depois que ela tiver sido processada por drivers de modo de usuário e atingir a parte inferior da pilha de modo de usuário. Na ilustração, o dispatcher encaminha a solicitação para a DLL do modo de usuário, Winusb.dll.
- Winusb.dll - uma DLL de modo de usuário fornecida pela Microsoft que expõe funções WinUSB que simplificam o processo de comunicação entre o driver do cliente e o WinUSB (Winusb.sys, carregado no modo kernel).
- Winusb.sys - um driver fornecido pela Microsoft que é exigido por todos os drivers de cliente UMDF para dispositivos USB. O driver deve ser instalado abaixo do refletor e atua como o gateway para a pilha de driver USB no modo kernel. Para obter mais informações, consulte Introdução ao WinUSB para desenvolvedores.
- Pilha de driver USB - um conjunto de drivers, fornecidos pela Microsoft, que lidam com a comunicação em nível de protocolo com o dispositivo USB. Para obter mais informações, consulte Drivers USB do lado do host no Windows.
Sempre que um aplicativo faz uma solicitação para a pilha de driver USB, o gerenciador de E/S do Windows envia a solicitação para o refletor, que a direciona para o driver do cliente no modo de usuário. O driver do cliente lida com a solicitação chamando métodos UMDF específicos, que chamam internamente Funções do WinUSB para enviar a solicitação ao WinUSB. Ao receber a solicitação, o WinUSB processa a solicitação ou a encaminha para a pilha de driver USB.