Смекни!
smekni.com

Протоколирование обмена информацией между компьютером и внешним запоминающим USB-устройством (стр. 3 из 7)

Канал сообщений, связанный с нулевой конечной точкой, называется Основным каналом сообщений (DefaultControlPipe или ControlPipe 0). Владельцем этого канала является USBD, и он используется для конфигурирования устройства. Основной канал сообщений поддерживает только управляющие передачи. Остальные каналы (они называются клиентскими каналами, ClientPipe) создаются в процессе конфигурирования устройства. Их владельцами являются драйверы устройств. По клиентским каналам могут передаваться как потоки, так и сообщения с помощью любых типов передач.

Набор клиентских каналов, с которыми работает драйвер устройства, называется интерфейсом устройства или связкой клиентских каналов.

1.4 Драйверная модель WDM

WDM (WindowsDriverModel) – новая модель архитектуры драйверов, предложенная Microsoft для Windows 2000, хотя эта архитектура развивалась, начиная с Windows 3.11, продолжая развиваться и в Windows 98 и WindowsNT, но по-настоящему полной она стала только в Windows 2000.

С точки зрения WDM, существует три типа драйверов:

· Драйвер шины – драйвер, обслуживающий контроллер шины, адаптер, мост или любые другие устройства, имеющие дочерние устройства. Для каждого типа шины в операционной системе имеется свой драйвер;

· Функциональный драйвер – основной драйвер устройства, предоставляющий его функциональный интерфейс. Этот драйвер обязателен кроме тех случаев, когда ввод-вывод осуществляется драйвером шины или драйвером фильтров шины. Функциональный драйвер по определению обладает наиболее полной информацией о своем устройстве. Обычно только этот драйвер имеет доступ к специфическим регистрам устройства;

· Драйвер фильтра – драйвер, поддерживающий дополнительную функциональность устройства (или существующего драйвера) или изменяющий запросы ввода / вывода и ответы на них от других драйверов. Таких драйверов может быть несколько, хотя их присутствие необязательно. Они могут работать как на более высоком уровне, чем функциональный драйвер или драйвер шины, так и на более низком.

В среде WDM один драйвер не может контролировать все аспекты устройства: драйвер шины информирует диспетчера PnP об устройствах, подключенных к шине, в то время как функциональный драйвер управляет устройством.

1.4.1 Драйверные слои

Согласно перечисленным выше типам драйверов, существует три типа
объектов:

· Объекты физических устройств (PDO, PhysicalDeviceObject) – эти объекты создаются для каждого физически идентифицируемого элемента аппаратуры, подключенного к шине данных;

· Объекты функциональных устройств (FDO, FunctionalDeviceObject) – подразумевает единицу логической функциональности устройства;

· Объекты фильтров устройств (FiDO, FilterDeviceObject) – предоставляют дополнительную функциональность.

В WindowsNT 5 последовательность загрузки драйверов устройств такая:

1. Во время загрузки операционной системы производится загрузка шинных драйверов для каждой известной системе шины (список шин создается при установке операционной системы и сохраняется в реестре);

2. Вызывается DriverEntry, а затем AddDevice для каждого шинного драйвера. В AddDevice создается FDO для драйвера системной шины. Затем на созданный FDO отправляется запрос IRP_MN_START_DEVICE;

3. Шинный драйвер составляет список всех устройств, подключенных к шине. Для каждого найденного устройства создается объект PDO;

4. На каждый PDO посылается запрос IRP_MN_QUERY_DEVICE_RELATION, в ответ на который шинный драйвер возвращает идентификаторы всех найденных устройств;

5. На эти PDO посылают запрос IRP_MN_QUERY_ID, в ответ на который драйвер системной шины сообщает идентификаторы этих устройств;

6. Получив идентификаторы, система пытается найти и загрузить драйверы устройств;

7. Найдя драйвер для устройств, система загружает его в память, вызывая его DriverEntry. Потом вызывается AddDevice, где создается FDO для устройства. Если устройств, управляемых этим драйвером, несколько, то AddDevice будет вызвана для каждого устройства. Если в реестре зарегистрированы дополнительные фильтры, то они также загружаются в память. Затем система посылает на FDO запрос IRP_MN_START_DEVICE;

8. Происходит посылка на FDO запроса IRP_MN_QUERY_DEVICE_RELATIONS. Если устройство само является шиной или держит на себе другие устройства, которыми само не управляет, то для устройства на нем повторяется вся последовательность действий, начиная с пункта 5.

Функция AddDevice, вызываемая для каждого FDO, вызывает IoCreateDevice и IoAttachDeviceToStack, обеспечивая построение стека устройств. Стек устройств обеспечивает прохождение запросов от пользовательских программ до аппаратного (нижнего) уровня драйверов (Рис. 1.4.1.1).

Рис. 1.4.1.1 Стек устройств


Из вышесказанного становится понятным, что разрабатываемый драйвер должен являться драйвером-фильтром нижнего уровня, связанным с клиентским драйвером USB‑накопителя. Необходимость работы с клиентским USB‑драйвером объясняется тем, что именно на этом уровне перехватываемая информация обладает требуемой структурированностью – передаются именно файлы, а не блоки информации (кадры или составленные из них транзакции), определяемые протоколом обмена по USB.

1.4.2 Точки входа WDM-драйвера

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

NTSTATUSDriverEntry(

INPDRIVER_OBJECTDriverObject, // указатель на объект драйвера

INPUNICODE_STRINGRegistryPath) // путь к подразделу регистра,

// относящегося к драйверу

Эта функция выполняется при загрузке драйвера операционной системой. В WDM‑драйверах на DriverEntry возложены обязанности по регистрации всех остальных точек входа драйвера.

NTSTATUS AddDevice (

IN PDRIVER_OBJECT DriverObject, // указательнаобъектдрайвера

INPDEVICE_OBJECTPhysicalDeviceObject) // указатель на родительский PDO

В драйверах, поддерживающих PnP, через эту точку входа менеджер PnP посылает драйверу уведомление об обнаружении устройства, за которое должен отвечать драйвер. ФункцияAddDevice должна создать объект устройства с помощью вызова IoCreateDeviceи при необходимости присоединить его к стеку устройств с помощью IoAttachDeviceToDeviceStack.

NTSTATUS DriverUnload (

IN PDRIVER_OBJECT DriverObject) // указательнаобъектдрайвера

Вызывается при выгрузке драйвера. В этой функции должны осво
бождаться все затребованные драйвером ресурсы. Драйверы WDM‑модели
выполняют эти действия в обработчике запросов IRP_MJ_PNP с субкодом IRP_MN_REMOVE_DEVICE, то есть при удалении устройства из системы.

Следует выделить отдельный класс точек входа драйвера, которые предназначены для обработки IRP‑пакетов с различными кодами операций. Эти точки входа регистрируются при загрузке драйвера в функции DriverEntry. Регистрация производится путем заполнения элементов массива MajorFunction адресами диспетчеризуемых функций. Индексом в этом массиве являются коды IRP_MJ_XXX, то есть описанные числами типы пакетов IRP. Диспетчер ввода / вывода, ориентируясь на заполнение этого массива, вызывает нужные функции драйвера.

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

1.5 Пакет запроса ввода / вывода (IRP)

Пакеты ввода / вывода (IRP‑пакеты) используются для передачи запросов к драйверу от его клиентов. Они являются структурами данных переменной длины, и состоят из стандартного заголовка, содержащего общую учетную информацию, и одного или нескольких блоков параметров, называемых ячейками стека ввода / вывода (I/OStackLocation).

Приведем структуру заголовка IRP‑пакета:

Таблица 1.5.1. Структура заголовка IRP‑пакета.

Поля Описание
IO_STATUS_BLOCK IoStatus Статус запроса
PVOID AssociatedIrp. SystemBuffer Указатель на системный буфер для случая, если устройство поддерживает буферизованный ввод / вывод
PMDL MdlAddress Указатель на MDL‑список в случае, если устройство поддерживает прямой ввод / вывод
PVOID UserBuffer Адрес пользовательского буфера для ввода / вывода
BOOLEAN Cancel Индикатор того, что IRP‑пакет должен быть аннулирован

Основное назначение ячеек стека ввода / вывода состоит в том, чтобы хранить функциональный код и параметры запроса на ввод / вывод. Ниже, в таблице 1.5.2 приводятся поля ячеек стека ввода / вывода, к которым драйвер может обращаться непосредственно по указателю (чего не рекомендуется делать для остальных полей):

Таблица 1.5.2. Структура ячейки стека ввода / вывода

Поля Описание
UCHAR MajorFunction Код IRP_MJ_XXX, описывающий назначение операции
UCHAR MinorFunction Субкод операции
PDEVICE_OBJECT DeviceObject Указатель на объект устройства, которому был адресован данный объект IRP
PFILE_OBJECT FileObject Файловый объект для данного запроса, если он задан
unionParameters (трактовка определяется значением MajorFunction)
struct Read Параметры для IRP типа IRP_MJ_READ:ULONG LengthULONG KeyLARGE_INTEGER ByteOffset
struct Write Параметры для IRP типа IRP_MJ_WRITE:ULONG LengthULONG KeyLARGE_INTEGER ByteOffset
struct DeviceControl Параметры для IRP типа IRP_MJ_DEVICE_CONTROL:ULONG OutputBufferLengthULONG InputBufferLengthULONG IoControlCodePVOID Type3InputBuffer

Приведем графическое представление структуры IRP‑пакета: