VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxUSB/win/dev/VBoxUsbPwr.cpp@ 63490

Last change on this file since 63490 was 62714, checked in by vboxsync, 9 years ago

HostDrivers: warnings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.3 KB
Line 
1/* $Id: VBoxUsbPwr.cpp 62714 2016-07-29 21:41:09Z vboxsync $ */
2/** @file
3 * USB Power state Handling
4 */
5
6/*
7 * Copyright (C) 2011-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "VBoxUsbCmn.h"
19
20#include <iprt/assert.h>
21
22DECLHIDDEN(VOID) vboxUsbPwrStateInit(PVBOXUSBDEV_EXT pDevExt)
23{
24 POWER_STATE PowerState;
25 PowerState.SystemState = PowerSystemWorking;
26 PowerState.DeviceState = PowerDeviceD0;
27 PoSetPowerState(pDevExt->pFDO, DevicePowerState, PowerState);
28 pDevExt->DdiState.PwrState.PowerState = PowerState;
29 pDevExt->DdiState.PwrState.PowerDownLevel = PowerDeviceUnspecified;
30}
31
32static NTSTATUS vboxUsbPwrMnDefault(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
33{
34 NTSTATUS Status;
35 PoStartNextPowerIrp(pIrp);
36 IoSkipCurrentIrpStackLocation(pIrp);
37 Status = PoCallDriver(pDevExt->pLowerDO, pIrp);
38 Assert(NT_SUCCESS(Status) || Status == STATUS_NOT_SUPPORTED);
39 vboxUsbDdiStateRelease(pDevExt);
40 return Status;
41}
42
43static NTSTATUS vboxUsbPwrMnPowerSequence(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
44{
45 AssertFailed();
46 return vboxUsbPwrMnDefault(pDevExt, pIrp);
47}
48
49typedef struct VBOXUSB_PWRDEV_CTX
50{
51 PVBOXUSBDEV_EXT pDevExt;
52 PIRP pIrp;
53} VBOXUSB_PWRDEV_CTX, *PVBOXUSB_PWRDEV_CTX;
54
55static VOID vboxUsbPwrIoDeviceCompletion(IN PDEVICE_OBJECT pDeviceObject,
56 IN UCHAR MinorFunction,
57 IN POWER_STATE PowerState,
58 IN PVOID pvContext,
59 IN PIO_STATUS_BLOCK pIoStatus)
60{
61 RT_NOREF3(pDeviceObject, MinorFunction, PowerState);
62 PVBOXUSB_PWRDEV_CTX pDevCtx = (PVBOXUSB_PWRDEV_CTX)pvContext;
63 PVBOXUSBDEV_EXT pDevExt = pDevCtx->pDevExt;
64 PIRP pIrp = pDevCtx->pIrp;
65 pIrp->IoStatus.Status = pIoStatus->Status;
66 pIrp->IoStatus.Information = 0;
67
68 PoStartNextPowerIrp(pIrp);
69 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
70 vboxUsbDdiStateRelease(pDevExt);
71
72 vboxUsbMemFree(pDevCtx);
73}
74
75static NTSTATUS vboxUsbPwrIoRequestDev(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
76{
77 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
78 POWER_STATE PwrState;
79 PwrState.SystemState = pSl->Parameters.Power.State.SystemState;
80 PwrState.DeviceState = pDevExt->DdiState.DevCaps.DeviceState[PwrState.SystemState];
81
82 NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
83 PVBOXUSB_PWRDEV_CTX pDevCtx = (PVBOXUSB_PWRDEV_CTX)vboxUsbMemAlloc(sizeof (*pDevCtx));
84 Assert(pDevCtx);
85 if (pDevCtx)
86 {
87 pDevCtx->pDevExt = pDevExt;
88 pDevCtx->pIrp = pIrp;
89
90 Status = PoRequestPowerIrp(pDevExt->pPDO, pSl->MinorFunction, PwrState,
91 vboxUsbPwrIoDeviceCompletion, pDevCtx, NULL);
92 Assert(NT_SUCCESS(Status));
93 if (NT_SUCCESS(Status))
94 return STATUS_MORE_PROCESSING_REQUIRED;
95
96 vboxUsbMemFree(pDevCtx);
97 }
98
99 PoStartNextPowerIrp(pIrp);
100 pIrp->IoStatus.Status = Status;
101 pIrp->IoStatus.Information = 0;
102 vboxUsbDdiStateRelease(pDevExt);
103
104 /* the "real" Status is stored in pIrp->IoStatus.Status,
105 * return success here to complete the Io */
106 return STATUS_SUCCESS;
107}
108
109static NTSTATUS vboxUsbPwrIoPostSysCompletion(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp, IN PVOID pvContext)
110{
111 RT_NOREF1(pDevObj);
112 PVBOXUSBDEV_EXT pDevExt = (PVBOXUSBDEV_EXT)pvContext;
113 NTSTATUS Status = pIrp->IoStatus.Status;
114 Assert(Status == STATUS_SUCCESS);
115 if (NT_SUCCESS(Status))
116 {
117 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
118 switch (pSl->MinorFunction)
119 {
120 case IRP_MN_SET_POWER:
121 pDevExt->DdiState.PwrState.PowerState.SystemState = pSl->Parameters.Power.State.SystemState;
122 break;
123
124 default:
125 break;
126 }
127
128 return vboxUsbPwrIoRequestDev(pDevExt, pIrp);
129 }
130
131 PoStartNextPowerIrp(pIrp);
132 vboxUsbDdiStateRelease(pDevExt);
133 return STATUS_SUCCESS;
134}
135
136static NTSTATUS vboxUsbPwrIoPostSys(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
137{
138 IoMarkIrpPending(pIrp);
139 IoCopyCurrentIrpStackLocationToNext(pIrp);
140 IoSetCompletionRoutine(pIrp, vboxUsbPwrIoPostSysCompletion, pDevExt, TRUE, TRUE, TRUE);
141 NTSTATUS Status = PoCallDriver(pDevExt->pLowerDO, pIrp);
142 Assert(NT_SUCCESS(Status)); NOREF(Status);
143 return STATUS_PENDING;
144}
145
146static NTSTATUS vboxUsbPwrQueryPowerSys(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
147{
148 /*PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
149 SYSTEM_POWER_STATE enmSysPState = pSl->Parameters.Power.State.SystemState;*/
150
151 return vboxUsbPwrIoPostSys(pDevExt, pIrp);
152}
153
154static NTSTATUS vboxUsbPwrIoPostDevCompletion(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp, IN PVOID pvContext)
155{
156 RT_NOREF1(pDevObj);
157 PVBOXUSBDEV_EXT pDevExt = (PVBOXUSBDEV_EXT)pvContext;
158
159 if (pIrp->PendingReturned)
160 IoMarkIrpPending(pIrp);
161
162 NTSTATUS Status = pIrp->IoStatus.Status;
163 Assert(Status == STATUS_SUCCESS);
164 if (NT_SUCCESS(Status))
165 {
166 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
167 switch (pSl->MinorFunction)
168 {
169 case IRP_MN_SET_POWER:
170 pDevExt->DdiState.PwrState.PowerState.DeviceState = pSl->Parameters.Power.State.DeviceState;
171 PoSetPowerState(pDevExt->pFDO, DevicePowerState, pSl->Parameters.Power.State);
172 break;
173
174 default:
175 break;
176 }
177 }
178
179 PoStartNextPowerIrp(pIrp);
180 vboxUsbDdiStateRelease(pDevExt);
181 return STATUS_SUCCESS;
182}
183
184static NTSTATUS vboxUsbPwrIoPostDev(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
185{
186 IoMarkIrpPending(pIrp);
187 IoCopyCurrentIrpStackLocationToNext(pIrp);
188 IoSetCompletionRoutine(pIrp, vboxUsbPwrIoPostDevCompletion, pDevExt, TRUE, TRUE, TRUE);
189 NTSTATUS Status = PoCallDriver(pDevExt->pLowerDO, pIrp);
190 Assert(NT_SUCCESS(Status)); RT_NOREF_PV(Status);
191 return STATUS_PENDING;
192}
193
194typedef struct VBOXUSB_IOASYNC_CTX
195{
196 PIO_WORKITEM pWrkItem;
197 PIRP pIrp;
198} VBOXUSB_IOASYNC_CTX, *PVBOXUSB_IOASYNC_CTX;
199
200static VOID vboxUsbPwrIoWaitCompletionAndPostAsyncWorker(IN PDEVICE_OBJECT pDeviceObject, IN PVOID pvContext)
201{
202 PVBOXUSBDEV_EXT pDevExt = (PVBOXUSBDEV_EXT)pDeviceObject->DeviceExtension;
203 PVBOXUSB_IOASYNC_CTX pCtx = (PVBOXUSB_IOASYNC_CTX)pvContext;
204 PIRP pIrp = pCtx->pIrp;
205
206 vboxUsbPwrIoPostDev(pDevExt, pIrp);
207
208 IoFreeWorkItem(pCtx->pWrkItem);
209 vboxUsbMemFree(pCtx);
210}
211
212static NTSTATUS vboxUsbPwrIoWaitCompletionAndPostAsync(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
213{
214 NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
215 PVBOXUSB_IOASYNC_CTX pCtx = (PVBOXUSB_IOASYNC_CTX)vboxUsbMemAlloc(sizeof (*pCtx));
216 Assert(pCtx);
217 if (pCtx)
218 {
219 PIO_WORKITEM pWrkItem = IoAllocateWorkItem(pDevExt->pFDO);
220 Assert(pWrkItem);
221 if (pWrkItem)
222 {
223 pCtx->pWrkItem = pWrkItem;
224 pCtx->pIrp = pIrp;
225 IoMarkIrpPending(pIrp);
226 IoQueueWorkItem(pWrkItem, vboxUsbPwrIoWaitCompletionAndPostAsyncWorker, DelayedWorkQueue, pCtx);
227 return STATUS_PENDING;
228 }
229 vboxUsbMemFree(pCtx);
230 }
231 return Status;
232}
233
234static NTSTATUS vboxUsbPwrQueryPowerDev(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
235{
236 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
237 DEVICE_POWER_STATE enmDevPState = pSl->Parameters.Power.State.DeviceState;
238 NTSTATUS Status = STATUS_SUCCESS;
239
240 if (enmDevPState >= pDevExt->DdiState.PwrState.PowerState.DeviceState)
241 {
242 Status = vboxUsbPwrIoWaitCompletionAndPostAsync(pDevExt, pIrp);
243 Assert(NT_SUCCESS(Status));
244 if (NT_SUCCESS(Status))
245 return Status;
246 }
247
248 pIrp->IoStatus.Status = Status;
249 pIrp->IoStatus.Information = 0;
250
251 PoStartNextPowerIrp(pIrp);
252
253 if (NT_SUCCESS(Status))
254 {
255 IoSkipCurrentIrpStackLocation(pIrp);
256 Status = PoCallDriver(pDevExt->pLowerDO, pIrp);
257 }
258 else
259 {
260 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
261 }
262
263 vboxUsbDdiStateRelease(pDevExt);
264
265 return Status;
266}
267
268static NTSTATUS vboxUsbPwrMnQueryPower(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
269{
270 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
271 switch (pSl->Parameters.Power.Type)
272 {
273 case SystemPowerState:
274 return vboxUsbPwrQueryPowerSys(pDevExt, pIrp);
275
276 case DevicePowerState:
277 return vboxUsbPwrQueryPowerDev(pDevExt, pIrp);
278
279 default:
280 AssertFailed();
281 return vboxUsbPwrMnDefault(pDevExt, pIrp);
282
283 }
284}
285
286static NTSTATUS vboxUsbPwrSetPowerSys(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
287{
288 /*PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
289 SYSTEM_POWER_STATE enmSysPState = pSl->Parameters.Power.State.SystemState;*/
290
291 return vboxUsbPwrIoPostSys(pDevExt, pIrp);
292}
293
294static NTSTATUS vboxUsbPwrSetPowerDev(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
295{
296 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
297 DEVICE_POWER_STATE enmDevPState = pSl->Parameters.Power.State.DeviceState;
298 DEVICE_POWER_STATE enmCurDevPState = pDevExt->DdiState.PwrState.PowerState.DeviceState;
299 NTSTATUS Status = STATUS_SUCCESS;
300
301 if (enmDevPState > enmCurDevPState && enmCurDevPState == PowerDeviceD0)
302 {
303 Status = vboxUsbPwrIoWaitCompletionAndPostAsync(pDevExt, pIrp);
304 Assert(NT_SUCCESS(Status));
305 if (NT_SUCCESS(Status))
306 return Status;
307 }
308
309 PoStartNextPowerIrp(pIrp);
310
311 if (NT_SUCCESS(Status))
312 {
313 IoCopyCurrentIrpStackLocationToNext(pIrp);
314 IoSetCompletionRoutine(pIrp, vboxUsbPwrIoPostDevCompletion, pDevExt, TRUE, TRUE, TRUE);
315 Status = PoCallDriver(pDevExt->pLowerDO, pIrp);
316 }
317 else
318 {
319 pIrp->IoStatus.Status = Status;
320 pIrp->IoStatus.Information = 0;
321
322 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
323 vboxUsbDdiStateRelease(pDevExt);
324 }
325
326 return Status;
327}
328
329
330static NTSTATUS vboxUsbPwrMnSetPower(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
331{
332 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
333 switch (pSl->Parameters.Power.Type)
334 {
335 case SystemPowerState:
336 return vboxUsbPwrSetPowerSys(pDevExt, pIrp);
337
338 case DevicePowerState:
339 return vboxUsbPwrSetPowerDev(pDevExt, pIrp);
340
341 default:
342 AssertFailed();
343 return vboxUsbPwrMnDefault(pDevExt, pIrp);
344 }
345}
346
347static NTSTATUS vboxUsbPwrMnWaitWake(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
348{
349 AssertFailed();
350 return vboxUsbPwrMnDefault(pDevExt, pIrp);
351}
352
353
354static NTSTATUS vboxUsbPwrDispatch(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
355{
356 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
357
358 switch (pSl->MinorFunction)
359 {
360 case IRP_MN_POWER_SEQUENCE:
361 return vboxUsbPwrMnPowerSequence(pDevExt, pIrp);
362
363 case IRP_MN_QUERY_POWER:
364 return vboxUsbPwrMnQueryPower(pDevExt, pIrp);
365
366 case IRP_MN_SET_POWER:
367 return vboxUsbPwrMnSetPower(pDevExt, pIrp);
368
369 case IRP_MN_WAIT_WAKE:
370 return vboxUsbPwrMnWaitWake(pDevExt, pIrp);
371
372 default:
373// AssertFailed();
374 return vboxUsbPwrMnDefault(pDevExt, pIrp);
375 }
376}
377
378DECLHIDDEN(NTSTATUS) vboxUsbDispatchPower(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
379{
380 PVBOXUSBDEV_EXT pDevExt = (PVBOXUSBDEV_EXT)pDeviceObject->DeviceExtension;
381 ENMVBOXUSB_PNPSTATE enmState = vboxUsbDdiStateRetainIfNotRemoved(pDevExt);
382 switch (enmState)
383 {
384 case ENMVBOXUSB_PNPSTATE_REMOVED:
385 PoStartNextPowerIrp(pIrp);
386
387 pIrp->IoStatus.Status = STATUS_DELETE_PENDING;
388 pIrp->IoStatus.Information = 0;
389
390 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
391
392 vboxUsbDdiStateRelease(pDevExt);
393
394 return STATUS_DELETE_PENDING;
395
396 case ENMVBOXUSB_PNPSTATE_START_PENDING:
397 PoStartNextPowerIrp(pIrp);
398 IoSkipCurrentIrpStackLocation(pIrp);
399
400 vboxUsbDdiStateRelease(pDevExt);
401
402 return PoCallDriver(pDevExt->pLowerDO, pIrp);
403
404 default:
405 return vboxUsbPwrDispatch(pDevExt, pIrp);
406 }
407}
408
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette