VirtualBox

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

Last change on this file since 55058 was 55058, checked in by vboxsync, 10 years ago

VBoxUSB: fixed BSOD on host computer at system waking up

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