Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Пишу драйвер USB, по Агурову, нужна помощь! 
:(
    Опции темы
scherbet
Дата 20.12.2009, 03:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 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 оказались разные ветвленые вьюверы и что-то другое. Мне нужен пустой голый шаблон по сути. Надеюсь сможете мне дать нужный вектор, где что посмотреть и поправить.

Спасибо.

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0442 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.