Здравствуйте!
Пишу 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;
}