Поделиться через


Как написать первый USB-драйвер клиента (UMDF)

В этой статье вы будете использовать шаблон драйвера пользовательского режима, USB (UMDF версии 2), предоставленный Microsoft Visual Studio 2022 для записи клиентского драйвера в пользовательском режиме (UMDF). После создания и установки драйвера клиента вы увидите драйвер клиента в диспетчер устройств и просмотрите выходные данные драйвера в отладчике.

UMDF (называется платформой в этой статье) основан на объектной модели компонента (COM). Каждый объект платформы должен реализовать IUnknown и его методы, QueryInterface, AddRef и Release по умолчанию. Методы AddRef и Release управляют временем существования объекта, поэтому драйвер клиента не должен поддерживать количество ссылок. Метод QueryInterface позволяет драйверу клиента получать указатели интерфейса на другие объекты платформы в объектной модели Windows Driver Framework (WDF). Объекты Платформы выполняют сложные задачи драйвера и взаимодействуют с Windows. Некоторые объекты платформы предоставляют интерфейсы, позволяющие драйверу клиента взаимодействовать с платформой.

Драйвер клиента на основе UMDF реализуется как встроенный COM-сервер (DLL), а C++ — предпочтительный язык для написания драйвера клиента для USB-устройства. Как правило, драйвер клиента реализует несколько интерфейсов, предоставляемых платформой. В этой статье описывается класс, определенный драйвером клиента, который реализует интерфейсы платформы в качестве класса обратного вызова. После создания экземпляров этих классов результирующие объекты обратного вызова сотрудничают с определенными объектами платформы. Это партнерство дает драйверу клиента возможность реагировать на события, связанные с устройством или системой, сообщаемые платформой. Когда Windows уведомляет платформу о определенных событиях, платформа вызывает обратный вызов драйвера клиента, если он доступен. В противном случае платформа продолжает обработку события по умолчанию. Код шаблона определяет классы обратного вызова драйвера, устройства и очереди.

Описание исходного кода, созданного шаблоном, см. в разделе "Общие сведения о коде шаблона UMDF" для драйвера USB-клиента.

Перед началом работы

Для разработки, отладки и установки драйвера пользовательского режима вам потребуется два компьютера:

  • Главный компьютер под управлением Windows 10 или более поздней версии операционной системы Windows. Главный компьютер — это среда разработки, в которой выполняется запись и отладка драйвера.
  • Целевой компьютер под управлением версии операционной системы, в которой требуется протестировать драйвер, например Windows 11 версии 22H2. На целевом компьютере есть драйвер пользовательского режима, который требуется выполнить отладку и один из отладчиков.

В некоторых случаях, когда хост-компьютеры и целевые компьютеры работают под управлением той же версии Windows, у вас может быть только один компьютер под управлением Windows 10 или более поздней версии Windows. В этой статье предполагается, что вы используете два компьютера для разработки, отладки и установки драйвера пользовательского режима.

Прежде чем начать, убедитесь, что выполнены следующие требования:

Требования к программному обеспечению

  • На хост-компьютере есть Visual Studio 2022.

  • На хост-компьютере установлена последняя версия пакета драйверов Windows (WDK) для Windows 11 версии 22H2.

    Пакет включает заголовки, библиотеки, инструменты, документацию и средства отладки, необходимые для разработки, сборки и отладки USB-драйвера клиента. Последнюю версию WDK можно получить из инструкций по получению WDK.

  • На хост-компьютере установлена последняя версия средств отладки для Windows. Последнюю версию можно получить из WDK или скачать и установить средства отладки для Windows.

  • Если вы используете два компьютера, необходимо настроить узел и целевые компьютеры для отладки в пользовательском режиме. Дополнительные сведения см. в разделе "Настройка отладки в пользовательском режиме" в Visual Studio.

Требования к аппаратному обеспечению

Получите USB-устройство, для которого вы напишете драйвер клиента. В большинстве случаев вы предоставляете USB-устройство и его спецификацию оборудования. Спецификация описывает возможности устройств и поддерживаемые команды поставщика. Используйте спецификацию для определения функциональных возможностей USB-драйвера и связанных решений по проектированию.

Если вы не знакомы с разработкой USB-драйверов, используйте комплект обучения OSR USB FX2 для изучения примеров USB, включенных в WDK. Он содержит устройство USB FX2 и все необходимые спецификации оборудования для реализации драйвера клиента.

Шаг 1. Создание кода драйвера

Дополнительные сведения о написании кода драйвера UMDF см. в статье "Написание драйвера UMDF на основе шаблона".

Для кода для USB выберите следующие параметры в Visual Studio 2022

  1. В диалоговом окне "Новый проект" в поле поиска в верхней части введите USB.
  2. В средней области выберите "Драйвер пользовательского режима", USB (UMDF V2).
  3. Выберите Далее.
  4. Введите имя проекта, выберите расположение сохранения и нажмите кнопку "Создать".

На следующих снимках экрана показано диалоговое окно "Новый проект " для шаблона драйвера в режиме пользователя USB.

Снимок экрана: параметры создания проекта Visual Studio.

Снимок экрана: экран настройки проекта в Visual Studio.

В этой статье предполагается, что имя проекта MyUSBDriver_UMDF_. Она содержит следующие файлы:

Файлы Description
Driver.h; Driver.c Содержит реализацию точки входа модуля драйвера. Связанные функции и обратные вызовы DriverEntry и WDFDRIVER.
Device.h; Device.c Связанные функции и обратные вызовы WDFDEVICE и WDFUSBDEVICE.
Queue.h; Queue.c Связанные функции и обратные вызовы WDFQUEUE.
Trace.h Определяет GUID интерфейса устройства. Он также объявляет функции трассировки и макросы.
<Имя> проекта.inf INF-файл, необходимый для установки драйвера клиента на целевом компьютере.

Шаг 2. Добавление сведений об устройстве

Перед сборкой драйвера необходимо добавить сведения об устройстве, в частности идентификатор оборудования. Чтобы указать идентификатор оборудования, выполните указанные ниже действия.

  1. В окне Обозреватель решений щелкните правой кнопкой мыши MyUSBDriver_UMDF_ и выберите "Свойства".
  2. В окне "Страницы свойств MyUSBDriver_UMDF_" перейдите к развертыванию установки> драйвера свойств > конфигурации, как показано здесь. Снимок экрана: окно страниц свойств Visual Studio 2022.
  3. Перед развертыванием проверьте удаление предыдущих версий драйверов.
  4. В качестве имени целевого устройства выберите имя компьютера, настроенного для тестирования и отладки.
  5. Выберите обновление драйвера идентификатора оборудования и введите идентификатор оборудования для драйвера. В этом упражнении идентификатор оборудования — Root\MyUSBDriver_UMDF_. Нажмите ОК.

Примечание.

В этом упражнении идентификатор оборудования не определяет реальный элемент оборудования. Он определяет мнимое устройство, которое будет присвоено место в дереве устройств в качестве дочернего элемента корневого узла. Для реального оборудования не выбирайте обновление драйвера идентификатора оборудования. Вместо этого выберите " Установить и проверить". Идентификатор оборудования можно увидеть в файле сведений о драйвере (INF). В окне Обозреватель решений перейдите к файлам драйверов MyUSBDriver_UMDF_ и дважды щелкните MyUSBDriver_UMDF_>.inf. Идентификатор оборудования находится в разделе [Standard.NT$ARCH$].

Все драйверы USB-клиента на основе UMDF требуют двух драйверов, предоставляемых Корпорацией Майкрософт, отражателя и WinUSB.

  • Отражатель: если драйвер успешно загружается, отражатель загружается в качестве самого верхнего драйвера в стеке режима ядра. Отражатель должен быть главным драйвером в стеке режима ядра. В соответствии с этим требованием INF-файл шаблона указывает рефлектор как службу и WinUSB в качестве драйвера нижнего фильтра в 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: пакет установки должен содержать монетталлеры для Winusb.sys, так как для драйвера клиента WinUSB — это шлюз в стек USB-драйверов в режиме ядра. Другим компонентом, который загружается, является библиотека DLL в пользовательском режиме с именем WinUsb.dll в процессе узла драйвера клиента (Wudfhost.exe). Winusb.dll предоставляет функции WinUSB, упрощающие процесс взаимодействия между драйвером клиента и WinUSB.

Шаг 3. Создание кода драйвера USB-клиента

