Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

387 lines
11 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. power.c
  5. Abstract:
  6. Author:
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. Revision History:
  11. --*/
  12. #include <stdio.h>
  13. #include "stddef.h"
  14. #include "wdm.h"
  15. #include "usbscan.h"
  16. #include "usbd_api.h"
  17. #include "private.h"
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text(PAGE, USPower)
  20. #endif
  21. NTSTATUS
  22. USPower(
  23. IN PDEVICE_OBJECT pDeviceObject,
  24. IN PIRP pIrp
  25. )
  26. /*++
  27. Routine Description:
  28. Process the Power IRPs sent to the PDO for this device.
  29. Arguments:
  30. pDeviceObject - pointer to the functional device object (FDO) for this device.
  31. pIrp - pointer to an I/O Request Packet
  32. Return Value:
  33. NT status code
  34. --*/
  35. {
  36. NTSTATUS Status;
  37. PUSBSCAN_DEVICE_EXTENSION pde;
  38. PIO_STACK_LOCATION pIrpStack;
  39. BOOLEAN hookIt = FALSE;
  40. POWER_STATE powerState;
  41. PAGED_CODE();
  42. DebugTrace(TRACE_PROC_ENTER,("USPower: Enter... \n"));
  43. //
  44. // Check arguments.
  45. //
  46. if( (NULL == pDeviceObject)
  47. || (NULL == pDeviceObject->DeviceExtension)
  48. || (NULL == pIrp) )
  49. {
  50. DebugTrace(TRACE_ERROR,("USPower: ERROR!! Invalid parameter passed.\n"));
  51. Status = STATUS_INVALID_PARAMETER;
  52. DebugTrace(TRACE_PROC_LEAVE,("USPower: Leaving.. Status = %x.\n", Status));
  53. return Status;
  54. }
  55. USIncrementIoCount(pDeviceObject);
  56. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  57. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  58. Status = STATUS_SUCCESS;
  59. switch (pIrpStack -> MinorFunction) {
  60. case IRP_MN_SET_POWER:
  61. DebugTrace(TRACE_STATUS,("USPower: IRP_MN_SET_POWER\n"));
  62. switch (pIrpStack -> Parameters.Power.Type) {
  63. case SystemPowerState:
  64. DebugTrace(TRACE_STATUS,("USPower: SystemPowerState\n"));
  65. //
  66. // find the device power state equivalent to the given system state
  67. //
  68. DebugTrace(TRACE_STATUS,("USPower: Set Power, SystemPowerState (%d)\n",
  69. pIrpStack -> Parameters.Power.State.SystemState));
  70. if (pIrpStack -> Parameters.Power.State.SystemState == PowerSystemWorking) {
  71. powerState.DeviceState = PowerDeviceD0;
  72. } else if (/* pde ->EnabledForWakeup */ FALSE) {
  73. DebugTrace(TRACE_STATUS,("USPower: USBSCAN always enabled for wakeup\n"));
  74. powerState.DeviceState = pde ->
  75. DeviceCapabilities.DeviceState[pIrpStack->Parameters.Power.State.SystemState];
  76. } else {
  77. //
  78. // wakeup not enabled, just go in to the 'OFF' state.
  79. //
  80. powerState.DeviceState = PowerDeviceD3;
  81. } //irpStack->Parameters.Power.State.SystemState
  82. //
  83. // are we already in this state?
  84. //
  85. if (powerState.DeviceState != pde -> CurrentDevicePowerState) {
  86. //
  87. // No, request that we be put into this state
  88. //
  89. DebugTrace(TRACE_STATUS,("USPower: Requesting powerstate %d\n",
  90. powerState.DeviceState));
  91. IoMarkIrpPending(pIrp);
  92. pde -> pPowerIrp = pIrp;
  93. Status = PoRequestPowerIrp(pde -> pPhysicalDeviceObject,
  94. IRP_MN_SET_POWER,
  95. powerState,
  96. USPoRequestCompletion,
  97. pDeviceObject,
  98. NULL);
  99. if (!NT_SUCCESS(Status)) {
  100. //
  101. // Allocation failed, we must complete the IRP
  102. // ourselves.
  103. //
  104. PoStartNextPowerIrp(pIrp);
  105. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  106. USDecrementIoCount(pDeviceObject);
  107. }
  108. //
  109. // We marked the IRP pending, so we must return
  110. // STATUS_PENDING (our caller will examine
  111. // Irp->IoStatus.Status)
  112. //
  113. Status = STATUS_PENDING;
  114. } else {
  115. //
  116. // Yes, just pass it on
  117. //
  118. IoCopyCurrentIrpStackLocationToNext(pIrp);
  119. PoStartNextPowerIrp(pIrp);
  120. Status = PoCallDriver(pde -> pStackDeviceObject, pIrp);
  121. USDecrementIoCount(pDeviceObject);
  122. }
  123. break;
  124. case DevicePowerState:
  125. DebugTrace(TRACE_STATUS,("USPower: DevicePowerState\n"));
  126. Status = USSetDevicePowerState(pDeviceObject,
  127. pIrpStack -> Parameters.Power.State.DeviceState,
  128. &hookIt);
  129. IoCopyCurrentIrpStackLocationToNext(pIrp);
  130. if (hookIt) {
  131. DebugTrace(TRACE_STATUS,("USPower: Set PowerIrp Completion Routine\n"));
  132. IoSetCompletionRoutine(pIrp,
  133. USPowerIrpComplete,
  134. // always pass FDO to completion routine
  135. pDeviceObject,
  136. hookIt,
  137. hookIt,
  138. hookIt);
  139. }
  140. PoStartNextPowerIrp(pIrp);
  141. Status = PoCallDriver(pde ->pStackDeviceObject, pIrp);
  142. if (!hookIt) {
  143. USDecrementIoCount(pDeviceObject);
  144. }
  145. break;
  146. } /* case irpStack->Parameters.Power.Type */
  147. break; /* IRP_MN_SET_POWER */
  148. case IRP_MN_QUERY_POWER:
  149. DebugTrace(TRACE_STATUS,("USPower: IRP_MN_QUERY_POWER\n"));
  150. IoCopyCurrentIrpStackLocationToNext(pIrp);
  151. PoStartNextPowerIrp(pIrp);
  152. Status = PoCallDriver(pde -> pStackDeviceObject, pIrp);
  153. USDecrementIoCount(pDeviceObject);
  154. break; /* IRP_MN_QUERY_POWER */
  155. default:
  156. DebugTrace(TRACE_STATUS,("USPower: Unknown power message (%x)\n",pIrpStack->MinorFunction));
  157. IoCopyCurrentIrpStackLocationToNext(pIrp);
  158. PoStartNextPowerIrp(pIrp);
  159. Status = PoCallDriver(pde -> pStackDeviceObject, pIrp);
  160. USDecrementIoCount(pDeviceObject);
  161. } /* pIrpStack -> MinorFunction */
  162. DebugTrace(TRACE_PROC_LEAVE,("USPower: Leaving... Status = 0x%x\n", Status));
  163. return Status;
  164. }
  165. NTSTATUS
  166. USPoRequestCompletion(
  167. IN PDEVICE_OBJECT pPdo,
  168. IN UCHAR MinorFunction,
  169. IN POWER_STATE PowerState,
  170. IN PDEVICE_OBJECT pDeviceObject,
  171. IN PIO_STATUS_BLOCK pIoStatus
  172. )
  173. /*++
  174. Routine Description:
  175. This routine is called when the port driver completes an IRP.
  176. Arguments:
  177. Return Value:
  178. The function value is the final status from the operation.
  179. --*/
  180. {
  181. NTSTATUS Status;
  182. PUSBSCAN_DEVICE_EXTENSION pde;
  183. PIRP pIrp;
  184. DebugTrace(TRACE_PROC_ENTER,("USPoRequestCompletion: Enter...\n"));
  185. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  186. pIrp = pde -> pPowerIrp;
  187. Status = pIoStatus -> Status;
  188. IoCopyCurrentIrpStackLocationToNext(pIrp);
  189. PoStartNextPowerIrp(pIrp);
  190. PoCallDriver(pde -> pStackDeviceObject, pIrp);
  191. USDecrementIoCount(pDeviceObject);
  192. DebugTrace(TRACE_PROC_LEAVE,("USPoRequestCompletion: Leaving... Status = 0x%x\n", Status));
  193. return Status;
  194. }
  195. USPowerIrpComplete(
  196. IN PDEVICE_OBJECT pPdo,
  197. IN PIRP pIrp,
  198. IN PDEVICE_OBJECT pDeviceObject
  199. )
  200. /*++
  201. Routine Description:
  202. This routine is called when the port driver completes an IRP.
  203. Arguments:
  204. Return Value:
  205. The function value is the final status from the operation.
  206. --*/
  207. {
  208. NTSTATUS Status;
  209. PUSBSCAN_DEVICE_EXTENSION pde;
  210. PIO_STACK_LOCATION pIrpStack;
  211. DebugTrace(TRACE_PROC_ENTER,("USPowerIrpComplete: Enter...\n"));
  212. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  213. Status = STATUS_SUCCESS;
  214. if (pIrp -> PendingReturned) {
  215. IoMarkIrpPending(pIrp);
  216. }
  217. pIrpStack = IoGetCurrentIrpStackLocation (pIrp);
  218. ASSERT(pIrpStack -> MajorFunction == IRP_MJ_POWER);
  219. ASSERT(pIrpStack -> MinorFunction == IRP_MN_SET_POWER);
  220. ASSERT(pIrpStack -> Parameters.Power.Type == DevicePowerState);
  221. ASSERT(pIrpStack -> Parameters.Power.State.DeviceState == PowerDeviceD0);
  222. pde -> AcceptingRequests = TRUE;
  223. pde -> CurrentDevicePowerState = PowerDeviceD0;
  224. pIrp -> IoStatus.Status = Status;
  225. USDecrementIoCount(pDeviceObject);
  226. DebugTrace(TRACE_PROC_LEAVE,("USPowerIrpComplete: Leaving... Status = 0x%x\n", Status));
  227. return Status;
  228. }
  229. NTSTATUS
  230. USSetDevicePowerState(
  231. IN PDEVICE_OBJECT pDeviceObject,
  232. IN DEVICE_POWER_STATE DeviceState,
  233. IN PBOOLEAN pHookIt
  234. )
  235. /*++
  236. Routine Description:
  237. Arguments:
  238. pDeviceObject - Pointer to the device object for the class device.
  239. DeviceState - Device specific power state to set the device in to.
  240. Return Value:
  241. --*/
  242. {
  243. NTSTATUS Status;
  244. PUSBSCAN_DEVICE_EXTENSION pde;
  245. DebugTrace(TRACE_PROC_ENTER,("USSetDevicePowerState: Enter...\n"));
  246. pde = (PUSBSCAN_DEVICE_EXTENSION)pDeviceObject -> DeviceExtension;
  247. Status = STATUS_SUCCESS;
  248. switch (DeviceState) {
  249. case PowerDeviceD3:
  250. // ASSERT(pde -> AcceptingRequests);
  251. // pde -> AcceptingRequests = FALSE;
  252. // USCancelPipe(pDeviceObject, ALL_PIPE, TRUE);
  253. // pde -> CurrentDevicePowerState = DeviceState;
  254. // break;
  255. case PowerDeviceD1:
  256. case PowerDeviceD2:
  257. #if DBG
  258. if (DeviceState) {
  259. DebugTrace(TRACE_STATUS,("USSetDevicePowerState: PowerDeviceD3 (OFF)\n"));
  260. } else {
  261. DebugTrace(TRACE_STATUS,("USSetDevicePowerState: PowerDeviceD1/D2 (SUSPEND)\n"));
  262. }
  263. #endif
  264. USCancelPipe(pDeviceObject, NULL, ALL_PIPE, TRUE);
  265. //
  266. // power states D1,D2 translate to USB suspend
  267. // D3 transltes to OFF
  268. pde -> CurrentDevicePowerState = DeviceState;
  269. break;
  270. case PowerDeviceD0:
  271. DebugTrace(TRACE_STATUS,("USSetDevicePowerState: PowerDeviceD0 (ON)\n"));
  272. //
  273. // finish the rest in the completion routine
  274. //
  275. *pHookIt = TRUE;
  276. // pass on to PDO
  277. break;
  278. default:
  279. DebugTrace(TRACE_WARNING,("USSetDevicePowerState: Bogus DeviceState = %x\n", DeviceState));
  280. }
  281. DebugTrace(TRACE_PROC_LEAVE,("USSetDevicePowerState: Leaving... Status = 0x%x\n", Status));
  282. return Status;
  283. }