VOID UfxDevice_Reset ( _In_ UFXDEVICE Device ) /*++ Routine Description: Cancels all transfers and disables non-zero endpoints in response to USB reset. Arguments: UfxDevice - UFXDEVICE object representing the device. --*/ { PUFXDEVICE_CONTEXT DeviceContext; PREGISTERS_CONTEXT RegistersContext; ULONG EpIndex; TraceEntry(); DeviceContext = UfxDeviceGetContext(Device); RegistersContext = DeviceGetRegistersContext(DeviceContext->FdoWdfDevice); // // Get EP0 back to setup stage. // TransferReset(WdfCollectionGetFirstItem(DeviceContext->Endpoints)); // // Disable all non-default endpoints // // // #### TODO: Insert code to disable non-default endpoints #### // // // End any transfers on non-default endpoints. // for (EpIndex = 1; EpIndex < WdfCollectionGetCount(DeviceContext->Endpoints); EpIndex++) { TransferReset(WdfCollectionGetItem(DeviceContext->Endpoints, EpIndex)); } TraceExit(); }
/** * @brief DPC callback. * Calls the Xen interface api to process the ringbuffer until the ringbuffer is empty, * then completes all requests provided by the Xen api. * * @todo consider completion within the XenDpc() loop. However this would release the device * lock. * * @param[in] Dpc The WDFDPC handle. * */ VOID FdoEvtDeviceDpcFunc( IN VOID *Context) { // --XT-- FDO context passed directly now. PUSB_FDO_CONTEXT fdoContext = (PUSB_FDO_CONTEXT)Context; // // this stuff needs to be done at DPC level in order to complete irps. // ULONG passes = 0; AcquireFdoLock(fdoContext); if (fdoContext->InDpc) { fdoContext->DpcOverLapCount++; ReleaseFdoLock(fdoContext); return; } fdoContext->InDpc = TRUE; BOOLEAN moreWork; do { moreWork = XenDpc(fdoContext, fdoContext->RequestCollection); passes++; if (fdoContext->DpcOverLapCount) { fdoContext->totalDpcOverLapCount += fdoContext->DpcOverLapCount; fdoContext->DpcOverLapCount = 0; moreWork = TRUE; } if (moreWork & (passes >= KeQueryActiveProcessorCount(NULL))) { // // reschedule the dpc to prevent starvation. // // --XT-- WdfDpcEnqueue(fdoContext->WdfDpc); // // --XT-- Schedule through the Xen interface now. // XenScheduleDPC(fdoContext->Xen); TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_DPC, __FUNCTION__": enqueue dpc at %d passes\n", passes); fdoContext->totalDpcReQueueCount++; break; } } while (moreWork); fdoContext->InDpc = FALSE; // allow another dpc instance to run and add to the collection. if (passes > fdoContext->maxDpcPasses) { fdoContext->maxDpcPasses = passes; } // // complete all queued Irps. Note that this section is re-entrant. // Note also that all of these requests have been "uncanceled" and ahve // been marked as completed in their request contexts and that the // additional reference on the request object has been removed. // The collection can be safely completed with no race conditions. // ULONG responseCount = 0; WDFREQUEST Request; while ((Request = (WDFREQUEST) WdfCollectionGetFirstItem(fdoContext->RequestCollection)) != NULL) { WdfCollectionRemoveItem(fdoContext->RequestCollection, 0); TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_DPC, __FUNCTION__": complete Request %p Status %x\n", Request, WdfRequestWdmGetIrp(Request)->IoStatus.Status); ReleaseFdoLock(fdoContext); WdfRequestCompleteWithPriorityBoost(Request, WdfRequestWdmGetIrp(Request)->IoStatus.Status, IO_SOUND_INCREMENT); AcquireFdoLock(fdoContext); responseCount++; } if (responseCount > fdoContext->maxRequestsProcessed) { fdoContext->maxRequestsProcessed = responseCount; } // // fire up any queued requests // DrainRequestQueue(fdoContext, FALSE); ReleaseFdoLock(fdoContext); // --XT-- this trace was way too noisy, made it verbose. TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_DPC, __FUNCTION__": exit responses processed %d passes %d\n", responseCount, passes); }
/** * @brief Allocate a workitem from or for our collection of workitems. * Must be called with the device lock held. * * @param[in] Device handle to the WDFDEVICE created by FdoEvtDeviceAdd. * @param[in] callback only optional if this is add device doing an allocation! * @param[in] Param0 arbitrary context data * @param[in] Param1 arbitrary context data * @param[in] Param2 arbitrary context data * @param[in] Param3 arbitrary context data * * @returns a WDFWORKITEM handle or NULL on failure. * */ WDFWORKITEM NewWorkItem( IN PUSB_FDO_CONTEXT fdoContext, IN PFN_WDF_WORKITEM callback, IN ULONG_PTR Param0, IN ULONG_PTR Param1, IN ULONG_PTR Param2, IN ULONG_PTR Param3) { // // First try to get a workitem from our collection of them. // WDFWORKITEM WorkItem = (WDFWORKITEM) WdfCollectionGetFirstItem(fdoContext->FreeWorkItems); if (WorkItem == NULL) { // // ok - allocate a new one. // TraceEvents(TRACE_LEVEL_VERBOSE, TRACE_DEVICE, __FUNCTION__": Device %p FreeWorkItems is empty, init count %d\n", fdoContext->WdfDevice, INIT_WORK_ITEM_COUNT); NTSTATUS status = STATUS_SUCCESS; WDF_OBJECT_ATTRIBUTES attributes; WDF_WORKITEM_CONFIG workitemConfig; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE( &attributes, USB_FDO_WORK_ITEM_CONTEXT); attributes.ParentObject = fdoContext->WdfDevice; WDF_WORKITEM_CONFIG_INIT( &workitemConfig, EvtFdoDeviceGenericWorkItem); status = WdfWorkItemCreate( &workitemConfig, &attributes, &WorkItem); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_DEVICE, __FUNCTION__": WdfWorkItemCreate error %x\n", status); return NULL; } } else { // note that WdfCollectionGetFirstItem doesn't remove it from the collection. WdfCollectionRemove(fdoContext->FreeWorkItems, WorkItem); } if (WorkItem) { // initialize it. PUSB_FDO_WORK_ITEM_CONTEXT context = WorkItemGetContext(WorkItem); context->FdoContext = fdoContext; context->CallBack = callback; context->Params[0] = Param0; context->Params[1] = Param1; context->Params[2] = Param2; context->Params[3] = Param3; } return WorkItem; }