scherbet
Гость
|
|
« : 20-12-2009 13:39 » |
|
Дали задание написать "простейший" 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 оказались разные ветвленые вьюверы и что-то другое. Мне нужен пустой голый шаблон , по сути. Надеюсь , сможете мне дать нужный вектор, где что посмотреть и поправить.
|
|
« Последнее редактирование: 20-12-2009 19:25 от Sel »
|
Записан
|
|
|
|