Добрый день.
Я сгенерировал 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;
}