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

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

ru
Offline Offline
Пол: Женский

« : 17-12-2015 11:05 » 

Здравствуйте!
Пишу USB-драйвер, за основу взят пример из WinDDK UsbSamp. Проблема в записи данных. Программа выполняет запрос на запись, процедура завершается со статусом Success, правильно определяет размер данных, но в переменную количества переданных данных возвращает 0. Не могу понять, в чем дело.
Использую в написании WinDDK 7600
Вот процедура записи:

Код:
VOID
Nu6EvtIoWrite(
IN WDFQUEUE         Queue,
IN WDFREQUEST       Request,
IN size_t           Length
)
{
    WDFUSBPIPE                       pipe;
    PDEVICE_CONTEXT               pDeviceContext;
    WDFMEMORY                       reqMemory;
    PMDL                                 requestMdl = NULL, newMdl=NULL;
    WDF_MEMORY_DESCRIPTOR       memDesc;
    ULONG                               BytesWrite;
    WDF_REQUEST_SEND_OPTIONS    SendOptions;
    NTSTATUS                            status;
    ULONG                                 urbFlags = 0;
    ULONG                                 stageLength = 0;
    ULONG                                 totalLength = Length;
    ULONG_PTR                          virtualAddress = 0;
    PREQUEST_CONTEXT              rwContext = NULL;
 
    WDF_OBJECT_ATTRIBUTES      objectAttribs;
    PURB                                   urb=NULL;
    WDFMEMORY                         urbMemory;
    USBD_PIPE_HANDLE               usbdPipeHandle;
   
 
    UNREFERENCED_PARAMETER(Length);
 
   
    pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
    pipe = pDeviceContext->BulkWritePipe;
 
    status = WdfRequestRetrieveInputWdmMdl(Request, &requestMdl);
    if (!NT_SUCCESS(status))
                         {
                    DbgPrint("WdfRequestRetrieveInputWdmMdl failed with status 0x % x\n",status);
                    goto Exit;
            }
   
    urbFlags |= USBD_TRANSFER_DIRECTION_OUT;
    DbgPrint("WdfRequestRetrieveINputWdmMdl OK\n, %d", &requestMdl);
   
   
    virtualAddress = (PUCHAR)MmGetMdlVirtualAddress(requestMdl);
 
    if (totalLength > MAX_TRANSFER_SIZE)
    {
        stageLength = MAX_TRANSFER_SIZE;
        DbgPrint("totalLength > MAX_TRANSFER_SIZE\n");
 
    }
    else
    {
        stageLength = totalLength;
        DbgPrint("stageLength = totalLength\n %d", stageLength);
    }
 
 
    newMdl = IoAllocateMdl(virtualAddress,
        totalLength,
        FALSE,
        FALSE,
        NULL);
 
    if (newMdl == NULL) {
        DbgPrint("Failed to alloc mem for mdl\n");
        status = STATUS_INSUFFICIENT_RESOURCES;
        goto Exit;
    }
 
 
 
    DbgPrint("IoAllocateMdl OK\n");
 
    IoBuildPartialMdl(requestMdl,
        newMdl,
        virtualAddress,
        stageLength);
 
    DbgPrint("IoBuildPartialMdl\n");
 
 
    WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
    objectAttribs.ParentObject = Request;
 
    status = WdfMemoryCreate(
        &objectAttribs,
        NonPagedPool,
        POOL_TAG,
        sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
        &urbMemory,
        &urb
        );
 
   
    if (!NT_SUCCESS(status)){
        DbgPrint("WdfMemoryCreate failed\n");
        goto Exit;
    }
 
   
 
 
    if (urb == NULL)
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        DbgPrint("urb=NULL\n");
        goto Exit;
    }
 
 
 
    usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe);
    UsbBuildInterruptOrBulkTransferRequest(
        urb,
        sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
        usbdPipeHandle,
        NULL,
        newMdl,
        stageLength,
        urbFlags,
        NULL);
 
    DbgPrint("UsbBuildInterruptOrBulkTransferRequest\n");
 
    status = WdfUsbTargetPipeFormatRequestForUrb(
        pipe,
        Request,
        urbMemory,
        NULL
        );
    if (!NT_SUCCESS(status)) {
        goto Exit;
    }
    WdfRequestSetCompletionRoutine(
        Request,
        WriteCompletion,
        pipe
        );
 
 
   
    if (WdfRequestSend(
        Request,
        WdfUsbTargetPipeGetIoTarget(pipe),
        &SendOptions//WDF_NO_SEND_OPTIONS
        ) == FALSE) {
        status = WdfRequestGetStatus(Request);
        goto Exit;
    }
Exit:
    if (!NT_SUCCESS(status)) {
        WdfRequestCompleteWithInformation(
            Request,
            status,
            0
            );
    }
    return;
}


