static NTSTATUS UsbChief_QueuePassiveLevelCallback(IN WDFDEVICE Device, IN WDFUSBPIPE Pipe) { NTSTATUS status = STATUS_SUCCESS; PWORKITEM_CONTEXT context; WDF_OBJECT_ATTRIBUTES attributes; WDF_WORKITEM_CONFIG workitemConfig; WDFWORKITEM hWorkItem; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, WORKITEM_CONTEXT); attributes.ParentObject = Device; WDF_WORKITEM_CONFIG_INIT(&workitemConfig, UsbChief_ReadWriteWorkItem); status = WdfWorkItemCreate( &workitemConfig, &attributes, &hWorkItem); if (!NT_SUCCESS(status)) return status; context = GetWorkItemContext(hWorkItem); context->Device = Device; context->Pipe = Pipe; WdfWorkItemEnqueue(hWorkItem); return STATUS_SUCCESS; }
VOID SimSensorTemperatureInterrupt ( _In_ WDFDEVICE Device ) /*++ Routine Description: This routine is invoked to simulate an interrupt from the virtual sensor device. It performs all the work a normal ISR would perform. Arguments: Device - Supplies a handle to the device. Return Value: None. --*/ { PFDO_DATA DevExt; DevExt = GetDeviceExtension(Device); WdfWorkItemEnqueue(DevExt->InterruptWorker); return; }
NTSTATUS QueuePassiveLevelCallback( _In_ WDFDEVICE Device, _In_ WDFUSBPIPE Pipe ) /*++ Routine Description: This routine is used to queue workitems so that the callback functions can be executed at PASSIVE_LEVEL in the context of a system thread. Arguments: Return Value: --*/ { NTSTATUS status = STATUS_SUCCESS; PWORKITEM_CONTEXT context; WDF_OBJECT_ATTRIBUTES attributes; WDF_WORKITEM_CONFIG workitemConfig; WDFWORKITEM hWorkItem; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, WORKITEM_CONTEXT); attributes.ParentObject = Device; WDF_WORKITEM_CONFIG_INIT(&workitemConfig, Rio500_EvtReadWriteWorkItem); status = WdfWorkItemCreate( &workitemConfig, &attributes, &hWorkItem ); if (!NT_SUCCESS(status)) { return status; } context = GetWorkItemContext(hWorkItem); context->Device = Device; context->Pipe = Pipe; // // Execute this work item. // WdfWorkItemEnqueue(hWorkItem); return STATUS_SUCCESS; }
void CyapaBootTimer(_In_ WDFTIMER hTimer) { WDFDEVICE Device = (WDFDEVICE)WdfTimerGetParentObject(hTimer); PDEVICE_CONTEXT pDevice = GetDeviceContext(Device); WDF_OBJECT_ATTRIBUTES attributes; WDF_WORKITEM_CONFIG workitemConfig; WDFWORKITEM hWorkItem; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT); attributes.ParentObject = Device; WDF_WORKITEM_CONFIG_INIT(&workitemConfig, CyapaBootWorkItem); WdfWorkItemCreate(&workitemConfig, &attributes, &hWorkItem); WdfWorkItemEnqueue(hWorkItem); WdfTimerStop(hTimer, FALSE); }
VOID VIOSerialPortPnpNotify ( IN WDFDEVICE WdfDevice, IN PVIOSERIAL_PORT port, IN BOOLEAN connected ) { WDF_OBJECT_ATTRIBUTES attributes; WDF_WORKITEM_CONFIG workitemConfig; WDFWORKITEM hWorkItem; PRAWPDO_VIOSERIAL_PORT pdoData = NULL; NTSTATUS status = STATUS_SUCCESS; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> %s\n", __FUNCTION__); port->HostConnected = connected; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, RAWPDO_VIOSERIAL_PORT); attributes.ParentObject = WdfDevice; WDF_WORKITEM_CONFIG_INIT(&workitemConfig, VIOSerialPortPnpNotifyWork); status = WdfWorkItemCreate( &workitemConfig, &attributes, &hWorkItem); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "WdfWorkItemCreate failed with status = 0x%08x\n", status); return; } pdoData = RawPdoSerialPortGetData(hWorkItem); pdoData->port = port; WdfWorkItemEnqueue(hWorkItem); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- %s\n", __FUNCTION__); }
NTSTATUS AndroidUsbPipeFileObject::QueueResetPipePassiveCallback() { ASSERT_IRQL_LOW_OR_DISPATCH(); // Initialize workitem WDF_OBJECT_ATTRIBUTES attr; WDF_OBJECT_ATTRIBUTES_INIT(&attr); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attr, AndroidUsbWorkitemContext); attr.ParentObject = wdf_device(); WDFWORKITEM wdf_work_item = NULL; WDF_WORKITEM_CONFIG workitem_config; WDF_WORKITEM_CONFIG_INIT(&workitem_config, ResetPipePassiveCallbackEntry); NTSTATUS status = WdfWorkItemCreate(&workitem_config, &attr, &wdf_work_item); ASSERT(NT_SUCCESS(status) && (NULL != wdf_work_item)); if (!NT_SUCCESS(status)) return status; // Initialize our extension to work item AndroidUsbWorkitemContext* context = GetAndroidUsbWorkitemContext(wdf_work_item); ASSERT(NULL != context); if (NULL == context) { WdfObjectDelete(wdf_work_item); return STATUS_INTERNAL_ERROR; } context->object_type = AndroidUsbWdfObjectTypeWorkitem; context->pipe_file_ext = this; // Enqueue this work item. WdfWorkItemEnqueue(wdf_work_item); return STATUS_SUCCESS; }
VOID VIOSerialPortCreateName( IN WDFDEVICE WdfDevice, IN PVIOSERIAL_PORT port, IN PPORT_BUFFER buf ) { WDF_OBJECT_ATTRIBUTES attributes; WDF_WORKITEM_CONFIG workitemConfig; WDFWORKITEM hWorkItem; PRAWPDO_VIOSERIAL_PORT pdoData = NULL; NTSTATUS status = STATUS_SUCCESS; size_t length; PVIRTIO_CONSOLE_CONTROL cpkt; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "--> %s\n", __FUNCTION__); cpkt = (PVIRTIO_CONSOLE_CONTROL)((ULONG_PTR)buf->va_buf + buf->offset); if (port && !port->NameString.Buffer) { length = buf->len - buf->offset - sizeof(VIRTIO_CONSOLE_CONTROL); port->NameString.Length = (USHORT)( length ); port->NameString.MaximumLength = port->NameString.Length + 1; port->NameString.Buffer = (PCHAR)ExAllocatePoolWithTag( NonPagedPool, port->NameString.MaximumLength, VIOSERIAL_DRIVER_MEMORY_TAG ); if (port->NameString.Buffer) { RtlCopyMemory( port->NameString.Buffer, (PVOID)((LONG_PTR)buf->va_buf + buf->offset + sizeof(*cpkt)), length ); port->NameString.Buffer[length] = '\0'; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "VIRTIO_CONSOLE_PORT_NAME name_size = %d %s\n", length, port->NameString.Buffer); } else { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "VIRTIO_CONSOLE_PORT_NAME: Unable to alloc string buffer\n" ); } WDF_OBJECT_ATTRIBUTES_INIT(&attributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, RAWPDO_VIOSERIAL_PORT); attributes.ParentObject = WdfDevice; WDF_WORKITEM_CONFIG_INIT(&workitemConfig, VIOSerialPortSymbolicNameWork); status = WdfWorkItemCreate( &workitemConfig, &attributes, &hWorkItem); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "WdfWorkItemCreate failed with status = 0x%08x\n", status); return; } pdoData = RawPdoSerialPortGetData(hWorkItem); pdoData->port = port; WdfWorkItemEnqueue(hWorkItem); } else { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "VIRTIO_CONSOLE_PORT_NAME invalid id = %d\n", cpkt->id); } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "<-- %s\n", __FUNCTION__); }
NTSTATUS PepScheduleWorker ( _In_ PPEP_WORK_CONTEXT WorkContext ) /*++ Routine Description: This function schedules a worker thread to process pending work requests. Arguments: WorkContext - Supplies the context of the work. Return Value: NTSTATUS. --*/ { WDF_OBJECT_ATTRIBUTES Attributes; NTSTATUS Status; BOOLEAN Synchronous; WDFWORKITEM WorkItem; WDF_WORKITEM_CONFIG WorkItemConfiguration; WorkItem = NULL; Synchronous = FALSE; // // Create a workitem to process events. // WDF_OBJECT_ATTRIBUTES_INIT(&Attributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&Attributes, PEP_WORK_ITEM_CONTEXT); Attributes.ParentObject = PepGlobalWdfDevice; // // Initialize the handler routine and create a new workitem. // WDF_WORKITEM_CONFIG_INIT(&WorkItemConfiguration, PepWorkerWrapper); // // Disable automatic serialization by the framework for the worker thread. // The parent device object is being serialized at device level (i.e., // WdfSynchronizationScopeDevice), and the framework requires it to be // passive level (i.e., WdfExecutionLevelPassive) if automatic // synchronization is desired. // WorkItemConfiguration.AutomaticSerialization = FALSE; // // Create the work item and queue it. If the workitem cannot be created // for some reason, just call the worker routine synchronously. // Status = WdfWorkItemCreate(&WorkItemConfiguration, &Attributes, &WorkItem); if (!NT_SUCCESS(Status)) { Synchronous = TRUE; TraceEvents(INFO, DBG_PEP, "%s: Failed to allocate work item to process pending" "work! Status = %!STATUS!. Will synchronously process.\n", __FUNCTION__, Status); } // // If the operation is to be performed synchronously, then directly // invoke the worker routine. Otherwise, queue a workitem to run the // worker routine. // if (Synchronous != FALSE) { PepProcessPendingWorkRequests(); } else { TraceEvents(INFO, DBG_PEP, "%s: Work request scheduled to run asynchronously. " "Device=%p, WorkType=%d, NotificationId=%d.\n", __FUNCTION__, (PVOID)WorkContext->PepInternalDevice, (ULONG)WorkContext->WorkType, (ULONG)WorkContext->NotificationId); WdfWorkItemEnqueue(WorkItem); } return STATUS_SUCCESS; }
VOID BalloonInterruptDpc( IN WDFINTERRUPT WdfInterrupt, IN WDFOBJECT WdfDevice ) { unsigned int len; PDEVICE_CONTEXT devCtx = GetDeviceContext(WdfDevice); PVOID buffer; BOOLEAN bHostAck = FALSE; UNREFERENCED_PARAMETER( WdfInterrupt ); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "--> %s\n", __FUNCTION__); WdfSpinLockAcquire(devCtx->InfDefQueueLock); if (virtqueue_get_buf(devCtx->InfVirtQueue, &len)) { bHostAck = TRUE; } if (virtqueue_get_buf(devCtx->DefVirtQueue, &len)) { bHostAck = TRUE; } WdfSpinLockRelease(devCtx->InfDefQueueLock); if(bHostAck) { KeSetEvent (&devCtx->HostAckEvent, IO_NO_INCREMENT, FALSE); } if (devCtx->StatVirtQueue) { WdfSpinLockAcquire(devCtx->StatQueueLock); buffer = virtqueue_get_buf(devCtx->StatVirtQueue, &len); WdfSpinLockRelease(devCtx->StatQueueLock); if (buffer) { /* * According to MSDN 'Using Framework Work Items' article: * Create one or more work items that your driver requeues as necessary. * Subsequently, each time that the driver's EvtInterruptDpc callback * function is called it must determine if the EvtWorkItem callback * function has run. If the EvtWorkItem callback function has not run, * the EvtInterruptDpc callback function does not call WdfWorkItemEnqueue, * because the work item is still queued. * A few drivers might need to call WdfWorkItemFlush to flush their work * items from the work-item queue. * * For each dpc (i.e. interrupt) we'll push stats exactly that many times. */ if (1==InterlockedIncrement(&devCtx->WorkCount)) { WdfWorkItemEnqueue(devCtx->StatWorkItem); } } } if(devCtx->Thread) { KeSetEvent(&devCtx->WakeUpThread, 0, FALSE); } }
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