VOID UfxDevice_EvtDeviceRemoteWakeupSignal ( _In_ UFXDEVICE UfxDevice ) /*++ Routine Description: Signals Remote Wakeup to the Host by issuing a link state change command. It acquires and releases the power reference to ensure a valid power state before accessing the device. Arguments: UfxDevice - UFXDEVICE object representing the device. --*/ { NTSTATUS Status; PUFXDEVICE_CONTEXT DeviceContext; PAGED_CODE(); TraceEntry(); DeviceContext = UfxDeviceGetContext(UfxDevice); // // Stop Idle to ensure the device is in working state // Status = WdfDeviceStopIdle(DeviceContext->FdoWdfDevice, TRUE); if (!NT_SUCCESS(Status)) { TraceError("Failed to stop idle %!STATUS!", Status); goto End; } // // Issue a Link State Change Request. // // // #### TODO: Insert code to issue a link state change on the controller #### // WdfDeviceResumeIdle(DeviceContext->FdoWdfDevice); End: UfxDeviceEventComplete(UfxDevice, Status); TraceExit(); }
NTSTATUS SerialDeviceFileCreateWorker ( IN WDFDEVICE Device ) { NTSTATUS status; PSERIAL_DEVICE_EXTENSION extension = SerialGetDeviceExtension (Device); // // Create a buffer for the RX data when no reads are outstanding. // extension->InterruptReadBuffer = NULL; extension->BufferSize = 0; switch (MmQuerySystemSize()) { case MmLargeSystem: { extension->BufferSize = 4096; extension->InterruptReadBuffer = ExAllocatePoolWithTag( NonPagedPool, extension->BufferSize, POOL_TAG ); if (extension->InterruptReadBuffer) { break; } } case MmMediumSystem: { extension->BufferSize = 1024; extension->InterruptReadBuffer = ExAllocatePoolWithTag( NonPagedPool, extension->BufferSize, POOL_TAG ); if (extension->InterruptReadBuffer) { break; } } case MmSmallSystem: { extension->BufferSize = 128; extension->InterruptReadBuffer = ExAllocatePoolWithTag( NonPagedPool, extension->BufferSize, POOL_TAG ); } } if (!extension->InterruptReadBuffer) { return STATUS_INSUFFICIENT_RESOURCES; } // // By taking a power reference by calling WdfDeviceStopIdle, we prevent the // framework from powering down our device due to idle timeout when there // is an open handle. Power reference also moves the device to D0 if we are // idled out. If you fail create anywhere later in this routine, do make sure // drop the reference. // status = WdfDeviceStopIdle(Device, TRUE); if (!NT_SUCCESS(status)) { return status; } // // wakeup is not currently enabled // extension->IsWakeEnabled = FALSE; // // On a new open we "flush" the read queue by initializing the // count of characters. // extension->CharsInInterruptBuffer = 0; extension->LastCharSlot = extension->InterruptReadBuffer + (extension->BufferSize - 1); extension->ReadBufferBase = extension->InterruptReadBuffer; extension->CurrentCharSlot = extension->InterruptReadBuffer; extension->FirstReadableChar = extension->InterruptReadBuffer; extension->TotalCharsQueued = 0; // // We set up the default xon/xoff limits. // extension->HandFlow.XoffLimit = extension->BufferSize >> 3; extension->HandFlow.XonLimit = extension->BufferSize >> 1; extension->WmiCommData.XoffXmitThreshold = extension->HandFlow.XoffLimit; extension->WmiCommData.XonXmitThreshold = extension->HandFlow.XonLimit; extension->BufferSizePt8 = ((3*(extension->BufferSize>>2))+ (extension->BufferSize>>4)); // // Mark the device as busy for WMI // extension->WmiCommData.IsBusy = TRUE; extension->IrpMaskLocation = NULL; extension->HistoryMask = 0; extension->IsrWaitMask = 0; extension->SendXonChar = FALSE; extension->SendXoffChar = FALSE; #if !DBG // // Clear out the statistics. // WdfInterruptSynchronize( extension->WdfInterrupt, SerialClearStats, extension ); #endif // // The escape char replacement must be reset upon every open. // extension->EscapeChar = 0; // // We don't want the device to be removed or stopped when there is an handle // // Note to anyone copying this sample as a starting point: // // This works in this driver simply because this driver supports exactly // one open handle at a time. If it supported more, then it would need // counting logic to determine when all the reasons for failing Stop/Remove // were gone. // WdfDeviceSetStaticStopRemove(Device, FALSE); // // Synchronize with the ISR and let it know that the device // has been successfully opened. // WdfInterruptSynchronize( extension->WdfInterrupt, SerialMarkOpen, extension ); return STATUS_SUCCESS; }
NTSTATUS UfxDeviceStopOrResumeIdle ( _In_ UFXDEVICE Device, _In_ USBFN_DEVICE_STATE UsbState, _In_ USBFN_PORT_TYPE UsbPort ) /*++ Routine Description: Examines the device USB state and port type and determines if it needs to stop or resume idle. Arguments: UfxDevice - UFXDEVICE object representing the device. Return Value: STATUS_SUCCESS on success, or an appropirate NTSTATUS message on failure. --*/ { PUFXDEVICE_CONTEXT DeviceContext; PCONTROLLER_CONTEXT ControllerContext; NTSTATUS Status; BOOLEAN NeedPower; DEVICE_POWER_STATE DxState = PowerDeviceD3; PAGED_CODE(); TraceEntry(); DeviceContext = UfxDeviceGetContext(Device); ControllerContext = DeviceGetControllerContext(DeviceContext->FdoWdfDevice); switch (UsbState) { case UsbfnDeviceStateAttached: __fallthrough; case UsbfnDeviceStateDefault: switch (UsbPort) { case UsbfnStandardDownstreamPort: __fallthrough; case UsbfnChargingDownstreamPort: __fallthrough; case UsbfnUnknownPort: NeedPower = TRUE; break; case UsbfnDedicatedChargingPort: case UsbfnProprietaryDedicatedChargingPort: NeedPower = FALSE; DxState = PowerDeviceD2; break; default: NeedPower = FALSE; } break; case UsbfnDeviceStateSuspended: NeedPower = FALSE; DxState = PowerDeviceD2; break; case UsbfnDeviceStateAddressed: __fallthrough; case UsbfnDeviceStateConfigured: NeedPower = TRUE; break; default: NeedPower = FALSE; } // // Determine if our lowest idle state has changed, and set it if so // if (DxState != ControllerContext->IdleSettings.DxState) { ControllerContext->IdleSettings.DxState = DxState; Status = WdfDeviceAssignS0IdleSettings( DeviceContext->FdoWdfDevice, &ControllerContext->IdleSettings); CHK_NT_MSG(Status, "Failed to update device idle settings"); } if (NeedPower && DeviceContext->IsIdle) { // // We don't want to update the USB state /port until we stop idle to // prevent D0 -> DX path from reading the wrong state. // TraceInformation("Stopping idle"); Status = WdfDeviceStopIdle(DeviceContext->FdoWdfDevice, TRUE); CHK_NT_MSG(Status, "Failed to stop idle"); DeviceContext->UsbState = UsbState; DeviceContext->UsbPort = UsbPort; DeviceContext->IsIdle = FALSE; } else if (!NeedPower && !DeviceContext->IsIdle) { // // We need to update USB state / port before resume idle to ensure // D0 -> DX path reads the correct state. // DeviceContext->UsbState = UsbState; DeviceContext->UsbPort = UsbPort; DeviceContext->IsIdle = TRUE; TraceInformation("Resuming idle"); WdfDeviceResumeIdle(DeviceContext->FdoWdfDevice); } else { TraceInformation("No idle action"); DeviceContext->UsbState = UsbState; DeviceContext->UsbPort = UsbPort; } Status = STATUS_SUCCESS; End: TraceExit(); return Status; }