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

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: USB driver  (Прочитано 13217 раз)
0 Пользователей и 1 Гость смотрят эту тему.
dgritsay
Гость
« : 16-01-2009 12:13 » 

Добрый день.
Я сгенерировал  USB драйвер для своего mass storage device при помощи Compuvare Driver Studio. Драйвер собрался, поставился, данные передает - т.е. все хорошо.
Но у меня возникла потребность совершить следующие действия:
 когда приходит IRP_MJ_WRITE перед тем как заслать в устройство буфер данных я должен в первую очередь послать устройству комманду, прочитать статус из устройства а уже потом
отсылать сами данные. Для отправки комманды и чтения данных модифицировал код драйвера по образу и подобию сгенеренного кода.
т.е. отправляю комманду (она устройству доходит), вызывается моя Completetion Routine, проверяет статус, если статус "хороший", из нее запускается функция чтения статуса из устройства. В результате - статус не читается, а сам драйвер зависает так (не реагирует больше на IRP), что необходима перегрузка OS.
Подскажите пожалуйста, в чем может быть проблема? Я понимаю что в ДНК Улыбаюсь Но хотя бы подскажите в какую сторону копать..
Почему комманда уходит, а прочитать статус я немогу? Может быть нельзя производить процедуру чтения в контексте IRP_MJ_WRITE ?

Код:

NTSTATUS TVModulePipe1Io(
    IN  PTVMODULE_DEVICE_EXTENSION DeviceExtension,
    IN  PIRP                                Irp,
    IN  PUSBD_PIPE_INFORMATION              PipeInformation
    )
{
    NTSTATUS                    status;
    ULONG                       totalLength;

status = STATUS_SUCCESS;

    if (Irp->MdlAddress != NULL)
    {
        totalLength = MmGetMdlByteCount(Irp->MdlAddress);
    }
    else
    {
      totalLength = 0;
    }


if (totalLength != 0)
{
// transfer the CBW
status = SendCBW(DeviceExtension, Irp, PipeInformation, totalLength, cmdWrite10);
}

return status;
}

NTSTATUS SendCBWCompletionRoutine(
    IN  PDEVICE_OBJECT DeviceObject,
    IN  PIRP           Irp,
    IN  PVOID          Context
    )

{
PTVMODULE_CBW_IO_CONTEXT IoContext;
    NTSTATUS                 status;

status = Irp->IoStatus.Status;


    if (NT_SUCCESS(status))
    {
IoContext = (PTVMODULE_CBW_IO_CONTEXT)Context;
ReceiveCSW(IoContext->DeviceExtension, IoContext->Irp, IoContext->PipeInformation, IoContext->transferLength);
status = STATUS_MORE_PROCESSING_REQUIRED;
}

    return status;
}

NTSTATUS ReceiveCSWCompletionRoutine(
    IN  PDEVICE_OBJECT DeviceObject,
    IN  PIRP           Irp,
    IN  PVOID          Context
    )

{

PTVMODULE_CSW_IO_CONTEXT IoContext;
    NTSTATUS                 status;

status = Irp->IoStatus.Status;

    TVModuleDebugPrint(DBG_IO, DBG_TRACE, __FUNCTION__"--. IRP %p STATUS %x", Irp, status);


    if (NT_SUCCESS(status))
    {
IoContext = (PTVMODULE_CSW_IO_CONTEXT)Context;
//status = InternalDataWrite(IoContext->DeviceExtension, IoContext->Irp, IoContext->PipeInformation);
Irp->IoStatus.Information = 0x0d;
status = STATUS_SUCCESS;
//return status;
}

    return status;
}


