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

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: USB Bulk Driver под Windows 7  (Прочитано 14084 раз)
0 Пользователей и 3 Гостей смотрят эту тему.
magbob
Интересующийся

ru
Offline Offline

« : 01-12-2009 13:03 » 

Есть драйвера WDM USB устройства. Под 2000,XP,Vista работают, а под Win7 нет. Ничего понять не могу.
Вот фрагмент кода

Код:
        // now that we have configuration descriptor lets find our interface
        // and enable it
        numInterfaces = configDescriptor->bNumInterfaces;
        interfaceBuffer = interfaceList =
            (PUSBD_INTERFACE_LIST_ENTRY)ExAllocatePoolWithTag(
                                            NonPagedPool,
                                            sizeof(USBD_INTERFACE_LIST_ENTRY) * (numInterfaces + 1),
                                            SELIK_POOL_TAG
                                            );

        if (interfaceBuffer == NULL)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        for (index = 0; index < numInterfaces; ++index)
        {
            interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
                                    configDescriptor,
                                    configDescriptor,
                                    index,
                                    0,
                                    -1,
                                    -1,
                                    -1
                                    );

            if (interfaceDescriptor != NULL)
            {
                interfaceList->InterfaceDescriptor = interfaceDescriptor;
                interfaceList->Interface = NULL;

                ++interfaceList;
            }
        }

        interfaceList->InterfaceDescriptor = NULL;
        interfaceList->Interface = NULL;

        ExFreePool(urb);
        urb = USBD_CreateConfigurationRequestEx(configDescriptor, interfaceBuffer);
        if (urb == NULL)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        // Здесь код который проверяет наличие endpoint
       ............................

        status = SELIKSubmitUrbSynch(DeviceExtension, urb);  //здесь возвращает статус 0xC000000D (STATUS_INVALID_PARAMETER)
        if (!NT_SUCCESS(status))
        {
            break;
        }

Вот код SELIKSubmitUrbSynch
NTSTATUS SELIKSubmitUrbSynch(
    IN  PSELIK_DEVICE_EXTENSION   DeviceExtension,
    IN  PURB                        Urb
    )
{
    NTSTATUS            status;
    PIRP                irp;
    IO_STATUS_BLOCK     ioStatus;
    KEVENT              event;
    PIO_STACK_LOCATION  irpStack;

    SELIKDebugPrint(DBG_IO, DBG_INFO, __FUNCTION__"++");

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    irp = IoBuildDeviceIoControlRequest(
            IOCTL_INTERNAL_USB_SUBMIT_URB,
            DeviceExtension->LowerDeviceObject,
            NULL,
            0,
            NULL,
            0,
            TRUE,
            &event,
            &ioStatus
            );

    if (irp != NULL)
    {
        irpStack = IoGetNextIrpStackLocation(irp);
        irpStack->Parameters.Others.Argument1 = Urb;

        status = IoCallDriver(DeviceExtension->LowerDeviceObject, irp); //здесь возвращает статус 0xC000000D (STATUS_INVALID_PARAMETER)
        if (status == STATUS_PENDING)
        {
            KeWaitForSingleObject(
                &event,
                Executive,
                KernelMode,
                FALSE,
                NULL
                );
           
            status = ioStatus.Status;   
        }
    }
    else
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
    }

    SELIKDebugPrint(DBG_IO, DBG_INFO, __FUNCTION__"--. STATUS %x", status);

    return status;
}

Что ему не хватает, понять не могу.  А черт его знает...
« Последнее редактирование: 01-12-2009 13:10 от Sel » Записан
Ochkarik
Модератор

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

« Ответ #1 : 01-12-2009 19:42 » 

http://msdn.microsoft.com/en-us/library/ms793125.aspx
IOCTL_INTERNAL_USB_SUBMIT_URB
Цитата
Output

Parameters.Others.Argument1 points to the URB structure. The UrbHeader.Status contains a USB status code for the requested operation. Any additional output depends on the UrbHeader.Function member of the URB submitted. See URB for details.
может имеет смысл посмотреть что в нем?

и кстати, вы DDK от win7 использовали? может быть там что то изменили?
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
magbob
Интересующийся

ru
Offline Offline

« Ответ #2 : 02-12-2009 11:12 » 

Посмотрел UrbHeader.Function и UrbHeader.Length заполняются как и в ХР. А вот UrbHeader.Status возвращает 80000300 (USBD_STATUS_INVALID_PARAMETER). Причем до выбора конфигурации я посылаю запросы получения дескриптеров устройства они проходят нормально.
DDK стоит последняя 7600.16385.0
Записан
Ochkarik
Модератор

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

« Ответ #3 : 02-12-2009 19:38 » 

может быть в Win7 более строго подошли к вызову USBD_CreateConfigurationRequestEx?
http://msdn.microsoft.com/en-us/library/ms790505.aspx
Цитата
Comments
...
Before the caller submits the URB returned by this routine, it can override the default settings for the interface(s) or endpoint(s) contained in the interface information structure(s). InterfaceList[x]->Interface, filled in on return from USBD_CreateConfigurationRequestEx, points to a USBD_INTERFACE_INFORMATION structure. This structure contains members that can select alternate interface and endpoint settings at device-configuration time. See USBD_INTERFACE_INFORMATION for details on these members.Before the caller submits the URB returned by this routine, it can override the default settings for the interface(s) or endpoint(s) contained in the interface information structure(s). InterfaceList[x]->Interface, filled in on return from USBD_CreateConfigurationRequestEx, points to a USBD_INTERFACE_INFORMATION structure. This structure contains members that can select alternate interface and endpoint settings at device-configuration time. See USBD_INTERFACE_INFORMATION for details on these members.
а вы заполняете список до вызова USBD_CreateConfigurationRequestEx. может быть они его стали очищать в этой функции?
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Ochkarik
Модератор

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

« Ответ #4 : 02-12-2009 19:44 » 

кстати
Цитата
The USBD_CreateConfigurationRequestEx function initializes the MaximumTransferSize member of each pipe information structure to USBD_ DEFAULT_MAXIMUM_TRANSFER_SIZE and the PipeFlags member to 0. Bear this in mind when you look at older driver samples and when you write your own driver.
http://msdn.microsoft.com/en-us/library/ms790486.aspx
там еще много чего написано, не дочитал) кушать хочу)
« Последнее редактирование: 02-12-2009 19:47 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
magbob
Интересующийся

ru
Offline Offline

« Ответ #5 : 03-12-2009 09:25 » 

Я, вроде, делаю, как рекомендуют в http://msdn.microsoft.com/en-us/library/ms790478.aspx
У меня простое устройство, никаких алЬтернативных конфигураций и интерфейсов, просто 3-и конечных точки Bulk и все.

Код:
        // now that we have configuration descriptor lets find our interface
        // and enable it
        numInterfaces = configDescriptor->bNumInterfaces;
        interfaceBuffer = interfaceList =
            (PUSBD_INTERFACE_LIST_ENTRY)ExAllocatePoolWithTag(
                                            NonPagedPool,
                                            sizeof(USBD_INTERFACE_LIST_ENTRY) * (numInterfaces + 1),
                                            SELIK_POOL_TAG
                                            );

        if (interfaceBuffer == NULL)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        for (index = 0; index < numInterfaces; ++index)
        {
            interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
                                    configDescriptor,
                                    configDescriptor,
                                    index,
                                    0,
                                    -1,
                                    -1,
                                    -1
                                    );

            if (interfaceDescriptor != NULL)
            {
                interfaceList->InterfaceDescriptor = interfaceDescriptor;
                interfaceList->Interface = NULL;

                ++interfaceList;

            }
        }

        interfaceList->InterfaceDescriptor = NULL;
        interfaceList->Interface = NULL;

        ExFreePool(urb);
        urb = USBD_CreateConfigurationRequestEx(configDescriptor, interfaceBuffer);
        if (urb == NULL)
        {
            status = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

После еще делаю проверочку

Код:
       interfaceInfo = &urb->UrbSelectConfiguration.Interface;
        // verify configuration
        interfaceDescriptor = interfaceBuffer->InterfaceDescriptor;
        if (interfaceDescriptor->bNumEndpoints != 3)
        {
            status = STATUS_DEVICE_CONFIGURATION_ERROR;
            break;
        }

        epDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)interfaceDescriptor;

        epDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)USBD_ParseDescriptors(
                                                    configDescriptor,
                                                    configDescriptor->wTotalLength,
                                                    epDescriptor,
                                                    USB_ENDPOINT_DESCRIPTOR_TYPE
                                                    );

        if ((epDescriptor == NULL) ||
            (epDescriptor->bEndpointAddress != 0x81) ||
            (epDescriptor->bmAttributes != USB_ENDPOINT_TYPE_BULK) ||
            (epDescriptor->wMaxPacketSize != 64))
        {
            status = STATUS_DEVICE_CONFIGURATION_ERROR;
            break;
        }
        else
        {
            interfaceInfo->Pipes[0].MaximumTransferSize = 2048;
interfaceInfo->Pipes[0].MaximumPacketSize = epDescriptor->wMaxPacketSize;
            interfaceInfo->Pipes[0].PipeFlags |= USBD_PF_CHANGE_MAX_PACKET;
            ++epDescriptor;
        }

       epDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)USBD_ParseDescriptors(
                                                    configDescriptor,
                                                    configDescriptor->wTotalLength,
                                                   epDescriptor,
                                                    USB_ENDPOINT_DESCRIPTOR_TYPE
                                                    );

        if ((epDescriptor == NULL) ||
            (epDescriptor->bEndpointAddress != 0x2) ||
            (epDescriptor->bmAttributes != USB_ENDPOINT_TYPE_BULK) ||
            (epDescriptor->wMaxPacketSize != 64))
        {
            status = STATUS_DEVICE_CONFIGURATION_ERROR;
            break;
        }
        else
        {
            interfaceInfo->Pipes[1].MaximumTransferSize = 2048;
interfaceInfo->Pipes[1].MaximumPacketSize = epDescriptor->wMaxPacketSize;
            interfaceInfo->Pipes[1].PipeFlags |= USBD_PF_CHANGE_MAX_PACKET;
            ++epDescriptor;
        }

        epDescriptor = (PUSB_ENDPOINT_DESCRIPTOR)USBD_ParseDescriptors(
                                                    configDescriptor,
                                                    configDescriptor->wTotalLength,
                                                    epDescriptor,
                                                    USB_ENDPOINT_DESCRIPTOR_TYPE
                                                    );

        if ((epDescriptor == NULL) ||
            (epDescriptor->bEndpointAddress != 0x83) ||
            (epDescriptor->bmAttributes != USB_ENDPOINT_TYPE_BULK) ||
            (epDescriptor->wMaxPacketSize != 512))
        {
            status = STATUS_DEVICE_CONFIGURATION_ERROR;
            break;
        }
        else
        {
            interfaceInfo->Pipes[2].MaximumTransferSize = 2048;
interfaceInfo->Pipes[2].MaximumPacketSize = epDescriptor->wMaxPacketSize;
            interfaceInfo->Pipes[2].PipeFlags |= USBD_PF_CHANGE_MAX_PACKET;
            ++epDescriptor;
        }

Ну а потом посылаю

Код:
        status = SELIKSubmitUrbSynch(DeviceExtension, urb);

Да и посмотрел interface там все вроде тривиально
Length = 76;
InterfaceNumber = 0;
AlternateSetting = 0;
Class = 0;
SubClass = 0;
Protocol = 0;
InterfaceHandle = 0;
NumberOfPipes = 3;


« Последнее редактирование: 03-12-2009 11:30 от Sel » Записан
magbob
Интересующийся

ru
Offline Offline

« Ответ #6 : 03-12-2009 10:32 » 