Чтобы создать драйвер, выполните приведенные действия.

  1. Откройте проект драйвера или решение в Visual Studio 2022.
  2. Щелкните правой кнопкой мыши решение в Обозреватель решений и выберите Configuration Manager.
  3. В Configuration Manager выберите конфигурацию активного решения (например, отладку или выпуск) и активную платформу решения (например, x64), соответствующую типу нужной сборки.
  4. Убедитесь, что GUID интерфейса устройства является точным во всем проекте.
    • GUID интерфейса устройства определяется в Trace.h и ссылается на нее в MyUSBDriverUMDFCreateDevice Device.c. При создании проекта с именем MyUSBDriver_UMDF_ Visual Studio 2022 определяет GUID интерфейса устройства с именемGUID_DEVINTERFACE_MyUSBDriver_UMDF_, но вызывает WdfDeviceCreateDeviceInterface неправильный параметр&GUID_DEVINTERFACE_MyUSBDriverUMDF. Замените неправильный параметр именем, определенным в Trace.h, чтобы обеспечить правильность сборки драйвера.
  5. В меню Построение выберите пункт Построить решение.

Дополнительные сведения см. в разделе "Создание драйвера".

Шаг 4. Настройка компьютера для тестирования и отладки

Для тестирования и отладки драйвера необходимо запустить отладчик на хост-компьютере и драйвере на целевом компьютере. До сих пор вы использовали Visual Studio на хост-компьютере для создания драйвера. Затем необходимо настроить целевой компьютер. Чтобы настроить целевой компьютер, следуйте инструкциям в статье "Подготовка компьютера для развертывания и тестирования драйверов".

Шаг 5. Включение трассировки для отладки ядра

Код шаблона содержит несколько сообщений трассировки (TraceEvents), которые помогают отслеживать вызовы функций. Все функции в исходном коде содержат сообщения трассировки, которые помечают запись и выход подпрограммы. Для ошибок сообщение трассировки содержит код ошибки и значимую строку. Так как трассировка WPP включена для проекта драйвера, файл символов PDB, созданный во время процесса сборки, содержит инструкции по форматированию сообщений трассировки. Если настроить хост-компьютеры и целевые компьютеры для трассировки WPP, драйвер может отправлять сообщения трассировки в файл или отладчик.

Настройка хост-компьютера для трассировки WPP

  1. Создайте файлы формата сообщения трассировки (TMF), извлекая инструкции по форматированию сообщений трассировки из файла символов PDB.

    Вы можете использовать Tracepdb.exe для создания файлов TMF. Средство находится в папке <>установки Windows Kits\10\bin\<architecture> папки WDK. Следующая команда создает файлы TMF для проекта драйвера.

    tracepdb -f <PDBFiles> -p <TMFDirectory>
    

    Параметр -f указывает расположение и имя файла символов PDB. Параметр -p указывает расположение файлов TMF, созданных Tracepdb. Дополнительные сведения см. в разделе "Команды Tracepdb".

    В указанном расположении по одному файлу кода C в проекте есть три файла. Они получают имена ФАЙЛОВ GUID.

  2. В отладчике введите следующие команды:

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

Выполните следующие команды.

  • Загрузите расширение Wmitrace.dll.
  • Проверяет, загружено ли расширение отладчика.
  • Добавляет расположение файлов TMF в путь поиска расширения отладчика.

Результат будет примерно таким:

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

Настройка целевого компьютера для трассировки WPP

  1. Убедитесь, что на целевом компьютере есть средство Tracelog. Средство находится в папке install_folder>Комплекты Windows\10\Tools\<arch> в WDK.< Дополнительные сведения см. в разделе "Синтаксис команды Tracelog".

  2. Откройте командное окно и запустите от имени администратора.

  3. Введите следующую команду:

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

Команда запускает сеанс трассировки с именем MyTrace.

Аргумент GUID указывает GUID поставщика трассировки, который является драйвером клиента. Guid можно получить из Trace.h в проекте Visual Studio 2022. В качестве другого варианта можно ввести следующую команду и указать GUID в GUID-файле. Файл содержит GUID в формате дефиса:

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

Сеанс трассировки можно остановить, введя следующую команду:

tracelog -stop MyTrace

Шаг 6. Развертывание драйвера на целевом компьютере

  1. В окне Обозреватель решений щелкните правой кнопкой мыши имя проекта (MyUSBDriver_UMDF_) и выберите "Свойства".
  2. В левой области перейдите к развертыванию драйвера >установки свойств > конфигурации.
  3. Для имени целевого устройства укажите имя целевого компьютера.
  4. Выберите "Установить или переустановить " и "Проверить".
  5. Нажмите OK.
  6. В меню отладки выберите "Начать отладку" или нажмите клавишу F5 на клавиатуре.

Примечание.

Не указывайте идентификатор оборудования устройства в разделе "Обновление драйвера оборудования". Идентификатор оборудования должен быть указан только в файле сведений о драйвере (INF).

Шаг 7. Просмотр драйвера в диспетчер устройств

  1. Введите следующую команду, чтобы открыть диспетчер устройств.

    devmgmt
    
  2. Убедитесь, что диспетчер устройств показан следующий узел.

    USB-устройство

    MyUSBDriver_UMDF_Device

Шаг 8. Просмотр выходных данных в отладчике

Убедитесь, что сообщения трассировки отображаются в окне интерпретации отладчика на хост-компьютере.

Результат выполнения должен быть аналогичен следующему:

[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

Замечания

Давайте рассмотрим, как платформа и драйвер клиента взаимодействуют с Windows и обрабатывают запросы, отправленные на USB-устройство. На этом рисунке показаны модули, загруженные в систему для USB-драйвера usb-клиента на основе UMDF.

Схема архитектуры клиентского драйвера в режиме пользователя.

Цель каждого модуля описана здесь:

  • Приложение — процесс пользовательского режима, который выдает запросы ввода-вывода для обмена данными с USB-устройством.
  • Диспетчер операций ввода-вывода — компонент Windows, который создает пакеты запросов ввода-вывода (IRPs) для представления полученных запросов приложений и пересылает их в верхнюю часть стека устройств в режиме ядра для целевого устройства.
  • Отражатель — драйвер, предоставленный корпорацией Майкрософт, установленный в верхней части стека устройств в режиме ядра (WUDFRd.sys). Рефлектор перенаправляет irps, полученные от диспетчера ввода-вывода, в процесс узла драйвера клиента. После получения запроса платформа и драйвер клиента обрабатывают запрос.
  • Процесс узла — процесс, в котором выполняется драйвер пользовательского режима (Wudfhost.exe). Он также размещает платформу и диспетчер ввода-вывода.
  • Драйвер клиента — драйвер функции в пользовательском режиме для USB-устройства.
  • UMDF — модуль платформы, который обрабатывает большинство взаимодействий с Windows от имени драйвера клиента. Он предоставляет интерфейсы драйвера устройств в пользовательском режиме (DDIs), которые драйвер клиента может использовать для выполнения распространенных задач драйвера.
  • Диспетчер — механизм, который выполняется в процессе узла; определяет, как перенаправить запрос в режим ядра после его обработки драйверами пользовательского режима и достигли нижней части стека пользовательского режима. На рисунке диспетчер перенаправит запрос в библиотеку DLL пользовательского режима Winusb.dll.
  • Winusb.dll — библиотека DLL, предоставляемая корпорацией Майкрософт, которая предоставляет функции WinUSB, упрощающие взаимодействие между драйвером клиента и WinUSB (Winusb.sys, загруженной в режиме ядра).
  • Winusb.sys — драйвер, предоставляемый корпорацией Майкрософт, который требуется всеми драйверами клиентов UMDF для USB-устройств. Драйвер должен быть установлен под отражателем и выступает в качестве шлюза в стек USB-драйверов в режиме ядра. Дополнительные сведения см. в разделе "Введение в WinUSB для разработчиков".
  • Стек USB-драйверов — набор драйверов, предоставляемых корпорацией Майкрософт, который обрабатывает обмен данными на уровне протокола с USB-устройством. Дополнительные сведения см. в статье о драйверах на стороне USB-узла в Windows.

Всякий раз, когда приложение запрашивает стек USB-драйверов, диспетчер ввода-вывода Windows отправляет запрос в отражатель, который направляет его драйверу клиента в пользовательском режиме. Драйвер клиента обрабатывает запрос, вызывая определенные методы UMDF, которые внутренне вызывают Функции WinUSB для отправки запроса в WinUSB. При получении запроса WinUSB обрабатывает запрос или пересылает его в стек USB-драйверов.