Compartir a través de


Cómo escribir su primer controlador de cliente USB (UMDF)

En este artículo, usará la plantilla Controlador en modo de usuario, USB (UMDF V2) proporcionada con Microsoft Visual Studio 2022 para escribir un controlador cliente basado en el marco de controladores en modo de usuario (UMDF). Después de compilar e instalar el controlador cliente, verá el controlador cliente en Administrador de dispositivos y verá la salida del controlador en un depurador.

UMDF (denominado marco en este artículo) se basa en el modelo de objetos de componente (COM). Cada objeto de marco debe implementar IUnknown y sus métodos, QueryInterface, AddRef y Release, de forma predeterminada. Los métodos AddRef y Release administran la duración del objeto, por lo que el controlador cliente no necesita mantener el recuento de referencias. El método QueryInterface permite al controlador cliente obtener punteros de interfaz a otros objetos de marco en el modelo de objetos de Windows Driver Frameworks (WDF). Los objetos de marco realizan tareas de controlador complicadas e interactúan con Windows. Algunos objetos de marco exponen interfaces que permiten que un controlador cliente interactúe con el marco.

Un controlador cliente basado en UMDF se implementa como un servidor COM (DLL) en proceso y C++ es el lenguaje preferido para escribir un controlador cliente para un dispositivo USB. Normalmente, el controlador cliente implementa varias interfaces expuestas por el marco. En este artículo se hace referencia a una clase definida por el controlador cliente que implementa interfaces de marco como una clase de devolución de llamada. Después de crear instancias de estas clases, los objetos de devolución de llamada resultantes se asocian con determinados objetos de marco. Esta asociación ofrece al controlador cliente la oportunidad de responder a eventos relacionados con el dispositivo o el sistema notificados por el marco. Cada vez que Windows notifica al marco sobre determinados eventos, el marco invoca la devolución de llamada del controlador cliente, si está disponible. De lo contrario, el marco continúa con el procesamiento predeterminado del evento. El código de plantilla define las clases de devolución de llamada de controlador, dispositivo y cola.

Para obtener una explicación sobre el código fuente generado por la plantilla, consulte Descripción del código de plantilla de UMDF para el controlador cliente USB.

Antes de comenzar

Para desarrollar, depurar e instalar un controlador en modo de usuario, necesita dos equipos:

  • Un equipo host que ejecute Windows 10 o una versión posterior del sistema operativo Windows. El equipo host es el entorno de desarrollo, donde escribe y depura el controlador.
  • Un equipo de destino que ejecute la versión del sistema operativo en el que quiere probar el controlador, por ejemplo, Windows 11, versión 22H2. El equipo de destino tiene el controlador en modo de usuario que desea depurar y uno de los depuradores.

En algunos casos, donde el equipo host y de destino ejecutan la misma versión de Windows, puede tener solo un equipo que ejecute Windows 10 o una versión posterior de Windows. En este artículo se da por supuesto que usa dos equipos para desarrollar, depurar e instalar el controlador en modo de usuario.

Antes de empezar, asegúrese de que cumple los siguientes requisitos:

Requisitos de software

  • El equipo host tiene Visual Studio 2022.

  • El equipo host tiene el Kit para controladores de Windows (WDK) más reciente para Windows 11, versión 22H2.

    El kit incluye encabezados, bibliotecas, herramientas, documentación y las herramientas de depuración necesarias para desarrollar, compilar y depurar un controlador cliente USB. Puede obtener la versión más reciente del WDK desde Cómo obtener el WDK.

  • El equipo host tiene la versión más reciente de las herramientas de depuración para Windows. Puede obtener la versión más reciente del WDK en Descarga e instalación de herramientas de depuración para Windows.

  • Si usa dos equipos, debe configurar el equipo host y de destino para la depuración en modo de usuario. Para obtener más información, consulte Configuración de la depuración en modo de usuario en Visual Studio.

Requisitos de hardware

Obtenga un dispositivo USB para el que escribirá el controlador cliente. En la mayoría de los casos, se le proporciona un dispositivo USB y su especificación de hardware. La especificación describe las funcionalidades del dispositivo y los comandos de proveedor admitidos. Use la especificación para determinar la funcionalidad del controlador USB y las decisiones de diseño relacionadas.

Si no está familiarizado con el desarrollo de controladores USB, use el kit de aprendizaje OSR USB FX2 para consultar las muestras de USB incluidas con el WDK. Contiene el dispositivo USB FX2 y todas las especificaciones de hardware necesarias para implementar un controlador cliente.

Paso 1: Generación del código del controlador

Para obtener más información sobre cómo escribir código de controlador UMDF, consulte Escritura de un controlador UMDF basado en una plantilla.

Para código específico de USB, seleccione las opciones siguientes en Visual Studio 2022.

  1. En el cuadro de diálogo Nuevo proyecto, en el cuadro de búsqueda de la parte superior, escriba USB.
  2. En el panel central, seleccione Controlador en modo de usuario, USB (UMDF V2).
  3. Seleccione Siguiente.
  4. Escriba un nombre de proyecto, elija una ubicación de guardado y seleccione Crear.

En las capturas de pantalla siguientes se muestra el cuadro de diálogo Nuevo proyecto para la plantilla Controlador en modo de usuario USB.

Captura de pantalla de las opciones de crear un proyecto de Visual Studio.

Captura de pantalla de la pantalla de configuración de crear un nuevo proyecto de Visual Studio.

En este artículo se supone que el nombre del proyecto es MyUSBDriver_UMDF_. Contiene los archivos siguientes:

Archivos Descripción
Driver.h; Driver.c Contiene la implementación del punto de entrada del módulo de controlador. Funciones y devoluciones de llamada relacionadas con DriverEntry y WDFDRIVER.
Device.h; Device.c Funciones y devoluciones de llamada relacionadas con WDFDEVICE y WDFUSBDEVICE.
Queue.h; Queue.c Funciones y devoluciones de llamada relacionadas con WDFQUEUE.
Trace.h Define el GUID de la interfaz de dispositivo. También declara funciones y macros de seguimiento.
<Nombre del proyecto>.inf Archivo INF necesario para instalar el controlador cliente en el equipo de destino.

Paso 2: Adición de información al dispositivo

Antes de compilar el controlador, debe agregar información sobre el dispositivo, específicamente el identificador de hardware. Para proporcionar el identificador de hardware:

  1. En la ventana del Explorador de soluciones, haga clic con el botón derecho en MyUSBDriver_UMDF_ y elija Propiedades.
  2. En la ventana Páginas de propiedades de MyUSBDriver_UMDF_, vaya a Propiedades de configuración> Instalación de controlador > Implementación, como se muestra aquí. Captura de pantalla de la ventana de páginas de propiedades de Visual Studio 2022.
  3. Active Quitar versiones anteriores del controlador antes de la implementación.
  4. En Nombre de dispositivo de destino, seleccione el nombre del equipo que configuró para probar y depurar.
  5. Seleccione Actualización del controlador de ID de hardware y escriba el identificador de hardware del controlador. En este ejercicio, el identificador de hardware es Root\MyUSBDriver_UMDF_. Seleccione Aceptar.

Nota:

En este ejercicio, el identificador de hardware no identifica un elemento real de hardware. Identifica un dispositivo imaginario al que se asignará un lugar en el árbol de dispositivos como elemento secundario del nodo raíz. En el caso del hardware real, no seleccione Actualización del controlador de ID de hardware. En su lugar, seleccione Instalar y comprobar. Puede ver el identificador de hardware en el archivo de información del controlador (INF). En la ventana Explorador de soluciones, vaya a MyUSBDriver_UMDF_> Archivos de controlador y haga doble clic en MyUSBDriver_UMDF_.inf. El identificador de hardware está en [Standard.NT$ARCH$].

Todos los controladores cliente USB basados en UMDF requieren dos controladores proporcionados por Microsoft, el reflector y WinUSB.

  • Reflector: si el controlador se carga correctamente, el reflector se carga como controlador superior en la pila del modo kernel. El reflector debe ser el controlador superior de la pila del modo kernel. Para cumplir este requisito, el archivo INF de la plantilla especifica el reflector como servicio y WinUSB como un controlador de filtro inferior en el 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: el paquete de instalación debe contener coinstaladores para Winusb.sys porque, para el controlador cliente, WinUSB es la puerta de enlace a la pila de controladores USB en modo kernel. Otro componente que se carga es un archivo DLL en modo de usuario, denominado WinUsb.dll, en el proceso de host del controlador cliente (Wudfhost.exe). Winusb.dll expone funciones de WinUSB que simplifican el proceso de comunicación entre el controlador cliente y WinUSB.

Paso 3: Compilación del código del controlador cliente USB

Para compilar el controlador:

  1. Abra el proyecto o la solución del controlador en Visual Studio 2022.
  2. En el Explorador de soluciones, haga clic con el botón derecho en la solución y seleccione Administrador de configuración.
  3. En Administrador de configuración, seleccione la Configuración de la solución activa (por ejemplo, Depuración o Versión) y la Plataforma de soluciones activas (por ejemplo, Win64), que corresponden al tipo de compilación que le interesa.
  4. Compruebe que el GUID de la interfaz de dispositivo es preciso en todo el proyecto.
    • El GUID de la interfaz de dispositivo se define en Trace.h y se hace referencia a él desde MyUSBDriverUMDFCreateDevice en Device.c. Al crear el proyecto con el nombre MyUSBDriver_UMDF_, Visual Studio 2022 define el GUID de la interfaz de dispositivo con el nombre GUID_DEVINTERFACE_MyUSBDriver_UMDF_ , pero llama a WdfDeviceCreateDeviceInterface con el parámetro incorrecto &GUID_DEVINTERFACE_MyUSBDriverUMDF. Reemplace el parámetro incorrecto por el nombre definido en Trace.h para asegurarse de que el controlador se compila correctamente.
  5. En el menú Compilar, seleccione Compilar solución.

Para obtener más información, consulte Compilación de un controlador.

Paso 4: Configuración de un equipo para probar y depurar

Para probar y depurar un controlador, ejecute el depurador en el equipo host y el controlador en el equipo de destino. Hasta ahora, ha usado Visual Studio en el equipo host para compilar un controlador. A continuación, debe configurar un equipo de destino. Para configurar un equipo de destino, siga las instrucciones de Aprovisionamiento de un equipo para la implementación y las pruebas de controladores.

Paso 5: Habilitación del seguimiento para la depuración de kernel

El código de plantilla contiene varios mensajes de seguimiento (TraceEvents) que pueden ayudarle a realizar un seguimiento de las llamadas de función. Todas las funciones del código fuente contienen mensajes de seguimiento que marcan la entrada y salida de una rutina. Para los errores, el mensaje de seguimiento contiene el código de error y una cadena significativa. Dado que el seguimiento de WPP está habilitado para el proyecto de controlador, el archivo de símbolos PDB creado durante el proceso de compilación contiene instrucciones de formato de mensaje de seguimiento. Si configura el equipo host y de destino para el seguimiento de WPP, el controlador puede enviar mensajes de seguimiento a un archivo o al depurador.

Para configurar el equipo host para el seguimiento de WPP

  1. Cree archivos de formato de mensaje de seguimiento (TMF) mediante la extracción de instrucciones de formato de mensaje de seguimiento del archivo de símbolos PDB.

    Puede usar Tracepdb.exe para crear archivos TMF. La herramienta se encuentra en la <carpeta de instalación>Windows Kits\10\bin\<arquitectura> del WDK. El comando siguiente crea archivos TMF para el proyecto de controlador.

    tracepdb -f <PDBFiles> -p <TMFDirectory>
    

    La opción -f especifica la ubicación y el nombre del archivo de símbolos PDB. La opción -p especifica la ubicación de los archivos TMF creados por Tracepdb. Para obtener más información, consulte Comandos Tracepdb.

    Hay tres archivos en la ubicación especificada, uno por archivo de código de C en el proyecto. Se les asignan nombres de archivo GUID.

  2. En el depurador, escriba los siguientes comandos:

    .load Wmitrace
    .chain
    !wmitrace.searchpath + <TMF file location>
    

Estos comandos:

  • Cargue la extensión Wmitrace.dll.
  • Comprueba que se carga la extensión del depurador.
  • Agrega la ubicación de los archivos TMF a la ruta de búsqueda de la extensión del depurador.

La salida será similar a esta:

Trace Format search path is: 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE;c:\drivers\tmf

Para configurar el equipo de destino para el seguimiento de WPP

  1. Asegúrese de que tiene la herramienta Tracelog en el equipo de destino. La herramienta se encuentra en la <carpeta de instalación>Windows Kits\10\Tools\<arquitectura> del WDK. Para obtener más información, consulte Sintaxis del comando Tracelog.

  2. Abra una ventana del símbolo del sistema como administrador.

  3. Escriba el siguiente comando:

    tracelog -start MyTrace -guid \#c918ee71-68c7-4140-8f7d-c907abbcb05d -flag 0xFFFF -level 7-rt -kd
    

El comando inicia una sesión de seguimiento denominada MyTrace.

El argumento guid especifica el GUID del proveedor de seguimiento, que es el controlador cliente. Puede obtener el GUID de Trace.h en el proyecto de Visual Studio 2022. Otra opción es escribir el siguiente comando y especificar el GUID en un archivo .guid. El archivo contiene el GUID en formato de guion:

tracelog -start MyTrace -guid c:\\drivers\\Provider.guid -flag 0xFFFF -level 7-rt -kd

Puede detener la sesión de seguimiento escribiendo el siguiente comando:

tracelog -stop MyTrace

Paso 6: Implementación del controlador en el equipo de destino

  1. En la ventana Explorador de soluciones, haga clic con el botón derecho en el nombre del proyecto (MyUSBDriver_UMDF_) y elija Propiedades.
  2. En el panel izquierdo, vaya a Propiedades de configuración> Instalación de controlador > Implementación.
  3. En Nombre del dispositivo de destino, especifique el nombre del equipo de destino.
  4. Seleccione Instalar/Reinstalar y comprobar.
  5. Seleccione Aceptar.
  6. En el menú Depurar, elija Iniciar depuración o pulse F5 en el teclado.

Nota:

No especifique el identificador de hardware del dispositivo en Actualización del controlador de ID de hardware. El identificador de hardware solo debe especificarse en el archivo de información del controlador (INF).

Paso 7: Visualización del controlador en Administrador de dispositivos

  1. Escriba el siguiente comando para abrir Administrador de dispositivos.

    devmgmt
    
  2. Compruebe que Administrador de dispositivos muestra el nodo siguiente.

    Dispositivo USB.

    MyUSBDriver_UMDF_Device

Paso 8: Visualización de la salida en el depurador

Compruebe que los mensajes de seguimiento aparecen en la ventana Inmediato del depurador en el equipo host.

La salida debe ser similar a la siguiente:

[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

Comentarios

Veamos cómo funcionan conjuntamente el marco y el controlador cliente para interactuar con Windows y controlar las solicitudes enviadas al dispositivo USB. En esta ilustración se muestran los módulos cargados en el sistema para un controlador cliente USB basado en UMDF.

Diagrama de la arquitectura del controlador cliente en modo de usuario.

El propósito de cada módulo se describe aquí:

  • Aplicación: un proceso en modo de usuario que emite solicitudes de E/S para comunicarse con el dispositivo USB.
  • Administrador de E/S: un componente de Windows que crea paquetes de solicitud de E/S (IRP) para representar las solicitudes de aplicación recibidas y los reenvía a la parte superior de la pila de dispositivos en modo kernel para el dispositivo de destino.
  • Reflector: un controlador en modo kernel proporcionado por Microsoft instalado en la parte superior de la pila de dispositivos en modo kernel (WUDFRd.sys). El reflector redirige los IRP recibidos del administrador de E/S al proceso de host del controlador cliente. Tras recibir la solicitud, el marco y el controlador cliente controlan la solicitud.
  • Proceso de host: el proceso en el que se ejecuta el controlador en modo de usuario (Wudfhost.exe). También hospeda el marco y el distribuidor de E/S.
  • Controlador cliente: controlador de función en modo de usuario para el dispositivo USB.
  • UMDF: el módulo de marco que controla la mayoría de las interacciones con Windows en nombre del controlador cliente. Expone las interfaces de controlador de dispositivo (DDI) en modo de usuario que el controlador cliente puede usar para realizar tareas comunes del controlador.
  • Distribuidor: mecanismo que se ejecuta en el proceso de host; determina cómo reenviar una solicitud al modo kernel después de que los controladores en modo de usuario la hayan procesado y haya alcanzado la parte inferior de la pila en modo de usuario. En la ilustración, el distribuidor reenvía la solicitud al archivo DLL en modo de usuario, Winusb.dll.
  • Winusb.dll: un archivo DLL en modo de usuario proporcionado por Microsoft que expone funciones WinUSB que simplifican el proceso de comunicación entre el controlador cliente y WinUSB (Winusb.sys, cargado en modo kernel).
  • Winusb.sys: un controlador proporcionado por Microsoft que requiere todos los controladores cliente UMDF para dispositivos USB. El controlador debe instalarse debajo del reflector y actúa como puerta de enlace a la pila del controlador USB en modo kernel. Para obtener más información, vea Introducción a WinUSB para desarrolladores.
  • Pila de controladores USB: un conjunto de controladores, proporcionados por Microsoft, que controlan la comunicación de nivel de protocolo con el dispositivo USB. Para obtener más información, consulte Controladores del lado host USB en Windows.

Cada vez que una aplicación realiza una solicitud para la pila de controladores USB, el administrador de E/S de Windows envía la solicitud al reflector, que lo dirige al controlador cliente en modo de usuario. El controlador cliente controla la solicitud mediante una llamada a métodos UMDF específicos, que llaman internamente a Funciones WinUSB para enviar la solicitud a WinUSB. Al recibir la solicitud, WinUSB procesa la solicitud o la reenvía a la pila del controlador USB.