Еще решил сделать эксперимент потихоньку перейти на KMDF.
Взял рыбу из step2 скомпилил и когда доходит до функции выбора конфигурации таже история.
WdfUsbTargetDeviceSelectConfig failed 0xc000000d
Записан
Ochkarik
Модератор

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

« Ответ #7 : 04-12-2009 16:48 » new

попробуйте посмотреть, как сделано в примерах в новом DDK. там кажется их нет в разделе WDM - посмотрите в разделе KMDF. там три примера даны - должны быть сходные функции.
наврал... совсем не похоже)
« Последнее редактирование: 04-12-2009 17:30 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
magbob
Интересующийся

ru
Offline Offline

« Ответ #8 : 10-12-2009 13:25 » 

Все я разобрался. Причем ответ нашел на этом же форуме. У меня устройство full speed и конечная точка д.б.64 байта.  Отлично
Хотя не понятно почему в микроконтроллере под нее выделено 512 байт? И непонятно почему это не нравится только windows7?  Здесь была моя ладья...

Но тут возник другой вопрос.  Не понял  Когда я делаю         
Код:
            UsbBuildInterruptOrBulkTransferRequest(
                urb,
                sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
                PipeInformation->PipeHandle,
                virtualAddress,
                NULL,
                MAX_SIZE,
                USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
                NULL
                );
с MAX_SIZE = 512 байт все работает как часы но медленно (250К/с).
Когда я делаю MAX_SIZE = 4096 все летает скорость порядка (800к/с до 1М/с) (что достаточно) но может глючить выдает ошибки
то USBD_STATUS_BUFFER_OVERRUN то USBD_STATUS_STALL_PID.  А черт его знает...

При инициализации пайпа установил флаги USBD_PF_ENABLE_RT_THREAD_ACCESS, USBD_PF_SHORT_PACKET_OPT;
Записан
Ochkarik
Модератор

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

« Ответ #9 : 10-12-2009 16:19 » 

ага) Была такая тема на 64 байта...
Насчет скорости, пайп в какую сторону данные передает, от ПК?
Посмотрите размер FIFO контроллера. Возможно оно не очень большое, и ошибки из за того, что переполняется FIFO на приемной стороне(контроллер не успевает выгребать большие пакеты из своего первичного FIFO).

А! У вас USBD_TRANSFER_DIRECTION_IN...
Второй вариант - тоже завязан на размер FIFO контроллера но на передачу. СКОРЕЕ ВСЕГО в ПК программная обработка пакетов. По крайней мере так было для 1394-FireWire шины:  пакет принимается и разбирается программно, по окончанию разбора отсылается подтверждение приема при помощи DPC(даже двух DPC). Время задержки обработки DPC в Windows - может сильно варьироваться!!! Я даже большие тесты проводил по этому поводу. Это может приводить к задержке отправки подтверждения приема(ACK), и соответственно к переполнению выходного FIFO контроллера на передающей стороне.
Это ЕСЛИ в реализации драйвера USB ПК - программная обработка пакетов и отсылки ACK-ов, НО ЭТУ ИНФОРМАЦИЮ Я НЕ ГАРАНТИРУЮ!!!

PS (данные тесты проводил довольно давно, поэтому прошу относится к представленным выводам с осторожностью)
Выводы из моих тестов (для ишны 1394): на некоторых ПК могут появлятся задержки выполнения DPC до единиц МС, иногда даже больше. Хотя в среднем пакеты обрабатывались за десятки МКС.
Большое влияние, как мне удалось выяснить - ВИДМО оказывает конфигурация шин и PCI мостов в ПК. А так же КРАЙНЕ кривая реализация(будете смеятся) драйвера CD-ROM. На этих ПК приходится отключать устройство CD-ROM (отключать драйвер), после чего подобные спонтанные задержки пропадают. Кстати задержки из за драйвера CD-ROM довольно стабильны - раз в где то 30 сек, пауза на несколько МС.


PPS хотя у вас скорости не те... но все равно размер TX|RX FIFO проверьте.
« Последнее редактирование: 10-12-2009 16:30 от Ochkarik » Записан

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

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines