1 /*++
2 
3 Copyright (c) Microsoft. All rights reserved.
4 
5 Module Name:
6 
7     PowerPolicyStateMachineKM.cpp
8 
9 Abstract:
10 
11 
12 Environment:
13 
14     Kernel mode only
15 
16 Revision History:
17 
18 --*/
19 
20 #include "../pnppriv.hpp"
21 
22 #if FX_IS_KERNEL_MODE
23 #include <usbdrivr.h>
24 #endif
25 
26 #include "fxusbidleinfo.hpp"
27 
28 extern "C" {
29 #if defined(EVENT_TRACING)
30 #include "PowerPolicyStateMachineKM.tmh"
31 #endif
32 }
33 
34 VOID
35 FxPkgPnp::PowerPolicyUpdateSystemWakeSource(
36     __in FxIrp* Irp
37     )
38 /*++
39 
40 Routine Description:
41     Gets source of wake if OS supports this.
42 
43 Arguments:
44     Irp
45 
46 Return Value:
47     None
48 
49   --*/
50 {
51     //
52     // Check to see if this device caused the machine to wake up
53     //
54     m_PowerPolicyMachine.m_Owner->m_SystemWakeSource =
55         PoGetSystemWake(Irp->GetIrp());
56 
57     if (m_PowerPolicyMachine.m_Owner->m_SystemWakeSource) {
58         DoTraceLevelMessage(
59             GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP,
60             "WDFDEVICE 0x%p !devobj 0x%p WW !irp 0x%p is a source of "
61             "wake",
62             m_Device->GetHandle(),
63             m_Device->GetDeviceObject(),
64             Irp->GetIrp());
65     }
66 }
67 
68 BOOLEAN
69 FxPkgPnp::ShouldProcessPowerPolicyEventOnDifferentThread(
70     __in KIRQL CurrentIrql,
71     __in BOOLEAN CallerSpecifiedProcessingOnDifferentThread
72     )
73 /*++
74 Routine Description:
75 
76     This function returns whether the power policy state machine should process
77     the current event on the same thread or on a different one.
78 
79 
80 
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 
91 
92 
93 
94 
95 
96 
97 
98 
99 
100 
101 
102 
103 
104 
105 
106 
107 
108 
109 Arguemnts:
110 
111     CurrentIrql - The current IRQL
112 
113     CallerSpecifiedProcessingOnDifferentThread - Whether or not caller of
114         PowerPolicyProcessEvent specified that the event be processed on a
115         different thread.
116 
117 Returns:
118     TRUE if the power policy state machine should process the event on a
119        different thread.
120 
121     FALSE if the power policy state machine should process the event on the
122        same thread
123 
124 --*/
125 {
126     //
127     // For KMDF, we ignore what the caller of PowerPolicyProcessEvent specified
128     // (which should always be FALSE, BTW) and base our decision on the current
129     // IRQL. If we are running at PASSIVE_LEVEL, we process on the same thread
130     // else we queue a work item.
131     //
132     UNREFERENCED_PARAMETER(CallerSpecifiedProcessingOnDifferentThread);
133 
134     ASSERT(FALSE == CallerSpecifiedProcessingOnDifferentThread);
135 
136     return (CurrentIrql == PASSIVE_LEVEL) ? FALSE : TRUE;
137 }
138 
139 _Must_inspect_result_
140 NTSTATUS
141 FxUsbIdleInfo::Initialize(
142     VOID
143     )
144 {
145     MdIrp pIrp;
146     MxDeviceObject attachedDevObj;
147 
148     attachedDevObj.SetObject(((FxPkgPnp*)m_CallbackInfo.IdleContext)->GetDevice()->GetAttachedDevice());
149 
150     pIrp = FxIrp::AllocateIrp(attachedDevObj.GetStackSize());
151 
152     if (pIrp == NULL) {
153         return STATUS_INSUFFICIENT_RESOURCES;
154     }
155 
156     m_IdleIrp.SetIrp(pIrp);
157 
158     return STATUS_SUCCESS;
159 }
160 
161 VOID
162 FxPkgPnp::PowerPolicySubmitUsbIdleNotification(
163     VOID
164     )
165 {
166     // FxIrp* usbIdleIrp;
167 
168     // //
169     // // This will be set to TRUE if USBSS completion event gets dropped.
170     // //
171     // m_PowerPolicyMachine.m_Owner->m_UsbIdle->m_EventDropped = FALSE;
172 
173     // usbIdleIrp = &m_PowerPolicyMachine.m_Owner->m_UsbIdle->m_IdleIrp;
174 
175     // usbIdleIrp->Reuse();
176 
177     // usbIdleIrp->SetCompletionRoutineEx(
178     //     m_Device->GetDeviceObject(),
179     //     _PowerPolicyUsbSelectiveSuspendCompletionRoutine,
180     //     this);
181 
182     // usbIdleIrp->SetMajorFunction(IRP_MJ_INTERNAL_DEVICE_CONTROL);
183     // usbIdleIrp->SetParameterIoctlCode(
184     //     IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION);
185     // usbIdleIrp->SetParameterIoctlInputBufferLength(
186     //     sizeof(m_PowerPolicyMachine.m_Owner->m_UsbIdle->m_CallbackInfo));
187     // usbIdleIrp->SetParameterIoctlType3InputBuffer(
188     //     (PVOID) &m_PowerPolicyMachine.m_Owner->m_UsbIdle->m_CallbackInfo);
189 
190     // m_PowerPolicyMachine.m_Owner->m_UsbIdle->m_IdleIrp.CallDriver(
191     //     m_Device->GetAttachedDevice()
192     //     );
193     ROSWDFNOTIMPLEMENTED;
194 }
195 
196 VOID
197 FxPkgPnp::PowerPolicyCancelUsbSS(
198     VOID
199     )
200 {
201     m_PowerPolicyMachine.m_Owner->m_UsbIdle->m_IdleIrp.Cancel();
202 }
203 
204 __drv_maxIRQL(PASSIVE_LEVEL)
205 VOID
206 FxUsbIdleInfo::_UsbIdleCallback(
207     __in PVOID Context
208     )
209 {
210     FxPkgPnp* pPkgPnp;
211     FxUsbIdleInfo* pThis;
212     FxCREvent event;
213 
214     pPkgPnp = (FxPkgPnp*) Context;
215 
216     DoTraceLevelMessage(
217         pPkgPnp->GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
218         "Entering USB Selective Suspend Idle callback");
219 
220     pThis = pPkgPnp->m_PowerPolicyMachine.m_Owner->m_UsbIdle;
221 
222     ASSERT(pThis->m_IdleCallbackEvent == NULL);
223     pThis->m_IdleCallbackEvent = event.GetSelfPointer();
224 
225     pPkgPnp->PowerPolicyProcessEvent(PwrPolUsbSelectiveSuspendCallback);
226 
227     event.EnterCRAndWaitAndLeave();
228     pThis->m_IdleCallbackEvent = NULL;
229 
230     DoTraceLevelMessage(
231         pPkgPnp->GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
232         "Leaving USB Selective Suspend Idle callback");
233 }
234 
235 
236 VOID
237 FxPowerPolicyMachine::UsbSSCallbackProcessingComplete(
238     VOID
239     )
240 {
241     ASSERT(m_Owner->m_UsbIdle->m_IdleCallbackEvent != NULL);
242     m_Owner->m_UsbIdle->m_IdleCallbackEvent->Set();
243 }
244 
245 
246 
247