VOID OsrFxEvtIoRead( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t Length ) /*++ Routine Description: Called by the framework when it receives Read or Write requests. Arguments: Queue - Default queue handle Request - Handle to the read/write request Lenght - Length of the data buffer associated with the request. The default property of the queue is to not dispatch zero lenght read & write requests to the driver and complete is with status success. So we will never get a zero length request. Return Value: --*/ { WDFUSBPIPE pipe; NTSTATUS status; WDFMEMORY reqMemory; PDEVICE_CONTEXT pDeviceContext; GUID activity = RequestToActivityId(Request); UNREFERENCED_PARAMETER(Queue); // // Log read start event, using IRP activity ID if available or request // handle otherwise. // EventWriteReadStart(&activity, WdfIoQueueGetDevice(Queue), (ULONG)Length); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "-->OsrFxEvtIoRead\n"); // // First validate input parameters. // if (Length > TEST_BOARD_TRANSFER_BUFFER_SIZE) { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "Transfer exceeds %d\n", TEST_BOARD_TRANSFER_BUFFER_SIZE); status = STATUS_INVALID_PARAMETER; goto Exit; } pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); pipe = pDeviceContext->BulkReadPipe; status = WdfRequestRetrieveOutputMemory(Request, &reqMemory); if(!NT_SUCCESS(status)){ TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestRetrieveOutputMemory failed %!STATUS!\n", status); goto Exit; } // // The format call validates to make sure that you are reading or // writing to the right pipe type, sets the appropriate transfer flags, // creates an URB and initializes the request. // status = WdfUsbTargetPipeFormatRequestForRead(pipe, Request, reqMemory, NULL // Offsets ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfUsbTargetPipeFormatRequestForRead failed 0x%x\n", status); goto Exit; } WdfRequestSetCompletionRoutine( Request, EvtRequestReadCompletionRoutine, pipe); // // Send the request asynchronously. // if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS) == FALSE) { // // Framework couldn't send the request for some reason. // TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestSend failed\n"); status = WdfRequestGetStatus(Request); goto Exit; } Exit: if (!NT_SUCCESS(status)) { // // log event read failed // EventWriteReadFail(&activity, WdfIoQueueGetDevice(Queue), status); WdfRequestCompleteWithInformation(Request, status, 0); } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ, "<-- OsrFxEvtIoRead\n"); return; }
VOID OsrFxEvtIoWrite( __in WDFQUEUE Queue, __in WDFREQUEST Request, __in size_t Length ) /*++ Routine Description: Called by the framework when it receives Read or Write requests. Arguments: Queue - Default queue handle Request - Handle to the read/write request Lenght - Length of the data buffer associated with the request. The default property of the queue is to not dispatch zero lenght read & write requests to the driver and complete is with status success. So we will never get a zero length request. Return Value: --*/ { NTSTATUS status; WDFUSBPIPE pipe; WDFMEMORY reqMemory; PDEVICE_CONTEXT pDeviceContext; GUID activity = RequestToActivityId(Request); UNREFERENCED_PARAMETER(Queue); // // Log write start event, using request as activity id. // EventWriteReadStart(&activity, WdfIoQueueGetDevice(Queue), (ULONG)Length); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "-->OsrFxEvtIoWrite\n"); // // First validate input parameters. // if (Length > TEST_BOARD_TRANSFER_BUFFER_SIZE) { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "Transfer exceeds %d\n", TEST_BOARD_TRANSFER_BUFFER_SIZE); status = STATUS_INVALID_PARAMETER; goto Exit; } pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); pipe = pDeviceContext->BulkWritePipe; status = WdfRequestRetrieveInputMemory(Request, &reqMemory); if(!NT_SUCCESS(status)){ TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "WdfRequestRetrieveInputBuffer failed\n"); goto Exit; } status = WdfUsbTargetPipeFormatRequestForWrite(pipe, Request, reqMemory, NULL); // Offset if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "WdfUsbTargetPipeFormatRequest failed 0x%x\n", status); goto Exit; } WdfRequestSetCompletionRoutine( Request, EvtRequestWriteCompletionRoutine, pipe); // // Send the request asynchronously. // if (WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS) == FALSE) { // // Framework couldn't send the request for some reason. // TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "WdfRequestSend failed\n"); status = WdfRequestGetStatus(Request); goto Exit; } Exit: if (!NT_SUCCESS(status)) { // // log event write failed // EventWriteWriteFail(&activity, WdfIoQueueGetDevice(Queue), status); WdfRequestCompleteWithInformation(Request, status, 0); } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- OsrFxEvtIoWrite\n"); return; }
VOID EvtRequestWriteCompletionRoutine( _In_ WDFREQUEST Request, _In_ WDFIOTARGET Target, _In_ PWDF_REQUEST_COMPLETION_PARAMS CompletionParams, _In_ WDFCONTEXT Context ) /*++ Routine Description: This is the completion routine for reads/writes If the irp completes with success, we check if we need to recirculate this irp for another stage of transfer. Arguments: Context - Driver supplied context Device - Device handle Request - Request handle Params - request completion params Return Value: None --*/ { NTSTATUS status; size_t bytesWritten = 0; GUID activity = RequestToActivityId(Request); PWDF_USB_REQUEST_COMPLETION_PARAMS usbCompletionParams; UNREFERENCED_PARAMETER(Target); UNREFERENCED_PARAMETER(Context); status = CompletionParams->IoStatus.Status; // // For usb devices, we should look at the Usb.Completion param. // usbCompletionParams = CompletionParams->Parameters.Usb.Completion; bytesWritten = usbCompletionParams->Parameters.PipeWrite.Length; if (NT_SUCCESS(status)){ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE, "Number of bytes written: %I64d\n", (INT64)bytesWritten); } else { TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "Write failed: request Status 0x%x UsbdStatus 0x%x\n", status, usbCompletionParams->UsbdStatus); } // // Log write stop event, using IRP activtiy ID if available or request // handle otherwise // EventWriteWriteStop(&activity, WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)), bytesWritten, status, usbCompletionParams->UsbdStatus); WdfRequestCompleteWithInformation(Request, status, bytesWritten); return; }
VOID EvtRequestReadCompletionRoutine( __in WDFREQUEST Request, __in WDFIOTARGET Target, __in PWDF_REQUEST_COMPLETION_PARAMS CompletionParams, __in WDFCONTEXT Context ) /*++ Routine Description: This is the completion routine for reads/writes If the irp completes with success, we check if we need to recirculate this irp for another stage of transfer. Arguments: Context - Driver supplied context Device - Device handle Request - Request handle Params - request completion params Return Value: None --*/ { NTSTATUS status; size_t bytesRead = 0; GUID activity = RequestToActivityId(Request); PWDF_USB_REQUEST_COMPLETION_PARAMS usbCompletionParams; UNREFERENCED_PARAMETER(Target); UNREFERENCED_PARAMETER(Context); status = CompletionParams->IoStatus.Status; usbCompletionParams = CompletionParams->Parameters.Usb.Completion; bytesRead = usbCompletionParams->Parameters.PipeRead.Length; if (NT_SUCCESS(status)){ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_READ, "Number of bytes read: %I64d\n", (INT64)bytesRead); } else { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "Read failed - request status 0x%x UsbdStatus 0x%x\n", status, usbCompletionParams->UsbdStatus); } // // Log read stop event, using request as activity id // EventWriteReadStop(&activity, WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)), bytesRead, status, usbCompletionParams->UsbdStatus); WdfRequestCompleteWithInformation(Request, status, bytesRead); return; }