Как написать первый 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 и все необходимые спецификации оборудования для реализации драйвера клиента.
Рекомендуем прочесть
- Основные понятия для всех разработчиков драйверов
- Узлы устройств и стеки устройств
- Начало работы с драйверами в Windows
- среда выполнения платформы драйвера режима пользователя
- Разработка драйверов с помощью Windows Driver Foundation, написанная Пенни Орвик и Гай Смит. Дополнительные сведения см. в разделе "Разработка драйверов с помощью WDF".
Шаг 1. Создание кода драйвера
Дополнительные сведения о написании кода драйвера UMDF см. в статье "Написание драйвера UMDF на основе шаблона".
Для кода для USB выберите следующие параметры в Visual Studio 2022
- В диалоговом окне "Новый проект" в поле поиска в верхней части введите USB.
- В средней области выберите "Драйвер пользовательского режима", USB (UMDF V2).
- Выберите Далее.
- Введите имя проекта, выберите расположение сохранения и нажмите кнопку "Создать".
На следующих снимках экрана показано диалоговое окно "Новый проект " для шаблона драйвера в режиме пользователя USB.
В этой статье предполагается, что имя проекта 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. Добавление сведений об устройстве
Перед сборкой драйвера необходимо добавить сведения об устройстве, в частности идентификатор оборудования. Чтобы указать идентификатор оборудования, выполните указанные ниже действия.
- В окне Обозреватель решений щелкните правой кнопкой мыши MyUSBDriver_UMDF_ и выберите "Свойства".
- В окне "Страницы свойств MyUSBDriver_UMDF_" перейдите к развертыванию установки> драйвера свойств > конфигурации, как показано здесь.
- Перед развертыванием проверьте удаление предыдущих версий драйверов.
- В качестве имени целевого устройства выберите имя компьютера, настроенного для тестирования и отладки.
- Выберите обновление драйвера идентификатора оборудования и введите идентификатор оборудования для драйвера. В этом упражнении идентификатор оборудования — 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-клиента
Чтобы создать драйвер, выполните приведенные действия.
- Откройте проект драйвера или решение в Visual Studio 2022.
- Щелкните правой кнопкой мыши решение в Обозреватель решений и выберите Configuration Manager.
- В Configuration Manager выберите конфигурацию активного решения (например, отладку или выпуск) и активную платформу решения (например, x64), соответствующую типу нужной сборки.
- Убедитесь, что GUID интерфейса устройства является точным во всем проекте.
- GUID интерфейса устройства определяется в Trace.h и ссылается на нее в
MyUSBDriverUMDFCreateDevice
Device.c. При создании проекта с именем MyUSBDriver_UMDF_ Visual Studio 2022 определяет GUID интерфейса устройства с именемGUID_DEVINTERFACE_MyUSBDriver_UMDF_
, но вызываетWdfDeviceCreateDeviceInterface
неправильный параметр&GUID_DEVINTERFACE_MyUSBDriverUMDF
. Замените неправильный параметр именем, определенным в Trace.h, чтобы обеспечить правильность сборки драйвера.
- GUID интерфейса устройства определяется в Trace.h и ссылается на нее в
- В меню Построение выберите пункт Построить решение.
Дополнительные сведения см. в разделе "Создание драйвера".
Шаг 4. Настройка компьютера для тестирования и отладки
Для тестирования и отладки драйвера необходимо запустить отладчик на хост-компьютере и драйвере на целевом компьютере. До сих пор вы использовали Visual Studio на хост-компьютере для создания драйвера. Затем необходимо настроить целевой компьютер. Чтобы настроить целевой компьютер, следуйте инструкциям в статье "Подготовка компьютера для развертывания и тестирования драйверов".
Шаг 5. Включение трассировки для отладки ядра
Код шаблона содержит несколько сообщений трассировки (TraceEvents), которые помогают отслеживать вызовы функций. Все функции в исходном коде содержат сообщения трассировки, которые помечают запись и выход подпрограммы. Для ошибок сообщение трассировки содержит код ошибки и значимую строку. Так как трассировка WPP включена для проекта драйвера, файл символов PDB, созданный во время процесса сборки, содержит инструкции по форматированию сообщений трассировки. Если настроить хост-компьютеры и целевые компьютеры для трассировки WPP, драйвер может отправлять сообщения трассировки в файл или отладчик.
Настройка хост-компьютера для трассировки WPP
Создайте файлы формата сообщения трассировки (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.
В отладчике введите следующие команды:
.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
Убедитесь, что на целевом компьютере есть средство Tracelog. Средство находится в папке install_folder>Комплекты Windows\10\Tools\<arch> в WDK.< Дополнительные сведения см. в разделе "Синтаксис команды Tracelog".
Откройте командное окно и запустите от имени администратора.
Введите следующую команду:
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. Развертывание драйвера на целевом компьютере
- В окне Обозреватель решений щелкните правой кнопкой мыши имя проекта (MyUSBDriver_UMDF_) и выберите "Свойства".
- В левой области перейдите к развертыванию драйвера >установки свойств > конфигурации.
- Для имени целевого устройства укажите имя целевого компьютера.
- Выберите "Установить или переустановить " и "Проверить".
- Нажмите OK.
- В меню отладки выберите "Начать отладку" или нажмите клавишу F5 на клавиатуре.
Примечание.
Не указывайте идентификатор оборудования устройства в разделе "Обновление драйвера оборудования". Идентификатор оборудования должен быть указан только в файле сведений о драйвере (INF).
Шаг 7. Просмотр драйвера в диспетчер устройств
Введите следующую команду, чтобы открыть диспетчер устройств.
devmgmt
Убедитесь, что диспетчер устройств показан следующий узел.
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-драйверов.