VOID RamDiskEvtIoWrite( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) /*++ Routine Description: This event is invoked when the framework receives IRP_MJ_WRITE request. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. Length - Length of the data buffer associated with the request. The default property of the queue is to not dispatch zero length read & write requests to the driver and complete is with status success. So we will never get a zero length request. Return Value: VOID --*/ { PDEVICE_EXTENSION devExt = QueueGetExtension(Queue)->DeviceExtension; NTSTATUS Status = STATUS_INVALID_PARAMETER; WDF_REQUEST_PARAMETERS Parameters; LARGE_INTEGER ByteOffset; WDFMEMORY hMemory; _Analysis_assume_(Length > 0); WDF_REQUEST_PARAMETERS_INIT(&Parameters); WdfRequestGetParameters(Request, &Parameters); ByteOffset.QuadPart = Parameters.Parameters.Write.DeviceOffset; if (RamDiskCheckParameters(devExt, ByteOffset, Length)) { Status = WdfRequestRetrieveInputMemory(Request, &hMemory); if(NT_SUCCESS(Status)){ Status = WdfMemoryCopyToBuffer(hMemory, // Source 0, // offset in Source memory where the copy has to start devExt->DiskImage + ByteOffset.LowPart, // destination Length); } } WdfRequestCompleteWithInformation(Request, Status, (ULONG_PTR)Length); }
NTSTATUS DeviceContext::CommandNciRead( _In_ WDFREQUEST Request ) { TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); NTSTATUS status; WDFMEMORY nciPacket; status = WdfRequestRetrieveInputMemory(Request, &nciPacket); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "WdfRequestRetrieveInputMemory failed. %!STATUS!", status); return status; } status = NfcCxNciReadNotification(_Device, nciPacket); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "NfcCxNciReadNotification failed. %!STATUS!", status); return status; } WdfRequestComplete(Request, STATUS_SUCCESS); TRACE_FUNCTION_SUCCESS(LEVEL_VERBOSE); return STATUS_SUCCESS; }
// 写操作 VOID RamDiskEvtIoWrite(IN WDFQUEUE Queue,IN WDFREQUEST Request,IN size_t Length) { PDEVICE_EXTENSION devExt = QueueGetExtension(Queue)->DeviceExtension; //从队列对象获得设备扩展 NTSTATUS Status = STATUS_INVALID_PARAMETER; WDF_REQUEST_PARAMETERS Parameters; LARGE_INTEGER ByteOffset; WDFMEMORY hMemory; //__analysis_assume(Length > 0); //参数清0 WDF_REQUEST_PARAMETERS_INIT(&Parameters); //从请求中获取信息 WdfRequestGetParameters(Request, &Parameters); //写入偏移 ByteOffset.QuadPart = Parameters.Parameters.Write.DeviceOffset; //检测写入是否合法 if (RamDiskCheckParameters(devExt, ByteOffset, Length)) { // from output to input Status = WdfRequestRetrieveInputMemory(Request, &hMemory); //获得内存状态 if(NT_SUCCESS(Status)) { // Source # offset in Source memory where the copy has to start # destination Status = WdfMemoryCopyToBuffer(hMemory, 0,devExt->DiskImage + ByteOffset.LowPart, Length); // from "from" to "to" } } WdfRequestCompleteWithInformation(Request, Status, (ULONG_PTR)Length); }
NTSTATUS GetTransferMemory(__in WDFREQUEST Request, __in WDF_REQUEST_TYPE RequestType, __out WDFMEMORY* wdfMemory) { return (RequestType == WdfRequestTypeWrite) ? WdfRequestRetrieveInputMemory(Request, wdfMemory) : WdfRequestRetrieveOutputMemory(Request, wdfMemory); }
// Bulk管道写操作 // VOID BulkWrite(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length) { NTSTATUS status = STATUS_SUCCESS; WDFMEMORY hMem = NULL; WDFDEVICE hDevice = NULL; WDFUSBPIPE BulkOutputPipe = NULL; UCHAR* lpBuf; UNREFERENCED_PARAMETER(Length); KDBG(DPFLTR_INFO_LEVEL, "[BulkWrite] size: %d", Length); // 获取管道句柄 hDevice = WdfIoQueueGetDevice(Queue); BulkOutputPipe = GetBulkPipe(FALSE, hDevice); if(NULL == BulkOutputPipe) { KDBG(DPFLTR_ERROR_LEVEL, "BulkOutputPipe = NULL"); WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); return; } status = WdfRequestRetrieveInputMemory(Request, &hMem); if(!NT_SUCCESS(status)) { KDBG(DPFLTR_ERROR_LEVEL, "WdfRequestRetrieveInputMemory failed(status = 0x%0.8x)!!!", status); WdfRequestComplete(Request, status); return; } // 打印出offset值。 // 在写缓冲的前两个字节中存有write offset的值 lpBuf = (UCHAR*)WdfMemoryGetBuffer(hMem, 0); KDBG(DPFLTR_TRACE_LEVEL, "write offset: %hd", *(WORD*)lpBuf); // 把当前的Request对象进行重利用,发送给USB总线。 // 格式化Request对象,设置Pipe句柄、完成函数等。 status = WdfUsbTargetPipeFormatRequestForWrite(BulkOutputPipe, Request, hMem, NULL); if(!NT_SUCCESS(status)) { KDBG(DPFLTR_ERROR_LEVEL, "WdfUsbTargetPipeFormatRequestForWrite(status 0x%0.8x)!!!", status); WdfRequestComplete(Request, status); return; } WdfRequestSetCompletionRoutine(Request, BulkWriteComplete, BulkOutputPipe); if(FALSE == WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(BulkOutputPipe), NULL)) { status = WdfRequestGetStatus(Request); KDBG(DPFLTR_ERROR_LEVEL, "WdfRequestSend failed with status 0x%0.8x\n", status); WdfRequestComplete(Request, status); } }
VOID EvtIoWrite( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) { NTSTATUS status; WDFUSBPIPE pipe; WDFMEMORY reqMemory; PDEVICE_CONTEXT pDeviceContext; BOOLEAN ret; UNREFERENCED_PARAMETER(Length); pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); pipe = pDeviceContext->BulkWritePipe; status = WdfRequestRetrieveInputMemory(Request, &reqMemory); if(!NT_SUCCESS(status)){ goto Exit; } status = WdfUsbTargetPipeFormatRequestForWrite(pipe, Request, reqMemory, NULL); // Offset if (!NT_SUCCESS(status)) { goto Exit; } WdfRequestSetCompletionRoutine( Request, EvtRequestWriteCompletionRoutine, pipe); ret = WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS); if (ret == FALSE) { status = WdfRequestGetStatus(Request); goto Exit; } else { return; } Exit: WdfRequestCompleteWithInformation(Request, status, 0); return; }
VOID EvtIoWrite( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) { WDFMEMORY memory; NTSTATUS status; PMY_SERIAL_DEVICE_EXTENSION pContext; PUCHAR buffer; size_t buf_size; size_t i = 0; KdPrint((DRIVER_NAME "-->EvtIoWrite\n")); pContext = MySerialGetDeviceExtension(WdfIoQueueGetDevice(Queue)); status = WdfRequestRetrieveInputMemory(Request, &memory); if(!NT_SUCCESS(status)) { KdPrint((DRIVER_NAME "EvtIoWrite Could not get request memory buffer 0x%x\n", status)); WdfRequestComplete(Request, status); KdPrint((DRIVER_NAME "<-- EvtDeviceIoWrite\n")); return; } buffer = WdfMemoryGetBuffer(memory, &buf_size); KdPrint((DRIVER_NAME "Sending a buffer of %d bytes\n", buf_size)); while (i < buf_size) { while (UartGetBit(pContext, LSR, LSR_ETHR) == 0 ) {} UartWriteByte(pContext, buffer[i]); i++; } WdfRequestCompleteWithInformation(Request, status, i); KdPrint((DRIVER_NAME "<--EvtIoWrite\n")); }
VOID tgwinkEvtIoWrite( WDFQUEUE Queue, WDFREQUEST Request, size_t Length ) { NTSTATUS status; WDFMEMORY mem; WDF_REQUEST_PARAMETERS params; ULONG offset; ULONG result; PDEVICE_CONTEXT context; WDFDEVICE device; device = WdfIoQueueGetDevice(Queue); context = DeviceGetContext(device); WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters(Request, ¶ms); offset = (ULONG)params.Parameters.Write.DeviceOffset; status = WdfRequestRetrieveInputMemory(Request, &mem); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoRead could not get request memory buffer, status 0x%x\n", status); WdfVerifierDbgBreakPoint(); WdfRequestCompleteWithInformation(Request, status, 0); return; } result = context->busInterface.SetBusData(context->busInterface.Context, PCI_WHICHSPACE_CONFIG, WdfMemoryGetBuffer(mem, NULL), offset, (ULONG)Length); WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, (ULONG_PTR)result); }
/*++ Routine Description: This event is called when the framework receives IRP_MJ_DEVICE_CONTROL requests from the system. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. OutputBufferLength - length of the request's output buffer, if an output buffer is available. InputBufferLength - length of the request's input buffer, if an input buffer is available. IoControlCode - the driver-defined or system-defined I/O control code (IOCTL) that is associated with the request. Return Value: VOID --*/ VOID PSDrv_EvtIoDeviceControl(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode) { WDFDEVICE device; PVOID ioBuffer; size_t bufLength; NTSTATUS status; PDEVICE_CONTEXT pDevContext; PFILE_CONTEXT pFileContext; ULONG length = 0; PSUSBDRV_PIPE_PROPERTY* pPipeProp; PSUSBDRV_CONTROL_TRANSFER* pControlTransfer; PSUSBDRV_DRIVER_VERSION* pDriverVersion; PSUSBDRV_INTERFACE_PROPERTY* pInterfaceProperty; unsigned int* pnDeviceSpeed; WDFMEMORY WdfMem = NULL; PUCHAR pControlBuffer; WDFMEMORY WdfMemOut = NULL; WDF_USB_INTERFACE_SELECT_SETTING_PARAMS selectSettingParams; UNREFERENCED_PARAMETER(InputBufferLength); PSDrv_DbgPrint(3, ("PSDrv_EvtIoDeviceControl - begins\n")); PAGED_CODE(); // initialize variables device = WdfIoQueueGetDevice(Queue); pDevContext = GetDeviceContext(device); switch(IoControlCode) { case IOCTL_PSDRV_RESET_PIPE: PSDrv_DbgPrint(3, ("IOControl: ResetPipe\n")); pFileContext = GetFileContext(WdfRequestGetFileObject(Request)); if (pFileContext->Pipe == NULL) { PSDrv_DbgPrint(3, ("Invalid pipe!\n")); status = STATUS_INVALID_PARAMETER; } else { status = ResetPipe(pFileContext->Pipe); } break; case IOCTL_PSDRV_ABORT_PIPE: PSDrv_DbgPrint(3, ("IOControl: AbortPipe\n")); pFileContext = GetFileContext(WdfRequestGetFileObject(Request)); if (pFileContext->Pipe == NULL) { PSDrv_DbgPrint(3, ("Invalid pipe!\n")); status = STATUS_INVALID_PARAMETER; } else { status = AbortPipe(pFileContext->Pipe); } break; case IOCTL_PSDRV_GET_CONFIG_DESCRIPTOR: PSDrv_DbgPrint(3, ("IOControl: GetConfigDescriptor\n")); if (pDevContext->UsbConfigurationDescriptor) { length = pDevContext->UsbConfigurationDescriptor->wTotalLength; status = WdfRequestRetrieveOutputBuffer(Request, length, &ioBuffer, &bufLength); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } RtlCopyMemory(ioBuffer, pDevContext->UsbConfigurationDescriptor, length); status = STATUS_SUCCESS; } else { PSDrv_DbgPrint(3, ("UsbConfigurationDescriptor is NULL!\n")); status = STATUS_INVALID_DEVICE_STATE; } break; case IOCTL_PSDRV_RESET_DEVICE: PSDrv_DbgPrint(3, ("IOControl: ResetDevice\n")); status = ResetDevice(device); break; case IOCTL_PSDRV_CONTROL_TRANSFER: PSDrv_DbgPrint(3, ("IOControl: ControlTransfer\n")); //Get a pointer to the input buffer status = WdfRequestRetrieveInputMemory(Request, &WdfMem); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputMemory failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (WdfMem == NULL) { PSDrv_DbgPrint(1, ("WdfMem is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pControlTransfer = WdfMemoryGetBuffer(WdfMem, NULL); if (pControlTransfer == NULL) { PSDrv_DbgPrint(1, ("pControlTransfer is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } //Get a pointer to the output buffer if (OutputBufferLength != 0) { status = WdfRequestRetrieveOutputMemory(Request, &WdfMemOut); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputMemory failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (WdfMemOut == NULL) { PSDrv_DbgPrint(1, ("WdfMemOut is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pControlBuffer = WdfMemoryGetBuffer(WdfMemOut, NULL); if (pControlBuffer == NULL) { PSDrv_DbgPrint(1, ("pControlBuffer is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } } else { PSDrv_DbgPrint(1, ("This control request has no buffer...\n")); pControlBuffer = NULL; } // Call the control transfer function status = ControlTransfer(pDevContext, pControlTransfer, pControlBuffer, OutputBufferLength, &length); break; case IOCTL_PSDRV_SET_PIPE_PROPERTY: PSDrv_DbgPrint(3, ("IOControl: SetPipeProperty\n")); status = WdfRequestRetrieveInputMemory(Request, &WdfMem); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputMemory failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (WdfMem == NULL) { PSDrv_DbgPrint(1, ("WdfMem is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pPipeProp = WdfMemoryGetBuffer(WdfMem, NULL); if (pPipeProp == NULL) { PSDrv_DbgPrint(1, ("pPipeProp is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pFileContext = GetFileContext(WdfRequestGetFileObject(Request)); if (pFileContext->Pipe == NULL) { PSDrv_DbgPrint(3, ("Invalid pipe!\n")); status = STATUS_INVALID_PARAMETER; } else { status = SetPipeProperty(pFileContext, pPipeProp); } break; case IOCTL_PSDRV_SET_INTERFACE: PSDrv_DbgPrint(3, ("IOControl: SetInterface\n")); status = WdfRequestRetrieveInputMemory(Request, &WdfMem); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveInputMemory failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (WdfMem == NULL) { PSDrv_DbgPrint(1, ("WdfMem is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } pInterfaceProperty = WdfMemoryGetBuffer(WdfMem, NULL); if (pInterfaceProperty == NULL) { PSDrv_DbgPrint(1, ("pInterfaceProperty is NULL!\n")); status = STATUS_INVALID_PARAMETER; break; } PSDrv_DbgPrint(3, ("SetInterface: Going to change AltIF to %d...\n", pInterfaceProperty->nAltIF)); WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING(&selectSettingParams, pInterfaceProperty->nAltIF); status = WdfUsbInterfaceSelectSetting(pDevContext->UsbInterface, WDF_NO_OBJECT_ATTRIBUTES, &selectSettingParams); if (status == STATUS_SUCCESS) { pDevContext->nCurrIf = 0; pDevContext->nCurrAltIf = pInterfaceProperty->nAltIF; PSDrv_DbgPrint(3, ("SetInterface: AltIF is now %d...\n", pInterfaceProperty->nAltIF)); } break; case IOCTL_PSDRV_GET_INTERFACE: PSDrv_DbgPrint(3, ("IOControl: GetInterface\n")); length = sizeof(PSUSBDRV_INTERFACE_PROPERTY); status = WdfRequestRetrieveOutputBuffer(Request, length, &pInterfaceProperty, &bufLength); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } pInterfaceProperty->nIF = pDevContext->nCurrIf; pInterfaceProperty->nAltIF = pDevContext->nCurrAltIf; status = STATUS_SUCCESS; break; case IOCTL_PSDRV_GET_DRIVER_VERSION: PSDrv_DbgPrint(3, ("IOControl: GetDriverVersion\n")); length = sizeof(PSUSBDRV_DRIVER_VERSION); status = WdfRequestRetrieveOutputBuffer(Request, length, &pDriverVersion, &bufLength); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } pDriverVersion->nMajor = PSUSBDRV_MAJOR_VERSION; pDriverVersion->nMinor = PSUSBDRV_MINOR_VERSION; pDriverVersion->nMaintenance = PSUSBDRV_MAINTENANCE_VERSION; pDriverVersion->nBuild = PSUSBDRV_BUILD_VERSION; status = STATUS_SUCCESS; break; case IOCTL_PSDRV_GET_DEVICE_SPEED: PSDrv_DbgPrint(3, ("IOControl: GetDeviceSpeed\n")); length = sizeof(unsigned int); status = WdfRequestRetrieveOutputBuffer(Request, length, &pnDeviceSpeed, &bufLength); if(!NT_SUCCESS(status)) { PSDrv_DbgPrint(1, ("WdfRequestRetrieveOutputBuffer failed! (Status = %x)\n", status)); status = STATUS_INVALID_PARAMETER; break; } if (pDevContext->IsDeviceHighSpeed == TRUE) { *pnDeviceSpeed = PSUSBDRV_DEVICE_HIGH_SPEED; } else { *pnDeviceSpeed = PSUSBDRV_DEVICE_FULL_SPEED; } break; default: PSDrv_DbgPrint(3, ("Unknown IOControl! (ControlCode = %x)\n", IoControlCode)); status = STATUS_INVALID_DEVICE_REQUEST; break; } WdfRequestCompleteWithInformation(Request, status, length); PSDrv_DbgPrint(3, ("PSDrv_EvtIoDeviceControl - ends\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 IRP activity ID if available or request // handle otherwise. // EventWriteWriteStart(&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; }
/////////////////////////////////////////////////////////////////////////////// // // BasicUsbEvtDeviceControl // // This routine is called by the framework when there is a // device control request for us to process // // INPUTS: // // Queue - Our default queue // // Request - A device control request // // OutputBufferLength - The length of the output buffer // // InputBufferLength - The length of the input buffer // // IoControlCode - The operation being performed // // OUTPUTS: // // None. // // RETURNS: // // None. // // IRQL: // // This routine is called at IRQL == PASSIVE_LEVEL, due to // our PASSIVE_LEVEL execution level contraint // // NOTES: // // /////////////////////////////////////////////////////////////////////////////// VOID BasicUsbEvtDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode) { NTSTATUS status; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; WDFMEMORY inputMemory; WDF_MEMORY_DESCRIPTOR inputMemoryDescriptor; PBASICUSB_DEVICE_CONTEXT devContext; #if DBG DbgPrint("BasicUsbEvtDeviceControl\n"); #endif devContext = BasicUsbGetContextFromDevice( WdfIoQueueGetDevice(Queue) ); switch (IoControlCode) { case IOCTL_OSR_BASICUSB_SET_BAR_GRAPH: { // // Validate the buffers for this request: // // OutputBufferLength - Must be zero // if (OutputBufferLength != 0) { #if DBG DbgPrint("Invalid parameter - output buffer supplied in "\ "SET_BAR_GRAPH IOCTL (%u bytes)\n", (ULONG)OutputBufferLength); #endif WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); return; } // // InputBufferLength - Must be at least 1 byte // if (InputBufferLength == 0) { #if DBG DbgPrint("No input buffer supplied in SET_BAR_GRAPH IOCTL\n"); #endif WdfRequestCompleteWithInformation(Request, STATUS_BUFFER_TOO_SMALL, sizeof(UCHAR)); return; } // // We need the input memory from the request so that we can pass // it to the bus driver. // status = WdfRequestRetrieveInputMemory(Request, &inputMemory); if (!NT_SUCCESS(status)) { #if DBG DbgPrint("WdfRequestRetrieveInputMemory failed 0x%0x\n", status); #endif WdfRequestComplete(Request, status); return; } // // The routine we want to call takes a memory descriptor, so // initialize that now with the handle to the user memory. // WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&inputMemoryDescriptor, inputMemory, NULL); // // Initialize the vendor command (defined by the device) that // allows us to light the bar graph. // WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR( &controlSetupPacket, BmRequestHostToDevice, BmRequestToDevice, USBFX2LK_SET_BARGRAPH_DISPLAY, 0, 0); // // And send the vendor command as a control transfer. This // shouldn't take very long, so we'll just send it synchronously // to the device. // // // We've specified an execution level restraint of // PASSIVE_LEVEL, so we're allowed to send this request // synchronously. // ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); status = WdfUsbTargetDeviceSendControlTransferSynchronously( devContext->BasicUsbUsbDevice, WDF_NO_HANDLE, NULL, &controlSetupPacket, &inputMemoryDescriptor, NULL); if (NT_SUCCESS(status)) { // // If the request succeeded, complete the request with success // and indicate to the user how much data was transferred (in // this case a single byte was sent to the device) // WdfRequestCompleteWithInformation(Request, status, sizeof(UCHAR)); } else { // // Bad news! Just complete the request with the failure status. // #if DBG DbgPrint("WdfUsbTargetDeviceSendControlTransferSynchronously "\ "failed 0x%0x\n", status); #endif WdfRequestComplete(Request, status); } return; } case IOCTL_OSR_BASICUSB_GET_SWITCHPACK_STATE: { // // Validate the buffers for this request: // // InputBufferLength - Must be zero // if (InputBufferLength != 0) { #if DBG DbgPrint("Invalid parameter - input buffer supplied in "\ "SWITCHPACK_STATE_CHANGE_NOTIFY IOCTL (%u bytes)\n", (ULONG)InputBufferLength); #endif WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); return; } // // OutputBufferLength - Must be at least 1 byte // if (OutputBufferLength == 0) { #if DBG DbgPrint("No input buffer supplied in "\ "SWITCHPACK_STATE_CHANGE_NOTIFY IOCTL\n"); #endif WdfRequestCompleteWithInformation(Request, STATUS_BUFFER_TOO_SMALL, sizeof(UCHAR)); return; } // // Forward the request to our switchpack state change requests // queue // status = WdfRequestForwardToIoQueue( Request, devContext->SwitchPackStateChangeQueue); if (!NT_SUCCESS(status)) { // // Bad news! Print out the status and fail the request. // #if DBG DbgPrint("WdfRequestForwardToIoQueue failed with Status "\ "code 0x%x", status); #endif WdfRequestComplete(Request, status); return; } return; } default: { #if DBG DbgPrint("Unknown IOCTL: 0x%x\n", IoControlCode); #endif WdfRequestCompleteWithInformation(Request, STATUS_INVALID_DEVICE_REQUEST, 0); return; } } return; }
/////////////////////////////////////////////////////////////////////////////// // // BasicUsbEvtWrite // // This routine is called by the framework when there is a // write request for us to process // // INPUTS: // // Queue - Our default queue // // Request - A write request // // Length - The length of the write operation // // OUTPUTS: // // None. // // RETURNS: // // None. // // IRQL: // // This routine is called at IRQL == PASSIVE_LEVEL, due to // our PASSIVE_LEVEL execution level contraint // // NOTES: // // /////////////////////////////////////////////////////////////////////////////// VOID BasicUsbEvtWrite(WDFQUEUE Queue, WDFREQUEST Request, size_t Length) { PBASICUSB_DEVICE_CONTEXT devContext; WDFMEMORY requestMemory; NTSTATUS status; WDF_REQUEST_PARAMETERS requestParams; WDF_REQUEST_SEND_OPTIONS sendOptions; UNREFERENCED_PARAMETER(Length); #if DBG DbgPrint("BasicUsbEvtWrite\n"); #endif devContext = BasicUsbGetContextFromDevice( WdfIoQueueGetDevice(Queue) ); // // The purpose of this routine will be to convert the write // that we received from the user into a USB request and send // it to the underlying bus driver. // // // First thing to do is get the input memory associated with the // request (only because it's a required parameter to // WdfUsbTargetPipeFormatRequestForWrite) // status = WdfRequestRetrieveInputMemory(Request, &requestMemory); if(!NT_SUCCESS(status)){ #if DBG DbgPrint("WdfRequestRetrieveInputMemory failed 0x%0x\n", status); #endif WdfRequestComplete(Request, status); return; } // // Take the user Write request and format it into a Bulk OUT // request. // status = WdfUsbTargetPipeFormatRequestForWrite(devContext->BulkOutPipe, Request, requestMemory, NULL); if(!NT_SUCCESS(status)){ #if DBG DbgPrint("WdfUsbTargetPipeFormatRequestForWrite failed 0x%0x\n", status); #endif WdfRequestComplete(Request, status); return; } // // We'd like to asynchronously send this newly formatted request // to the underlying bus driver. In order to do that, we *must* // supply a completion routine that calls WdfRequestComplete. // Failure to do so is not architecturally defined, which means // it ain't gonna work. // // Note that because we have modified the request, we are not // allowed to use the WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET // flag as a cheap shortcut, we MUST supply the completion // routine. // WdfRequestSetCompletionRoutine(Request, BasicUsbEvtRequestWriteCompletionRoutine, NULL); // // Send the request! // if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(devContext->BulkOutPipe), NULL)) { // // Bad news. The target didn't get the request, so get the // failure status and complete the request ourselves.. // status = WdfRequestGetStatus(Request); #if DBG DbgPrint("WdfRequestSend failed 0x%0x\n", status); #endif WdfRequestComplete(Request, status); return; } return; }
VOID MonitorEvtDeviceControl ( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode ) /*++ Handles device IO control requests. This callback drives all communication between the usermode exe and this driver. --*/ { NTSTATUS status = STATUS_SUCCESS; UNREFERENCED_PARAMETER(Queue); UNREFERENCED_PARAMETER(OutputBufferLength); DoTraceMessage(TRACE_DEVICE_CONTROL, "MonitorSample Dispatch Device Control: 0x%x", IoControlCode); switch (IoControlCode) { case MONITOR_IOCTL_ENABLE_MONITOR: { WDFMEMORY pMemory; void* pBuffer; if (InputBufferLength < sizeof(MONITOR_SETTINGS)) { status = STATUS_INVALID_PARAMETER; } else { status = WdfRequestRetrieveInputMemory(Request, &pMemory); if (NT_SUCCESS(status)) { pBuffer = WdfMemoryGetBuffer(pMemory, NULL); status = MonitorCoEnableMonitoring((MONITOR_SETTINGS*) pBuffer); } } break; } case MONITOR_IOCTL_DISABLE_MONITOR: { status = STATUS_SUCCESS; MonitorCoDisableMonitoring(); break; } default: { status = STATUS_INVALID_PARAMETER; } } WdfRequestComplete(Request, status); }
VOID XferCtrl ( __in WDFQUEUE Queue, __in WDFREQUEST Request, __in size_t InputBufferLength, __in size_t OutputBufferLength) { NTSTATUS status; PDEVICE_CONTEXT deviceContext; PREQUEST_CONTEXT requestContext; WDFMEMORY transferMemory; PWDF_USB_CONTROL_SETUP_PACKET setupPacket; WDF_REQUEST_SEND_OPTIONS sendOptions; WDFMEMORY_OFFSET _transferOffset; PWDFMEMORY_OFFSET transferOffset = &_transferOffset; UNREFERENCED_PARAMETER(InputBufferLength); UNREFERENCED_PARAMETER(OutputBufferLength); deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); requestContext = GetRequestContext(Request); setupPacket = (PWDF_USB_CONTROL_SETUP_PACKET)&requestContext->IoControlRequest.control; USBDBG("bmDir=%s bmType=%s bmRecipient=%s bmReserved=%03u bRequest=%u wIndex=%u wValue=%u wLength=%u\n", GetBmRequestDirString(setupPacket->Packet.bm.Request.Dir), GetBmRequestTypeString(setupPacket->Packet.bm.Request.Type), GetBmRequestRecipientString(setupPacket->Packet.bm.Request.Recipient), setupPacket->Packet.bm.Request.Reserved, setupPacket->Packet.bRequest, setupPacket->Packet.wIndex.Value, setupPacket->Packet.wValue.Value, setupPacket->Packet.wLength); // If the device and config descriptor requests are not handled they will be the "true" // descriptors directly from the device. i.e. if the device has two unassociated interfaces // the composite layer will split it into two but each virtual device interface would show // both interface deacriptors. // if (setupPacket->Packet.bm.Request.Dir == BMREQUEST_DEVICE_TO_HOST && setupPacket->Packet.bm.Request.Type == BMREQUEST_STANDARD && setupPacket->Packet.bRequest == USB_REQUEST_GET_DESCRIPTOR) { UCHAR descriptorType = setupPacket->Packet.wValue.Bytes.HiByte; // UCHAR descriptorIndex = setupPacket->Packet.wValue.Bytes.LowByte; ULONG descriptorSize = 0; PVOID descriptorIn = NULL; PVOID outputBuffer = NULL; size_t outputBufferLength = 0; if (requestContext->IoControlCode == LIBUSB_IOCTL_GET_DESCRIPTOR) { switch(descriptorType) { case USB_DESCRIPTOR_TYPE_DEVICE: descriptorSize = sizeof(deviceContext->UsbDeviceDescriptor); descriptorIn = &deviceContext->UsbDeviceDescriptor; break; case USB_DESCRIPTOR_TYPE_CONFIGURATION: if (setupPacket->Packet.wValue.Bytes.LowByte == 0) { descriptorSize = deviceContext->ConfigurationDescriptorSize; descriptorIn = deviceContext->UsbConfigurationDescriptor; } else { // we only support the one for now. ;) WdfRequestCompleteWithInformation(Request, STATUS_NO_MORE_ENTRIES, 0); return; } break; } if (descriptorIn && descriptorSize) { // handle (or fail) this standard request here. status = WdfRequestRetrieveOutputBuffer(Request, 2, &outputBuffer, &outputBufferLength); if (NT_SUCCESS(status)) { descriptorSize = (ULONG)min(descriptorSize, outputBufferLength); RtlCopyMemory(outputBuffer, descriptorIn, descriptorSize); WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, descriptorSize); return; } USBERR("WdfRequestRetrieveOutputBuffer failed. status=%Xh\n", status); WdfRequestCompleteWithInformation(Request, status, 0); return; } } } if (METHOD_FROM_CTL_CODE(requestContext->IoControlCode) == METHOD_BUFFERED && requestContext->RequestType == WdfRequestTypeWrite) { // support for some of the legacy LIBUSB_IOCTL codes which place the data input // buffer at the end of the libusb_request structure. status = WdfRequestRetrieveInputMemory(Request, &transferMemory); if (!NT_SUCCESS(status)) { USBERR("WdfRequestRetrieveInputMemory failed. status=%Xh\n", status); goto Exit; } if (requestContext->Length < sizeof(libusb_request)) { // this can never happen because the input buffer length is checked for // this by the default IoControl event. status = STATUS_BUFFER_TOO_SMALL; USBERR("input buffer length is less than sizeof(libusb_request) status=%Xh\n", status); goto Exit; } transferOffset->BufferOffset = sizeof(libusb_request); transferOffset->BufferLength = requestContext->Length - sizeof(libusb_request); if (transferOffset->BufferLength == 0) { // this is okay but no input data means transferOffset->BufferOffset is pointing // to invalid memory; because the length is also zero it is still most likely safe. transferOffset = NULL; transferMemory = NULL; } } else { // native control transfers are direct; data comes from/goes to the out buffer whether reading or writing. transferOffset = NULL; status = WdfRequestRetrieveOutputMemory(Request, &transferMemory); if (!NT_SUCCESS(status) && status != STATUS_BUFFER_TOO_SMALL) { USBERR("WdfRequestRetrieveOutputMemory failed. status=%Xh\n", status); goto Exit; } if (status == STATUS_BUFFER_TOO_SMALL) { // zero length transfer buffer, this is okay. transferMemory = NULL; USBMSG("zero-length transfer buffer\n"); } } status = WdfUsbTargetDeviceFormatRequestForControlTransfer( deviceContext->WdfUsbTargetDevice, Request, setupPacket, transferMemory, transferOffset); if (!NT_SUCCESS(status)) { USBERR("WdfUsbTargetDeviceFormatRequestForControlTransfer failed. status=%Xh\n", status); goto Exit; } WdfRequestSetCompletionRoutine(Request, XferCtrlComplete, NULL); WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, 0); status = SetRequestTimeout(requestContext, Request, &sendOptions); if (!NT_SUCCESS(status)) { USBERR("SetRequestTimeout failed. status=%Xh\n", status); goto Exit; } if (!WdfRequestSend(Request, WdfUsbTargetDeviceGetIoTarget(deviceContext->WdfUsbTargetDevice), &sendOptions)) { status = WdfRequestGetStatus(Request); USBERR("WdfRequestSend failed. status=%Xh\n", status); } else { USBMSGN("[Ok] status=%Xh", status); return; } Exit: if (!NT_SUCCESS(status)) { WdfRequestCompleteWithInformation(Request, status, 0); } return; }
VOID ToasterEvtIoWrite ( WDFQUEUE Queue, WDFREQUEST Request, size_t Length ) /*++ Routine Description: Performs write to the toaster device. This event is called when the framework receives IRP_MJ_WRITE requests. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. 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: None --*/ { NTSTATUS status; ULONG_PTR bytesWritten =0; WDFMEMORY memory; UNREFERENCED_PARAMETER(Queue); UNREFERENCED_PARAMETER(Length); KdPrint(("ToasterEvtIoWrite. Request: 0x%p, Queue: 0x%p\n", Request, Queue)); PAGED_CODE(); // // Get the request buffer and perform write operation here // status = WdfRequestRetrieveInputMemory(Request, &memory); if(NT_SUCCESS(status) ) { // // 1) Use WdfMemoryCopyToBuffer to copy data from the request // to driver buffer. // 2) Or get the buffer pointer from the request by calling // WdfRequestRetrieveInputBuffer // 3) Or you can get the buffer pointer from the memory handle // by calling WdfMemoryGetBuffer. // bytesWritten = Length; } WdfRequestCompleteWithInformation(Request, status, bytesWritten); }
VOID EchoEvtIoWrite( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) /*++ Routine Description: This event is invoked when the framework receives IRP_MJ_WRITE request. This routine allocates memory buffer, copies the data from the request to it, and stores the buffer pointer in the queue-context with the length variable representing the buffers length. The actual completion of the request is defered to the periodic timer dpc. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. Length - number of bytes to be read. 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: VOID --*/ { NTSTATUS Status; WDFMEMORY memory; PQUEUE_CONTEXT queueContext = QueueGetContext(Queue); PVOID writeBuffer = NULL; _Analysis_assume_(Length > 0); KdPrint(("EchoEvtIoWrite Called! Queue 0x%p, Request 0x%p Length %d\n", Queue,Request,Length)); if( Length > MAX_WRITE_LENGTH ) { KdPrint(("EchoEvtIoWrite Buffer Length to big %d, Max is %d\n", Length,MAX_WRITE_LENGTH)); WdfRequestCompleteWithInformation(Request, STATUS_BUFFER_OVERFLOW, 0L); return; } // Get the memory buffer Status = WdfRequestRetrieveInputMemory(Request, &memory); if( !NT_SUCCESS(Status) ) { KdPrint(("EchoEvtIoWrite Could not get request memory buffer 0x%x\n", Status)); WdfVerifierDbgBreakPoint(); WdfRequestComplete(Request, Status); return; } // Release previous buffer if set if( queueContext->WriteMemory != NULL ) { WdfObjectDelete(queueContext->WriteMemory); queueContext->WriteMemory = NULL; } Status = WdfMemoryCreate(WDF_NO_OBJECT_ATTRIBUTES, NonPagedPool, 'sam1', Length, &queueContext->WriteMemory, &writeBuffer ); if(!NT_SUCCESS(Status)) { KdPrint(("EchoEvtIoWrite: Could not allocate %d byte buffer\n", Length)); WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES); return; } // Copy the memory in Status = WdfMemoryCopyToBuffer( memory, 0, // offset into the source memory writeBuffer, Length ); if( !NT_SUCCESS(Status) ) { KdPrint(("EchoEvtIoWrite WdfMemoryCopyToBuffer failed 0x%x\n", Status)); WdfVerifierDbgBreakPoint(); WdfObjectDelete(queueContext->WriteMemory); queueContext->WriteMemory = NULL; WdfRequestComplete(Request, Status); return; } // Set transfer information WdfRequestSetInformation(Request, (ULONG_PTR)Length); // Specify the request is cancelable WdfRequestMarkCancelable(Request, EchoEvtRequestCancel); // Defer the completion to another thread from the timer dpc queueContext->CurrentRequest = Request; queueContext->CurrentStatus = Status; return; }
VOID EvtIoDeviceControl( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode ) { WDFDEVICE device; PDEVICE_CONTEXT pDevContext; size_t bytesTransferred = 0; NTSTATUS status; WDF_USB_CONTROL_SETUP_PACKET controlSetupPacket; WDF_MEMORY_DESCRIPTOR memDesc; WDFMEMORY memory; WDF_REQUEST_SEND_OPTIONS sendOptions; UNREFERENCED_PARAMETER(InputBufferLength); UNREFERENCED_PARAMETER(OutputBufferLength); device = WdfIoQueueGetDevice(Queue); pDevContext = GetDeviceContext(device); switch(IoControlCode) { case IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY: if(InputBufferLength < sizeof(UCHAR)) { status = STATUS_BUFFER_OVERFLOW; bytesTransferred = sizeof(UCHAR); break; } status = WdfRequestRetrieveInputMemory(Request, &memory); if (!NT_SUCCESS(status)) { KdPrint(("WdfRequestRetrieveMemory failed %!STATUS!", status)); break; } WDF_USB_CONTROL_SETUP_PACKET_INIT_VENDOR(&controlSetupPacket, BmRequestHostToDevice, BmRequestToDevice, USBFX2LK_SET_BARGRAPH_DISPLAY, // Request 0, // Value 0); // Index WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&memDesc, memory, NULL); // // Send the I/O with a timeout to avoid hanging the calling // thread indefinitely. // WDF_REQUEST_SEND_OPTIONS_INIT(&sendOptions, WDF_REQUEST_SEND_OPTION_TIMEOUT); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&sendOptions, WDF_REL_TIMEOUT_IN_MS(100)); status = WdfUsbTargetDeviceSendControlTransferSynchronously( pDevContext->UsbDevice, NULL, // Optional WDFREQUEST &sendOptions, // PWDF_REQUEST_SEND_OPTIONS &controlSetupPacket, &memDesc, (PULONG)&bytesTransferred); if (!NT_SUCCESS(status)) { KdPrint(("SendControlTransfer failed %!STATUS!", status)); break; } break; default: status = STATUS_INVALID_DEVICE_REQUEST; break; } WdfRequestCompleteWithInformation(Request, status, bytesTransferred); return; }