Использование интерфейсов устройств в драйверах 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 отправлял запросы ввода-вывода в интерфейс устройства, который предоставляет другой драйвер, можно создать удаленный целевой объект ввода-вывода , представляющий интерфейс устройства.

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

  1. Когда драйвер вызывает IWDFDriver::CreateDevice, драйвер может предоставить интерфейс IPnpCallbackRemoteInterfaceNotification . Функция обратного вызова IPnpCallbackRemoteInterfaceNotification::OnRemoteInterfaceArrival этого интерфейса информирует драйвер о доступности интерфейсов устройства.

  2. После вызова IWDFDriver::CreateDevice драйвер может вызывать IWDFDevice2::RegisterRemoteInterfaceNotification для каждого интерфейса устройства, который будет использовать драйвер.

Впоследствии платформа вызывает функцию обратного вызова драйвера IPnpCallbackRemoteInterfaceNotification::OnRemoteInterfaceArrival каждый раз, когда становится доступным указанный интерфейс устройства. Функция обратного вызова может вызывать IWDFRemoteInterfaceInitialize::GetInterfaceGuid и IWDFRemoteInterfaceInitialize::RetrieveSymbolicLink , чтобы определить, какой интерфейс устройства поступил.

Функция обратного вызова IPnpCallbackRemoteInterfaceNotification::OnRemoteInterfaceArrival обычно должна выполнять следующие действия:

  1. Вызовите IWDFDevice2::CreateRemoteInterface , чтобы создать объект удаленного интерфейса, при необходимости предоставляя интерфейсы IRemoteInterfaceCallbackEvent и IRemoteInterfaceCallbackRemoval .

  2. Вызовите IWDFDevice2::CreateRemoteTarget , чтобы создать удаленный целевой объект, при необходимости предоставляя интерфейс IRemoteTargetCallbackRemoval .

  3. Вызовите IWDFRemoteTarget::OpenRemoteInterface , чтобы подключить интерфейс устройства к удаленному целевому объекту.

    Если интерфейс устройства создается перечислителем программного обеспечения SWENUM, драйвер должен вызвать OpenRemoteInterface из рабочего элемента. (Например, см. функцию QueueUserWorkItem в windows SDK.)

Теперь драйвер может форматировать и отправлять запросы ввода-вывода в удаленный целевой объект ввода-вывода.

В дополнение к функции обратного вызова IPnpCallbackRemoteInterfaceNotification::OnRemoteInterfaceArrival драйвер на основе UMDF может предоставлять две дополнительные функции обратного вызова для получения уведомлений о событиях интерфейса устройства: