Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Пишу драйвер USB по Агурову, нужна помощь!  (Прочитано 10398 раз)
0 Пользователей и 1 Гость смотрят эту тему.
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 » Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 20-12-2009 18:54 » 

ищите Driver Studio 3.2. в нем есть визард шаблона. (на голом Си) и разбираетесь что он вам сгенерит)
он старенький, но думаю подойдет для ваших целей. только ставьте минимум галочек в визарде  - проще будет разбираться) там комментарии вроде будут. да, визард можно натравить на конкретное устройство подключенное к ПК (намекаю)))
я тут пример (им генерированный) выкладывал - поищите по форуму на слово FTDI.
Jungo - лучше не надо... хотя не знаю что он сейчас из себя представляет...

с кодом - простите, устал как собака, не соображаю совсем)
а примеры USB в DDK есть, но довольно запутанные...
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
DenisVV
Новенький

ru
Offline Offline

« Ответ #2 : 07-01-2011 09:49 » new

Доброго времени суток, всех с Праздником!
Подскажите решение проблемы:
Изучаю написание драйверов для USB устройств. Изучил труды Агурова, и собрал проекты что у него в книге. Но у Агурова все программы(драйвера) только чтобы читать данные из устройства в компьютер. Подскажите где взять пример драйвера для записи (отправки байтов из компьютера в USB устройство) или что следует поменять в драйвере(чтобы  вместо READ было WRITE)?
Записан
chesland
Интересующийся

ua
Offline Offline

« Ответ #3 : 07-01-2011 12:03 » 

Дали задание написать "простейший" usb драйвер. Без прерываний, чтобы загружался, отображался в реестре, затем выгружался и чистил за собой следы.  Начал разбираться...
Я тоже новичок в написании дров. Но если тебе нужен драйвер, который загружается-выгружается, то для начала делай НЕ USB-драйвер.
Для этого возьми книгу автор-"Солдатов"(название не помню) - там(почти без ошибок) нормальный пример простейшего драйвера, который загружается-выгружается. Потом сделаешь из него - USBдрайвер.

По "Агурову" ты драйвер не напишешь(поверь моему опыту) - описание для общего понимания отличное, но тексты - НЕРАБОЧИЕ практически все.
Компилируй утилитой "build" из набора DDK - меньше будет проблем и вопросов.

И еще... Как же ты хочешь устанавливать USB-драйвер без USB-устройства???
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 07-01-2011 14:14 » 

DenisVV, вам стоит пройтись по тексту кода  что вы написали, и просмотреть что делает каждая функция, из тех что вы использовали)
вы сразу получите ответ на свой вопрос)
копать в сторону UsbBuildInterruptOrBulkTransferRequest()  Ага
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines