_Use_decl_annotations_ VOID MouFilter_IoRead(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length) { PDEVICE_EXTENSION devExt; MOUSE_REPORT* mouseReport; NTSTATUS status = STATUS_SUCCESS; WDFDEVICE hDevice; UNREFERENCED_PARAMETER(Length); PAGED_CODE(); hDevice = WdfIoQueueGetDevice(Queue); devExt = FilterGetData(hDevice); status = WdfRequestRetrieveOutputBuffer(Request, sizeof(MOUSE_REPORT), (void**) &mouseReport, NULL); if (!NT_SUCCESS(status)){ DebugPrint(("WdfRequestRetrieveInputBuffer failed %x\n", status)); } else { DebugPrint(("Setting mouse report data to (%d, %d)", 50, 50)); mouseReport->xData = 50; mouseReport->yData = 50; mouseReport->ReportId = 0x01; } WdfRequestComplete(Request, status); }
VOID VIOSerialPortWriteRequestCancel(IN WDFREQUEST Request) { PVIOSERIAL_PORT Port = RawPdoSerialPortGetData( WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)))->port; PSINGLE_LIST_ENTRY iter; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> %s Request: 0x%p\n", __FUNCTION__, Request); // synchronize with VIOSerialReclaimConsumedBuffers because the pending // request is not guaranteed to be alive after we return from this callback WdfSpinLockAcquire(Port->OutVqLock); iter = &Port->WriteBuffersList; while ((iter = iter->Next) != NULL) { PWRITE_BUFFER_ENTRY entry = CONTAINING_RECORD(iter, WRITE_BUFFER_ENTRY, ListEntry); if (entry->Request == Request) { entry->Request = NULL; break; } } WdfSpinLockRelease(Port->OutVqLock); WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0L); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- %s\n", __FUNCTION__); }
VOID VIOSerialPortWriteIoStop(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG ActionFlags) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData( WdfIoQueueGetDevice(Queue)); PVIOSERIAL_PORT pport = pdoData->port; TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "--> %s\n", __FUNCTION__); WdfSpinLockAcquire(pport->OutVqLock); if (ActionFlags & WdfRequestStopActionSuspend) { WdfRequestStopAcknowledge(Request, FALSE); } else if (ActionFlags & WdfRequestStopActionPurge) { if (WdfRequestUnmarkCancelable(Request) != STATUS_CANCELLED) { pport->PendingWriteRequest = NULL; WdfRequestComplete(Request, STATUS_OBJECT_NO_LONGER_EXISTS); } } WdfSpinLockRelease(pport->OutVqLock); TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "<-- %s\n", __FUNCTION__); }
VOID VIOSerialPortIoStop( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG ActionFlags ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(Queue)); PVIOSERIAL_PORT pport = pdoData->port; ASSERT(pport->PendingReadRequest == Request); TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "-->%s\n", __FUNCTION__); WdfSpinLockAcquire(pport->InBufLock); if (ActionFlags & WdfRequestStopActionSuspend ) { WdfRequestStopAcknowledge(Request, FALSE); } else if(ActionFlags & WdfRequestStopActionPurge) { if (WdfRequestUnmarkCancelable(Request) != STATUS_CANCELLED) { pport->PendingReadRequest = NULL; WdfRequestCompleteWithInformation(Request , STATUS_CANCELLED, 0L); } } WdfSpinLockRelease(pport->InBufLock); return; }
VOID VIOSerialPortReadRequestCancel( IN WDFREQUEST Request ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request))); BOOLEAN reqComplete = FALSE; TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "-->%s called on request 0x%p\n", __FUNCTION__, Request); WdfSpinLockAcquire(pdoData->port->InBufLock); ASSERT(pdoData->port->PendingReadRequest == Request); if (pdoData->port->PendingReadRequest) { pdoData->port->PendingReadRequest = NULL; reqComplete = TRUE; } WdfSpinLockRelease(pdoData->port->InBufLock); if (reqComplete) { WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0L); } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE,"<-- %s\n", __FUNCTION__); return; }
// Fill in the given struct _HID_DEVICE_ATTRIBUTES // NTSTATUS HidFx2GetDeviceAttributes(_In_ WDFREQUEST hRequest) { NTSTATUS status = STATUS_SUCCESS; PHID_DEVICE_ATTRIBUTES pDeviceAttributes = NULL; PUSB_DEVICE_DESCRIPTOR pUsbDeviceDescriptor = NULL; PDEVICE_EXTENSION pDeviceInfo = NULL; TraceVerbose(DBG_IOCTL, "(%!FUNC!) Entry\n"); pDeviceInfo = GetDeviceContext(WdfIoQueueGetDevice(WdfRequestGetIoQueue(hRequest))); status = WdfRequestRetrieveOutputBuffer(hRequest, sizeof (HID_DEVICE_ATTRIBUTES), &pDeviceAttributes, NULL); if (NT_SUCCESS(status)) { // Retrieve USB device descriptor saved in device context pUsbDeviceDescriptor = WdfMemoryGetBuffer(pDeviceInfo->hDeviceDescriptor, NULL); pDeviceAttributes->Size = sizeof (HID_DEVICE_ATTRIBUTES); pDeviceAttributes->VendorID = pUsbDeviceDescriptor->idVendor; pDeviceAttributes->ProductID = pUsbDeviceDescriptor->idProduct; pDeviceAttributes->VersionNumber = pUsbDeviceDescriptor->bcdDevice; // Report how many bytes were copied WdfRequestSetInformation(hRequest, sizeof (HID_DEVICE_ATTRIBUTES)); } else // WdfRequestRetrieveOutputBuffer failed { TraceErr(DBG_IOCTL, "(%!FUNC!) WdfRequestRetrieveOutputBuffer failed %!STATUS!\n", status); } TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit = %!STATUS!\n", status); return status; }
VOID XenUsb_EvtRequestCancelPvUrb(WDFREQUEST request) { WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(request)); PXENUSB_DEVICE_DATA xudd = GetXudd(device); WDF_REQUEST_PARAMETERS wrp; partial_pvurb_t *partial_pvurb; pvurb_t *pvurb; KIRQL old_irql; FUNCTION_ENTER(); FUNCTION_MSG("cancelling request %p\n", request); WDF_REQUEST_PARAMETERS_INIT(&wrp); KeAcquireSpinLock(&xudd->urb_ring_lock, &old_irql); WdfRequestGetParameters(request, &wrp); pvurb = (pvurb_t *)wrp.Parameters.Others.Arg1; FUNCTION_MSG("pvurb = %p\n", pvurb); ASSERT(pvurb); partial_pvurb = (partial_pvurb_t *)xudd->partial_pvurb_queue.Flink; while (partial_pvurb != (partial_pvurb_t *)&xudd->partial_pvurb_queue) { partial_pvurb_t *next_partial_pvurb = (partial_pvurb_t *)partial_pvurb->entry.Flink; ASSERT(!partial_pvurb->on_ring); FUNCTION_MSG("partial_pvurb = %p is not yet on ring\n", partial_pvurb); RemoveEntryList(&partial_pvurb->entry); ExFreePoolWithTag(partial_pvurb, XENUSB_POOL_TAG); pvurb->ref--; partial_pvurb = next_partial_pvurb; } partial_pvurb = (partial_pvurb_t *)xudd->partial_pvurb_ring.Flink; while (partial_pvurb != (partial_pvurb_t *)&xudd->partial_pvurb_ring) { partial_pvurb_t *next_partial_pvurb = (partial_pvurb_t *)partial_pvurb->entry.Flink; partial_pvurb_t *partial_pvurb_cancel; FUNCTION_MSG("partial_pvurb = %p is on ring\n", partial_pvurb); ASSERT(partial_pvurb->on_ring); partial_pvurb_cancel = ExAllocatePoolWithTag(NonPagedPool, sizeof(*partial_pvurb_cancel), XENUSB_POOL_TAG); /* todo - use lookaside */ ASSERT(partial_pvurb_cancel); /* what would we do if this failed? */ partial_pvurb_cancel->req = partial_pvurb->req; partial_pvurb_cancel->req.pipe = usbif_setunlink_pipe(partial_pvurb_cancel->req.pipe); partial_pvurb_cancel->req.u.unlink.unlink_id = partial_pvurb->req.id; partial_pvurb_cancel->pvurb = pvurb; partial_pvurb_cancel->mdl = NULL; partial_pvurb_cancel->other_partial_pvurb = partial_pvurb; partial_pvurb->other_partial_pvurb = partial_pvurb_cancel; partial_pvurb_cancel->on_ring = FALSE; pvurb->ref++; InsertHeadList(&xudd->partial_pvurb_queue, &partial_pvurb_cancel->entry); partial_pvurb = next_partial_pvurb; } if (pvurb->ref) { PutRequestsOnRing(xudd); KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql); } else { KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql); WdfRequestComplete(request, STATUS_CANCELLED); } FUNCTION_EXIT(); }
VOID DefaultQueue_EvtIoDeviceControl( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode ) /*++ Routine Description: EvtIoDeviceControl handler for the default Queue Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. OutputBufferLength - Size of the output buffer in bytes InputBufferLength - Size of the input buffer in bytes IoControlCode - I/O control code. --*/ { WDFDEVICE WdfDevice; PCONTROLLER_CONTEXT ControllerContext; BOOLEAN HandledbyUfx; TraceEntry(); TraceVerbose("Queue 0x%p, Request 0x%p, OutputBufferLength %d, " "InputBufferLength %d, IoControlCode %d", Queue, Request, (int) OutputBufferLength, (int) InputBufferLength, IoControlCode); WdfDevice = WdfIoQueueGetDevice(Queue); ControllerContext = DeviceGetControllerContext(WdfDevice); HandledbyUfx = UfxDeviceIoControl( ControllerContext->UfxDevice, Request, OutputBufferLength, InputBufferLength, IoControlCode); if (!HandledbyUfx) { TraceError("Recieved an unsupported IOCTL"); WdfRequestComplete(Request, STATUS_INVALID_DEVICE_REQUEST); } TraceExit(); }
VOID CY001Drv::DeviceIoControlSerial_sta(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode) { CY001Drv* pThis = (CY001Drv*)CY001Drv::GetDrvClassFromDevice(WdfIoQueueGetDevice(Queue)); pThis->DeviceIoControlParallel(Queue, Request, OutputBufferLength, InputBufferLength, IoControlCode); }
// Pass down Idle notification request to lower driver // NTSTATUS HidFx2SendIdleNotification(_In_ WDFREQUEST hRequest) { NTSTATUS status = STATUS_SUCCESS; WDF_REQUEST_SEND_OPTIONS options; WDFIOTARGET hNextLowerDriver; WDFDEVICE hDevice; PIO_STACK_LOCATION pCurrentIrpStack = NULL; IO_STACK_LOCATION nextIrpStack; TraceVerbose(DBG_IOCTL, "(%!FUNC!) Entry\n"); hDevice = WdfIoQueueGetDevice(WdfRequestGetIoQueue(hRequest)); pCurrentIrpStack = IoGetCurrentIrpStackLocation(WdfRequestWdmGetIrp(hRequest)); // Convert the request to corresponding USB Idle notification request if (pCurrentIrpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO)) { ASSERT(sizeof(HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO) == sizeof(USB_IDLE_CALLBACK_INFO)); #pragma warning(suppress :4127) // conditional expression is constant warning if (sizeof(HID_SUBMIT_IDLE_NOTIFICATION_CALLBACK_INFO) == sizeof(USB_IDLE_CALLBACK_INFO)) { // prepare next stack location RtlZeroMemory(&nextIrpStack, sizeof(IO_STACK_LOCATION)); nextIrpStack.MajorFunction = pCurrentIrpStack->MajorFunction; nextIrpStack.Parameters.DeviceIoControl.InputBufferLength = pCurrentIrpStack->Parameters.DeviceIoControl.InputBufferLength; nextIrpStack.Parameters.DeviceIoControl.Type3InputBuffer = pCurrentIrpStack->Parameters.DeviceIoControl.Type3InputBuffer; nextIrpStack.Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION; nextIrpStack.DeviceObject = WdfIoTargetWdmGetTargetDeviceObject(WdfDeviceGetIoTarget(hDevice)); // Format the I/O request for the driver's local I/O target by using the contents of the specified WDM I/O stack location structure. WdfRequestWdmFormatUsingStackLocation(hRequest, &nextIrpStack); // Send the request down using Fire and forget option. WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); hNextLowerDriver = WdfDeviceGetIoTarget(hDevice); if (WdfRequestSend(hRequest, hNextLowerDriver, &options) == FALSE) { status = STATUS_UNSUCCESSFUL; } } else // Incorrect DeviceIoControl.InputBufferLength { status = STATUS_INFO_LENGTH_MISMATCH; TraceErr(DBG_IOCTL, "(%!FUNC!) Incorrect DeviceIoControl.InputBufferLength, %!STATUS!\n", status); return status; } } else // DeviceIoControl.InputBufferLength too small { status = STATUS_BUFFER_TOO_SMALL; TraceErr(DBG_IOCTL, "(%!FUNC!) DeviceIoControl.InputBufferLength too small, %!STATUS!\n", status); return status; } TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit = %!STATUS!\n", status); return status; }
void MouseTrapEvtIoInternalDeviceControl(WDFQUEUE queue, WDFREQUEST request, size_t outputBufferLength, size_t inputBufferLength, ULONG ioControlCode) { UNREFERENCED_PARAMETER(outputBufferLength); UNREFERENCED_PARAMETER(inputBufferLength); NTSTATUS status = STATUS_SUCCESS; PAGED_CODE(); // Ensure paging is allowed in current IRQL // Get extension data WDFDEVICE hDevice = WdfIoQueueGetDevice(queue); PDEVICE_CONTEXT context = DeviceGetContext(hDevice); if(ioControlCode == IOCTL_INTERNAL_MOUSE_CONNECT) { // Only allow one connection. if(context->UpperConnectData.ClassService == NULL) { // Copy the connection parameters to the device extension. PCONNECT_DATA connectData; size_t length; status = WdfRequestRetrieveInputBuffer(request, sizeof(CONNECT_DATA), &connectData, &length); if(NT_SUCCESS(status)) { // Hook into the report chain (I am not sure this is correct) context->UpperConnectData = *connectData; connectData->ClassDeviceObject = WdfDeviceWdmGetDeviceObject(hDevice); #pragma warning(push) #pragma warning(disable:4152) connectData->ClassService = MouseTrapServiceCallback; #pragma warning(pop) } else { DebugPrint(("[MouseTrap] WdfRequestRetrieveInputBuffer failed %x\n", status)); } } else { status = STATUS_SHARING_VIOLATION; } } else if(ioControlCode == IOCTL_INTERNAL_MOUSE_DISCONNECT) { status = STATUS_NOT_IMPLEMENTED; } // Complete on error if(!NT_SUCCESS(status)) { WdfRequestComplete(request, status); return; } // Dispatch to higher level driver WDF_REQUEST_SEND_OPTIONS options; WDF_REQUEST_SEND_OPTIONS_INIT(&options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); if(WdfRequestSend(request, WdfDeviceGetIoTarget(hDevice), &options) == FALSE) { NTSTATUS status = WdfRequestGetStatus(request); DebugPrint(("[MouseTrap] WdfRequestSend failed: 0x%x\n", status)); WdfRequestComplete(request, status); } }
VOID Rio500_EvtIoWrite( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t Length ) /*++ Routine Description: Called by the framework when it receives 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: VOID --*/ { WDFUSBPIPE pipe; WDF_USB_PIPE_INFORMATION pipeInfo; PAGED_CODE(); // // Get the pipe associate with this request. // WDFDEVICE device = WdfIoQueueGetDevice(Queue); PDEVICE_CONTEXT pDevContext = GetDeviceContext(device); pipe = pDevContext->WritePipe; if (pipe == NULL) { Rio500_DbgPrint(1, ("Write pipe handle is NULL\n")); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_PARAMETER, 0); return; } WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo); WdfUsbTargetPipeGetInformation(pipe, &pipeInfo); if (WdfUsbPipeTypeBulk == pipeInfo.PipeType) { ReadWriteBulkEndPoints(Queue, Request, (ULONG)Length, WdfRequestTypeWrite); return; } Rio500_DbgPrint(1, ("ISO transfer is not supported for buffered I/O transfer\n")); WdfRequestCompleteWithInformation(Request, STATUS_INVALID_DEVICE_REQUEST, 0); }
VOID OnTopLevelIoDefault( _In_ WDFQUEUE FxQueue, _In_ WDFREQUEST FxRequest ) /*++ Routine Description: Accepts all incoming requests and pends or forwards appropriately. Arguments: FxQueue - Handle to the framework queue object that is associated with the I/O request. FxRequest - Handle to a framework request object. Return Value: None. --*/ { FuncEntry(TRACE_FLAG_SPBAPI); UNREFERENCED_PARAMETER(FxQueue); WDFDEVICE device; PDEVICE_CONTEXT pDevice; WDF_REQUEST_PARAMETERS params; NTSTATUS status; device = WdfIoQueueGetDevice(FxQueue); pDevice = GetDeviceContext(device); WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters(FxRequest, ¶ms); status = WdfRequestForwardToIoQueue(FxRequest, pDevice->SpbQueue); if (!NT_SUCCESS(status)) { CyapaPrint( DEBUG_LEVEL_ERROR, DBG_IOCTL, "Failed to forward WDFREQUEST %p to SPB queue %p - %!STATUS!", FxRequest, pDevice->SpbQueue, status); WdfRequestComplete(FxRequest, status); } FuncExit(TRACE_FLAG_SPBAPI); }
VOID FireShockEvtIoWrite( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t Length ) { NTSTATUS status; PDEVICE_CONTEXT pDeviceContext; LPVOID buffer; size_t bufferLength; size_t transferred = 0; pDeviceContext = DeviceGetContext(WdfIoQueueGetDevice(Queue)); switch (pDeviceContext->DeviceType) { case DualShock3: status = WdfRequestRetrieveInputBuffer( Request, DS3_HID_OUTPUT_REPORT_SIZE, &buffer, &bufferLength); if (NT_SUCCESS(status) && Length == bufferLength) { status = SendControlRequest( pDeviceContext, BmRequestHostToDevice, BmRequestClass, SetReport, USB_SETUP_VALUE(HidReportRequestTypeOutput, HidReportRequestIdOne), 0, buffer, (ULONG)bufferLength); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_QUEUE, "SendControlRequest failed with status %!STATUS!", status); break; } transferred = bufferLength; } break; default: status = STATUS_NOT_SUPPORTED; break; } WdfRequestCompleteWithInformation(Request, status, transferred); }
// 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 EvtIoDeviceControl(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode) { WDFDEVICE Device = WdfIoQueueGetDevice(Queue); UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); switch (IoControlCode) { case IOCTL_PCIDTF_GET_INFO: PciDtfDeviceGetInfo(Device, Request); break; case IOCTL_PCIDTF_READ_CFG: PciDtfDeviceReadWriteCfg(Device, Request, TRUE); break; case IOCTL_PCIDTF_WRITE_CFG: PciDtfDeviceReadWriteCfg(Device, Request, FALSE); break; case IOCTL_PCIDTF_GET_REG: PciDtfDeviceGetReg(Device, Request); break; case IOCTL_PCIDTF_READ_REG: PciDtfDeviceReadWriteReg(Device, Request, TRUE); break; case IOCTL_PCIDTF_WRITE_REG: PciDtfDeviceReadWriteReg(Device, Request, FALSE); break; case IOCTL_PCIDTF_ALLOC_DMA: PciDtfDeviceAllocDma(Device, Request); break; case IOCTL_PCIDTF_FREE_DMA: PciDtfDeviceFreeDma(Device, Request); break; case IOCTL_PCIDTF_READ_DMA: PciDtfDeviceReadWriteDma(Device, Request, TRUE); break; case IOCTL_PCIDTF_WRITE_DMA: PciDtfDeviceReadWriteDma(Device, Request, FALSE); break; case IOCTL_PCIDTF_GET_DMA_INFO: PciDtfDeviceGetDma(Device, Request); break; default: TRACE_MSG(TRACE_LEVEL_ERROR, TRACE_FLAG_QUEUE, "Unsupported I/O control code=0x%X (0x%X)\n", IoControlCode, IoGetFunctionCodeFromCtlCode(IoControlCode)); WdfRequestComplete(Request, STATUS_INVALID_DEVICE_REQUEST); break; } }
VOID EvtIoRead( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) { WDFUSBPIPE pipe; NTSTATUS status; WDFMEMORY reqMemory; PDEVICE_CONTEXT pDeviceContext; BOOLEAN ret; UNREFERENCED_PARAMETER(Length); pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue)); pipe = pDeviceContext->BulkReadPipe; status = WdfRequestRetrieveOutputMemory(Request, &reqMemory); if(!NT_SUCCESS(status)){ goto Exit; } status = WdfUsbTargetPipeFormatRequestForRead(pipe, Request, reqMemory, NULL // Offsets ); if (!NT_SUCCESS(status)) { goto Exit; } WdfRequestSetCompletionRoutine( Request, EvtRequestReadCompletionRoutine, 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 SimSensorIoInternalDeviceControl ( WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode) /*++ Description: The system uses IoInternalDeviceControl requests to communicate with the ACPI driver on the device stack. For proper operation of thermal zones, these requests must be forwarded unless the driver knows how to handle them. --*/ { WDF_REQUEST_SEND_OPTIONS RequestSendOptions; BOOLEAN Return; NTSTATUS Status; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); UNREFERENCED_PARAMETER(IoControlCode); DebugEnter(); WdfRequestFormatRequestUsingCurrentType(Request); WDF_REQUEST_SEND_OPTIONS_INIT( &RequestSendOptions, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); Return = WdfRequestSend( Request, WdfDeviceGetIoTarget(WdfIoQueueGetDevice(Queue)), &RequestSendOptions); if (Return == FALSE) { Status = WdfRequestGetStatus(Request); DebugPrint(SIMSENSOR_WARN, "WdfRequestSend() Failed. Request Status=0x%x\n", Status); WdfRequestComplete(Request, Status); } DebugExit(); }
/////////////////////////////////////////////////////////////////////////////// // SmplFilterEvtIoDefault /////////////////////////////////////////////////////////////////////////////// VOID SmplFilterEvtIoDefault( __in WDFQUEUE Queue, __in WDFREQUEST Request ) { WDF_REQUEST_PARAMETERS RequestParameters; BOOLEAN bResult; WDF_REQUEST_PARAMETERS_INIT(&RequestParameters); WdfRequestGetParameters(Request, &RequestParameters); if(WdfRequestTypeRead == RequestParameters.Type) { DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "SmplFilterEvtIoDefault WdfRequestTypeRead\n"); WdfRequestFormatRequestUsingCurrentType(Request); WdfRequestSetCompletionRoutine(Request, SmplFilterCompletionRoutineRead, NULL); bResult = WdfRequestSend(Request, WdfDeviceGetIoTarget(WdfIoQueueGetDevice(Queue)), NULL); } else { WDF_REQUEST_SEND_OPTIONS Options; WDF_REQUEST_SEND_OPTIONS_INIT(&Options, WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET); DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "SmplFilterEvtIoDefault other Request type\n"); bResult = WdfRequestSend(Request, WdfDeviceGetIoTarget(WdfIoQueueGetDevice(Queue)), &Options); } if(FALSE == bResult) { DbgPrintEx( DPFLTR_IHVDRIVER_ID, 1234, "WdfRequestSend failed!\n"); WdfRequestComplete(Request, WdfRequestGetStatus(Request)); } } // end SmplFilterEvtIoDefault
/////////////////////////////////////////////////////////////////////////////// // SmplQueueEvtStatePoFxStopComplete // Callback invoked by KMDF when stop transiton of the supplied queue has // completed. /////////////////////////////////////////////////////////////////////////////// VOID SmplQueueEvtStatePoFxStopComplete( _In_ WDFQUEUE Queue, _In_ WDFCONTEXT Context ) { DEVICE_CONTEXT *pDeviceContext = WdfObjectGetTypedContext(WdfIoQueueGetDevice(Queue), DEVICE_CONTEXT); UNREFERENCED_PARAMETER(Context); // // Queue has been stopped. Complete the idle transition. // PoFxCompleteIdleCondition(pDeviceContext->PoHandle, 0 /* Component */); } // end SmplQueueEvtStatePoFxStopComplete
VOID EvtIoDeviceControl( __in WDFQUEUE IoQueue, __in WDFREQUEST Request, __in size_t OutBufferLength, __in size_t InBufferLength, __in ULONG IoControlCode ) { PDEVICE_CONTEXT DeviceContext; ULONG_PTR Information; NTSTATUS Status; PAGED_CODE(); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "--> EvtIoDeviceControl(%x)\n", IoControlCode); // // Get the pointer to the device's context area. // We are using the queue handle to get the device handle. // DeviceContext = GetDeviceContext(WdfIoQueueGetDevice(IoQueue)); Information = 0; switch(IoControlCode) { case IOCTL_SHOW_DATA: //Status = EraseFirstSector(WdfIoQueueGetDevice(IoQueue)); //ShowFwhRegisters(DeviceContext->Lpc); //ShowRcrbRegisters(DeviceContext->Rcrb); //ShowSpiRegisters(DeviceContext->Rcrb + SPIBAR_OFFSET); Status = STATUS_SUCCESS; break; default: Status = STATUS_INVALID_DEVICE_REQUEST; break; } // // Complete the I/O request // WdfRequestCompleteWithInformation(Request, Status, Information); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "<-- EvtIoDeviceControl(%x)\n", IoControlCode); }
/////////////////////////////////////////////////////////////////////////////// // // CDFilterEvtRead // // This routine is called by the framework for read requests // being sent to the device we're filtering // // INPUTS: // // Queue - Our default queue // // Request - A read request // // Length - The length of the read operation // // OUTPUTS: // // None. // // RETURNS: // // None. // // IRQL: // // This routine is called at IRQL <= DISPATCH_LEVEL // // NOTES: // // /////////////////////////////////////////////////////////////////////////////// VOID CDFilterEvtRead(WDFQUEUE Queue, WDFREQUEST Request, size_t Length) { NTSTATUS status; PFILTER_DEVICE_CONTEXT devContext; #if DBG DbgPrint("CDFilterEvtRead: Processing read. Length = 0x%x\n", Length); #endif // // Get the context that we setup during DeviceAdd processing // devContext = CDFilterGetDeviceContext(WdfIoQueueGetDevice(Queue)); // // Setup the request for the next driver // WdfRequestFormatRequestUsingCurrentType(Request); // // Set the completion routine... // WdfRequestSetCompletionRoutine(Request, CDFilterReadComplete, NULL); // // And send it! // if (!WdfRequestSend(Request, devContext->TargetToSendRequestsTo, WDF_NO_SEND_OPTIONS)) { // // Oops! Something bad happened, complete the request // status = WdfRequestGetStatus(Request); #if DBG DbgPrint("WdfRequestSend failed - 0x%x\n", status); #endif WdfRequestComplete(Request, status); } return; }
VOID VIOSerialPortWriteRequestCancel(IN WDFREQUEST Request) { PVIOSERIAL_PORT Port = RawPdoSerialPortGetData( WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)))->port; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> %s Request: 0x%p\n", __FUNCTION__, Request); // synchronize with VIOSerialReclaimConsumedBuffers because the pending // request is not guaranteed to be alive after we return from this callback WdfSpinLockAcquire(Port->OutVqLock); Port->PendingWriteRequest = NULL; WdfSpinLockRelease(Port->OutVqLock); WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0L); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- %s\n", __FUNCTION__); }
VOID SerialCancelImmediate( IN WDFREQUEST Request ) /*++ Routine Description: This routine is used to cancel a request that is waiting on a comm event. Arguments: Request - Pointer to the WDFREQUEST for the current request Return Value: None. --*/ { PSERIAL_DEVICE_EXTENSION Extension = NULL; WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)); UNREFERENCED_PARAMETER(Request); Extension = SerialGetDeviceExtension(device); SerialTryToCompleteCurrent( Extension, SerialGrabImmediateFromIsr, STATUS_CANCELLED, &Extension->CurrentImmediateRequest, NULL, NULL, Extension->ImmediateTotalTimer, NULL, SerialGetNextImmediate, SERIAL_REF_CANCEL ); }
// Bulk管道读操作 // VOID BulkRead(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_CONTEXT pContext = NULL; WDFUSBPIPE BulkInputPipe; WDFMEMORY hMem; WDFDEVICE hDevice = WdfIoQueueGetDevice(Queue); KDBG(DPFLTR_INFO_LEVEL, "[BulkRead] size: %d", Length); // 取管道 pContext = GetDeviceContext(hDevice); BulkInputPipe = GetBulkPipe(TRUE, hDevice); if(NULL == BulkInputPipe){ WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); return; } status = WdfRequestRetrieveOutputMemory(Request, &hMem); if(!NT_SUCCESS(status)) { KDBG(DPFLTR_INFO_LEVEL, "WdfRequestRetrieveOutputMemory failed with status 0x%0.8x!!!", status); WdfRequestComplete(Request, status); return; } // 和写一样,仍然是对Request对象的重利用 // 除了重利用外,也可以新建一个Request对象。新建的方法在本工程其他地方用得较多。 status = WdfUsbTargetPipeFormatRequestForRead(BulkInputPipe, Request, hMem, NULL); if(!NT_SUCCESS(status)) { KDBG(DPFLTR_INFO_LEVEL, "WdfUsbTargetPipeFormatRequestForRead failed with status 0x%08x\n", status); WdfRequestComplete(Request, status); return; } WdfRequestSetCompletionRoutine(Request, BulkReadComplete, BulkInputPipe); if(FALSE == WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pContext->UsbBulkInPipe), NULL)) { status = WdfRequestGetStatus(Request); KDBG(DPFLTR_INFO_LEVEL, "WdfRequestSend failed with status 0x%08x\n", status); WdfRequestComplete(Request, status); } }
VOID ForwardRequestToIoTarget( _In_ WDFQUEUE queue, _In_ WDFREQUEST request, _In_ size_t length) { TraceEntry(); Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! - Queue 0x%p, Request 0x%p Length %Iu", queue, request, length); auto device = WdfIoQueueGetDevice(queue); auto context = GetDeviceContext(device); if (length > context->MaxLengthInBytesForRWTransfers) { TraceError("%!FUNC! - Buffer Length to big %Iu, Max is %Iu. Status - %!STATUS!", length, context->MaxLengthInBytesForRWTransfers, STATUS_BUFFER_OVERFLOW); WdfRequestCompleteWithInformation(request, STATUS_BUFFER_OVERFLOW, NULL); return; } auto targetDevice = WdfDeviceGetIoTarget(device); WdfRequestFormatRequestUsingCurrentType(request); WDF_REQUEST_SEND_OPTIONS options; WDF_REQUEST_SEND_OPTIONS_INIT( &options, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS | WDF_REQUEST_SEND_OPTION_TIMEOUT); WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&options, WDF_ABS_TIMEOUT_IN_SEC(10)); auto sendSuccess = WdfRequestSend(request, targetDevice, &options); auto status = WdfRequestGetStatus(request); if (!sendSuccess || !NT_SUCCESS(status)) { TraceError("%!FUNC! - WdfRequestSend returned %d with status: %!STATUS!", sendSuccess, status); WdfRequestCompleteWithInformation(request, status, NULL); return; } WdfRequestComplete(request, status); }
VOID VIOSerialPortReadRequestCancel( IN WDFREQUEST Request ) { PRAWPDO_VIOSERIAL_PORT pdoData = RawPdoSerialPortGetData(WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request))); TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "-->%s called on request 0x%p\n", __FUNCTION__, Request); // synchronize with VIOSerialQueuesInterruptDpc because the pending // request is not guaranteed to be alive after we return from this callback WdfSpinLockAcquire(pdoData->port->InBufLock); pdoData->port->PendingReadRequest = NULL; WdfSpinLockRelease(pdoData->port->InBufLock); WdfRequestCompleteWithInformation(Request, STATUS_CANCELLED, 0L); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE, "<-- %s\n", __FUNCTION__); }
VOID VirtRngEvtIoRead(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length) { PDEVICE_CONTEXT context = GetDeviceContext(WdfIoQueueGetDevice(Queue)); NTSTATUS status; PVOID buffer; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "--> %!FUNC! Queue: %p Request: %p Length: %d", Queue, Request, (ULONG)Length); status = WdfRequestRetrieveOutputBuffer(Request, Length, &buffer, NULL); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestRetrieveOutputBuffer failed: %!STATUS!", status); WdfRequestComplete(Request, status); return; } status = WdfRequestMarkCancelableEx(Request, VirtRngEvtRequestCancel); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestMarkCancelableEx failed: %!STATUS!", status); WdfRequestComplete(Request, status); return; } status = VirtQueueAddBuffer(context, Request, Length); if (!NT_SUCCESS(status)) { if (WdfRequestUnmarkCancelable(Request) != STATUS_CANCELLED) { WdfRequestComplete(Request, status); } } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<-- %!FUNC!"); }
VOID FireShockEvtIoRead( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t Length ) { NTSTATUS status; PDEVICE_CONTEXT pDeviceContext; UNREFERENCED_PARAMETER(Length); pDeviceContext = DeviceGetContext(WdfIoQueueGetDevice(Queue)); status = WdfRequestForwardToIoQueue(Request, pDeviceContext->IoReadQueue); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_QUEUE, "WdfRequestForwardToIoQueue failed with status %!STATUS!", status); WdfRequestComplete(Request, status); } }
VOID LoopbackEvtIoDeviceControl( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode) { UNREFERENCED_PARAMETER((OutputBufferLength, InputBufferLength)); TraceEntry(); NTSTATUS status = STATUS_SUCCESS; if (IoControlCode != LOOPBACK_IOCTL_ALTER_MAX_LENGTH || InputBufferLength != 4) { status = STATUS_UNSUCCESSFUL; goto Cleanup; } PUINT32 buffer; status = WdfRequestRetrieveInputBuffer(Request, 4, (PVOID*)&buffer, nullptr); if (!NT_SUCCESS(status)) { TraceError("%!FUNC! - Unable to read IOCTL input buffer. Status - %!STATUS!", status); goto Cleanup; } auto device = WdfIoQueueGetDevice(Queue); auto context = GetDeviceContext(device); context->MaxLengthInBytesForRWTransfers = *buffer; Cleanup: WdfRequestComplete(Request, status); }