NTSTATUS SendCBW(
    IN  PTVMODULE_DEVICE_EXTENSION DeviceExtension,
    IN PIRP Irp,
    IN PUSBD_PIPE_INFORMATION PipeInformation,
IN ULONG transferLength,
IN UCHAR cbwCommand
)
{
NTSTATUS status = STATUS_SUCCESS;

PURB urb;
    PIO_STACK_LOCATION          irpStack;
PUCHAR buffer;
    PMDL mdl;
PTVMODULE_CBW_IO_CONTEXT IoContext;
 

UCHAR WRITE10[] = {0x55, 0x53, 0x42, 0x43, 0xc8, 0x6f, 0x58, 0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,         
                 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };


IoContext = (PTVMODULE_CBW_IO_CONTEXT)ExAllocatePoolWithTag(
NonPagedPool,
sizeof (TVMODULE_CBW_IO_CONTEXT),
TVMODULE_POOL_TAG
);
IoContext->DeviceExtension = DeviceExtension;
IoContext->Irp = Irp;
IoContext->PipeInformation = PipeInformation;
IoContext->transferLength = transferLength;

buffer = (PUCHAR)ExAllocatePoolWithTag(
NonPagedPool,
31,
TVMODULE_POOL_TAG
);

RtlCopyMemory(buffer, WRITE10, 31);

    mdl = IoAllocateMdl(
buffer,
31,
FALSE,
FALSE,
NULL
);

    MmBuildMdlForNonPagedPool(mdl);


urb = (PURB)ExAllocatePoolWithTag(
   NonPagedPool,
   sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
   TVMODULE_POOL_TAG
           );

    UsbBuildInterruptOrBulkTransferRequest(
            urb,
            sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
            PipeInformation->PipeHandle,
            NULL,
            mdl,
            31,//transferLength,
            USBD_TRANSFER_DIRECTION_OUT,
            NULL
            );

irpStack = IoGetNextIrpStackLocation(Irp);
irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
irpStack->Parameters.Others.Argument1 = urb;
irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;

    IoSetCompletionRoutine(
                Irp,
                SendCBWCompletionRoutine,
                IoContext,
                TRUE,
                TRUE,
                TRUE
                );

IoMarkIrpPending(Irp);

    IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
status = STATUS_PENDING;

return status;
}

NTSTATUS ReceiveCSW(
    IN  PTVMODULE_DEVICE_EXTENSION DeviceExtension,
    IN PIRP Irp,
    IN PUSBD_PIPE_INFORMATION PipeInformation,
IN ULONG transferLength
)
{
PURB urb;
    PIO_STACK_LOCATION          irpStack;
PUCHAR buffer;
    PMDL mdl;
PTVMODULE_CSW_IO_CONTEXT    IoContext;

IoContext = (PTVMODULE_CSW_IO_CONTEXT)ExAllocatePoolWithTag(
NonPagedPool,
sizeof(TVMODULE_CSW_IO_CONTEXT),
TVMODULE_POOL_TAG
);

IoContext->DeviceExtension = DeviceExtension;
IoContext->Irp = Irp;
IoContext->PipeInformation = PipeInformation;

buffer = (PUCHAR)ExAllocatePoolWithTag(
NonPagedPool,
0x0d,
TVMODULE_POOL_TAG
);

    mdl = IoAllocateMdl(
buffer,
0x0d,
FALSE,
FALSE,
NULL
);

    MmBuildMdlForNonPagedPool(mdl);


urb = (PURB)ExAllocatePoolWithTag(
   NonPagedPool,
   sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
   TVMODULE_POOL_TAG
           );

    UsbBuildInterruptOrBulkTransferRequest(
            urb,
            sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
            PipeInformation->PipeHandle,
            NULL,
            mdl,
            0x0d,//transferLength,
            USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
            NULL
            );

irpStack = IoGetNextIrpStackLocation(Irp);
irpStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
irpStack->Parameters.Others.Argument1 = urb;
irpStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;

    IoSetCompletionRoutine(
                Irp,
                ReceiveCSWCompletionRoutine,
                IoContext,
                TRUE,
                TRUE,
                TRUE
                );

    IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);

return STATUS_MORE_PROCESSING_REQUIRED;
}


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

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

« Ответ #1 : 16-01-2009 12:40 » 

сейчас еще код гляну, но кажется дело в том, что когда к вам приходит Completetion - текущий IRQL == DISPATCH_LEVEL.

для таких целей обычно используют Event. перед вызовом IoCallDriver создате событие. сразу после вызова ставите WFSO (WaiteForSingleObject) а в CompletetionRuntime выставляете этот Event.
примеры таких процедур тут много раз приводил) поищите поиском по форуму.

PS сама нумега такие функции должна была сгенерить. называются что то типа SendIrpSynchronously
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
dgritsay
Гость
« Ответ #2 : 16-01-2009 12:44 » 

Спасибо за ответ. Улыбаюсь
Да, я видел такие процедуры... Сейчас попробую.  Но меня терзают смутные сомнения - можно ли в контексте IRP_MJ_WRITE запусать операцию чтения? Не в этом ли собака порылась? Может быть мне нужно формировать IRP_MJ_READ руками?


сейчас еще код гляну, но кажется дело в том, что когда к вам приходит Completetion - текущий IRQL == DISPATCH_LEVEL.

для таких целей обычно используют Event. перед вызовом IoCallDriver создате событие. сразу после вызова ставите WFSO (WaiteForSingleObject) а в CompletetionRuntime выставляете этот Event.
примеры таких процедур тут много раз приводил) поищите поиском по форуму.

PS сама нумега такие функции должна была сгенерить. называются что то типа SendIrpSynchronously
Записан
dgritsay
Гость
« Ответ #3 : 16-01-2009 12:49 » 

Да, и еще - в коде который был сгенерен драйвер студией если из User mode пришел большой буфер с данными, то он режется на части. первая отправляется из TVModulePipe1Io, а остальные как раз из Completetion routine...  И это у них как-то работает. Я же по идее делаю тоже самое...
Записан
Ochkarik
Модератор

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

« Ответ #4 : 16-01-2009 12:50 » 

правильно режется. максимальный размер одной USB транзакции зависит от поддерживаемого устройством и не превышает кажется то ли одного то ли четырех кб
Записан

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

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

« Ответ #5 : 16-01-2009 12:51 » 

подробнее советую посмотреть в Агурове. там неплохо написано и на русском) в нете можно найти)
хм... странно...
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
dgritsay
Гость
« Ответ #6 : 16-01-2009 12:54 » 

Да я ж не против что оно режится.. Улыбаюсь  я знаю, что так надо... мне непонятно, почему у меня не работает чтение статуса из девайса. Девайс точно рабочий - я пытался отправлять и принимать комманды из user mode - все классно.. теперь мне надо делать тоже самое из драйвера и результат: по спине лопатой - на Жаль Жаль Жаль
Записан
Ochkarik
Модератор

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

« Ответ #7 : 16-01-2009 12:57 » new

смотрю... действительно из Completetion перепосылается...
Записан

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

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

« Ответ #8 : 16-01-2009 13:10 » 

непонял... а чего в DDK для UsbBuildInterruptOrBulkTransferRequest
 только USBD_TRANSFER_DIRECTION_IN описан?

и чего то вы ресурсами разбрасываетесь... не освободили MDL, buffer...

так вроде багов не заметно... если только действительно внутри Write - read нельзя делать.
« Последнее редактирование: 16-01-2009 13:18 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
dgritsay
Гость
« Ответ #9 : 16-01-2009 13:23 » 

я знаю про ресурсы - но мне сейчас важно запустить обмен. как только это заработает - я это все подмету.. Улыбаюсь
Я кажется понял где у меня ошибка.. Таки в днк... я ж пытаюсь _прочитать_ данный из пайпа, который предназначен на запись.... совсем заработался... Жаль
сейчас буду проверять.


непонял... а чего в DDK для UsbBuildInterruptOrBulkTransferRequest
 только USBD_TRANSFER_DIRECTION_IN описан?

и чего то вы ресурсами разбрасываетесь... не освободили MDL, buffer...

так вроде багов не заметно... если только действительно внутри Write - read нельзя делать.
Записан
Ochkarik
Модератор

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

« Ответ #10 : 16-01-2009 16:01 » 

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

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
dgritsay
Гость
« Ответ #11 : 16-01-2009 22:29 » 

Да, проблема оказалась именно в этом. Вопрос снимается. Совет таким же новичкам как я - не пытайтесь читать из write пайпа.. это больно. Улыбаюсь
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines