VirtualBox

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

Last change on this file since 46150 was 36968, checked in by vboxsync, 14 years ago

rework usb

  • 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 36968 2011-05-05 08:55:16Z 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 vboxUsbDdiStateWaitOtherCompleted(pDevExt);
213
214 vboxUsbPwrIoPostDev(pDevExt, pIrp);
215
216 IoFreeWorkItem(pCtx->pWrkItem);
217 vboxUsbMemFree(pCtx);
218}
219
220static NTSTATUS vboxUsbPwrIoWaitCompletionAndPostAsync(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
221{
222 NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
223 PVBOXUSB_IOASYNC_CTX pCtx = (PVBOXUSB_IOASYNC_CTX)vboxUsbMemAlloc(sizeof (*pCtx));
224 Assert(pCtx);
225 if (pCtx)
226 {
227 PIO_WORKITEM pWrkItem = IoAllocateWorkItem(pDevExt->pFDO);
228 Assert(pWrkItem);
229 if (pWrkItem)
230 {
231 pCtx->pWrkItem = pWrkItem;
232 pCtx->pIrp = pIrp;
233 IoMarkIrpPending(pIrp);
234 IoQueueWorkItem(pWrkItem, vboxUsbPwrIoWaitCompletionAndPostAsyncWorker, DelayedWorkQueue, pCtx);
235 return STATUS_PENDING;
236 }
237 vboxUsbMemFree(pCtx);
238 }
239 return Status;
240}
241
242static NTSTATUS vboxUsbPwrQueryPowerDev(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
243{
244 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
245 DEVICE_POWER_STATE enmDevPState = pSl->Parameters.Power.State.DeviceState;
246 NTSTATUS Status = STATUS_SUCCESS;
247
248 if (enmDevPState >= pDevExt->DdiState.PwrState.PowerState.DeviceState)
249 {
250 Status = vboxUsbPwrIoWaitCompletionAndPostAsync(pDevExt, pIrp);
251 Assert(NT_SUCCESS(Status));
252 if (NT_SUCCESS(Status))
253 return Status;
254 }
255
256 pIrp->IoStatus.Status = Status;
257 pIrp->IoStatus.Information = 0;
258
259 PoStartNextPowerIrp(pIrp);
260
261 if (NT_SUCCESS(Status))
262 {
263 IoSkipCurrentIrpStackLocation(pIrp);
264 Status = PoCallDriver(pDevExt->pLowerDO, pIrp);
265 }
266 else
267 {
268 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
269 }
270
271 vboxUsbDdiStateRelease(pDevExt);
272
273 return Status;
274}
275
276static NTSTATUS vboxUsbPwrMnQueryPower(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
277{
278 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
279
280 switch (pSl->Parameters.Power.Type)
281 {
282 case SystemPowerState:
283 {
284 return vboxUsbPwrQueryPowerSys(pDevExt, pIrp);
285 }
286 case DevicePowerState:
287 {
288 return vboxUsbPwrQueryPowerDev(pDevExt, pIrp);
289 }
290 default:
291 {
292 Assert(0);
293 return vboxUsbPwrMnDefault(pDevExt, pIrp);
294 }
295
296 }
297 return vboxUsbPwrMnDefault(pDevExt, pIrp);
298}
299
300static NTSTATUS vboxUsbPwrSetPowerSys(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
301{
302 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
303 SYSTEM_POWER_STATE enmSysPState = pSl->Parameters.Power.State.SystemState;
304
305 return vboxUsbPwrIoPostSys(pDevExt, pIrp);
306}
307
308static NTSTATUS vboxUsbPwrSetPowerDev(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
309{
310 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
311 DEVICE_POWER_STATE enmDevPState = pSl->Parameters.Power.State.DeviceState;
312 DEVICE_POWER_STATE enmCurDevPState = pDevExt->DdiState.PwrState.PowerState.DeviceState;
313 NTSTATUS Status = STATUS_SUCCESS;
314
315 if (enmDevPState > enmCurDevPState && enmCurDevPState == PowerDeviceD0)
316 {
317 Status = vboxUsbPwrIoWaitCompletionAndPostAsync(pDevExt, pIrp);
318 Assert(NT_SUCCESS(Status));
319 if (NT_SUCCESS(Status))
320 return Status;
321 }
322
323 PoStartNextPowerIrp(pIrp);
324
325 if (NT_SUCCESS(Status))
326 {
327 IoCopyCurrentIrpStackLocationToNext(pIrp);
328 IoSetCompletionRoutine(pIrp, vboxUsbPwrIoPostDevCompletion, pDevExt, TRUE, TRUE, TRUE);
329 Status = PoCallDriver(pDevExt->pLowerDO, pIrp);
330 }
331 else
332 {
333 pIrp->IoStatus.Status = Status;
334 pIrp->IoStatus.Information = 0;
335
336 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
337 vboxUsbDdiStateRelease(pDevExt);
338 }
339
340 return Status;
341}
342
343
344static NTSTATUS vboxUsbPwrMnSetPower(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
345{
346 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
347
348 switch (pSl->Parameters.Power.Type)
349 {
350 case SystemPowerState:
351 {
352 return vboxUsbPwrSetPowerSys(pDevExt, pIrp);
353 }
354 case DevicePowerState:
355 {
356 return vboxUsbPwrSetPowerDev(pDevExt, pIrp);
357 }
358 default:
359 {
360 Assert(0);
361 return vboxUsbPwrMnDefault(pDevExt, pIrp);
362 }
363
364 }
365 return vboxUsbPwrMnDefault(pDevExt, pIrp);
366}
367
368static NTSTATUS vboxUsbPwrMnWaitWake(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
369{
370 AssertFailed();
371 return vboxUsbPwrMnDefault(pDevExt, pIrp);
372}
373
374
375static NTSTATUS vboxUsbPwrDispatch(IN PVBOXUSBDEV_EXT pDevExt, IN PIRP pIrp)
376{
377 PIO_STACK_LOCATION pSl = IoGetCurrentIrpStackLocation(pIrp);
378
379 switch (pSl->MinorFunction)
380 {
381 case IRP_MN_POWER_SEQUENCE:
382 {
383 return vboxUsbPwrMnPowerSequence(pDevExt, pIrp);
384 }
385 case IRP_MN_QUERY_POWER:
386 {
387 return vboxUsbPwrMnQueryPower(pDevExt, pIrp);
388 }
389 case IRP_MN_SET_POWER:
390 {
391 return vboxUsbPwrMnSetPower(pDevExt, pIrp);
392 }
393 case IRP_MN_WAIT_WAKE:
394 {
395 return vboxUsbPwrMnWaitWake(pDevExt, pIrp);
396 }
397 default:
398 {
399// Assert(0);
400 return vboxUsbPwrMnDefault(pDevExt, pIrp);
401 }
402 }
403}
404
405DECLHIDDEN(NTSTATUS) vboxUsbDispatchPower(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
406{
407 PVBOXUSBDEV_EXT pDevExt = (PVBOXUSBDEV_EXT)pDeviceObject->DeviceExtension;
408 ENMVBOXUSB_PNPSTATE enmState = vboxUsbDdiStateRetainIfNotRemoved(pDevExt);
409 switch (enmState)
410 {
411 case ENMVBOXUSB_PNPSTATE_REMOVED:
412 {
413 PoStartNextPowerIrp(pIrp);
414
415 pIrp->IoStatus.Status = STATUS_DELETE_PENDING;
416 pIrp->IoStatus.Information = 0;
417
418 IoCompleteRequest(pIrp, IO_NO_INCREMENT);
419
420 vboxUsbDdiStateRelease(pDevExt);
421
422 return STATUS_DELETE_PENDING;
423 }
424 case ENMVBOXUSB_PNPSTATE_START_PENDING:
425 {
426 PoStartNextPowerIrp(pIrp);
427 IoSkipCurrentIrpStackLocation(pIrp);
428
429 vboxUsbDdiStateRelease(pDevExt);
430
431 return PoCallDriver(pDevExt->pLowerDO, pIrp);
432 }
433 default:
434 {
435 return vboxUsbPwrDispatch(pDevExt, pIrp);
436 }
437 }
438}
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