Использование интерфейсов устройств в драйверах UMDF
Предупреждение
UMDF 2 является последней версией UMDF и заменяет UMDF 1. Все новые драйверы UMDF должны быть написаны с помощью UMDF 2. В UMDF 1 новые функции не добавляются, а поддержка UMDF 1 в более новых версиях Windows 10 ограничена. Универсальные драйверы Windows должны использовать UMDF 2.
Архивные примеры UMDF 1 можно найти в Windows 11 версии 22H2 — обновление примеров драйверов за май 2022 г.
Дополнительные сведения см. в разделе начало работы с помощью UMDF.
Интерфейс устройства — это символьная ссылка на устройство Plug and Play (PnP), которое приложение может использовать для доступа к устройству. Приложение в пользовательском режиме может передавать символьное имя интерфейса элементу API, например функции CreateFile Microsoft Win32. Чтобы получить символьное имя ссылки интерфейса устройства, приложение пользовательского режима может вызывать функции SetupDi . Дополнительные сведения о функциях SetupDi см. в разделе Функции интерфейса устройства SetupDi.
Каждый интерфейс устройства принадлежит классу интерфейса устройства. Например, стек драйверов для устройства CD-ROM может предоставлять интерфейс, принадлежащий классу GUID_DEVINTERFACE_CDROM. Один из драйверов устройства CD-ROM регистрирует экземпляр класса GUID_DEVINTERFACE_CDROM, чтобы сообщить системе и приложениям о доступности устройства CD-ROM. Дополнительные сведения о классах интерфейсов устройств см. в статье Общие сведения об интерфейсах устройств.
Регистрация интерфейса устройства
Чтобы зарегистрировать экземпляр класса интерфейса устройства, драйвер на основе UMDF может вызвать функцию обратного вызова IWDFDevice::CreateDeviceInterface из функции обратного вызова IDriverEntry::OnDeviceAdd . Если драйвер поддерживает несколько экземпляров интерфейса, он может назначить уникальную ссылочной строку каждому экземпляру.
Включение и отключение интерфейса устройства
В случае успешного создания платформа автоматически включает и отключает интерфейс на основе состояния PnP устройства.
Кроме того, драйвер может отключить и повторно включить интерфейс устройства при необходимости. Например, если драйвер определяет, что его устройство перестало отвечать, драйвер может вызвать IWDFDevice::AssignDeviceInterfaceState , чтобы отключить интерфейсы устройства и запретить приложениям получать новые дескрипторы интерфейса. (Существующие дескрипторы интерфейса не затрагиваются.) Если устройство позже станет доступным, драйвер может снова вызвать IWDFDevice::AssignDeviceInterfaceState , чтобы повторно включить интерфейсы.
Получение запросов на доступ к интерфейсу устройства
Когда приложение запрашивает доступ к интерфейсу устройства драйвера, платформа вызывает функцию обратного вызова IQueueCallbackCreate::OnCreateFile драйвера. Драйвер может вызвать IWDFFile::RetrieveFileName , чтобы получить имя устройства или файла, к которому обращается приложение. Если драйвер указал ссылочные строки при регистрации интерфейса устройства, операционная система включает строку ссылки в файл или имя устройства, возвращаемое IWDFFile::RetrieveFileName .
Создание событий устройства
Драйвер на основе UMDF может создавать пользовательские события для конкретного устройства (называемые событиями устройства), вызывая IWDFDevice::P ostEvent. Драйвер, зарегистрированный для использования любого из интерфейсов устройства, может получать уведомления о пользовательских событиях устройства. Драйверы на основе UMDF получают такие уведомления, предоставляя функцию обратного вызова IRemoteInterfaceCallbackEvent::OnRemoteInterfaceEvent .
Пользовательские события уникальны для устройства. Разработчик драйвера, создающего событие, и разработчик драйвера, получающего событие, должны понимать значение события.
Доступ к интерфейсу устройства другого драйвера
Если вы хотите, чтобы драйвер на основе UMDF отправлял запросы ввода-вывода в интерфейс устройства, который предоставляет другой драйвер, можно создать удаленный целевой объект ввода-вывода , представляющий интерфейс устройства.
Во-первых, драйвер должен зарегистрироваться для получения уведомления о доступности интерфейса устройства. Выполните указанные ниже действия.
Когда драйвер вызывает IWDFDriver::CreateDevice, драйвер может предоставить интерфейс IPnpCallbackRemoteInterfaceNotification . Функция обратного вызова IPnpCallbackRemoteInterfaceNotification::OnRemoteInterfaceArrival этого интерфейса информирует драйвер о доступности интерфейсов устройства.
После вызова IWDFDriver::CreateDevice драйвер может вызывать IWDFDevice2::RegisterRemoteInterfaceNotification для каждого интерфейса устройства, который будет использовать драйвер.
Впоследствии платформа вызывает функцию обратного вызова драйвера IPnpCallbackRemoteInterfaceNotification::OnRemoteInterfaceArrival каждый раз, когда становится доступным указанный интерфейс устройства. Функция обратного вызова может вызывать IWDFRemoteInterfaceInitialize::GetInterfaceGuid и IWDFRemoteInterfaceInitialize::RetrieveSymbolicLink , чтобы определить, какой интерфейс устройства поступил.
Функция обратного вызова IPnpCallbackRemoteInterfaceNotification::OnRemoteInterfaceArrival обычно должна выполнять следующие действия:
Вызовите IWDFDevice2::CreateRemoteInterface , чтобы создать объект удаленного интерфейса, при необходимости предоставляя интерфейсы IRemoteInterfaceCallbackEvent и IRemoteInterfaceCallbackRemoval .
Вызовите IWDFDevice2::CreateRemoteTarget , чтобы создать удаленный целевой объект, при необходимости предоставляя интерфейс IRemoteTargetCallbackRemoval .
Вызовите IWDFRemoteTarget::OpenRemoteInterface , чтобы подключить интерфейс устройства к удаленному целевому объекту.
Если интерфейс устройства создается перечислителем программного обеспечения SWENUM, драйвер должен вызвать OpenRemoteInterface из рабочего элемента. (Например, см. функцию QueueUserWorkItem в windows SDK.)
Теперь драйвер может форматировать и отправлять запросы ввода-вывода в удаленный целевой объект ввода-вывода.
В дополнение к функции обратного вызова IPnpCallbackRemoteInterfaceNotification::OnRemoteInterfaceArrival драйвер на основе UMDF может предоставлять две дополнительные функции обратного вызова для получения уведомлений о событиях интерфейса устройства:
Функция обратного вызова IRemoteInterfaceCallbackRemoval::OnRemoteInterfaceRemoval уведомляет драйвер об удалении интерфейса устройства.
Функция обратного вызова IRemoteInterfaceCallbackEvent::OnRemoteInterfaceEvent уведомляет драйвер о поступлении пользовательских событий устройства.