Процедура завершения:
Код:
VOID
WriteCompletion(
IN WDFREQUEST                  Request,
IN WDFIOTARGET                 Target,
PWDF_REQUEST_COMPLETION_PARAMS CompletionParams,
IN WDFCONTEXT                  Context
)
 
 
{
    PWDF_USB_REQUEST_COMPLETION_PARAMS usbCompletionParams;
    PMDL                    requestMdl;
    WDFUSBPIPE              pipe;
    ULONG                   stageLength;
    NTSTATUS               status;
    PREQUEST_CONTEXT        rwContext;
    PURB                    urb;
    PCHAR                   operation;
    ULONG                   bytesWrite;
    size_t          bytesTransferred = 0;
    PDEVICE_CONTEXT deviceContext;
 
 
    UNREFERENCED_PARAMETER(Target);
    UNREFERENCED_PARAMETER(Context);
 
    deviceContext = (PDEVICE_CONTEXT)Context;
    status = CompletionParams->IoStatus.Status;
    if (!NT_SUCCESS(status))
    {
        // Get the USBD status code for more information about the error condition.
        //status = CompletionParams->Parameters.Usb.Completion->UsbdStatus;
        DbgPrint("Bulk transfer failed 0x % x\n", status);
        goto End;
    }
    usbCompletionParams = CompletionParams->Parameters.Usb.Completion;
    bytesTransferred =
        CompletionParams->Parameters.Usb.Completion->Parameters.PipeWrite.Length;
 
    KdPrint(("Bulk transfer completed. Transferred %d bytes. \n",bytesTransferred));
 
   
    WdfRequestComplete(Request, status, bytesTransferred);
    DbgPrint("request completed with status  0x%x\n", status);
    return;
 
   
End:
    WdfRequestCompleteWithInformation(Request, status, bytesTransferred);
    DbgPrint("writecomletion complete\n");
    return;
}


Записан
Ochkarik
Модератор

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

« Ответ #1 : 18-12-2015 09:01 » 

   ULONG                                 totalLength = Length;
...
    UNREFERENCED_PARAMETER(Length);
...
        stageLength = MAX_TRANSFER_SIZE;
или
        stageLength = totalLength;

... у вас на входе Length - точно не ноль?
PS Pipe на чтение/запись не перепутали?

Добавлено через 5 минут и 22 секунды:
UsbSamp использует METHOD_BUFFERED

PPS минуточку... какой еще DIRECT_IO??? вы о чем?
« Последнее редактирование: 18-12-2015 09:08 от Ochkarik » Записан

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

ru
Offline Offline
Пол: Женский

« Ответ #2 : 18-12-2015 11:51 » 

Простите, не так выразилась, я имела в виду METHOD_DIRECT.

Как же METHOD_BUFFERED? Либо я что-то не понимаю, разве не с помощью этой функции устанавливается тип ввода-вывода  WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect) (взято из usbSamp)?

Length на входе точно не ноль, так как я этот параметр вывожу в отладочной информации.

Pipe на чтение/запись выставлены верно, так как передача без иcпользования MDL работает.

Причем проверяла newMdl:
               MmGetMdlByteCount(newMdl)
тоже возвращает необходимый размер
Записан
Ochkarik
Модератор

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

« Ответ #3 : 18-12-2015 20:40 » 

метод доступа для IOCTL входит в само значение IOCTL как флаг - откройте h файл где он определяется

Добавлено через 1 минуту и 53 секунды:
https://msdn.microsoft.com/en-us/library/windows/hardware/ff554436(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/hardware/ff543023(v=vs.85).aspx

Добавлено через 50 минут и 5 секунд:
а вообще я чет засомневался, с WDF не работал... почитать надоть, достаточно ли этой функции или все равно код определять надо правильно.
мутный он WDF какой то)
« Последнее редактирование: 18-12-2015 21:32 от Ochkarik » Записан

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

ru
Offline Offline
Пол: Женский

« Ответ #4 : 19-12-2015 13:08 » 

Что мутный, то полностью согласна!)

Так, я уже начинаю путаться!) Сейчас речь идет не об IOCTL. С IOCTL все понятно, а вот непосредственно для процедур Read/Write метод доступа определяется по-другому, исходя из комментариев в примере, я сделала вывод, что все-таки задается посредством функции, что я обозначила выше.

Пробовала передавать без помощи URB и MDL все работает, но я сомневаюсь насчет быстродействия, повлияет ли это как-то на скорость передачи данных.
Записан
Ochkarik
Модератор

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

« Ответ #5 : 19-12-2015 14:58 » 

ничего не понял - каких процедур Read/Write ? чьих процедур?
ааа. так вы про флаги DeviceObject->Flags?  DO_DIRECT_IO или DO_BUFFERED_IO
что то я перестал понимать про что мы говорим)
еще раз - DeviceObject->Flags имеет отношение к вопросу? или тема неправильно заполнена?

Добавлено через 8 минут и 50 секунд:
Nu6EvtIoWrite это у вас кто вызывает?
« Последнее редактирование: 19-12-2015 15:06 от Ochkarik » Записан

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

ru
Offline Offline
Пол: Женский

« Ответ #6 : 19-12-2015 16:21 » 

Так, все по порядку.
Nu6EvtIoWrite. Эту процедуру на запись вызывает мое тестирующее приложение посредством WriteFile. Проблема заключается в том, что когда я использую списки MDL и передача осуществляется пакетами с помощью процедуры UsbBuildInterruptOrBulkTransferRequest как в коде,что описан выше, количество переданных данных равняется нулю, а вот без использования MDL и этой функции все получается, то есть я пользуюсь функцией WdfRequestRetrieveInputMemory для получения указателя на буфер без излишних манипуляций с памятью.

Заранее прошу прощения, если выражаюсь как-то невнятно, сама до конца не могу разобраться со всеми этими функциями!(
Рабочий код смогу предоставить только в понедельник

Добавлено через 1 минуту и 12 секунд:
Пока забудем про флаги, тут проблема в другом)

Добавлено через 8 дней, 14 часов, 29 минут и 35 секунд:
Подправила процедуру WriteCompletion. Взяла большую часть опять же из примера UsbSamp. Вина моя, нельзя для пакетов URB применять

Код:
bytesTransferred =
CompletionParams->Parameters.Usb.Completion->Parameters.PipeWrite.Length;

Черным по белому написано это в документации. :Улыбаюсь
« Последнее редактирование: 28-12-2015 06:52 от Манник » Записан
Ochkarik
Модератор

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

« Ответ #7 : 28-12-2015 11:25 » new

вот оно что!
Записан

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

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines