VirtualBox

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

Last change on this file since 78177 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

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