static VOID CompleteHIDQueueRequest( PINPUT_DEVICE pContext, PINPUT_CLASS_COMMON pClass) { WDFREQUEST request; NTSTATUS status; if (!pClass->bDirty) { // nothing to do return; } status = WdfIoQueueRetrieveNextRequest(pContext->HidQueue, &request); if (NT_SUCCESS(status)) { status = RequestCopyFromBuffer( request, pClass->pHidReport, pClass->cbHidReportSize); WdfRequestComplete(request, status); if (NT_SUCCESS(status)) { pClass->bDirty = FALSE; } } }
// This function gets called when the timeout period of debounce timer elapses. // It reports a switch change by completing a pending request // void HidFx2EvtTimerFunction(_In_ WDFTIMER hTimer) { WDFDEVICE hDevice = NULL; WDFREQUEST hRequest; PDEVICE_EXTENSION pDevContext = NULL; NTSTATUS status = STATUS_SUCCESS; size_t cBytesReturned = 0; unsigned char bToggledSwitch = 0; ULONG cBytesToCopy = 0; PHIDFX2_IO_REPORT pInputReport = NULL; TraceVerbose(DBG_IOCTL, "(%!FUNC!) Enter\n"); hDevice = WdfTimerGetParentObject(hTimer); pDevContext = GetDeviceContext(hDevice); bToggledSwitch = pDevContext->bLatestToggledSwitch; TraceInfo(DBG_IOCTL, "(%!FUNC!) mode %d switch %d\n", pDevContext->driverMode, bToggledSwitch); if (!((pDevContext->driverMode == DM_BUTTON || pDevContext->driverMode == DM_BUTTON_AND_LED) && bToggledSwitch == 0)) { // Check if there are any pending requests in the Interrupt Message Queue. // If a request is found then complete the pending request. status = WdfIoQueueRetrieveNextRequest(pDevContext->hInterruptMsgQueue, &hRequest); if (NT_SUCCESS(status)) { cBytesToCopy = sizeof(pInputReport[0]); status = WdfRequestRetrieveOutputBuffer(hRequest, cBytesToCopy, &pInputReport, &cBytesReturned); // BufferLength if (NT_SUCCESS(status)) { TraceInfo(DBG_IOCTL, "(%!FUNC!) WdfRequestRetrieveOutputBuffer switch %d\n", bToggledSwitch); pInputReport->bReportId = GENERIC_DESKTOP_REPORT_ID; pInputReport->bData = bToggledSwitch; cBytesReturned = cBytesToCopy; } else // WdfRequestRetrieveOutputBuffer failed { TraceErr(DBG_IOCTL, "(%!FUNC!) WdfRequestRetrieveOutputBuffer failed with status: %!STATUS!\n", status); } WdfRequestCompleteWithInformation(hRequest, status, cBytesReturned); } else if (status != STATUS_NO_MORE_ENTRIES) { TraceErr(DBG_IOCTL, "(%!FUNC!) WdfIoQueueRetrieveNextRequest status %!STATUS!\n", status); } } else { TraceInfo(DBG_IOCTL, "(%!FUNC!) ignore switch"); } TraceVerbose(DBG_IOCTL, "(%!FUNC!) Exit\n"); }
VOID NICCheckForQueuedSends( IN PFDO_DATA FdoData ) /*++ Routine Description: Arguments: FdoData Pointer to our FdoData Return Value: --*/ { WDFREQUEST request; WDFDMATRANSACTION dmaTransaction; NTSTATUS status; UNREFERENCED_PARAMETER( dmaTransaction ); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> NICCheckForQueuedSends\n"); // // If we queued any transmits because we didn't have any TCBs earlier, // dequeue and send those packets now, as long as we have free TCBs. // while (MP_TCB_RESOURCES_AVAIABLE(FdoData)) { status = WdfIoQueueRetrieveNextRequest( FdoData->PendingWriteQueue, &request ); if(!NT_SUCCESS(status) ) { if(STATUS_NO_MORE_ENTRIES != status) { TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "WdfIoQueueRetrieveNextRequest failed %X\n", status); } break; } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "\t processing Request %p \n", request); status = NICInitiateDmaTransfer(FdoData, request); if(!NT_SUCCESS(status)) { WdfRequestCompleteWithInformation(request, status, 0); } FdoData->nWaitSend--; } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- NICCheckForQueuedSends\n"); }
VOID NICFreeQueuedSendPackets( IN PFDO_DATA FdoData ) /*++ Routine Description: Free and complete the pended sends on SendQueueHead Assumption: This function is called with the Send SPINLOCK held. Arguments: FdoData Pointer to our FdoData Return Value: None --*/ { WDFREQUEST request; NTSTATUS status; TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "--> NICFreeQueuedSendPackets\n"); do { status = WdfIoQueueRetrieveNextRequest( FdoData->PendingWriteQueue, &request ); if(!NT_SUCCESS(status) ) { if(STATUS_NO_MORE_ENTRIES != status){ TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "WdfIoQueueRetrieveNextRequest failed %x\n", status); } break; } FdoData->nWaitSend--; WdfSpinLockRelease(FdoData->SendLock); WdfRequestCompleteWithInformation(request, status, 0); WdfSpinLockAcquire(FdoData->SendLock); } WHILE (TRUE); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE, "<-- NICFreeQueuedSendPackets\n"); }
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(); }
// 中断Pipe回调函数。这样一旦设备产生了中断信息,驱动就能够读取到。 // VOID InterruptRead(WDFUSBPIPE Pipe, WDFMEMORY Buffer, size_t NumBytesTransferred, WDFCONTEXT Context) { NTSTATUS status; size_t size = 0; PDEVICE_CONTEXT pContext = (PDEVICE_CONTEXT)Context; WDFREQUEST Request = NULL; CHAR *pchBuf = NULL; KDBG(DPFLTR_INFO_LEVEL, "[InterruptRead]"); UNREFERENCED_PARAMETER(Pipe); // Read数据缓冲区。注意到,缓冲区长度总是管道最大包长度的倍数。 // 我们这里只用缓冲区的第一个有效字节。 pchBuf = (CHAR*)WdfMemoryGetBuffer(Buffer, &size); if(pchBuf == NULL || size == 0) return; // 第一个字节为确认字节,一定是0xD4 //if(pchBuf[0] != 0xD4)return; // 从队列中提取一个未完成请求 status = WdfIoQueueRetrieveNextRequest(pContext->InterruptManualQueue, &Request); if(NT_SUCCESS(status)) { CHAR* pOutputBuffer = NULL; status = WdfRequestRetrieveOutputBuffer(Request, 1, &pOutputBuffer, NULL); if(NT_SUCCESS(status)) { // 把结果返回给应用程序 pOutputBuffer[0] = pchBuf[1]; WdfRequestCompleteWithInformation(Request, status, 1); } else { // 返回错误 WdfRequestComplete(Request, status); } KDBG(DPFLTR_INFO_LEVEL, "Get and finish an interrupt read request."); }else{ // 队列空,将放弃从设备获取的数据。 KDBG(DPFLTR_INFO_LEVEL, "Manual interrupt queue is empty!!!"); } }
static VOID XenBus_EvtIoRead(WDFQUEUE queue, WDFREQUEST request, size_t length) { NTSTATUS status; WDFFILEOBJECT file_object = WdfRequestGetFileObject(request); PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object); KIRQL old_irql; UNREFERENCED_PARAMETER(queue); FUNCTION_ENTER(); status = WdfRequestForwardToIoQueue(request, xpdid->xenbus.io_queue); if (!NT_SUCCESS(status)) { KdPrint((__DRIVER_NAME " could not forward request (%08x)\n", status)); } KeAcquireSpinLock(&xpdid->lock, &old_irql); if (!IsListEmpty(&xpdid->xenbus.read_list_head)) { status = WdfIoQueueRetrieveNextRequest(xpdid->xenbus.io_queue, &request); if (NT_SUCCESS(status)) { KdPrint((__DRIVER_NAME " found pending read\n")); XenBus_ProcessReadRequest(xpdid->xenbus.io_queue, request, 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); } } else { KdPrint((__DRIVER_NAME " no data to read\n")); KeReleaseSpinLock(&xpdid->lock, old_irql); } FUNCTION_EXIT(); return; }
VOID SerialGetNextRequest( IN WDFREQUEST * CurrentOpRequest, IN WDFQUEUE QueueToProcess, OUT WDFREQUEST * NextRequest, IN BOOLEAN CompleteCurrent, IN PSERIAL_DEVICE_EXTENSION Extension ) /*++ Routine Description: This function is used to make the head of the particular queue the current request. It also completes the what was the old current request if desired. Arguments: CurrentOpRequest - Pointer to a pointer to the currently active request for the particular work list. Note that this item is not actually part of the list. QueueToProcess - The list to pull the new item off of. NextIrp - The next Request to process. Note that CurrentOpRequest will be set to this value under protection of the cancel spin lock. However, if *NextIrp is NULL when this routine returns, it is not necessaryly true the what is pointed to by CurrentOpRequest will also be NULL. The reason for this is that if the queue is empty when we hold the cancel spin lock, a new request may come in immediately after we release the lock. CompleteCurrent - If TRUE then this routine will complete the request pointed to by the pointer argument CurrentOpRequest. Return Value: None. --*/ { WDFREQUEST oldRequest = NULL; PREQUEST_CONTEXT reqContext; NTSTATUS status; UNREFERENCED_PARAMETER(Extension); oldRequest = *CurrentOpRequest; *CurrentOpRequest = NULL; // // Check to see if there is a new request to start up. // status = WdfIoQueueRetrieveNextRequest( QueueToProcess, CurrentOpRequest ); if(!NT_SUCCESS(status)) { ASSERTMSG("WdfIoQueueRetrieveNextRequest failed", status == STATUS_NO_MORE_ENTRIES); } *NextRequest = *CurrentOpRequest; if (CompleteCurrent) { if (oldRequest) { reqContext = SerialGetRequestContext(oldRequest); SerialCompleteRequest(oldRequest, reqContext->Status, reqContext->Information); } } }
VOID HidFx2CompleteReadReport( WDFDEVICE Device ) /*++ Routine Description This method handles the completion of the pended request for the IOCTL_HID_READ_REPORT Arguments: Device - Handle to a framework device. Return Value: None. --*/ { NTSTATUS status = STATUS_SUCCESS; WDFREQUEST request; PDEVICE_EXTENSION pDevContext = NULL; size_t bytesReturned = 0; #ifndef USE_ALTERNATE_HID_REPORT_DESCRIPTOR UCHAR toggledSwitch = 0; #endif // USE_ALTERNATE_HID_REPORT_DESCRIPTOR ULONG bytesToCopy = 0; PHIDFX2_INPUT_REPORT inputReport = NULL; pDevContext = GetDeviceContext(Device); // // Check if there are any pending requests in the Interrupt Message Queue. // If a request is found then complete the pending request. // status = WdfIoQueueRetrieveNextRequest(pDevContext->InterruptMsgQueue, &request); if (NT_SUCCESS(status)) { // // IOCTL_HID_READ_REPORT is METHOD_NEITHER so WdfRequestRetrieveOutputBuffer // will correctly retrieve buffer from Irp->UserBuffer. Remember that // HIDCLASS provides the buffer in the Irp->UserBuffer field // irrespective of the ioctl buffer type. However, framework is very // strict about type checking. You cannot get Irp->UserBuffer by using // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER // internal ioctl. // bytesToCopy = sizeof(HIDFX2_INPUT_REPORT); status = WdfRequestRetrieveOutputBuffer(request, bytesToCopy, &inputReport, &bytesReturned);// BufferLength if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "WdfRequestRetrieveOutputBuffer failed with status: 0x%x\n", status); } else { #ifndef USE_ALTERNATE_HID_REPORT_DESCRIPTOR // // Map switch pack state. The lower 7 bits of switch pack // state are mapped to usages in consumer control collection // while the highest one bit is mapped to sleep usage in system // control collection // toggledSwitch = pDevContext->LatestToggledSwitch; if (toggledSwitch & CONSUMER_CONTROL_BUTTONS_BIT_MASK) { // //these are consumer control buttons // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "Consumer control SwitchState: 0x%x\n", toggledSwitch); inputReport->ReportId = CONSUMER_CONTROL_REPORT_ID; inputReport->SwitchStateAsByte = toggledSwitch; bytesReturned = bytesToCopy; } else if (toggledSwitch & SYSTEM_CONTROL_BUTTONS_BIT_MASK) { // // these are system control buttons // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "System Control SwitchState: 0x%x\n", toggledSwitch); inputReport->ReportId = SYSTEM_CONTROL_REPORT_ID; inputReport->SwitchStateAsByte = toggledSwitch; bytesReturned = bytesToCopy; } else { // // We can't be here since we already rejected the switch // state with no swicthes turned on // ASSERT(FALSE); } #else // // Using vendor collection reports instead of HID collections that integrate // into consumer and system control // TraceEvents(TRACE_LEVEL_INFORMATION, DBG_IOCTL, "Vendor SwitchState: 0x%x\n", pDevContext->CurrentSwitchState); inputReport->ReportId = DIP_SWITCHES_REPORT_ID; inputReport->SwitchStateAsByte = pDevContext->CurrentSwitchState; bytesReturned = bytesToCopy; #endif // USE_ALTERNATE_HID_REPORT_DESCRIPTOR } WdfRequestCompleteWithInformation(request, status, bytesReturned); } else if (status != STATUS_NO_MORE_ENTRIES) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "WdfIoQueueRetrieveNextRequest status %08x\n", status); } return; }
/////////////////////////////////////////////////////////////////////////////// // // BasicUsbInterruptPipeReadComplete // // This is the callback we supplied for the continuous reader // on the interrupt IN pipe. It is called whenever the user // changes the state of the switches on the switch pack // // INPUTS: // // Pipe - Our interrupt IN pipe // // Buffer - The WDFMEMORY object associated with the // transfer. The buffer of thie memory contains // the state of the switch pack // // NumBytesTransferred - Self explanatory // // Context - One of our per device context structures // (passed as a parameter to // WDF_USB_CONTINUOUS_READER_CONFIG_INIT) // // OUTPUTS: // // None. // // RETURNS: // // STATUS_SUCCESS, otherwise an error indicating why the driver could not // load. // // IRQL: // // This routine is called at IRQL <= DISPATCH_LEVEL. // // NOTES: // // Even though we've applied a PASSIVE_LEVEL execution // level constraint on our device, this callback falls // outstide of the callbacks that the constraint is // enforced on. // /////////////////////////////////////////////////////////////////////////////// VOID BasicUsbInterruptPipeReadComplete( IN WDFUSBPIPE Pipe, IN WDFMEMORY Buffer, IN size_t NumBytesTransferred, IN WDFCONTEXT Context ) { PUCHAR dataBuffer; WDFREQUEST stateChangeRequest; PBASICUSB_DEVICE_CONTEXT devContext; PUCHAR userBuffer; NTSTATUS status; UNREFERENCED_PARAMETER(Pipe); UNREFERENCED_PARAMETER(NumBytesTransferred); UNREFERENCED_PARAMETER(Context); // // Someone toggled the switch pack. Complete a pending user // request if there is one. // devContext = (PBASICUSB_DEVICE_CONTEXT)Context; dataBuffer = (PUCHAR)WdfMemoryGetBuffer(Buffer, NULL); #if DBG DbgPrint("Interrupt read complete. Bytes transferred = 0x%x, Data = 0x%x\n", (ULONG)NumBytesTransferred, *dataBuffer); #endif // // See if there is anyone waiting to be notified of the state // change. // status = WdfIoQueueRetrieveNextRequest( devContext->SwitchPackStateChangeQueue, &stateChangeRequest); if (NT_SUCCESS(status)) { #if DBG DbgPrint("State change request 0x%p pending\n", stateChangeRequest); #endif // // Yup, someone waiting. Complete their request with the switch // pack state. // status = WdfRequestRetrieveOutputBuffer(stateChangeRequest, sizeof(UCHAR), (PVOID *)&userBuffer, NULL); if (NT_SUCCESS(status)) { // // Stuff the value into the buffer... // *userBuffer = *dataBuffer; // // And complete the request, indicating the proper number of // bytes transferred. // WdfRequestCompleteWithInformation(stateChangeRequest, STATUS_SUCCESS, sizeof(UCHAR)); } else { #if DBG DbgPrint("Failed to get user buffer ofState change request 0x%x\n", status); #endif WdfRequestComplete(stateChangeRequest, status); } } else { #if DBG DbgPrint("No state change requests pending? (0x%x)\n", status); #endif } return; }
VOID OsrUsbIoctlGetInterruptMessage( _In_ WDFDEVICE Device, _In_ NTSTATUS ReaderStatus ) /*++ Routine Description This method handles the completion of the pended request for the IOCTL IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE. Arguments: Device - Handle to a framework device. Return Value: None. --*/ { NTSTATUS status; WDFREQUEST request; PDEVICE_CONTEXT pDevContext; size_t bytesReturned = 0; PSWITCH_STATE switchState = NULL; pDevContext = GetDeviceContext(Device); do { // // Check if there are any pending requests in the Interrupt Message Queue. // If a request is found then complete the pending request. // status = WdfIoQueueRetrieveNextRequest(pDevContext->InterruptMsgQueue, &request); if (NT_SUCCESS(status)) { status = WdfRequestRetrieveOutputBuffer(request, sizeof(SWITCH_STATE), &switchState, NULL);// BufferLength if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "User's output buffer is too small for this IOCTL, expecting a SWITCH_STATE\n"); bytesReturned = sizeof(SWITCH_STATE); } else { // // Copy the state information saved by the continuous reader. // if (NT_SUCCESS(ReaderStatus)) { switchState->SwitchesAsUChar = pDevContext->CurrentSwitchState; bytesReturned = sizeof(SWITCH_STATE); } else { bytesReturned = 0; } } // // Complete the request. If we failed to get the output buffer then // complete with that status. Otherwise complete with the status from the reader. // WdfRequestCompleteWithInformation(request, NT_SUCCESS(status) ? ReaderStatus : status, bytesReturned); status = STATUS_SUCCESS; } else if (status != STATUS_NO_MORE_ENTRIES) { KdPrint(("WdfIoQueueRetrieveNextRequest status %08x\n", status)); } request = NULL; } while (status == STATUS_SUCCESS); return; }
VOID CBUpdateCardState( PSMARTCARD_EXTENSION SmartcardExtension, UCHAR IccState, BOOLEAN SystemWakeUp ) { ULONG oldState; NTSTATUS status; KIRQL irql; WDFREQUEST request; PDEVICE_EXTENSION DeviceExtension; KeAcquireSpinLock( &SmartcardExtension->OsData->SpinLock, &irql ); SmartcardDebug( DEBUG_TRACE, ( "PSCR!CBUpdateCardState: Enter \n" ) ); oldState = (SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT ? SCARD_PRESENT : SCARD_ABSENT); SmartcardExtension->ReaderCapabilities.CurrentState = (IccState == PSCR_ICC_PRESENT ? SCARD_PRESENT : SCARD_ABSENT); SmartcardDebug( DEBUG_DRIVER, ( "PSCR!CBUpdateCardState: Smart card %s\n", IccState == PSCR_ICC_PRESENT ? "inserted" : "removed") ); if ( SmartcardExtension->OsData->NotificationIrp != NULL && (SystemWakeUp && (oldState == SCARD_PRESENT || SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_PRESENT) || SmartcardExtension->ReaderCapabilities.CurrentState != oldState)) { PIRP notificationIrp ; notificationIrp = InterlockedExchangePointer( &(SmartcardExtension->OsData->NotificationIrp), NULL ); DeviceExtension = GetDeviceExtension(WdfWdmDeviceGetWdfDeviceHandle(SmartcardExtension->OsData->DeviceObject)); KeReleaseSpinLock( &SmartcardExtension->OsData->SpinLock, irql ); status = WdfIoQueueRetrieveNextRequest( DeviceExtension->NotificationQueue, &request); if (NT_SUCCESS(status)) { SmartcardDebug( DEBUG_DRIVER, ( "PSCR!CBUpdateCardState: Completing Irp %p\n", notificationIrp) ); WdfRequestCompleteWithInformation(request, status, 0); } else { NT_ASSERTMSG("WdfIoQueueRetrieveNextRequest failed", status == STATUS_NO_MORE_ENTRIES); } } else { KeReleaseSpinLock( &SmartcardExtension->OsData->SpinLock, irql ); } SmartcardDebug( DEBUG_TRACE, ( "PSCR!CBUpdateCardState: Exit \n" ) ); }
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; }
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(); }
VOID kmdf1394_BusResetRoutine( IN PVOID Context) { WDFDEVICE device= Context; PDEVICE_EXTENSION deviceExtension = GetDeviceContext(device); NTSTATUS ntStatus = STATUS_SUCCESS; WDFREQUEST request; WDF_WORKITEM_CONFIG workItemConfig; WDFWORKITEM workItem; WDF_OBJECT_ATTRIBUTES attributes; ENTER("kmdf1394_BusResetRoutine"); TRACE(TL_TRACE, ("Context = 0x%x\n", Context)); WDF_WORKITEM_CONFIG_INIT (&workItemConfig, kmdf1394_BusResetRoutineWorkItem); WDF_OBJECT_ATTRIBUTES_INIT (&attributes); attributes.ParentObject = device; ntStatus = WdfWorkItemCreate( &workItemConfig, &attributes, &workItem); if (!NT_SUCCESS (ntStatus)) { TRACE(TL_ERROR, ("Failed to create workitem %x\n", ntStatus)); return; } // // Execute this work item. // WdfWorkItemEnqueue (workItem); // // If we have any bus reset notify irps, then nows the // time to complete them. // WHILE (TRUE) { ntStatus = WdfIoQueueRetrieveNextRequest ( deviceExtension->BusResetRequestsQueue, &request); if(NT_SUCCESS (ntStatus)) { TRACE(TL_TRACE, ("Completing BusReset Request = 0x%p\n", request)); WdfRequestCompleteWithInformation (request, STATUS_SUCCESS, 0); // continue; } else if (STATUS_NO_MORE_ENTRIES == ntStatus) { TRACE (TL_TRACE, ("Request Queue is empty.\n")); break; } else { ASSERTMSG ( "WdfIoQueueRetrieveNextRequest failed", ntStatus); break; } } EXIT("kmdf1394_BusResetRoutine", ntStatus); } // kmdf1394_BusResetRoutine
VOID BusDogAddTraceToFifo( WDFDEVICE device, ULONG DeviceId, BUSDOG_REQUEST_TYPE Type, BUSDOG_REQUEST_PARAMS Params, PVOID TraceBuffer, ULONG BufferLength ) { PBUSDOG_FILTER_TRACE_FIFO_ITEM pTraceItem = NULL; WDFREQUEST request; NTSTATUS status; WdfSpinLockAcquire(BusDogTraceFifoLock); // // First add trace to the fifo // pTraceItem = BusDogTraceFifo.TraceItems[BusDogTraceFifo.WriteIndex]; pTraceItem = __BusDogCreateTrace( pTraceItem, DeviceId, Type, Params, TraceBuffer, BufferLength); BusDogTraceFifo.TraceItems[BusDogTraceFifo.WriteIndex] = pTraceItem; BusDogTraceFifo.WriteIndex++; if (BusDogTraceFifo.WriteIndex >= BUSDOG_FILTER_TRACE_FIFO_LENGTH) BusDogTraceFifo.WriteIndex = 0; if (BusDogTraceFifo.WriteIndex == BusDogTraceFifo.ReadIndex) { BusDogPrint(BUSDOG_DEBUG_ERROR, "On noes! We have overflow\n"); } // // Now see if we can complete a request from the manual queue // status = WdfIoQueueRetrieveNextRequest( BufferRequestQueue, &request); if (NT_SUCCESS(status)) { size_t bytesWritten; status = __BusDogFufillRequestWithTraces(request, &bytesWritten); // // Ok for better or worse we finally completed this request // WdfRequestCompleteWithInformation(request, status, bytesWritten); } else { if (status != STATUS_NO_MORE_ENTRIES) { BusDogPrint(BUSDOG_DEBUG_ERROR, "WdfIoQueueRetrieveNextRequest failed - 0x%x\n", status); } } WdfSpinLockRelease(BusDogTraceFifoLock); }
VOID CyCompleteIoctlRequest( __in WDFDEVICE WdfDevice ) { NTSTATUS NtStatus; WDFREQUEST request; PDEVICE_CONTEXT pDevContext; size_t szBytesReturned = 0; PUCHAR pucData; PREQUEST_CONTEXT pReqContext; pDevContext = CyGetDeviceContext(WdfDevice); do { //check for pending request NtStatus = WdfIoQueueRetrieveNextRequest(pDevContext->IntInMsgQ, &request); if (NT_SUCCESS(NtStatus)) { pReqContext = CyGetRequestContext(request); if(pReqContext->IsNeitherIO) { pucData = WdfMemoryGetBuffer(pReqContext->OutputMemoryBufferWrite,NULL); *pucData = pDevContext->ucIntInData; szBytesReturned = sizeof(UCHAR); } else { NtStatus = WdfRequestRetrieveOutputBuffer(request, sizeof(UCHAR), &pucData, NULL);// BufferLength if (!NT_SUCCESS(NtStatus)) { CyTraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "User's output buffer is too small for this IOCTL, expecting a SWITCH_STATE\n"); szBytesReturned = sizeof(UCHAR); } else { *pucData = pDevContext->ucIntInData; szBytesReturned = sizeof(UCHAR); } } WdfRequestCompleteWithInformation(request, NtStatus, szBytesReturned); NtStatus = STATUS_SUCCESS; } else if (NtStatus != STATUS_NO_MORE_ENTRIES) { CyTraceEvents(TRACE_LEVEL_ERROR,DBG_IOCTL,"WdfIoQueueRetrieveNextRequest status %08x\n", NtStatus); } request = NULL; } while (NtStatus == STATUS_SUCCESS); }