VOID GFilterIOCallback( IN WDFDEVICE Device, IN WDFREQUEST Request) { NTSTATUS status; WDF_REQUEST_PARAMETERS params; char *buf; size_t bufLength; // Filter the desired information WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters(Request, ¶ms); switch (params.Type) { //!todo - Record the IRP contents case WdfRequestTypeRead: DEBUG("Intercepted Read IRP"); // We must register a callback for when the read completes (in case it is asynchronous) so the buffers will contain something from // the device (or what ever driver is below us). WdfRequestSetCompletionRoutine( Request, GFilterReadCompleteionRoutine, WDF_NO_CONTEXT); // This should be the filter|device context so we can pass the results to the PDO break; case WdfRequestTypeWrite: DEBUG("Intercepted Write IRP"); status = WdfRequestRetrieveInputBuffer( Request, //!todo This should work for BUFFERED and DIRECT, but I think it will break for Neither !! 1, (PVOID)&buf, &bufLength); CHECKSTATUS(status, ERROR("Failed to retrieve intercepted write buffer. 0x%0.4", status); break;); DEBUG("Intercepted Write of %d bytes: %#0.2x ...", bufLength, (unsigned char)buf[0]); //!todo place the buf into the RAW PDO context break; // All else can just be passed on... }
//读操作 VOID RamDiskEvtIoRead(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.Read.DeviceOffset; //检测读取是否合法 if (RamDiskCheckParameters(devExt, ByteOffset, Length)) { //获得内存状态 Status = WdfRequestRetrieveOutputMemory(Request, &hMemory); if(NT_SUCCESS(Status)) { // Destination # Offset into the destination # source Status = WdfMemoryCopyFromBuffer(hMemory,0, devExt->DiskImage + ByteOffset.LowPart, Length); } } WdfRequestCompleteWithInformation(Request, Status, (ULONG_PTR)Length); }
// 写操作 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); }
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); }
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(); }
NTSTATUS SerialCompleteIfError( PSERIAL_DEVICE_EXTENSION extension, WDFREQUEST Request ) /*++ Routine Description: If the current request is not an IOCTL_SERIAL_GET_COMMSTATUS request and there is an error and the application requested abort on errors, then cancel the request. Arguments: extension - Pointer to the device context Request - Pointer to the WDFREQUEST to test. Return Value: STATUS_SUCCESS or STATUS_CANCELLED. --*/ { WDF_REQUEST_PARAMETERS params; NTSTATUS status = STATUS_SUCCESS; if ((extension->HandFlow.ControlHandShake & SERIAL_ERROR_ABORT) && extension->ErrorWord) { WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters( Request, ¶ms ); // // There is a current error in the driver. No requests should // come through except for the GET_COMMSTATUS. // if ((params.Type != WdfRequestTypeDeviceControl) || (params.Parameters.DeviceIoControl.IoControlCode != IOCTL_SERIAL_GET_COMMSTATUS)) { status = STATUS_CANCELLED; SerialCompleteRequest(Request, status, 0); } } return status; }
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); }
static VOID XenPci_IoWatch(char *path, PVOID context) { NTSTATUS status; watch_context_t *watch_context = context; WDFFILEOBJECT file_object = watch_context->file_object; PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object); KIRQL old_irql; struct xsd_sockmsg *rep; xenbus_read_queue_item_t *list_entry; size_t remaining; WDFREQUEST request; FUNCTION_ENTER(); KeAcquireSpinLock(&xpdid->lock, &old_irql); remaining = sizeof(struct xsd_sockmsg) + strlen(path) + 1 + strlen(watch_context->token) + 1; rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg) + strlen(path) + 1 + strlen(watch_context->token) + 1, XENPCI_POOL_TAG); rep->type = XS_WATCH_EVENT; rep->req_id = 0; rep->tx_id = 0; rep->len = (ULONG)(strlen(path) + 1 + strlen(watch_context->token) + 1); remaining -= sizeof(struct xsd_sockmsg); RtlStringCbCopyA((PCHAR)(rep + 1), remaining, path); remaining -= strlen(path) + 1; RtlStringCbCopyA((PCHAR)(rep + 1) + strlen(path) + 1, remaining, watch_context->token); list_entry = (xenbus_read_queue_item_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(xenbus_read_queue_item_t), XENPCI_POOL_TAG); list_entry->data = rep; list_entry->length = sizeof(*rep) + rep->len; list_entry->offset = 0; InsertTailList(&xpdid->xenbus.read_list_head, (PLIST_ENTRY)list_entry); status = WdfIoQueueRetrieveNextRequest(xpdid->xenbus.io_queue, &request); if (NT_SUCCESS(status)) { WDF_REQUEST_PARAMETERS parameters; WDF_REQUEST_PARAMETERS_INIT(¶meters); WdfRequestGetParameters(request, ¶meters); KdPrint((__DRIVER_NAME " found pending read - MinorFunction = %d, length = %d\n", (ULONG)parameters.MinorFunction, (ULONG)parameters.Parameters.Read.Length)); XenBus_ProcessReadRequest(xpdid->xenbus.io_queue, request, parameters.Parameters.Read.Length); KeReleaseSpinLock(&xpdid->lock, old_irql); WdfRequestComplete(request, STATUS_SUCCESS); } else { KdPrint((__DRIVER_NAME " no pending read (%08x)\n", status)); KeReleaseSpinLock(&xpdid->lock, old_irql); } FUNCTION_EXIT(); }
static VOID XenUsb_EvtIoDefault( WDFQUEUE queue, WDFREQUEST request) { NTSTATUS status; WDF_REQUEST_PARAMETERS parameters; FUNCTION_ENTER(); UNREFERENCED_PARAMETER(queue); status = STATUS_BAD_INITIAL_PC; WDF_REQUEST_PARAMETERS_INIT(¶meters); WdfRequestGetParameters(request, ¶meters); switch (parameters.Type) { case WdfRequestTypeCreate: FUNCTION_MSG("WdfRequestTypeCreate\n"); break; case WdfRequestTypeClose: FUNCTION_MSG("WdfRequestTypeClose\n"); break; case WdfRequestTypeRead: FUNCTION_MSG("WdfRequestTypeRead\n"); break; case WdfRequestTypeWrite: FUNCTION_MSG("WdfRequestTypeWrite\n"); break; case WdfRequestTypeDeviceControl: FUNCTION_MSG("WdfRequestTypeDeviceControl\n"); break; case WdfRequestTypeDeviceControlInternal: FUNCTION_MSG("WdfRequestTypeDeviceControlInternal\n"); break; default: FUNCTION_MSG("Unknown type %x\n", parameters.Type); break; } WdfRequestComplete(request, status); FUNCTION_EXIT(); }
__forceinline void PwmCreateRequestGetAccess( _In_ WDFREQUEST WdfRequest, _Out_ ACCESS_MASK* DesiredAccessPtr, _Out_ ULONG* ShareAccessPtr ) { NT_ASSERT(ARGUMENT_PRESENT(DesiredAccessPtr)); NT_ASSERT(ARGUMENT_PRESENT(ShareAccessPtr)); WDF_REQUEST_PARAMETERS wdfRequestParameters; WDF_REQUEST_PARAMETERS_INIT(&wdfRequestParameters); WdfRequestGetParameters(WdfRequest, &wdfRequestParameters); NT_ASSERTMSG( "Expected create request", wdfRequestParameters.Type == WdfRequestTypeCreate); *DesiredAccessPtr = wdfRequestParameters.Parameters.Create.SecurityContext->DesiredAccess; *ShareAccessPtr = wdfRequestParameters.Parameters.Create.ShareAccess; }
/////////////////////////////////////////////////////////////////////////////// // 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
VOID tgwinkEvtIoRead( 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.Read.DeviceOffset; status = WdfRequestRetrieveOutputMemory(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.GetBusData(context->busInterface.Context, PCI_WHICHSPACE_CONFIG, WdfMemoryGetBuffer(mem, NULL), offset, (ULONG)Length); WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, (ULONG_PTR)result); }
VOID SerialStartOrQueue( IN PSERIAL_DEVICE_EXTENSION Extension, IN WDFREQUEST Request, IN WDFQUEUE QueueToExamine, IN WDFREQUEST *CurrentOpRequest, IN PSERIAL_START_ROUTINE Starter ) /*++ Routine Description: This routine is used to either start or queue any requst that can be queued in the driver. Arguments: Extension - Points to the serial device extension. Request - The request to either queue or start. In either case the request will be marked pending. QueueToExamine - The queue the request will be place on if there is already an operation in progress. CurrentOpRequest - Pointer to a pointer to the request the is current for the queue. The pointer pointed to will be set with to Request if what CurrentOpRequest points to is NULL. Starter - The routine to call if the queue is empty. Return Value: --*/ { NTSTATUS status; PREQUEST_CONTEXT reqContext; WDF_REQUEST_PARAMETERS params; reqContext = SerialGetRequestContext(Request); WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters( Request, ¶ms); // // If this is a write request then take the amount of characters // to write and add it to the count of characters to write. // if (params.Type == WdfRequestTypeWrite) { Extension->TotalCharsQueued += reqContext->Length; } else if ((params.Type == WdfRequestTypeDeviceControl) && ((params.Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_IMMEDIATE_CHAR) || (params.Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_XOFF_COUNTER))) { reqContext->IoctlCode = params.Parameters.DeviceIoControl.IoControlCode; // We need this in the destroy callback Extension->TotalCharsQueued++; } if (IsQueueEmpty(QueueToExamine) && !(*CurrentOpRequest)) { // // There were no current operation. Mark this one as // current and start it up. // *CurrentOpRequest = Request; Starter(Extension); return; } else { // // We don't know how long the request will be in the // queue. If it gets cancelled while waiting in the queue, we will // be notified by EvtCanceledOnQueue callback so that we can readjust // the lenght or free the buffer. // reqContext->Extension = Extension; // We need this in the destroy callback status = WdfRequestForwardToIoQueue(Request, QueueToExamine); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestForwardToIoQueue failed%X\n", status); ASSERTMSG("WdfRequestForwardToIoQueue failed ", FALSE); SerialCompleteRequest(Request, status, 0); } return; } }
NTSTATUS HidFx2SetOutput(_In_ WDFREQUEST hRequest) { NTSTATUS status = STATUS_SUCCESS; PHID_XFER_PACKET pTransferPacket = NULL; WDF_REQUEST_PARAMETERS params; PHIDFX2_IO_REPORT pOutputReport = NULL; WDFDEVICE hDevice; PAGED_CODE(); TraceVerbose(DBG_IOCTL, "(%!FUNC!) Enter\n"); hDevice = WdfIoQueueGetDevice(WdfRequestGetIoQueue(hRequest)); WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters(hRequest, ¶ms); if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) { status = STATUS_BUFFER_TOO_SMALL; TraceErr(DBG_IOCTL, "(%!FUNC!) Userbuffer is small %!STATUS!\n", status); return status; } pTransferPacket = (PHID_XFER_PACKET) WdfRequestWdmGetIrp(hRequest)->UserBuffer; if (pTransferPacket == NULL) { status = STATUS_INVALID_DEVICE_REQUEST; TraceErr(DBG_IOCTL, "(%!FUNC!) Irp->UserBuffer is NULL %!STATUS!\n", status); return status; } if (pTransferPacket->reportBufferLen == 0) { status = STATUS_BUFFER_TOO_SMALL; TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is 0, %!STATUS!\n", status); return status; } if (pTransferPacket->reportBufferLen < sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is too small, %!STATUS!\n", status); return status; } if (pTransferPacket->reportId != GENERIC_DESKTOP_REPORT_ID) { status = STATUS_INVALID_DEVICE_REQUEST; TraceErr(DBG_IOCTL, "(%!FUNC!) Incorrect report ID, %!STATUS!\n", status); return status; } pOutputReport = (PHIDFX2_IO_REPORT)pTransferPacket->reportBuffer; if (pOutputReport->bData == 0) { status = SendVendorCommand(hDevice, HIDFX2_SET_BARGRAPH_DISPLAY, BARGRAPH_LED_ALL_OFF); } else { status = SendVendorCommand(hDevice, HIDFX2_SET_BARGRAPH_DISPLAY, BARGRAPH_LED_ALL_ON); } TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit status %!STATUS!\n", status); return status; }
NTSTATUS HidFx2GetInput(_In_ WDFREQUEST hRequest) { NTSTATUS status = STATUS_SUCCESS; WDF_REQUEST_PARAMETERS params; WDFDEVICE hDevice; PHID_XFER_PACKET pTransferPacket = NULL; PHIDFX2_IO_REPORT pOutputReport = NULL; unsigned char bSwitchState = 0; PAGED_CODE(); TraceVerbose(DBG_IOCTL, "(%!FUNC!) Enter\n"); hDevice = WdfIoQueueGetDevice(WdfRequestGetIoQueue(hRequest)); WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters(hRequest, ¶ms); if (params.Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_XFER_PACKET)) { status = STATUS_BUFFER_TOO_SMALL; TraceErr(DBG_IOCTL, "(%!FUNC!) Userbuffer is small %!STATUS!\n", status); return status; } pTransferPacket = (PHID_XFER_PACKET) WdfRequestWdmGetIrp(hRequest)->UserBuffer; if (pTransferPacket == NULL) { status = STATUS_INVALID_DEVICE_REQUEST; TraceErr(DBG_IOCTL, "(%!FUNC!) Irp->UserBuffer is NULL %!STATUS!\n", status); return status; } if (pTransferPacket->reportBufferLen == 0) { status = STATUS_BUFFER_TOO_SMALL; TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is 0, %!STATUS!\n", status); return status; } if (pTransferPacket->reportBufferLen < sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; TraceErr(DBG_IOCTL, "(%!FUNC!) HID_XFER_PACKET->reportBufferLen is too small, %!STATUS!\n", status); return status; } if (pTransferPacket->reportId != GENERIC_DESKTOP_REPORT_ID) { status = STATUS_INVALID_DEVICE_REQUEST; TraceErr(DBG_IOCTL, "(%!FUNC!) Incorrect report ID, %!STATUS!\n", status); return status; } pOutputReport = (PHIDFX2_IO_REPORT)pTransferPacket->reportBuffer; // Get the switch state directly from the hardware status = HidFx2GetSwitchState(hDevice, &bSwitchState); TraceVerbose(DBG_IOCTL, "(%!FUNC!) switch state 0x%x\n", bSwitchState); //Mask off everything except the actual switch bit bSwitchState &= RADIO_SWITCH_BUTTONS_BIT_MASK; TraceVerbose(DBG_IOCTL, "(%!FUNC!) maskedswitch state 0x%x\n", bSwitchState); pOutputReport->bReportId = GENERIC_DESKTOP_REPORT_ID; pOutputReport->bData = bSwitchState; TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit status %!STATUS!\n", status); return status; }
VOID AmccPciEvtIoDefault( __in WDFQUEUE Queue, __in WDFREQUEST Request ) /*++ Routine Description: Start the IRP on the device. This driver allows only one I/O to be active on the adapter at any one time. If multiple I/Os are sent to the driver, they will be queued and completed as they complete on the adapter (one IRP per interrupt). Arguments: Queue - Default queue handle Request - Handle to the write request Parameters - Contains current stack location information from the IRP Return Value: None --*/ { PAMCC_DEVICE_EXTENSION devExt; REQUEST_CONTEXT * transfer; NTSTATUS status; size_t length; WDF_DMA_DIRECTION direction; WDFDMATRANSACTION dmaTransaction; WDF_REQUEST_PARAMETERS params; WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters( Request, ¶ms ); // // Get the device extension. // devExt = AmccPciGetDevExt(WdfIoQueueGetDevice( Queue )); // // Validate and gather parameters. // switch (params.Type) { case WdfRequestTypeRead: length = params.Parameters.Read.Length; direction = WdfDmaDirectionReadFromDevice; break; case WdfRequestTypeWrite: length = params.Parameters.Write.Length; direction = WdfDmaDirectionWriteToDevice; break; default: TraceEvents(TRACE_LEVEL_WARNING, AMCC_TRACE_IO, "Request type not Read or Write\n"); WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); return; } TraceEvents(TRACE_LEVEL_INFORMATION, AMCC_TRACE_IO, "Request %p: %s %d bytes", Request, (direction)?"Write":"Read", (ULONG)length); // // The length must be non-zero. // if (length == 0) { TraceEvents(TRACE_LEVEL_WARNING, AMCC_TRACE_IO, "Zero transfer length input to read/write"); WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); return; } transfer = GetRequestContext(Request); // // Create new DmaRequst to conduct this DMA transaction. // status = WdfDmaTransactionCreate( devExt->DmaEnabler, WDF_NO_OBJECT_ATTRIBUTES, &dmaTransaction ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO, "WdfDmaRequestCreate failed: %X", status); WdfRequestComplete(Request, status); return; } // // Create new DmaTransaction. // status = WdfDmaTransactionInitializeUsingRequest( dmaTransaction, Request, AmccPciProgramDma, direction ); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO, "WdfDmaRequestInitializeWithRequest failed: %X", status); WdfObjectDelete(dmaTransaction); WdfRequestComplete(Request, status); return; } // // Fill transfer context structure // transfer->Request = Request; transfer->DmaTransaction = dmaTransaction; // // Save the current Request as the "in-progress" request. // devExt->CurrentRequest = Request; // // Execute this dmaTransaction transaction. // status = WdfDmaTransactionExecute( dmaTransaction, WDF_NO_CONTEXT); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, AMCC_TRACE_IO, "WdfDmaTransactionExecute failed: %X", status); WdfObjectDelete(dmaTransaction); WdfRequestComplete(Request, status); return; } return; }
VOID XenUsb_EvtIoInternalDeviceControl_ROOTHUB_SUBMIT_URB( WDFQUEUE queue, WDFREQUEST request, size_t output_buffer_length, size_t input_buffer_length, ULONG io_control_code) { //NTSTATUS status; WDFDEVICE device = WdfIoQueueGetDevice(queue); PXENUSB_PDO_DEVICE_DATA xupdd = GetXupdd(device); PXENUSB_DEVICE_DATA xudd = GetXudd(xupdd->wdf_device_bus_fdo); WDF_REQUEST_PARAMETERS wrp; PURB urb; PUSBD_INTERFACE_INFORMATION interface_information; ULONG i, j; xenusb_device_t *usb_device; xenusb_endpoint_t *endpoint; //USB_DEFAULT_PIPE_SETUP_PACKET setup_packet; urb_decode_t decode_data; ULONG decode_retval; UNREFERENCED_PARAMETER(input_buffer_length); UNREFERENCED_PARAMETER(output_buffer_length); UNREFERENCED_PARAMETER(io_control_code); //FUNCTION_ENTER(); WDF_REQUEST_PARAMETERS_INIT(&wrp); WdfRequestGetParameters(request, &wrp); urb = (PURB)wrp.Parameters.Others.Arg1; ASSERT(urb); #if 0 FUNCTION_MSG("urb = %p\n", urb); FUNCTION_MSG(" Length = %d\n", urb->UrbHeader.Length); FUNCTION_MSG(" Function = %d\n", urb->UrbHeader.Function); FUNCTION_MSG(" Status = %d\n", urb->UrbHeader.Status); FUNCTION_MSG(" UsbdDeviceHandle = %p\n", urb->UrbHeader.UsbdDeviceHandle); FUNCTION_MSG(" UsbdFlags = %08x\n", urb->UrbHeader.UsbdFlags); #endif usb_device = urb->UrbHeader.UsbdDeviceHandle; if (!usb_device) usb_device = xupdd->usb_device; decode_retval = XenUsb_DecodeControlUrb(urb, &decode_data); if (decode_retval == URB_DECODE_UNKNOWN) { FUNCTION_MSG("Unknown URB - Calling WdfRequestCompletestatus with status = %08x\n", STATUS_UNSUCCESSFUL); //STATUS_UNSUCCESSFUL); urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION; WdfRequestComplete(request, STATUS_UNSUCCESSFUL); return; } urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION; if (decode_retval != URB_DECODE_NOT_CONTROL) { FUNCTION_MSG("bmRequestType = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.B); FUNCTION_MSG(" Recipient = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient); FUNCTION_MSG(" Type = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type); FUNCTION_MSG(" Dir = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Dir); FUNCTION_MSG("bRequest = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.bRequest); FUNCTION_MSG("wValue = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.W); FUNCTION_MSG(" Low = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.LowByte); FUNCTION_MSG(" High = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.HiByte); FUNCTION_MSG("wIndex = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex); FUNCTION_MSG(" Low = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte); FUNCTION_MSG(" High = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.HiByte); FUNCTION_MSG("wLength = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wLength); } switch(urb->UrbHeader.Function) { case URB_FUNCTION_SELECT_CONFIGURATION: FUNCTION_MSG("URB_FUNCTION_SELECT_CONFIGURATION\n"); FUNCTION_MSG(" ConfigurationDescriptor = %p\n", urb->UrbSelectConfiguration.ConfigurationDescriptor); if (urb->UrbSelectConfiguration.ConfigurationDescriptor) { FUNCTION_MSG(" bLength = %d\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->bLength); FUNCTION_MSG(" bDescriptorType = %d\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->bDescriptorType); FUNCTION_MSG(" wTotalLength = %d\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->wTotalLength); FUNCTION_MSG(" bNumInterfaces = %d\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->bNumInterfaces); FUNCTION_MSG(" bConfigurationValue = %d\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->bConfigurationValue); FUNCTION_MSG(" iConfiguration = %d\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->iConfiguration); FUNCTION_MSG(" bmAttributes = %04x\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->bmAttributes); FUNCTION_MSG(" MaxPower = %d\n", urb->UrbSelectConfiguration.ConfigurationDescriptor->MaxPower); } FUNCTION_MSG(" ConfigurationHandle = %p\n", urb->UrbSelectConfiguration.ConfigurationHandle); if (urb->UrbSelectConfiguration.ConfigurationDescriptor) { urb->UrbSelectConfiguration.ConfigurationHandle = xupdd->usb_device->configs[0]; interface_information = &urb->UrbSelectConfiguration.Interface; for (i = 0; i < urb->UrbSelectConfiguration.ConfigurationDescriptor->bNumInterfaces; i++) { FUNCTION_MSG("InterfaceInformation[%d]\n", i); FUNCTION_MSG(" Length = %d\n", interface_information->Length); FUNCTION_MSG(" InterfaceNumber = %d\n", interface_information->InterfaceNumber); FUNCTION_MSG(" AlternateSetting = %d\n", interface_information->AlternateSetting); FUNCTION_MSG(" Class = %02x\n", (ULONG)interface_information->Class); FUNCTION_MSG(" SubClass = %02x\n", (ULONG)interface_information->SubClass); FUNCTION_MSG(" Protocol = %02x\n", (ULONG)interface_information->Protocol); FUNCTION_MSG(" Reserved = %02x\n", (ULONG)interface_information->Reserved); FUNCTION_MSG(" InterfaceHandle = %p\n", interface_information->InterfaceHandle); FUNCTION_MSG(" NumberOfPipes = %d\n", interface_information->NumberOfPipes); interface_information->InterfaceHandle = xupdd->usb_device->configs[0]->interfaces[0]; interface_information->Class = 0x09; interface_information->SubClass = 0x00; interface_information->SubClass = 0x00; for (j = 0; j < interface_information->NumberOfPipes; j++) { FUNCTION_MSG(" Pipe[%d]\n", i); FUNCTION_MSG(" MaximumPacketSize = %d\n", interface_information->Pipes[j].MaximumPacketSize); FUNCTION_MSG(" EndpointAddress = %d\n", interface_information->Pipes[j].EndpointAddress); FUNCTION_MSG(" Interval = %d\n", interface_information->Pipes[j].Interval); FUNCTION_MSG(" PipeType = %d\n", interface_information->Pipes[j].PipeType); FUNCTION_MSG(" PipeHandle = %d\n", interface_information->Pipes[j].PipeHandle); FUNCTION_MSG(" MaximumTransferSize = %d\n", interface_information->Pipes[j].MaximumTransferSize); FUNCTION_MSG(" PipeFlags = %08x\n", interface_information->Pipes[j].PipeFlags); interface_information->Pipes[j].MaximumPacketSize = 2; interface_information->Pipes[j].EndpointAddress = 0x81; interface_information->Pipes[j].Interval = 12; interface_information->Pipes[j].PipeType = UsbdPipeTypeInterrupt; interface_information->Pipes[j].PipeHandle = xupdd->usb_device->configs[0]->interfaces[0]->endpoints[j]; interface_information->Pipes[j].MaximumTransferSize = 4096; /* made up number - possibly not used */ // this is input actually interface_information->Pipes[j].PipeFlags = 0; } interface_information = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)interface_information + interface_information->Length); } } urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; case URB_FUNCTION_SELECT_INTERFACE: FUNCTION_MSG("URB_FUNCTION_SELECT_INTERFACE\n"); interface_information = &urb->UrbSelectInterface.Interface; FUNCTION_MSG("InterfaceInformation\n"); FUNCTION_MSG(" Length = %d\n", interface_information->Length); FUNCTION_MSG(" InterfaceNumber = %d\n", interface_information->InterfaceNumber); FUNCTION_MSG(" AlternateSetting = %d\n", interface_information->AlternateSetting); FUNCTION_MSG(" Class = %02x\n", (ULONG)interface_information->Class); FUNCTION_MSG(" SubClass = %02x\n", (ULONG)interface_information->SubClass); FUNCTION_MSG(" Protocol = %02x\n", (ULONG)interface_information->Protocol); FUNCTION_MSG(" Reserved = %02x\n", (ULONG)interface_information->Reserved); FUNCTION_MSG(" InterfaceHandle = %p\n", interface_information->InterfaceHandle); FUNCTION_MSG(" NumberOfPipes = %d\n", interface_information->NumberOfPipes); for (i = 0; i < interface_information->NumberOfPipes; i++) { FUNCTION_MSG(" Pipe[%d]\n", i); FUNCTION_MSG(" MaximumPacketSize = %d\n", interface_information->Pipes[i].MaximumPacketSize); FUNCTION_MSG(" EndpointAddress = %d\n", interface_information->Pipes[i].EndpointAddress); FUNCTION_MSG(" Interval = %d\n", interface_information->Pipes[i].Interval); FUNCTION_MSG(" PipeType = %d\n", interface_information->Pipes[i].PipeType); FUNCTION_MSG(" PipeHandle = %d\n", interface_information->Pipes[i].PipeHandle); FUNCTION_MSG(" MaximumTransferSize = %d\n", interface_information->Pipes[i].MaximumTransferSize); FUNCTION_MSG(" PipeFlags = %08x\n", interface_information->Pipes[i].PipeFlags); } urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION; break; #if (NTDDI_VERSION >= NTDDI_VISTA) case URB_FUNCTION_CONTROL_TRANSFER_EX: #endif case URB_FUNCTION_CONTROL_TRANSFER: case URB_FUNCTION_CLASS_DEVICE: case URB_FUNCTION_CLASS_OTHER: case URB_FUNCTION_CLASS_INTERFACE: case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: case URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE: case URB_FUNCTION_GET_STATUS_FROM_DEVICE: switch(decode_data.setup_packet.default_pipe_setup_packet.bRequest) { case USB_REQUEST_GET_STATUS: // switch device, interface, endpoint switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type) { case BMREQUEST_STANDARD: FUNCTION_MSG(" USB_REQUEST_GET_STATUS\n"); FUNCTION_MSG(" Type=Standard\n"); switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient) { case BMREQUEST_TO_DEVICE: FUNCTION_MSG(" Recipient=Device\n"); ((PUSHORT)decode_data.buffer)[0] = 0x0001; /* self powered */ urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; default: FUNCTION_MSG(" Recipient=%d\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient); break; } break; case BMREQUEST_CLASS: switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient) { case BMREQUEST_TO_DEVICE: ((PUSHORT)decode_data.buffer)[0] = 0x0000; ((PUSHORT)decode_data.buffer)[1] = 0x0000; urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; case BMREQUEST_TO_OTHER: FUNCTION_MSG(" USB_REQUEST_GET_STATUS\n"); FUNCTION_MSG(" Type=Class\n"); FUNCTION_MSG(" Recipient=Other (port = %d)\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte); ((PUSHORT)decode_data.buffer)[0] = xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status; ((PUSHORT)decode_data.buffer)[1] = xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_change; urb->UrbHeader.Status = USBD_STATUS_SUCCESS; FUNCTION_MSG(" status = %04x, change = %04x\n", xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status, xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_change); break; default: FUNCTION_MSG(" USB_REQUEST_GET_STATUS\n"); FUNCTION_MSG(" Type=Class\n"); FUNCTION_MSG(" Recipient=%d\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient); break; } break; default: FUNCTION_MSG(" USB_REQUEST_GET_STATUS\n"); FUNCTION_MSG(" Type=%d\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type); break; } break; case USB_REQUEST_GET_DESCRIPTOR: FUNCTION_MSG(" USB_REQUEST_GET_DESCRIPTOR\n"); // should separate into Standard and Class switch (decode_data.setup_packet.default_pipe_setup_packet.wValue.HiByte) { case USB_DEVICE_DESCRIPTOR_TYPE: FUNCTION_MSG(" USB_DEVICE_DESCRIPTOR_TYPE\n"); FUNCTION_MSG(" length = %d\n", *decode_data.length); memcpy(decode_data.buffer, &usb_device->device_descriptor, sizeof(USB_DEVICE_DESCRIPTOR)); *decode_data.length = sizeof(USB_DEVICE_DESCRIPTOR); urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; case USB_CONFIGURATION_DESCRIPTOR_TYPE: { xenusb_config_t *usb_config; PUCHAR ptr; FUNCTION_MSG(" USB_CONFIGURATION_DESCRIPTOR_TYPE\n"); FUNCTION_MSG(" length = %d\n", *decode_data.length); usb_config = usb_device->active_config; ptr = (PUCHAR)decode_data.buffer; memcpy(ptr, &usb_config->config_descriptor, sizeof(USB_CONFIGURATION_DESCRIPTOR)); ptr += sizeof(USB_CONFIGURATION_DESCRIPTOR); ((PUSB_CONFIGURATION_DESCRIPTOR)decode_data.buffer)->wTotalLength = sizeof(USB_CONFIGURATION_DESCRIPTOR); if (*decode_data.length > 9) { for (i = 0; i < usb_config->config_descriptor.bNumInterfaces; i++) { memcpy(ptr, &usb_config->interfaces[i]->interface_descriptor, sizeof(USB_INTERFACE_DESCRIPTOR)); ptr += sizeof(USB_INTERFACE_DESCRIPTOR); ((PUSB_CONFIGURATION_DESCRIPTOR)decode_data.buffer)->wTotalLength += sizeof(USB_INTERFACE_DESCRIPTOR); for (j = 0; j < usb_config->interfaces[i]->interface_descriptor.bNumEndpoints; j++) { memcpy(ptr, &usb_config->interfaces[i]->endpoints[j]->endpoint_descriptor, sizeof(USB_ENDPOINT_DESCRIPTOR)); ptr += sizeof(USB_ENDPOINT_DESCRIPTOR); ((PUSB_CONFIGURATION_DESCRIPTOR)decode_data.buffer)->wTotalLength += sizeof(USB_ENDPOINT_DESCRIPTOR); } } } *decode_data.length = ((PUSB_CONFIGURATION_DESCRIPTOR)decode_data.buffer)->wTotalLength; //if (urb->UrbControlDescriptorRequest.TransferBufferLength == 9) // ((PUSB_CONFIGURATION_DESCRIPTOR)decode_data.buffer)->wTotalLength = 32; urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; } case 0x00: // unknown... doing the same as 0x29 seems to work FUNCTION_MSG(" USB_00_DESCRIPTOR_TYPE (doesn't exist)\n"); urb->UrbHeader.Status = USBD_STATUS_BAD_DESCRIPTOR; break; case 0x29: // Hub Descriptor { PUSB_HUB_DESCRIPTOR uhd; FUNCTION_MSG(" USB_HUB_DESCRIPTOR_TYPE\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.HiByte); FUNCTION_MSG(" length = %d\n", *decode_data.length); uhd = decode_data.buffer; // TODO adjust for real number of ports *decode_data.length = FIELD_OFFSET(USB_HUB_DESCRIPTOR, bRemoveAndPowerMask[0]) + 2 + 1; uhd->bDescriptorLength = (UCHAR)*decode_data.length; uhd->bDescriptorType = 0x29; uhd->bNumberOfPorts = (UCHAR)xudd->num_ports; uhd->wHubCharacteristics = 0x0012; // no power switching no overcurrent protection uhd->bPowerOnToPowerGood = 1; // 2ms units uhd->bHubControlCurrent = 0; // DeviceRemovable bits (includes an extra bit at the start) uhd->bRemoveAndPowerMask[0] = 0; uhd->bRemoveAndPowerMask[1] = 0; // PortPwrCtrlMask uhd->bRemoveAndPowerMask[2] = 0xFF; urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; } default: FUNCTION_MSG(" USB_%02x_DESCRIPTOR_TYPE\n", (ULONG)decode_data.setup_packet.default_pipe_setup_packet.wValue.HiByte); FUNCTION_MSG("bmRequestType = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.B); FUNCTION_MSG(" Recipient = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient); FUNCTION_MSG(" Type = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type); FUNCTION_MSG(" Dir = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Dir); FUNCTION_MSG("bRequest = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.bRequest); FUNCTION_MSG("wValue = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.W); FUNCTION_MSG(" Low = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.LowByte); FUNCTION_MSG(" High = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.HiByte); FUNCTION_MSG("wIndex = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex); FUNCTION_MSG(" Low = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte); FUNCTION_MSG(" High = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.HiByte); FUNCTION_MSG("wLength = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wLength); break; } break; case USB_REQUEST_CLEAR_FEATURE: FUNCTION_MSG(" USB_REQUEST_CLEAR_FEATURE\n"); switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type) { case BMREQUEST_STANDARD: /* Standard */ FUNCTION_MSG(" Type=Standard\n"); switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient) { case BMREQUEST_TO_DEVICE: FUNCTION_MSG(" Recipient=Device\n"); switch (decode_data.setup_packet.default_pipe_setup_packet.wValue.W) { case 1: /* DEVICE_REMOTE_WAKEUP */ FUNCTION_MSG(" Feature=DEVICE_REMOTE_WAKEUP\n"); /* fake this */ urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; default: FUNCTION_MSG(__DRIVER_NAME " Feature=%d (not valid)\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.W); break; } break; default: FUNCTION_MSG(__DRIVER_NAME " Recipient=%d (not valid)\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient); break; } break; break; case BMREQUEST_CLASS: /* Class */ FUNCTION_MSG(" Type=Class\n"); switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient) { case BMREQUEST_TO_OTHER: FUNCTION_MSG(" Recipient=Other (port = %d)\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte); switch (urb->UrbControlVendorClassRequest.Value) { case PORT_ENABLE: FUNCTION_MSG(" PORT_ENABLE\n"); xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status &= ~(1 << PORT_ENABLE); urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; case PORT_SUSPEND: FUNCTION_MSG(" PORT_SUSPEND (NOOP)\n"); /* do something here */ urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; case C_PORT_CONNECTION: FUNCTION_MSG(" C_PORT_CONNECTION\n"); xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_change &= ~(1 << PORT_CONNECTION); urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; case C_PORT_ENABLE: FUNCTION_MSG(" C_PORT_ENABLE\n"); xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_change &= ~(1 << PORT_ENABLE); urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; case C_PORT_RESET: FUNCTION_MSG(" C_PORT_RESET\n"); xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_change &= ~(1 << PORT_RESET); urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; default: FUNCTION_MSG(" Unknown Value %04X\n", urb->UrbControlVendorClassRequest.Value); break; } FUNCTION_MSG(" status = %04x, change = %04x\n", xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status, xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_change); break; default: FUNCTION_MSG(" Recipient=%d\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient); break; } break; default: FUNCTION_MSG(" Type=%d\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type); break; } break; case USB_REQUEST_SET_FEATURE: FUNCTION_MSG(" USB_REQUEST_SET_FEATURE\n"); FUNCTION_MSG(" SetPortFeature\n"); switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type) { case 0: /* Standard */ FUNCTION_MSG(" Type=Standard\n"); switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient) { case BMREQUEST_TO_DEVICE: FUNCTION_MSG(" Recipient=Device\n"); switch (decode_data.setup_packet.default_pipe_setup_packet.wValue.W) { case 1: /* DEVICE_REMOTE_WAKEUP */ FUNCTION_MSG(" Feature=DEVICE_REMOTE_WAKEUP\n"); /* fake this */ urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; default: FUNCTION_MSG(__DRIVER_NAME " Feature=%d (not valid)\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.W); break; } break; default: FUNCTION_MSG(__DRIVER_NAME " Recipient=%d (not valid)\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient); break; } break; case 1: /* Class */ FUNCTION_MSG(" Type=Class\n"); switch (decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient) { case BMREQUEST_TO_OTHER: FUNCTION_MSG(" Recipient=Other (port = %d)\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte); switch (decode_data.setup_packet.default_pipe_setup_packet.wValue.W) { case PORT_ENABLE: FUNCTION_MSG(" PORT_ENABLE (NOOP)\n"); /* do something here */ urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; case PORT_SUSPEND: FUNCTION_MSG(" PORT_SUSPEND (NOOP)\n"); /* do something here */ urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; case PORT_RESET: FUNCTION_MSG(" PORT_RESET\n"); /* just fake the reset by setting the status bit to indicate that the reset is complete*/ //xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status |= (1 << PORT_RESET); //xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].reset_counter = 10; // TODO: maybe fake a 10ms time here... xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status &= ~(1 << PORT_RESET); xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status |= (1 << PORT_ENABLE); xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_change |= (1 << PORT_RESET); urb->UrbHeader.Status = USBD_STATUS_SUCCESS; endpoint = xupdd->usb_device->configs[0]->interfaces[0]->endpoints[0]; XenUsbHub_ProcessHubInterruptEvent(endpoint); break; case PORT_POWER: FUNCTION_MSG(" PORT_POWER\n"); xudd->ports[decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte - 1].port_status |= (1 << PORT_POWER); urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; default: FUNCTION_MSG(" PORT_%04X\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.W); break; } FUNCTION_MSG(" status = %04x, change = %04x\n", xudd->ports[urb->UrbControlVendorClassRequest.Index - 1].port_status, xudd->ports[urb->UrbControlVendorClassRequest.Index - 1].port_change); break; default: FUNCTION_MSG(__DRIVER_NAME " Recipient=%d (not valid)\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient); break; } break; } break; default: FUNCTION_MSG(" USB_REQUEST_%02x\n", (ULONG)decode_data.setup_packet.default_pipe_setup_packet.bRequest); FUNCTION_MSG(" TransferBufferLength returned = %d\n", urb->UrbControlDescriptorRequest.TransferBufferLength); break; } break; case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL: FUNCTION_MSG("URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL\n"); FUNCTION_MSG(" PipeHandle = %p\n", urb->UrbPipeRequest.PipeHandle); urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; case URB_FUNCTION_ABORT_PIPE: FUNCTION_MSG("URB_FUNCTION_ABORT_PIPE\n"); FUNCTION_MSG(" PipeHandle = %p\n", urb->UrbPipeRequest.PipeHandle); urb->UrbHeader.Status = USBD_STATUS_SUCCESS; break; case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: /* 11.12.4 */ #if 0 FUNCTION_MSG("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER\n"); FUNCTION_MSG(" PipeHandle = %p\n", urb->UrbBulkOrInterruptTransfer.PipeHandle); FUNCTION_MSG(" TransferFlags = %08x\n", urb->UrbBulkOrInterruptTransfer.TransferFlags); FUNCTION_MSG(" TransferBufferLength = %d\n", urb->UrbBulkOrInterruptTransfer.TransferBufferLength); FUNCTION_MSG(" TransferBuffer = %p\n", urb->UrbBulkOrInterruptTransfer.TransferBuffer); FUNCTION_MSG(" TransferBufferMdl = %p\n", urb->UrbBulkOrInterruptTransfer.TransferBufferMDL); #endif endpoint = urb->UrbBulkOrInterruptTransfer.PipeHandle; //WdfSpinLockAcquire(endpoint->lock); WdfRequestForwardToIoQueue(request, endpoint->queue); XenUsbHub_ProcessHubInterruptEvent(endpoint); //WdfSpinLockRelease(endpoint->lock); //FUNCTION_EXIT(); return; default: FUNCTION_MSG("URB_FUNCTION_%04x\n", urb->UrbHeader.Function); if (decode_retval != URB_DECODE_NOT_CONTROL) { FUNCTION_MSG("bmRequestType = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.B); FUNCTION_MSG(" Recipient = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Recipient); FUNCTION_MSG(" Type = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Type); FUNCTION_MSG(" Dir = %x\n", decode_data.setup_packet.default_pipe_setup_packet.bmRequestType.Dir); FUNCTION_MSG("bRequest = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.bRequest); FUNCTION_MSG("wValue = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.W); FUNCTION_MSG(" Low = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.LowByte); FUNCTION_MSG(" High = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wValue.HiByte); FUNCTION_MSG("wIndex = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex); FUNCTION_MSG(" Low = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.LowByte); FUNCTION_MSG(" High = %02x\n", decode_data.setup_packet.default_pipe_setup_packet.wIndex.HiByte); FUNCTION_MSG("wLength = %04x\n", decode_data.setup_packet.default_pipe_setup_packet.wLength); } urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION; break; } if (urb->UrbHeader.Status == USBD_STATUS_SUCCESS) { //FUNCTION_MSG("Calling WdfRequestCompletestatus with status = %08x\n", STATUS_SUCCESS); WdfRequestComplete(request, STATUS_SUCCESS); } else { FUNCTION_MSG("Calling WdfRequestCompletestatus with status = %08x\n", STATUS_UNSUCCESSFUL); WdfRequestComplete(request, STATUS_UNSUCCESSFUL); } //FUNCTION_EXIT(); return; }
VOID NonPnpEvtDeviceIoInCallerContext( IN WDFDEVICE Device, IN WDFREQUEST Request ) /*++ Routine Description: This I/O in-process callback is called in the calling threads context/address space before the request is subjected to any framework locking or queueing scheme based on the device pnp/power or locking attributes set by the driver. The process context of the calling app is guaranteed as long as this driver is a top-level driver and no other filter driver is attached to it. This callback is only required if you are handling method-neither IOCTLs, or want to process requests in the context of the calling process. Driver developers should avoid defining neither IOCTLs and access user buffers, and use much safer I/O tranfer methods such as buffered I/O or direct I/O. Arguments: Device - Handle to a framework device object. Request - Handle to a framework request object. Framework calls PreProcess callback only for Read/Write/ioctls and internal ioctl requests. Return Value: VOID --*/ { NTSTATUS status = STATUS_SUCCESS; PREQUEST_CONTEXT reqContext = NULL; WDF_OBJECT_ATTRIBUTES attributes; WDF_REQUEST_PARAMETERS params; size_t inBufLen, outBufLen; PVOID inBuf, outBuf; PAGED_CODE(); WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters(Request, ¶ms ); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Entered NonPnpEvtDeviceIoInCallerContext %p \n", Request); // // Check to see whether we have recevied a METHOD_NEITHER IOCTL. if not // just send the request back to framework because we aren't doing // any pre-processing in the context of the calling thread process. // if(!(params.Type == WdfRequestTypeDeviceControl && params.Parameters.DeviceIoControl.IoControlCode == IOCTL_NONPNP_METHOD_NEITHER)) { // // Forward it for processing by the I/O package // status = WdfDeviceEnqueueRequest(Device, Request); if( !NT_SUCCESS(status) ) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Error forwarding Request 0x%x", status); goto End; } return; } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "EvtIoPreProcess: received METHOD_NEITHER ioctl \n"); // // In this type of transfer, the I/O manager assigns the user input // to Type3InputBuffer and the output buffer to UserBuffer of the Irp. // The I/O manager doesn't copy or map the buffers to the kernel // buffers. // status = WdfRequestRetrieveUnsafeUserInputBuffer(Request, 0, &inBuf, &inBufLen); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Error WdfRequestRetrieveUnsafeUserInputBuffer failed 0x%x", status); goto End; } status = WdfRequestRetrieveUnsafeUserOutputBuffer(Request, 0, &outBuf, &outBufLen); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Error WdfRequestRetrieveUnsafeUserOutputBuffer failed 0x%x", status); goto End; } // // Allocate a context for this request so that we can store the memory // objects created for input and output buffer. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT); status = WdfObjectAllocateContext(Request, &attributes, &reqContext); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Error WdfObjectAllocateContext failed 0x%x", status); goto End; } // // WdfRequestProbleAndLockForRead/Write function checks to see // whether the caller in the right thread context, creates an MDL, // probe and locks the pages, and map the MDL to system address // space and finally creates a WDFMEMORY object representing this // system buffer address. This memory object is associated with the // request. So it will be freed when the request is completed. If we // are accessing this memory buffer else where, we should store these // pointers in the request context. // #pragma prefast(suppress:6387, "If inBuf==NULL at this point, then inBufLen==0") status = WdfRequestProbeAndLockUserBufferForRead(Request, inBuf, inBufLen, &reqContext->InputMemoryBuffer); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Error WdfRequestProbeAndLockUserBufferForRead failed 0x%x", status); goto End; } #pragma prefast(suppress:6387, "If outBuf==NULL at this point, then outBufLen==0") status = WdfRequestProbeAndLockUserBufferForWrite(Request, outBuf, outBufLen, &reqContext->OutputMemoryBuffer); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Error WdfRequestProbeAndLockUserBufferForWrite failed 0x%x", status); goto End; } // // Finally forward it for processing by the I/O package // status = WdfDeviceEnqueueRequest(Device, Request); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Error WdfDeviceEnqueueRequest failed 0x%x", status); goto End; } return; End: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "EvtIoPreProcess failed %x \n", status); WdfRequestComplete(Request, status); return; }
static VOID XenUsb_EvtIoInternalDeviceControl_PVURB( WDFQUEUE queue, WDFREQUEST request, size_t output_buffer_length, size_t input_buffer_length, ULONG io_control_code) { NTSTATUS status; WDFDEVICE device = WdfIoQueueGetDevice(queue); PXENUSB_DEVICE_DATA xudd = GetXudd(device); WDF_REQUEST_PARAMETERS wrp; pvurb_t *pvurb; partial_pvurb_t *partial_pvurb; KIRQL old_irql; UNREFERENCED_PARAMETER(input_buffer_length); UNREFERENCED_PARAMETER(output_buffer_length); UNREFERENCED_PARAMETER(io_control_code); FUNCTION_ENTER(); ASSERT(io_control_code == IOCTL_INTERNAL_PVUSB_SUBMIT_URB); WDF_REQUEST_PARAMETERS_INIT(&wrp); WdfRequestGetParameters(request, &wrp); pvurb = (pvurb_t *)wrp.Parameters.Others.Arg1; ASSERT(pvurb); RtlZeroMemory(&pvurb->rsp, sizeof(pvurb->rsp)); pvurb->status = STATUS_SUCCESS; pvurb->request = request; pvurb->ref = 1; pvurb->total_length = 0; partial_pvurb = ExAllocatePoolWithTag(NonPagedPool, sizeof(*partial_pvurb), XENUSB_POOL_TAG); /* todo - use lookaside */ if (!partial_pvurb) { WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES); FUNCTION_EXIT(); return; } KeAcquireSpinLock(&xudd->urb_ring_lock, &old_irql); status = WdfRequestMarkCancelableEx(request, XenUsb_EvtRequestCancelPvUrb); if (!NT_SUCCESS(status)) { KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql); FUNCTION_MSG("WdfRequestMarkCancelableEx returned %08x\n", status); WdfRequestComplete(request, STATUS_INSUFFICIENT_RESOURCES); FUNCTION_EXIT(); return; } partial_pvurb->req = pvurb->req; partial_pvurb->mdl = pvurb->mdl; /* 1:1 right now, but may need to split up large pvurb into smaller partial_pvurb's */ partial_pvurb->pvurb = pvurb; partial_pvurb->other_partial_pvurb = NULL; partial_pvurb->on_ring = FALSE; if (!partial_pvurb->mdl) { partial_pvurb->req.nr_buffer_segs = 0; partial_pvurb->req.buffer_length = 0; } else { ULONG remaining = MmGetMdlByteCount(partial_pvurb->mdl); USHORT offset = (USHORT)MmGetMdlByteOffset(partial_pvurb->mdl); int i; partial_pvurb->req.buffer_length = (USHORT)MmGetMdlByteCount(partial_pvurb->mdl); partial_pvurb->req.nr_buffer_segs = (USHORT)ADDRESS_AND_SIZE_TO_SPAN_PAGES(MmGetMdlVirtualAddress(partial_pvurb->mdl), MmGetMdlByteCount(partial_pvurb->mdl)); for (i = 0; i < partial_pvurb->req.nr_buffer_segs; i++) { partial_pvurb->req.seg[i].gref = XnGrantAccess(xudd->handle, (ULONG)MmGetMdlPfnArray(partial_pvurb->mdl)[i], FALSE, INVALID_GRANT_REF, (ULONG)'XUSB'); partial_pvurb->req.seg[i].offset = (USHORT)offset; partial_pvurb->req.seg[i].length = (USHORT)min((USHORT)remaining, (USHORT)PAGE_SIZE - offset); offset = 0; remaining -= partial_pvurb->req.seg[i].length; FUNCTION_MSG("seg = %d\n", i); FUNCTION_MSG(" gref = %d\n", partial_pvurb->req.seg[i].gref); FUNCTION_MSG(" offset = %d\n", partial_pvurb->req.seg[i].offset); FUNCTION_MSG(" length = %d\n", partial_pvurb->req.seg[i].length); } FUNCTION_MSG("buffer_length = %d\n", partial_pvurb->req.buffer_length); FUNCTION_MSG("nr_buffer_segs = %d\n", partial_pvurb->req.nr_buffer_segs); } InsertTailList(&xudd->partial_pvurb_queue, &partial_pvurb->entry); PutRequestsOnRing(xudd); KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql); FUNCTION_EXIT(); }
VOID NICServiceReadIrps( PFDO_DATA FdoData, PMP_RFD *PacketArray, ULONG PacketArrayCount ) /*++ Routine Description: Copy the data from the recv buffers to pending read IRP buffers and complete the IRP. When used as network driver, copy operation can be avoided by devising a private interface between us and the NDIS-WDM filter and have the NDIS-WDM edge to indicate our buffers directly to NDIS. Called at DISPATCH_LEVEL. Take advantage of that fact while acquiring spinlocks. Arguments: FdoData Pointer to our FdoData Return Value: None --*/ { PMP_RFD pMpRfd = NULL; ULONG index; NTSTATUS status; PVOID buffer; WDFREQUEST request; size_t bufLength=0; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "--> NICServiceReadIrps\n"); for(index=0; index < PacketArrayCount; index++) { pMpRfd = PacketArray[index]; ASSERT(pMpRfd); status = WdfIoQueueRetrieveNextRequest( FdoData->PendingReadQueue, &request ); if(NT_SUCCESS(status)){ WDF_REQUEST_PARAMETERS params; ULONG length = 0; WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters( request, ¶ms ); ASSERT(status == STATUS_SUCCESS); bufLength = params.Parameters.Read.Length; status = WdfRequestRetrieveOutputBuffer(request, bufLength, &buffer, &bufLength); if(NT_SUCCESS(status) ) { length = min((ULONG)bufLength, pMpRfd->PacketSize); RtlCopyMemory(buffer, pMpRfd->Buffer, length); Hexdump((TRACE_LEVEL_VERBOSE, DBG_READ, "Received Packet Data: %!HEXDUMP!\n", log_xstr(buffer, (USHORT)length))); FdoData->BytesReceived += length; } WdfRequestCompleteWithInformation(request, status, length); }else { ASSERTMSG("WdfIoQueueRetrieveNextRequest failed", (status == STATUS_NO_MORE_ENTRIES || status == STATUS_WDF_PAUSED)); } WdfSpinLockAcquire(FdoData->RcvLock); ASSERT(MP_TEST_FLAG(pMpRfd, fMP_RFD_RECV_PEND)); MP_CLEAR_FLAG(pMpRfd, fMP_RFD_RECV_PEND); if (FdoData->RfdShrinkCount < NIC_RFD_SHRINK_THRESHOLD) { NICReturnRFD(FdoData, pMpRfd); } else { ASSERT(FdoData->CurrNumRfd > FdoData->NumRfd); status = PciDrvQueuePassiveLevelCallback(FdoData, NICFreeRfdWorkItem, (PVOID)pMpRfd, NULL); if(NT_SUCCESS(status)){ FdoData->RfdShrinkCount = 0; FdoData->CurrNumRfd--; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "Shrink... CurrNumRfd = %d\n", FdoData->CurrNumRfd); } else { // // We couldn't queue a workitem to free memory, so let us // put that back in the main pool and try again next time. // NICReturnRFD(FdoData, pMpRfd); } } WdfSpinLockRelease(FdoData->RcvLock); }// end of loop TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<-- NICServiceReadIrps\n"); return; }
VOID MarsEvtIoRead ( WDFQUEUE Queue, WDFREQUEST Request, size_t Length ) /*++ Routine Description: This event is called when the framework receives IRP_MJ_READ 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. --*/ { WDFDEVICE device; PFDO_DATA fdoData; PMDL mdlAddress; WDF_REQUEST_PARAMETERS parameters; NTSTATUS status; ULONG bytesRead; device = WdfIoQueueGetDevice(Queue); fdoData = MarsFdoGetData(device); status = WdfRequestRetrieveOutputWdmMdl(Request,&mdlAddress); if (!NT_SUCCESS(status)) { WdfRequestComplete(Request, status); return; } WDF_REQUEST_PARAMETERS_INIT(¶meters); WdfRequestGetParameters(Request, ¶meters); status = SdioReadWriteBuffer(device, fdoData->FunctionFocus, mdlAddress, (ULONG)parameters.Parameters.Read.DeviceOffset, (ULONG)parameters.Parameters.Read.Length, FALSE, &bytesRead); WdfRequestCompleteWithInformation(Request, status, bytesRead); return; }
static VOID XenBus_EvtIoWrite(WDFQUEUE queue, WDFREQUEST request, size_t length) { NTSTATUS status; PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfIoQueueGetDevice(queue)); WDFFILEOBJECT file_object = WdfRequestGetFileObject(request); PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object); KIRQL old_irql; WDFREQUEST read_request; PUCHAR buffer; PUCHAR src_ptr; ULONG src_len; PUCHAR dst_ptr; ULONG copy_len; struct xsd_sockmsg *rep; xenbus_read_queue_item_t *list_entry; watch_context_t *watch_context; PCHAR watch_path; PCHAR watch_token; PCHAR msg; FUNCTION_ENTER(); status = WdfRequestRetrieveInputBuffer(request, length, &buffer, NULL); ASSERT(NT_SUCCESS(status)); src_ptr = (PUCHAR)buffer; src_len = (ULONG)length; dst_ptr = xpdid->xenbus.u.buffer + xpdid->xenbus.len; while (src_len != 0) { KdPrint((__DRIVER_NAME " %d bytes of write buffer remaining\n", src_len)); /* get a complete msg header */ if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg)) { copy_len = min(sizeof(xpdid->xenbus.u.msg) - xpdid->xenbus.len, src_len); if (!copy_len) continue; memcpy(dst_ptr, src_ptr, copy_len); dst_ptr += copy_len; src_ptr += copy_len; src_len -= copy_len; xpdid->xenbus.len += copy_len; } /* exit if we can't get that */ if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg)) continue; /* get a complete msg body */ if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len) { copy_len = min(sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len - xpdid->xenbus.len, src_len); if (!copy_len) continue; memcpy(dst_ptr, src_ptr, copy_len); dst_ptr += copy_len; src_ptr += copy_len; src_len -= copy_len; xpdid->xenbus.len += copy_len; } /* exit if we can't get that */ if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len) { continue; } switch (xpdid->xenbus.u.msg.type) { case XS_WATCH: case XS_UNWATCH: KeAcquireSpinLock(&xpdid->lock, &old_irql); watch_context = (watch_context_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(watch_context_t), XENPCI_POOL_TAG); watch_path = (PCHAR)(xpdid->xenbus.u.buffer + sizeof(struct xsd_sockmsg)); watch_token = (PCHAR)(xpdid->xenbus.u.buffer + sizeof(struct xsd_sockmsg) + strlen(watch_path) + 1); RtlStringCbCopyA(watch_context->path, ARRAY_SIZE(watch_context->path), watch_path); RtlStringCbCopyA(watch_context->token, ARRAY_SIZE(watch_context->path), watch_token); watch_context->file_object = file_object; if (xpdid->xenbus.u.msg.type == XS_WATCH) InsertTailList(&xpdid->xenbus.watch_list_head, &watch_context->entry); KeReleaseSpinLock(&xpdid->lock, old_irql); if (xpdid->xenbus.u.msg.type == XS_WATCH) msg = XenBus_AddWatch(xpdd, XBT_NIL, watch_path, XenPci_IoWatch, watch_context); else msg = XenBus_RemWatch(xpdd, XBT_NIL, watch_path, XenPci_IoWatch, watch_context); KeAcquireSpinLock(&xpdid->lock, &old_irql); if (msg != NULL) { rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg) + strlen(msg) + 1, XENPCI_POOL_TAG); rep->type = XS_ERROR; rep->req_id = xpdid->xenbus.u.msg.req_id; rep->tx_id = xpdid->xenbus.u.msg.tx_id; rep->len = (ULONG)(strlen(msg) + 0); RtlStringCbCopyA((PCHAR)(rep + 1), strlen(msg) + 1, msg); if (xpdid->xenbus.u.msg.type == XS_WATCH) RemoveEntryList(&watch_context->entry); } else { if (xpdid->xenbus.u.msg.type == XS_WATCH) { WdfObjectReference(file_object); } else { RemoveEntryList(&watch_context->entry); WdfObjectDereference(file_object); } rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg), XENPCI_POOL_TAG); rep->type = xpdid->xenbus.u.msg.type; rep->req_id = xpdid->xenbus.u.msg.req_id; rep->tx_id = xpdid->xenbus.u.msg.tx_id; rep->len = 0; } KeReleaseSpinLock(&xpdid->lock, old_irql); break; default: rep = XenBus_Raw(xpdd, &xpdid->xenbus.u.msg); break; } xpdid->xenbus.len = 0; KeAcquireSpinLock(&xpdid->lock, &old_irql); list_entry = (xenbus_read_queue_item_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(xenbus_read_queue_item_t), XENPCI_POOL_TAG); list_entry->data = rep; list_entry->length = sizeof(*rep) + rep->len; list_entry->offset = 0; InsertTailList(&xpdid->xenbus.read_list_head, (PLIST_ENTRY)list_entry); // Check if someone was waiting for the answer already status = WdfIoQueueRetrieveNextRequest(xpdid->xenbus.io_queue, &read_request); if (NT_SUCCESS(status)) { WDF_REQUEST_PARAMETERS parameters; KdPrint((__DRIVER_NAME " post-write: found pending read\n")); WDF_REQUEST_PARAMETERS_INIT(¶meters); WdfRequestGetParameters(read_request, ¶meters); XenBus_ProcessReadRequest(xpdid->xenbus.io_queue, read_request, parameters.Parameters.Read.Length); WdfRequestComplete(read_request, STATUS_SUCCESS); } else { KdPrint((__DRIVER_NAME " post-write: no pending read (%08x)\n", status)); } KeReleaseSpinLock(&xpdid->lock, old_irql); } KdPrint((__DRIVER_NAME " completing request with length %d\n", length)); WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, length); FUNCTION_EXIT(); }
VCHIQ_PAGED_SEGMENT_BEGIN /*++ Routine Description: VchiqIoDeviceControl handles VCHIQ IOCTL. Arguments: DeviceContextPtr - Pointer to device context WdfRequest - A handle to a framework request object. OutputBufferLength - The length, in bytes, of the request's output buffer, if an output buffer is available. InputBufferLength - The length, in bytes, 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: None --*/ _Use_decl_annotations_ VOID VchiqIoDeviceControl ( WDFQUEUE Queue, WDFREQUEST WdfRequest, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode ) { NTSTATUS status; VCHIQ_FILE_CONTEXT* vchiqFileContextPtr; WDFDEVICE device = WdfIoQueueGetDevice(Queue); DEVICE_CONTEXT* deviceContextPtr = VchiqGetDeviceContext(device); PAGED_CODE(); if (deviceContextPtr->VCConnected == FALSE) { VCHIQ_LOG_WARNING("VCHIQ interface not ready"); status = STATUS_DEVICE_NOT_READY; goto CompleteRequest; } // First process IOCTL that does not require a file context switch (IoControlCode) { case IOCTL_VCHIQ_CONNECT: { // Connect is a simple ioctl to ensure that we have establish // connection with VC firmware. Connection is establish by // initiating the slots which if we reach this point has // already been initialize. We just send a message to notify // the firmware too WDFFILEOBJECT wdfFileObject = WdfRequestGetFileObject(WdfRequest); if (wdfFileObject == NULL) { WDF_REQUEST_PARAMETERS wdfRequestParameters; WdfRequestGetParameters(WdfRequest, &wdfRequestParameters); VCHIQ_LOG_ERROR( "Fail to retrieve file object. \ (WdfRequest = 0x%p, Type = 0x%lx)", WdfRequest, (ULONG)wdfRequestParameters.Type); status = STATUS_INTERNAL_ERROR; goto CompleteRequest; } // Create a file context here as vchiq_arm would immediately begin // to send IOCTL to wait for completion message vchiqFileContextPtr = VchiqGetFileContext(wdfFileObject); if (vchiqFileContextPtr != NULL) { VCHIQ_LOG_ERROR( "Caller has already connected to a service"); status = STATUS_UNSUCCESSFUL; goto CompleteRequest; } status = VchiqAllocateFileObjContext( deviceContextPtr, wdfFileObject, &vchiqFileContextPtr); if (!NT_SUCCESS (status)) { VCHIQ_LOG_ERROR( "VchiqAllocateFileObjContext failed (%!STATUS!)", status); goto CompleteRequest; } status = VchiqQueueMessageAsync( deviceContextPtr, vchiqFileContextPtr, VCHIQ_MAKE_MSG(VCHIQ_MSG_CONNECT, 0, 0), NULL, 0); if (!NT_SUCCESS (status)) { VCHIQ_LOG_ERROR( "VchiqQueueMessageAsync failed (%!STATUS!)", status); goto CompleteRequest; } goto CompleteRequest; } case IOCTL_VCHIQ_GET_CONFIG: { VCHIQ_CONFIG vchiqCurrentConfig = { VCHIQ_MAX_MSG_SIZE, VCHIQ_MAX_MSG_SIZE, VCHIQ_NUM_SERVICE_BULKS, VCHIQ_MAX_SERVICES, VCHIQ_VERSION, VCHIQ_VERSION_MIN }; VCHIQ_GET_CONFIG* clientConfigPtr; status = WdfRequestRetrieveInputBuffer( WdfRequest, sizeof(*clientConfigPtr), &clientConfigPtr, NULL); if (!NT_SUCCESS(status)) { VCHIQ_LOG_ERROR( "WdfRequestRetrieveInputBuffer failed (%!STATUS!)", status); goto CompleteRequest; } // Ensure that the buffer provided is not too big. if (clientConfigPtr->ConfigSize > sizeof(VCHIQ_CONFIG)) { VCHIQ_LOG_WARNING("Config buffer too big"); status = STATUS_INVALID_PARAMETER; goto CompleteRequest; } VCHIQ_CONFIG* configurationPtr; size_t bufferSize; configurationPtr = WdfMemoryGetBuffer( clientConfigPtr->WdfMemoryConfiguration, &bufferSize); if ((configurationPtr == NULL) || (bufferSize != sizeof(*configurationPtr))) { VCHIQ_LOG_ERROR( "Caller provided invalid VCHIQ_CONFIG buffer 0x%08x %d", (ULONG)configurationPtr, bufferSize); status = STATUS_INVALID_PARAMETER; goto CompleteRequest; } RtlCopyMemory( configurationPtr, &vchiqCurrentConfig, sizeof(*clientConfigPtr->PConfig)); status = STATUS_SUCCESS; } goto CompleteRequest; case IOCTL_VCHIQ_LIB_VERSION: { ULONG* libVersion; status = WdfRequestRetrieveInputBuffer( WdfRequest, sizeof(*libVersion), &libVersion, NULL); if (!NT_SUCCESS(status)) { VCHIQ_LOG_ERROR( "WdfRequestRetrieveInputBuffer failed (%!STATUS!)", status); goto CompleteRequest; } if (*libVersion < VCHIQ_VERSION_MIN) { VCHIQ_LOG_ERROR( "Library version %d unsupported", *libVersion); status = STATUS_NOT_SUPPORTED; goto CompleteRequest; } status = STATUS_SUCCESS; } goto CompleteRequest; case IOCTL_VCHIQ_CREATE_SERVICE: default: { WDFFILEOBJECT wdfFileObject = WdfRequestGetFileObject(WdfRequest); if (wdfFileObject == NULL) { WDF_REQUEST_PARAMETERS wdfRequestParameters; WdfRequestGetParameters(WdfRequest, &wdfRequestParameters); VCHIQ_LOG_ERROR( "Fail to retrieve file object. \ (WdfRequest = 0x%p, Type = 0x%lx)", WdfRequest, (ULONG)wdfRequestParameters.Type); status = STATUS_INTERNAL_ERROR; goto CompleteRequest; } vchiqFileContextPtr = VchiqGetFileContext(wdfFileObject); if ((vchiqFileContextPtr == NULL) && (IoControlCode == IOCTL_VCHIQ_CREATE_SERVICE)) { // Functional test does not call connect prior to a create // service call, so we allocate a file context here instead status = VchiqAllocateFileObjContext( deviceContextPtr, wdfFileObject, &vchiqFileContextPtr); if (!NT_SUCCESS (status)) { VCHIQ_LOG_ERROR( "VchiqAllocateFileObjContext failed (%!STATUS!)", status); goto CompleteRequest; } } else if (vchiqFileContextPtr == NULL) { VCHIQ_LOG_ERROR( "Caller has not connected to a service %d", ((IoControlCode >> 2) & 0x0FFF)); status = STATUS_UNSUCCESSFUL; goto CompleteRequest; } } }
VOID MarsEvtIoWrite ( WDFQUEUE Queue, WDFREQUEST Request, size_t Length ) /*++ Routine Description: Called by the framework as soon as it receive a write IRP. If the device is not ready, fail the request. Otherwise get scatter-gather list for this request and send the packet to the hardware for DMA. 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 IO operation 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: --*/ { WDFDEVICE device; PFDO_DATA fdoData; PMDL mdlAddress; WDF_REQUEST_PARAMETERS parameters; NTSTATUS status; ULONG bytesRead; device = WdfIoQueueGetDevice(Queue); fdoData = MarsFdoGetData(device); status = WdfRequestRetrieveInputWdmMdl(Request,&mdlAddress); if (!NT_SUCCESS(status)) { WdfRequestComplete(Request, status); return; } WDF_REQUEST_PARAMETERS_INIT(¶meters); WdfRequestGetParameters(Request, ¶meters); status = SdioReadWriteBuffer(device, fdoData->FunctionFocus, mdlAddress, (ULONG)parameters.Parameters.Read.DeviceOffset, (ULONG)parameters.Parameters.Read.Length, TRUE, &bytesRead); WdfRequestCompleteWithInformation(Request, status, bytesRead); return; }
_Use_decl_annotations_ VOID TreeSampleProcessOtherDeviceIo( WDFDEVICE MasterDevice, WDFREQUEST Request ) /*++ Routine Description: This routine is called when an unrecognized IO request is made to the device. This can be used to process private calls directly to the secure device. Arguments: MasterDevice - Supplies a handle to the master device object. DeviceContext - Supplies a pointer to the context. Request - Supplies a pointer to the WDF request object. Return Value: NTSTATUS code. --*/ { PWCHAR Buffer; size_t BufferSize; ULONG BytesWritten; WDF_REQUEST_PARAMETERS Parameters; NTSTATUS Status; PAGED_CODE(); UNREFERENCED_PARAMETER(MasterDevice); WDF_REQUEST_PARAMETERS_INIT(&Parameters); WdfRequestGetParameters(Request, &Parameters); BytesWritten = 0; switch (Parameters.Parameters.DeviceIoControl.IoControlCode) { case IOCTL_SAMPLE_DBGPRINT: Status = WdfRequestRetrieveInputBuffer(Request, 0, (PVOID*)&Buffer, &BufferSize); if (!NT_SUCCESS(Status)) { goto TreeSampleProcessOtherDeviceIoEnd; } // // Must be NULL-terminated // if (Buffer[BufferSize / sizeof(WCHAR) - 1] != L'\0') { Status = STATUS_INVALID_PARAMETER; goto TreeSampleProcessOtherDeviceIoEnd; } DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, "[TrEEMiniportSample] %ws\n", (PWSTR)Buffer); break; default: Status = STATUS_INVALID_DEVICE_REQUEST; } TreeSampleProcessOtherDeviceIoEnd: WdfRequestCompleteWithInformation(Request, Status, BytesWritten); }
VOID EvtIoDeviceControl( WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode) { NTSTATUS status; BOOLEAN completeRequest = TRUE; WDFDEVICE device = WdfIoQueueGetDevice(Queue); PINPUT_DEVICE pContext = GetDeviceContext(device); ULONG uReportSize; HID_XFER_PACKET Packet; WDF_REQUEST_PARAMETERS params; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "--> %s, code = %d\n", __FUNCTION__, IoControlCode); switch (IoControlCode) { case IOCTL_HID_GET_DEVICE_DESCRIPTOR: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_GET_DEVICE_DESCRIPTOR\n"); // // Return the device's HID descriptor. // ASSERT(pContext->HidDescriptor.bLength != 0); status = RequestCopyFromBuffer(Request, &pContext->HidDescriptor, pContext->HidDescriptor.bLength); break; case IOCTL_HID_GET_DEVICE_ATTRIBUTES: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_GET_DEVICE_ATTRIBUTES\n"); // // Return the device's attributes in a HID_DEVICE_ATTRIBUTES structure. // status = RequestCopyFromBuffer(Request, &pContext->HidDeviceAttributes, sizeof(HID_DEVICE_ATTRIBUTES)); break; case IOCTL_HID_GET_REPORT_DESCRIPTOR: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_GET_REPORT_DESCRIPTOR\n"); // // Return the report descriptor for the HID device. // status = RequestCopyFromBuffer(Request, pContext->HidReportDescriptor, pContext->HidDescriptor.DescriptorList[0].wReportLength); break; case IOCTL_HID_READ_REPORT: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_READ_REPORT\n"); // // Queue up a report request. We'll complete it when we actually // receive data from the device. // status = WdfRequestForwardToIoQueue( Request, pContext->HidQueue); if (NT_SUCCESS(status)) { completeRequest = FALSE; } else { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTLS, "WdfRequestForwardToIoQueue failed with 0x%x\n", status); } break; case IOCTL_HID_WRITE_REPORT: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "IOCTL_HID_WRITE_REPORT\n"); // // Write a report to the device, commonly used for controlling keyboard // LEDs. We'll complete the request after the host processes all virtio // buffers we add to the status queue. // WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters(Request, ¶ms); if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) { status = STATUS_BUFFER_TOO_SMALL; } else { RtlCopyMemory(&Packet, WdfRequestWdmGetIrp(Request)->UserBuffer, sizeof(HID_XFER_PACKET)); WdfRequestSetInformation(Request, Packet.reportBufferLen); status = ProcessOutputReport(pContext, Request, &Packet); if (NT_SUCCESS(status)) { completeRequest = FALSE; } } break; default: TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTLS, "Unrecognized IOCTL %d\n", IoControlCode); status = STATUS_NOT_IMPLEMENTED; break; } if (completeRequest) { WdfRequestComplete(Request, status); } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "<-- %s\n", __FUNCTION__); }
VOID vJoy_EvtIoDeviceControlForRawPdo( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode ) /*++ Routine Description: This routine is the dispatch routine for device control requests. 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 --*/ { NTSTATUS status = STATUS_SUCCESS; WDFDEVICE parent; WDF_REQUEST_FORWARD_OPTIONS forwardOptions; PDEVICE_EXTENSION pDevContext = NULL; WDFMEMORY inMemory, outMemory; PVOID buffer; size_t bufSize; WDFDEVICE hRawDevice = WdfIoQueueGetDevice(Queue); PRPDO_DEVICE_DATA pdoData = PdoGetData(hRawDevice); WDF_REQUEST_SEND_OPTIONS RequestOptions; WDFIOTARGET TargetOnParent; JOYSTICK_POSITION_V2 * iReport; WDFFILEOBJECT FileObj; USHORT id=0; PFILEOBJECT_EXTENSION pExtension=NULL; WDFREQUEST requestForceFeedback; PHID_XFER_PACKET transferPacket = NULL; PVOID ForceFeedbackBuffer = NULL; PVOID GenBuffer = NULL; size_t bytesReturned = 0; WDF_REQUEST_PARAMETERS Params; BOOLEAN FfbStat = FALSE; ULONG bytesToCopy = 0; BYTE Byte_tmp; UNREFERENCED_PARAMETER(OutputBufferLength); UNREFERENCED_PARAMETER(InputBufferLength); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "Entered vJoy_EvtIoDeviceControlForRawPdo\n"); // // Process the ioctl and complete it when you are done. // Since the queue is configured for serial dispatch, you will // not receive another ioctl request until you complete this one. // switch (IoControlCode) { case 1234: // TODO: Remove for production //RequestOptions.Flags = WDF_REQUEST_SEND_OPTION_TIMEOUT; //RequestOptions.Size = sizeof(WDF_REQUEST_SEND_OPTIONS); //WDF_REQUEST_SEND_OPTIONS_SET_TIMEOUT(&RequestOptions, WDF_REL_TIMEOUT_IN_SEC(1)); //status = WdfIoTargetSendInternalIoctlSynchronously(pdoData->IoTargetToParent, Request, IoControlCode , NULL, NULL, &RequestOptions, NULL); break; // Testing case GET_DEV_STAT: // Get information for a device by device ID TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case GET_DEV_STAT\n"); // Get the buffer from the request // Get the data from the request WDF_REQUEST_PARAMETERS_INIT(&Params); WdfRequestGetParameters(Request, &Params); bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength; if (bytesToCopy<5) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: failed - bytesToCopy=%d\n", bytesToCopy); WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // Get the buffer status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned); if (bytesReturned<5) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: failed - bytesReturned=%d\n", bytesReturned); WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // Get the id number from input buffer status = WdfRequestRetrieveInputBuffer(Request, sizeof(BYTE), &buffer, &bufSize); if (!NT_SUCCESS(status) || (bufSize!=1)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: failed to retrieve input buffer\n"); WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // Get target ID id = *(BYTE *)buffer; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: id=%d\n", id); // Put data into output buffer // Byte 1: // Bit 0: Implemented? // Bit 1: FFB Device Enabled? // Bit 2: File Object associated with this device? pDevContext = GetDeviceContext(pdoData->hParentDevice); Byte_tmp = 0; // Implemented mask if (pDevContext->DeviceImplemented[id - 1]) Byte_tmp |= 1; else Byte_tmp &= 0xFE; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: Dev Implemented=%x\n", pDevContext->DeviceImplemented[id - 1]); // FFB mask TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: Dev Enabled=%x\n", pDevContext->FfbEnable[id - 1]); if (pDevContext->FfbEnable[id - 1]) Byte_tmp |= 2; else Byte_tmp &= 0xFD; // File Object if (pDevContext->DeviceFileObject[id - 1]) Byte_tmp |= 4; else Byte_tmp &= 0xFB; ((BYTE *)GenBuffer)[0] = Byte_tmp; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: Buffer[0]=%x\n", ((BYTE *)GenBuffer)[0]); // Byte2-5: Process ID // Get the context FileObj = pDevContext->DeviceFileObject[id - 1]; if (FileObj) *(DWORD *)(&((BYTE *)GenBuffer)[1]) = GetFileObjectContext(FileObj)->CallingProcessId; else *(DWORD *)(&((BYTE *)GenBuffer)[1]) = 0; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo[GET_DEV_STAT]: ProcessID=%x\n", *(DWORD *)(&((BYTE *)GenBuffer)[1])); // Complete the transaction WdfRequestCompleteWithInformation(Request, status, bytesReturned); return; case GET_DRV_INFO: // Get information for this driver TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO]\n"); // Get the buffer from the request // Get the data from the request WDF_REQUEST_PARAMETERS_INIT(&Params); WdfRequestGetParameters(Request, &Params); // Number of bytes to copy must be at least one byte bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength; if (bytesToCopy <1 ) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - bytesToCopy <1\n"); WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // Output buffer must be at least one byte status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned); if (bytesReturned<1) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - bytesReturned <1\n"); WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; pDevContext = GetDeviceContext(pdoData->hParentDevice); // Return the data in the output buffer // BYTE 0 ////////////////////////////// // Bit 0 : Supports FFB? // Bit 1 : Reserved // Bit 2 : Mode: Multi-device // Bit 3 : Mode: FFB // BYTE 1 ////////////////////////////// // Bits 0-7 : Maximum number of possible devices (16 ==> 255) not regarding to mode // BYTE 2 ////////////////////////////// // Bits 0-7 : Number of existing devices // BYTE 3 ////////////////////////////// // Bits 0-7 : Number of devices that can still be implemented (This is the number of possible devices for the current mode minus the number of already existing devices). ////////////////////////////////// // Byte 0 Byte_tmp = 0; Byte_tmp |= 0x01; // FFB Supported Byte_tmp |= 0x00; // Default Mode (TODO: Change to real mode when Implemented) Multi-Device=0x04; FFB=0x80 ((BYTE *)GenBuffer)[0] = Byte_tmp; // Byte 1 if (bytesToCopy >= 2 && bytesReturned >= 2) { ((BYTE *)GenBuffer)[1] = MAX_N_DEVICES; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - Data byte[1]=%02x\n", ((BYTE *)GenBuffer)[1]); } // Byte 2 if (bytesToCopy >= 3 && bytesReturned >= 3) { ((BYTE *)GenBuffer)[2] = (BYTE)(pDevContext->nDevices); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - Data byte[2]=%02x\n", ((BYTE *)GenBuffer)[2]); } // Byte 3 - TODO: Change according to mode if (bytesToCopy >= 4 && bytesReturned >= 4) { ((BYTE *)GenBuffer)[3] = MAX_N_DEVICES - (BYTE)(pDevContext->nDevices); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: [GET_DRV_INFO] - Data byte[3]=%02x\n", ((BYTE *)GenBuffer)[3]); } ////////////////////////////////// // Complete the transaction WdfRequestCompleteWithInformation(Request, status, bytesReturned); return; case GET_DEV_INFO: // Get information for this device (and for the driver) // Get the buffer from the request // Get the data from the request WDF_REQUEST_PARAMETERS_INIT(&Params); WdfRequestGetParameters(Request, &Params); bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength; if (bytesToCopy<6) { WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned); if (bytesReturned<6) { WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // Get the context, id and the status id = GetIdFromRawPdoRequest(Request, pExtension); // Illegal ID if (id == 0xFFFF) { WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // Copy the state to the buffer pDevContext = GetDeviceContext(pdoData->hParentDevice); ((BYTE *)GenBuffer)[0] = (BYTE)id; ((BYTE *)GenBuffer)[1] = (BYTE)(pDevContext->nDevices); ((BYTE *)GenBuffer)[2] = pDevContext->DeviceImplemented ? 1:0; ((BYTE *)GenBuffer)[3] = MAX_N_DEVICES; ((BYTE *)GenBuffer)[4] = 1; // Driver does support FFB ((BYTE *)GenBuffer)[5] = pDevContext->FfbEnable[id - 1]; // Device support FFB // Complete the transaction WdfRequestCompleteWithInformation(Request, status, bytesReturned); return; case 0x910: // Backward compatibility value of LOAD_POSITIONS case LOAD_POSITIONS: // KdBreakPoint(); Break When loading position status = WdfRequestRetrieveInputBuffer( Request, sizeof(JOYSTICK_POSITION), &buffer, &bufSize); if(!NT_SUCCESS(status)) break; // Get interface that this IRP came from, // then get the implicated id of the top-level collection id = GetIdFromRawPdoRequest(Request, pExtension); // Illegal ID if (id==0xFFFF) { WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // Get the incoming report and compare the id in the report // to the implicated id of the top-level collection // They should match iReport = buffer; if (iReport->bDevice != id) { WdfRequestComplete(Request, STATUS_CANCELLED); return; }; pDevContext = GetDeviceContext(pdoData->hParentDevice); LoadPositions(iReport, pDevContext, bufSize); status = vJoyCompleteReadReport(pdoData->hParentDevice, (BYTE)id); break; case GET_FFB_STAT: /* Get the status of the FFB mechanism */ // Get the buffer from the request // Get the data from the request WDF_REQUEST_PARAMETERS_INIT(&Params); WdfRequestGetParameters(Request, &Params); bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength; status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned); if (!bytesReturned) { WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // Get the context, id and the status id = GetIdFromRawPdoRequest(Request, pExtension); // Illegal ID if (id == 0xFFFF) { WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // Copy the state to the buffer pDevContext = GetDeviceContext(pdoData->hParentDevice); ((BYTE *)GenBuffer)[0] = pDevContext->FfbEnable[id-1]; // Complete the transaction WdfRequestCompleteWithInformation(Request, status, bytesReturned); return; case SET_FFB_STAT: /*Set the status of the FFB mechanism - Obsolete*/ // Get the data from the request WDF_REQUEST_PARAMETERS_INIT(&Params); WdfRequestGetParameters(Request, &Params); // Get interface that this IRP came from, // then get the implicated id of the top-level collection // Get the context, id and the status id = GetIdFromRawPdoRequest(Request, pExtension); // Illegal ID if (id == 0xFFFF) { WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // Get the data, process the data and complete the transaction //pDevContext = GetDeviceContext(pdoData->hParentDevice); - Obsolete //FfbActiveSet(*(BOOLEAN *)Params.Parameters.DeviceIoControl.Type3InputBuffer, id, pDevContext); - Obsolete WdfRequestComplete(Request, status); return; case GET_FFB_DATA: // Get interface that this IRP came from, // then get the implicated id of the top-level collection id = GetIdFromRawPdoRequest(Request, pExtension); // If FFB is not active then just reject this request pDevContext = GetDeviceContext(pdoData->hParentDevice); if (id == 0xFFFF || !pDevContext->FfbEnable[id - 1]) { WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // If FFB is active then forward this request to the ReadQ and return status = WdfRequestForwardToIoQueue(Request, pDevContext->FfbReadQ[id - 1]); if(!NT_SUCCESS(status)){ TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "WdfRequestForwardToIoQueue (FfbWriteQ[%d]) failed with status: 0x%x\n", id - 1, status); WdfRequestComplete(Request, status); } return; case GET_DRV_DEV_EN: // Get the number of devices that are currently enabled TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case GET_DRV_DEV_EN\n"); // Get the buffer from the request // Get the data from the request WDF_REQUEST_PARAMETERS_INIT(&Params); WdfRequestGetParameters(Request, &Params); bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesToCopy=%d\n", bytesToCopy); if (bytesToCopy<1) { WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesReturned=%d\n", bytesReturned); if (bytesReturned<1) { WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; if (!pdoData) break; pDevContext = GetDeviceContext(pdoData->hParentDevice); if (!pDevContext) break; // The number of the max supported devices ((BYTE *)GenBuffer)[0] = (BYTE)(pDevContext->nDevices); // Complete the transaction WdfRequestCompleteWithInformation(Request, status, bytesReturned); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: GenBuffer[0]=%d\n", ((BYTE *)GenBuffer)[0]); return; case GET_DRV_DEV_MAX: // Get the max possible number of devices that this driver supports TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case GET_DRV_DEV_MAX\n"); // Get the buffer from the request // Get the data from the request WDF_REQUEST_PARAMETERS_INIT(&Params); WdfRequestGetParameters(Request, &Params); bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesToCopy=%d\n", bytesToCopy); if (bytesToCopy<1) { WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesReturned=%d\n", bytesReturned); if (bytesReturned<1) { WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // The number of the max supported devices ((BYTE *)GenBuffer)[0] = MAX_N_DEVICES; // Complete the transaction WdfRequestCompleteWithInformation(Request, status, bytesReturned); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: GenBuffer[0]=%d\n", ((BYTE *)GenBuffer)[0]); return; case IS_DRV_FFB_CAP: // Test is this version of vJoy driver supports FFB TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case IS_DRV_FFB_CAP\n"); // Get the data from the request (Bytes to copy) WDF_REQUEST_PARAMETERS_INIT(&Params); WdfRequestGetParameters(Request, &Params); bytesToCopy = Params.Parameters.DeviceIoControl.OutputBufferLength; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesToCopy=%d\n", bytesToCopy); if (bytesToCopy<1) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesToCopy=%d (Failed)\n", bytesToCopy); WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // Get the buffer from the request status = WdfRequestRetrieveOutputBuffer(Request, bytesToCopy, &GenBuffer, &bytesReturned); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesReturned=%d\n", bytesReturned); if (bytesReturned<1) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: bytesReturned=%d (Failed)\n", bytesReturned); WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // Yes, this driver supports FFB ((BYTE *)GenBuffer)[0] = 1; // Complete the transaction WdfRequestCompleteWithInformation(Request, status, bytesReturned); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: GenBuffer[0]=%d\n", ((BYTE *)GenBuffer)[0]); return; case RESET_DEV: /* Resets device(s) to predefined values */ TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: Case RESET_DEV\n"); // then get the implicated id of the top-level collection id = GetIdFromRawPdoRequest(Request, pExtension); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtIoDeviceControlForRawPdo: ID=%d\n", id); // Sanity check if (id == 0xFFFF) { WdfRequestComplete(Request, STATUS_NO_SUCH_DEVICE); return; }; // Get the context of vJoy device pDevContext = GetDeviceContext(pdoData->hParentDevice); // Reset device(s) status = ResetDevice(id, pDevContext); WdfRequestCompleteWithInformation(Request, status, 0); return; default: break; } WdfRequestComplete(Request, status); return; }
/*++ Routine Description: This is the dispatch routine for write. It validates the parameters for the write request and if all is ok then it places the request on the work queue. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Pointer to the WDFREQUEST for the current request Length - Length of the IO operation 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: --*/ _Use_decl_annotations_ VOID SerialEvtIoWrite( WDFQUEUE Queue, WDFREQUEST Request, size_t Length ) { PSERIAL_DEVICE_EXTENSION extension; NTSTATUS status; WDFDEVICE hDevice; WDF_REQUEST_PARAMETERS params; PREQUEST_CONTEXT reqContext; size_t bufLen; UCHAR tempIER=0x00; hDevice = WdfIoQueueGetDevice(Queue); extension = SerialGetDeviceExtension(hDevice); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE, "++SerialEvtIoWrite(%p, 0x%I64x)\r\n", Request, Length); if (SerialCompleteIfError(extension, Request) != STATUS_SUCCESS) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE, "--SerialEvtIoWrite 1 %Xh\r\n", (ULONG)STATUS_CANCELLED); return; } WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters(Request, ¶ms); // Initialize the scratch area of the request. reqContext = SerialGetRequestContext(Request); reqContext->MajorFunction = params.Type; reqContext->Length = (ULONG) Length; status = WdfRequestRetrieveInputBuffer (Request, Length, &reqContext->SystemBuffer, &bufLen); if (!NT_SUCCESS (status)) { SerialCompleteRequest(Request , status, 0); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE, "--SerialEvtIoWrite 2 %Xh\r\n", status); return; } SerialStartOrQueue(extension, Request, extension->WriteQueue, &extension->CurrentWriteRequest, SerialStartWrite); // enable mini Uart Tx interrupt TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INTERRUPT, "SerialEvtIoWrite() - enable Tx interrupt\r\n"); tempIER=READ_INTERRUPT_ENABLE(extension, extension->Controller); WRITE_INTERRUPT_ENABLE(extension, extension->Controller, (tempIER | SERIAL_IER_THR)); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_WRITE, "--SerialEvtIoWrite()=%X\r\n", status); return; }