- •Введение 5
- •1 Исследовательский раздел
- •1.1 Анализ существующих аналогичных систем
- •1.1.1 Обзор архитектуры устройств usb
- •1.2 Обоснование выбора программно-аппаратных средств
- •1.3 Постановка задачи
- •1.4 Развернутое техническое задание
- •1.4.1 Общие сведения
- •2.1.1 Основные дескрипторы usb драйвера
- •2.1.1.1 Дескриптор устройства
- •2.1.1.2 Дескриптор расширения устройства
- •2.1.1.3 Дескриптор конфигурации
- •2.1.1.4 Дескриптор интерфейса
- •2.1.1.5 Дескриптор конечной точки
- •2.2 Разработка функциональной схемы драйвера
- •2.2.1 Драйвер в иерархии wdm
- •2.2.2 Уровни обмена данными usb устройств
- •2.2.3 Архитектура системного драйвера usb
- •2.2.4 Основные рабочие процедуры драйвера
- •2.2.5 Управление перемещаемостью кода в драйвере
- •2.3 Разработка алгоритмического обеспечения
- •2.3.1 Инициализация драйвера
- •2.3.3 Обработка расширенных запросов ioctl
- •2.3.4 Поддержка запросов Plug and Play
- •2.3.5 Управление питанием
- •2.3.5.1 Обработка запросов irp_mj_power
- •2.3.6 Процедура деинициализации драйвера
- •2.4 Разработка программного обеспечения
- •2.4.1 Процедура DriverEntry
- •2.4.2 Процедура DriverUnload
- •2.4.3 Процедура AddDevice
- •2.4.4 Процедура передачи запроса usbd
- •2.4.5 Обработчики usbCreate и usbClose
- •2.4.6 Обработчик ConfigureDevice
- •2.4.7 Обработчики запросов на чтение и запись
- •3 Технологический раздел
- •3.1 Технология разработки драйверов для операционных систем семейства Windows
- •3.1.1 Архитектура Windows Driver Model
- •3.1.2 Выбор типа разрабатываемого драйвера
- •3.1.3 Разработка usb драйвера
- •3.2 Технология отладки драйверов в операционных системах семейства Windows
- •3.2.1 Основные отладочные тесты
- •3.2.2 Основные «проблемы», возникающие при отладке драйвера
- •3.2.2.1 Аппаратные проблемы
- •3.2.2.2 Программные проблемы
- •3.2.3 Основные отладчики и утилиты для проверки драйвера
- •3.2.3.1 Отладчик WinDbg
- •3.2.3.2 Driver Verifier
- •3.2.4 Общие приемы отладки драйвера
- •3.2.4.1 Установка фиксированных точек прерывания
- •3.2.4.2 Промежуточный вывод на экран
- •3.2.4.3 Сохранение отладочного кода в исходном тексте драйвера
- •3.2.4.4 Перехват некорректных условий
- •3.2.4.5 Обнаружение утечек памяти
- •3.2.5 Замечания по отладке драйверов
- •4 Безопасность жизнедеятельности
- •4.1 Анализ эргономических параметров рабочего места пользователя пэвм
- •4.1.1 Общие эргономические аспекты рабочего места
- •4.2 Организация рабочего места пользователя с учётом эргономических требований
- •4.2.1 Организация рабочего стола
- •4.2.2 Рабочее кресло
- •4.2.3 Работа с клавиатурой и мышью
- •4.2.4 Расположение и эргономические характеристики монитора
- •4.2.5 Внутренний объем
- •4.2.6 Рабочая поза пользователя пэвм
- •4.3 Экологическая оценка и переработка узлов компьютерной техники содержащих платину
- •4.3.1 Извлечение платины из отработанных катализаторов
- •4.3.2 Извлечение платины из радиооборудования и сплавов для электрических контактов
- •5 Экономический раздел
- •5.1 Планирование разработки драйвера с построением графика выполнения работ
- •5.1.1 Определение этапов и работ по созданию программного продукта
- •5.1.2 Расчет трудоемкости и продолжительности работ
- •5.1.3 Построение графика выполнения работ
- •5.2 Расчет затрат на разработку
- •5.3 Оценка экономической эффективности проекта
- •1 К исследовательскому разделу
- •2 К специальному разделу
- •3 К технологическому разделу
- •4 К разделу «Безопасность Жизнедеятельности»
- •5 К экономическому разделу
- •Приложение а Установка драйвера с помощью inf-файла
- •Приложение б Графические материалы
2.4.6 Обработчик ConfigureDevice
Конфигурирование устройства (процедура OnConfigureDevice) состоит из следующих действий:
передача запроса с достаточным размером;
получение дескриптора;
создание конечных точек;
конфигурирование конечных точек.
NTSTATUS ConfigureDevice(
IN PDEVICE_OBJECT DeviceObject
)
// Инициализация экземпляра устройства USB, а также выбор (настройка)
// и сохранение конфигурации
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus;
PURB urb;
ULONG siz;
deviceExtension = DeviceObject->DeviceExtension;
ASSERT( deviceExtension->UsbConfigurationDescriptor == NULL );
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if ( !urb )
return STATUS_INSUFFICIENT_RESOURCES;
Вызывающая сторона должна позаботиться о буфере достаточного размера, чтобы он мог вместить данные, в противном случае данные будет урезаны, но без возвращения ошибки. Поэтому переменная «siz» и задействуется в приведенном листинге
siz = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 128;
// Мы выйдем из цикла как только UsbBuildGetDescriptorRequest() получит
// буфер достаточного размера (deviceExtension-
// >UsbConfigurationDescriptor), чтобы вместить все данные
while( 1 ) {
deviceExtension->UsbConfigurationDescriptor = ExAllocatePool(NonPagedPool, siz);
if ( !deviceExtension->UsbConfigurationDescriptor ) {
ExFreePool(urb);
return STATUS_INSUFFICIENT_RESOURCES;
}
UsbBuildGetDescriptorRequest(urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST), USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
deviceExtension->UsbConfigurationDescriptor,
NULL,
siz,
NULL);
ntStatus = CallUSBD(DeviceObject, urb);
if (urb->UrbControlDescriptorRequest.TransferBufferLength>0 &&
deviceExtension->UsbConfigurationDescriptor->wTotalLength > siz)
{
siz = deviceExtension->UsbConfigurationDescriptor->wTotalLength;
ExFreePool(deviceExtension->UsbConfigurationDescriptor);
deviceExtension->UsbConfigurationDescriptor = NULL;
} else {
break;
}
}
ExFreePool(urb);
Теперь у нас есть конфигурационный дескриптор для той конфигурации, которая нам нужна. Теперь мы осуществляем вызов для конфигурирования каналов, ассоциируемых с конфигурацией.
ntStatus = SelectInterface(DeviceObject,
deviceExtension->UsbConfigurationDescriptor);
return ntStatus;
}
2.4.7 Обработчики запросов на чтение и запись
Процедуры USBRead и USBWrite обслуживают запросы на чтение запись данных для устройства.
NTSTATUS USBRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PUSBD_PIPE_INFORMATION pipeHandle;
PFILE_OBJECT fileObject;
PIO_STACK_LOCATION irpStack, nextStack;
PDEVICE_EXTENSION deviceExtension;
PURB urb;
PISOUSB_RW_CONTEXT context = NULL;
if ( !Irp->MdlAddress ) {
// NULL для запроса нулевой длины, поэтому просто возвращаем SUCCESS
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
return ntStatus;
}
IncrementIoCount(DeviceObject);
deviceExtension = DeviceObject->DeviceExtension;
if ( ! CanAcceptIoRequests( DeviceObject ) )
{
ntStatus = STATUS_DELETE_PENDING;
Irp->IoStatus.Status = ntStatus;
DecrementIoCount(DeviceObject);
IoCompleteRequest (Irp, IO_NO_INCREMENT );
return ntStatus;
}
irpStack = IoGetCurrentIrpStackLocation (Irp);
fileObject = irpStack->FileObject;
pipeHandle = fileObject->FsContext;
if (!pipeHandle)
{
ntStatus = STATUS_INVALID_HANDLE;
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
return ntStatus;
}
ASSERT( UsbdPipeTypeIsochronous == pipeHandle->PipeType );
//Вызов ResetPipe() сбрасывает канал USB.
ResetPipe(DeviceObject, pipeHandle, FALSE);
// BuildIsoRequest() используется для построения USBD запроса для
// IRP_MJ_READ и IRP_MJ_WRITE IOCTL-ов.
urb = BuildIsoRequest(DeviceObject,
Irp,
pipeHandle,
TRUE);
if (urb) {
nextStack = IoGetNextIrpStackLocation(Irp);
ASSERT(nextStack != NULL);
ASSERT(DeviceObject->StackSize>1);
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.Others.Argument1 = urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine(Irp,
IsoUsb_IsoReadWrite_Complete,
urb,
TRUE,
TRUE,
TRUE);
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
Irp);
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
return ntStatus;
}
NTSTATUS USBWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PUSBD_PIPE_INFORMATION pipeHandle;
PFILE_OBJECT fileObject;
PIO_STACK_LOCATION irpStack, nextStack;
PDEVICE_EXTENSION deviceExtension;
PURB urb;
PISOUSB_RW_CONTEXT context = NULL;
if ( !Irp->MdlAddress )
{
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
return ntStatus;
}
IncrementIoCount(DeviceObject);
deviceExtension = DeviceObject->DeviceExtension;
if ( ! CanAcceptIoRequests( DeviceObject ) )
{
ntStatus = STATUS_DELETE_PENDING;
Irp->IoStatus.Status = ntStatus;
DecrementIoCount(DeviceObject);
IoCompleteRequest(Irp, IO_NO_INCREMENT );
return ntStatus;
}
irpStack = IoGetCurrentIrpStackLocation(Irp);
fileObject = irpStack->FileObject;
pipeHandle = fileObject->FsContext;
if (!pipeHandle)
{
ntStatus = STATUS_INVALID_HANDLE;
Irp->IoStatus.Status = ntStatus;
Irp->IoStatus.Information = 0;
IoCompleteRequest (Irp,
IO_NO_INCREMENT
);
return ntStatus;
}
ResetPipe(DeviceObject, pipeHandle, FALSE);
urb = BuildIsoRequest(DeviceObject,
Irp,
pipeHandle,
FALSE);
if (urb)
{
nextStack = IoGetNextIrpStackLocation(Irp);
ASSERT(nextStack != NULL);
ASSERT(DeviceObject->StackSize>1);
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.Others.Argument1 = urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine(Irp,
IsoUsb_IsoReadWrite_Complete,
urb,
TRUE,
TRUE,
TRUE);
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
Irp);
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
return ntStatus;
}