Новичок
Профиль
Группа: Участник
Сообщений: 1
Регистрация: 16.6.2007
Репутация: нет Всего: нет
|
Дали задание написать "простейший" usb драйвер. Без прерываний, чтобы загружался, отображался в реестре, затем выгружался, и чистил за собой следы. Начал разбираться... Сначала сделал просто тестовый драйвер, чтобы понять принцип билдинга DDK и дальнейшего запуска, следуя изложенному примеру http://habrahabr.ru/blogs/system_programming/40466/Теперь вот переписал все из Агурова по написанию USB. | Код | // shchDriver.c #include <ntddk.h>
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { NTSTATUS ntStatus = STATUS_SUCCESS;
// Основные обработчики драйвера DriverObject->MajorFunction[IRP_MJ_CREATE]=OnCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE ]=OnClose; DriverObject->MajorFunction[IRP_MJ_READ ] =OnDeviceRead; DriverObject->MajorFunction[IRP_MJ_PNP ] =OnDispatchPnp; DriverObject->MajorFunction[IRP_MJ_POWER ] =OnDispatchPower; DriverObject->DriverUnload = OnUnload; DriverObject->DriverExtension->AddDevice=onAddDevice;
return ntStatus //DbgPrint("Hello world!\n"); //return STATUS_SUCCESS; } NTSTATUS OnAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_OBJECT deviceObject = NULL; PDEVICE_EXTENSION pdx;
WCHAR NameBuffer[] = L"\\Device\\" DEVICE_NAME_STRING; WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING; UNICODE_STRING uniNameString, uniDOSString;
// Создание буферов для имен RtlInitUnicodeString(&uniNameString, NameBuffer); RtlInitUnicodeString(&uniDOSString , DOSNameBuffer); DbgPrint("UniName=%s DosName=%s", uniDOSString, uniNameString);
//Инициализация объекта драйвера ntStatus = IoCreateDevice(DriverObject, sizeof (DEVICE_EXTENSION), &uniNameString, FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject );
// Создание символьного имени драйвера ntStatus = IoCreateSymbolicLink(&uniDOSString, &uniNameString);
// Инициализация блока данных объекта устройства DbgPrint("Init device extension"); pdx = (PDEVICE_EXTENSION) (deviceObject->DeviceExtension); pdx->OpenHandles == 0; // Драйвер будет использовать прямой ввод/вывод для запросов // чтения и записи deviceObject->Flags |= DO_DIRECT_IO;
// Сохраняем ссылку на драйвер нижнего уровня. Ему мы будем // пересылать запросы на ввод/вывод pdx->StackDeviceObject = IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject); return ntStatus; }
typedef struct _DEVICE_EXTENSION { //Объект устройства в стеке IRP PDEVICE_OBJECT StackDeviceObject; // Число устройств для этого драйвера ULONG OpenHandles; // TRUE, если устройство стартовано BOOLEAN Started; } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
NTSTATUS OnCreate(IN PDEVICE_OBJECT fdo,IN PIRP Irp) { Irp->IoStatus.Information = 0; ntStatus = Irp->IoStatus.Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return ntStatus; }
NTSTATUS OnClose(IN PDEVICE_OBJECT fdo, IN PIRP Irp) { NTSTATUS ntStatus; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION )fdo->DeviceExtension; // счетчик открытых устройств pdx->OpenHandles--; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; ntStatus = Irp->IoStatus.Status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return ntStatus; }
NTSTATUS OnDispatchPower(IN PDEVICE_OBJECT fdo,IN PIRP Irp) { PIO_STACK_LOCATION irpStack, nextStack; PDEVICE_EXTENSION pdx = fdo->DeviceExtension; NTSTATUS ntStatus;
Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; irpStack = IoGetCurrentIrpStackLocation(Irp);
nextStack = IoGetNextIrpStackLocation(Irp); RtlCopyMemory(nextStack, irpStack, sizeof(IO_STACK_LOCATION));
PoStartNextPowerIrp(Irp); ntStatus = PoCallDriver(pdx->StackDeviceObject, Irp);
if (ntStatus == STATUS_PENDING) { IoMarkIrpPending(Irp); } return ntStatus; }
NTSTATUS OnDispatchPnp(IN PDEVICE_OBJECT fdo,IN PIRP Irp) { PIO_STACK_LOCATION irpStack; PDEVICE_EXTENSION pdx = fdo->DeviceExtension; ULONG fcn; NTSTATUS ntStatus;
/* Получаем текущую позицию в стеке драйверов */ irpStack = IoGetCurrentIrpStackLocation (Irp); /* Номер функции */ fcn = irpStack->MinorFunction;
switch (fcn) { /* Обработка старта устройства */ case IRP_MN_START_DEVICE: { ntStatus = OnStartDevice(fdo); if (ntStatus == STATUS_SUCCESS) { pdx->Started = TRUE; } break; } case IRP_MN_STOP_DEVICE: { // Сначала передаем запрос драйверу ниже по стеку IoSkipCurrentIrpStackLocation(Irp); IoCallDriver(pdx->StackDeviceObject, Irp); // отрабатьюаем остановку нашего устройства ntStatus = OnStopDevice(fdo); break; }
/* Удаление устройства из системы */ case IRP MN REMOVE DEVICE: { ntStatus = OnRemoveDevice(fdo,Irp); break; } // Все остальные запросы передаем драйверу дальше по стеку default: { IoSkipCurrent rpStackLocation(Irp); ntStatus = IoCallDriver(pdx->StackDeviceObject, Irp); } } return ntStatus; } /////////////////////////////////////////////////////////// NTSTATUS DoCallUSBD(IN PDEVICE_OBJECT fdo,IN PURB Urb) { NTSTATUS ntStatus, status = STATUS_SUCCESS; PDEVICE_EXTENSION pdx;
PIRP irp; KEVENT event; IO_STATUS_BLOCK ioStatus; PIO_STACK_LOCATION nextStack;
pdx = fdo->DeviceExtension;
// объект синхронизации KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB, pdx->StackDeviceObject,NULL, 0, NULL, 0,TRUE, /* INTERNAL */ &event, &ioStatus );
// получение следующей позиции в стеке драйверов nextStack = IoGetNextIrpStackLocation(irp);
// Формирование параметров для вызова nextStack->Parameters.Others.Argument1 = Urb;
// Вызов ntStatus = IoCallDriver(pdx->StackDeviceObject, irp);
// Если запрос еще выполняется... if (ntStatus == STATUS_PENDING) { status = KeWaitForSingleObject(&event,Suspended, KernelMode, FALSE, NULL); } else { ioStatus.Status = ntStatus; }
// Обработка результата запроса ntStatus = ioStatus.Status;
if (NT_SUCCESS(ntStatus)) { if (!(USBD_SUCCESS(Urb->UrbHeader.Status))) ntStatus = STATUS_UNSUCCESSFUL; } return ntStatus;
}
NTSTATUS OnstartDevice(IN PDEVICE_OBJECT fdo) { PDEVICE_EXTENSI0N pcx; NTSTATUS ntStatus; PUSB_DEVICE_DESCRIPTOR deviceDescriptor = NULL; PURB urb; ULONG size;
pdx = fdo->DeviceExtension; urb = ExAllocatePool( NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
size = sizeof(USB_DEVICE_DESCRIPTOR); deviceDescriptor = ExAllocatePool(NonPagedPool, size);
UsbBuildGetDescriptorRequest(urb,(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST), USB_DEVICE_DESCRIPTOR_TYPE,0,0,deviceDescriptor,NULL,size,NULL
);
// Передача запроса на выполнение ntStatus = DoCallUSBD(fdo, urb);
// Отображение дескриптора if (NT SUCCESS(ntStatus)) {
DbgPrint("Device Descriptor: "); DbgPrint("bLength %d ",deviceDescriptor->bLength); DbgPrint("bDescriptorType 0x%x",deviceDescriptor->bDescriptorType); DbgPrint("bcdUSB 0x%x",deviceDescriptor->bcdUSB); DbgPrint("bDeviceClass 0x%x",deviceDescriptor->bDeviceClass); DbgPrint("bDeviceSubClass 0x%x",deviceDescriptor->bDeviceSubClass); DbgPrint("bDeviceProtocol 0x%x",deviceDescriptor->bDeviceProtocol); DbgPrint("bMaxPacketSizeO 0x%x",deviceDescriptor->bMaxPacketSizeO); DbgPrint("idVendor 0x%x",deviceDescriptor->idVendor); DbgPrint("idProduct 0x%x",deviceDescriptor->idProduct); DbgPrint("bcdDevice 0x%x",deviceDescriptor->bcdDevice); DbgPrint("iManufacturer 0x%x",deviceDescriptor->iManufacturer); DbgPrint("iProduct 0x%x",deviceDescriptor->iProduct); DbgPrint("iSerialNumber 0x%x",deviceDescriptor->iSerialNumber); ; }
// Освободить занятую память ExFreePool(deviceDescriptor); ExFreePool(urb);
if (NT_SUCCESS(ntStatus)) { // Конфигурируем устройство ntStatus = OnConfigureDevice(fdo); }
return ntStatus; }
NTSTATUS OnConfigureDevice(IN PDEVICE_OBJECT fdo ) { PDEVICE_EXTENSION pdx; NTSTATUS ntStatus; PURB urb = NULL; ULONG size; PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL; UCHAR alternateSetting, MyInterfaceNumber; PUSBD_INTERFACE_INFORMATION interfaceObject; USBD_INTERFACE_LIST_ENTRY interfaceList;
pdx = fdo->DeviceExtension;
// Память для URB urb = ExAllocatePool(NonPagedPool,sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST)); // Получить только дескриптор конфигурации size = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 16; configurationDescriptor = ExAllocatePool(NonPagedPool, size);
UsbBuildGetDescriptorRequest(urb,(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),USB_CONFIGURATION_DESCRIPTOR_TYPE,0,0, configurationDescriptor, NULL,sizeof (USB_CONFIGURATION_DESCRIPTOR) ,NULL);
ntStatus = DoCallUSBD(fdo, urb);
// Определение нужного размера буфера size = configurationDescriptor->wTotalLength + 16;
// Освободить старый буфер и отвести новый, нужного размера ExFreePool(configurationDescriptor); configurationDescriptor = NULL; configurationDescriptor = ExAllocatePool(NonPagedPool, size);
// Получение полного дескриптора конфигурации UsbBuildGetDescriptorRequest(urb,(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),USB_CONFIGURATION_DESCRIPTORJTYPE, 0, 0, configurationDescriptor, NULL, size, NULL);
ntStatus = DoCallUSBD(fdo, urb);
// Получение конфигурации interfaceList.InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx( ConfigurationDescriptor, ConfigurationDescriptor, -1, -1, -1, -1, -1 );
// Создание запроса для получения конфигурации urb = USBD_CreateConfigurationRequestEx( ConfigurationDescriptor, &interfaceList );
// Получение указателя на буфер описания интерфейса interfaceObject = (PUSBD_INTERFACE_INFORMATION) (&(urb->UrbSelectConfiguration.Interface));
// Конфигурирование конечных точек интерфейса for (j=0; j<interfaceList[0].InterfaceDescriptor->bNumEndpoints; j++) { PUSBD_PIPE_INFORMATION pipe; pipe = &interfaceObject->Pipes[j];
pipe->MaximumTransferSize = 1024; // установить при необходимости
DbgPrint("PipeType 0x%x\n", pipe->PipeType); DbgPrint("EndpointAddress 0x%x\n", pipe ->EndpointAddress); DbgPrint("MaxPacketSize 0x%x\n", pipe ->MaximumPacketSize); DbgPrint("Interval 0x%x\n", pipe ->Interval); DbgPrint("Handle 0x%x\n", pipe ->PipeHandle); DbgPrint ("MaximumTransferSize Ox%x\n", pipe ->MaximumTransferSize) ; )
ntStatus = DoCallUSBD(fdo, urb) ;
ExFreePool (urb) ; ExFreePool (configurationDescriptor) ;
return ntStatus; }
NTSTATUS OnstopDevice(IN PDEVICE_OBJECT fdo) { PDEVICE_EXTENSION pdx; NTSTATUS ntStatus - STATUS_SUCCESS; PURB urb; ULONG size;
pdx = fdo->DeviceExtension;
size= sizeof(struct _URB_SELECT_CONFIGURATION); urb = ExAllocatePool(NonPagedPool, size);
if (urb) { NTSTATUS status;
UsbBuildSelectConfigurationRequest(urb, (USHORT) size, NULL); status = DoCallUSBD(fdo, urb); ExFreePool(urb); } else { ntStatus = STATUS_NO_MEMORY; }
return ntStatus; }
NTSTATUS OnRemoveDevice(IN PDEVICE_OBJECT fdo, IN PIRP Irp ) { NTSTATUS ntStatus; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension; ULONG i;
WCHAR NameBuffer [] = L"\\Device\\" DEVICE_NAME_STRING; WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE__NAME_STRING; UNICODE_STRING uniNameString, uniDOSString;
// Создание буферов для имен RtlInitUnicodeString(SuniNameString, NameBuffer); RtlInitUnicodeString(&uniDOSString , DOSNameBuffer);
// Удаление символьного имени драйвера ntStatus = IoDeleteSymbolicLink(&uniNameString);
IoDetachDevice(pdx->StackDeviceObject); IoDeleteDevice(fdo);
IoSkipCurrentIrpStackLocation(Irp) ; ntStatus = IoCallDriver(pdx->StackDeviceObject, Irp);
return ntStatus; }
NTSTATUS OnDeviceRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp)
{ NTSTATUS ntStatus = STATUS_SUCCESS; PUSBD_PIPE_INFORMATION pipelnfo = NULL, USBD_PIPE_HANDLE pipeHandle = NULL, PURB urb = NULL, ULONG urbSize = 0;
pipelnfo = ... ; // одна из конечных точек pipeHandle = pipeInfo->PipeHandle;
urbSize = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
urb = ExAllocatePool(NonPagedPool,urbSize);
transferFlags = USBD_SHORT_TRANSFER_OK; if (USB_ENDPOINT_DIRECTION_IN(pipeInfo->EndpointAddress)) transferFlags |= USBD_TRANSFER_DIRECTION_IN;
// Формирование запроса UsbBuildlnterruptOrBulkTransferRequest(urb,(USHORT) urbSize, pipeHandle, NULL,Irp->MdlAddress,bufferLength, transferFlags, NULL );
// Выполнение запроса ntStatus = DoCallUSBD(fdo, urb); if (NT_SUCCESS(ntStatus)) { Irp->IoStatus.Information = urb->UrbBulkOrInterruptTransfer.TransferBufferLength; }
// Освободить память ExFreePool(urb);
// Вернуть результат запроса return ntStatus; }
|
Но уверен что много чего не хватает, и наверное есть много ошибок. При билде выдал много всего. Перечитал много всего, но везде советует пишут про Jungo и Driver Studio, но это сами понимаете мне не подходит. Думал найду что-то нибудь в примерах ddk, но там по usb оказались разные ветвленые вьюверы и что-то другое. Мне нужен пустой голый шаблон по сути. Надеюсь сможете мне дать нужный вектор, где что посмотреть и поправить. Спасибо.
|