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.

569 lines
13 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. ApmBatt.c
  5. Abstract:
  6. Control Method Battery Miniport Driver - Wacked to work on APM.
  7. Author:
  8. Bryan Willman
  9. Ron Mosgrove (Intel)
  10. Environment:
  11. Kernel mode
  12. Revision History:
  13. --*/
  14. #include "ApmBattp.h"
  15. #include "ntddk.h"
  16. #include "ntapm.h"
  17. ULONG ApmBattDebug = APMBATT_ERROR;
  18. //ULONG ApmBattDebug = -1;
  19. //
  20. // Prototypes
  21. //
  22. NTSTATUS
  23. DriverEntry(
  24. IN PDRIVER_OBJECT DriverObject,
  25. IN PUNICODE_STRING RegistryPath
  26. );
  27. NTSTATUS
  28. ApmBattOpenClose(
  29. IN PDEVICE_OBJECT DeviceObject,
  30. IN PIRP Irp
  31. );
  32. NTSTATUS
  33. ApmBattIoctl(
  34. IN PDEVICE_OBJECT DeviceObject,
  35. IN PIRP Irp
  36. );
  37. //
  38. // Globals. Globals are a little odd in a device driver,
  39. // but this is an odd driver
  40. //
  41. //
  42. // Vector used to call NtApm.sys (our PDO) and ask about
  43. // current battery status
  44. //
  45. ULONG (*NtApmGetBatteryLevel)() = NULL;
  46. //
  47. // APM event notifications and SET_POWER ops will cause
  48. // this value to be incremented.
  49. //
  50. ULONG TagValue = 1;
  51. //
  52. // If somebody tries to claim there is more than 1 APM driver battery
  53. // in the system, somebody somewhere is very confused. So keep track
  54. // and forbig this.
  55. //
  56. ULONG DeviceCount = 0;
  57. //
  58. //
  59. //
  60. #ifdef ALLOC_PRAGMA
  61. #pragma alloc_text(INIT,DriverEntry)
  62. #pragma alloc_text(PAGE,ApmBattQueryTag)
  63. #pragma alloc_text(PAGE,ApmBattQueryInformation)
  64. #pragma alloc_text(PAGE,ApmBattQueryStatus)
  65. #pragma alloc_text(PAGE,ApmBattSetStatusNotify)
  66. #pragma alloc_text(PAGE,ApmBattDisableStatusNotify)
  67. #pragma alloc_text(PAGE,ApmBattOpenClose)
  68. #pragma alloc_text(PAGE,ApmBattIoctl)
  69. #endif
  70. NTSTATUS
  71. DriverEntry(
  72. IN PDRIVER_OBJECT DriverObject,
  73. IN PUNICODE_STRING RegistryPath
  74. )
  75. /*++
  76. Routine Description:
  77. This routine initializes the ACPI Embedded Controller Driver
  78. Arguments:
  79. DriverObject - Pointer to driver object created by system.
  80. RegistryPath - Pointer to the Unicode name of the registry path
  81. for this driver.
  82. Return Value:
  83. The function value is the final status from the initialization operation.
  84. --*/
  85. {
  86. ApmBattPrint (APMBATT_TRACE, ("ApmBatt DriverEntry - Obj (%08x) Path (%08x)\n",
  87. DriverObject, RegistryPath));
  88. //
  89. // Set up the device driver entry points.
  90. //
  91. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ApmBattIoctl;
  92. DriverObject->MajorFunction[IRP_MJ_CREATE] = ApmBattOpenClose;
  93. DriverObject->MajorFunction[IRP_MJ_CLOSE] = ApmBattOpenClose;
  94. DriverObject->MajorFunction[IRP_MJ_POWER] = ApmBattPowerDispatch;
  95. DriverObject->MajorFunction[IRP_MJ_PNP] = ApmBattPnpDispatch;
  96. DriverObject->DriverExtension->AddDevice = ApmBattAddDevice;
  97. return STATUS_SUCCESS;
  98. }
  99. NTSTATUS
  100. ApmBattOpenClose(
  101. IN PDEVICE_OBJECT DeviceObject,
  102. IN PIRP Irp
  103. )
  104. /*++
  105. Routine Description:
  106. This is the routine called as a result of a Open or Close on the device
  107. Arguments:
  108. DeviceObject - Battery for request
  109. Irp - IO request
  110. Return Value:
  111. STATUS_SUCCESS - no way to fail this puppy
  112. --*/
  113. {
  114. PAGED_CODE();
  115. ApmBattPrint (APMBATT_TRACE, ("ApmBattOpenClose\n"));
  116. //
  117. // Complete the request and return status.
  118. //
  119. Irp->IoStatus.Status = STATUS_SUCCESS;
  120. Irp->IoStatus.Information = 0;
  121. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  122. return(STATUS_SUCCESS);
  123. }
  124. NTSTATUS
  125. ApmBattIoctl(
  126. IN PDEVICE_OBJECT DeviceObject,
  127. IN PIRP Irp
  128. )
  129. /*++
  130. Routine Description:
  131. IOCTL handler. As this is an exclusive battery device, send the
  132. Irp to the battery class driver to handle battery IOCTLs.
  133. Arguments:
  134. DeviceObject - Battery for request
  135. Irp - IO request
  136. Return Value:
  137. Status of request
  138. --*/
  139. {
  140. NTSTATUS Status;
  141. PCM_BATT ApmBatt;
  142. PAGED_CODE();
  143. ApmBattPrint (APMBATT_TRACE, ("ApmBattIoctl\n"));
  144. ApmBatt = (PCM_BATT) DeviceObject->DeviceExtension;
  145. Status = BatteryClassIoctl (ApmBatt->Class, Irp);
  146. if (Status == STATUS_NOT_SUPPORTED) {
  147. //
  148. // Not for the battery, complete it
  149. //
  150. Irp->IoStatus.Status = Status;
  151. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  152. }
  153. return Status;
  154. }
  155. NTSTATUS
  156. ApmBattQueryTag (
  157. IN PVOID Context,
  158. OUT PULONG TagPtr
  159. )
  160. /*++
  161. Routine Description:
  162. BATTERY CLASS ENTRY
  163. Called by the class driver to retrieve the batteries current tag value
  164. The battery class driver will serialize all requests it issues to
  165. the miniport for a given battery.
  166. Arguments:
  167. Context - Miniport context value for battery
  168. TagPtr - Pointer to return current tag
  169. Return Value:
  170. Success if there is a battery currently installed, else no such device.
  171. --*/
  172. {
  173. ULONG BatteryLevel;
  174. UNREFERENCED_PARAMETER(Context);
  175. PAGED_CODE();
  176. ApmBattPrint ((APMBATT_TRACE | APMBATT_MINI),
  177. ("ApmBattQueryTag - TagValue = %08x\n", TagValue));
  178. //
  179. // The code that catches APM event notification, and the code
  180. // that handles Power IRPs, will both increment the tag.
  181. // We simply report that.
  182. //
  183. *TagPtr = TagValue;
  184. //
  185. // Call ntapm, it will return a DWORD with the relevent data in it,
  186. // crack this DWORD, and fill this stuff in.
  187. //
  188. if (NtApmGetBatteryLevel) {
  189. BatteryLevel = NtApmGetBatteryLevel();
  190. if ((BatteryLevel & NTAPM_NO_BATT) || (BatteryLevel & NTAPM_NO_SYS_BATT)) {
  191. return STATUS_NO_SUCH_DEVICE;
  192. } else {
  193. return STATUS_SUCCESS;
  194. }
  195. } else {
  196. //
  197. // if we cannot get battery status, it's likely we don't have
  198. // a battery, so say we don't have one.
  199. //
  200. return STATUS_NO_SUCH_DEVICE;
  201. }
  202. }
  203. NTSTATUS
  204. ApmBattQueryInformation (
  205. IN PVOID Context,
  206. IN ULONG BatteryTag,
  207. IN BATTERY_QUERY_INFORMATION_LEVEL Level,
  208. IN ULONG AtRate OPTIONAL,
  209. OUT PVOID Buffer,
  210. IN ULONG BufferLength,
  211. OUT PULONG ReturnedLength
  212. )
  213. /*++
  214. Routine Description:
  215. BATTERY CLASS ENTRY
  216. Called by the class driver to retrieve battery information
  217. The battery class driver will serialize all requests it issues to
  218. the miniport for a given battery.
  219. We return invalid parameter when we can't handle a request for a
  220. specific level of information. This is defined in the battery class spec.
  221. Arguments:
  222. Context - Miniport context value for battery
  223. BatteryTag - Tag of current battery
  224. Level - type of information required
  225. AtRate - Used only when Level==BatteryEstimatedTime
  226. Buffer - Location for the information
  227. BufferLength - Length in bytes of the buffer
  228. ReturnedLength - Length in bytes of the returned data
  229. Return Value:
  230. Success if there is a battery currently installed, else no such device.
  231. --*/
  232. {
  233. NTSTATUS Status;
  234. PVOID ReturnBuffer;
  235. ULONG ReturnBufferLength;
  236. ULONG CapabilityVector = (BATTERY_SYSTEM_BATTERY | BATTERY_CAPACITY_RELATIVE);
  237. BATTERY_INFORMATION bi;
  238. PAGED_CODE();
  239. ApmBattPrint ((APMBATT_TRACE | APMBATT_MINI),
  240. ("ApmBattQueryInformation Level=%08xl\n", Level));
  241. //
  242. // We cannot tell (reliably/safely) if there is a battery
  243. // present or not, so always return what the query code tells us
  244. //
  245. ReturnBuffer = NULL;
  246. ReturnBufferLength = 0;
  247. Status = STATUS_SUCCESS;
  248. //
  249. // Get the info requested
  250. //
  251. switch (Level) {
  252. case BatteryInformation:
  253. ApmBattPrint((APMBATT_TRACE|APMBATT_MINI), ("Batteryinformation\n"));
  254. RtlZeroMemory(&bi, sizeof(bi));
  255. bi.Capabilities = CapabilityVector;
  256. bi.Technology = BATTERY_SECONDARY_CHARGABLE;
  257. bi.DesignedCapacity = 100;
  258. bi.FullChargedCapacity = UNKNOWN_CAPACITY;
  259. ReturnBuffer = (PVOID) &bi;
  260. ReturnBufferLength = sizeof(bi);
  261. break;
  262. case BatteryEstimatedTime:
  263. case BatteryTemperature:
  264. case BatteryGranularityInformation:
  265. case BatteryDeviceName:
  266. case BatteryManufactureDate:
  267. case BatteryManufactureName:
  268. case BatteryUniqueID:
  269. Status = STATUS_INVALID_DEVICE_REQUEST;
  270. break;
  271. default:
  272. Status = STATUS_INVALID_PARAMETER;
  273. break;
  274. }
  275. //
  276. // Done, return buffer if needed
  277. //
  278. *ReturnedLength = ReturnBufferLength;
  279. if (BufferLength < ReturnBufferLength) {
  280. Status = STATUS_BUFFER_TOO_SMALL;
  281. }
  282. if (NT_SUCCESS(Status) && ReturnBuffer) {
  283. RtlZeroMemory (Buffer, BufferLength); // Clear entire user buffer
  284. RtlCopyMemory (Buffer, ReturnBuffer, ReturnBufferLength); // Copy what's needed
  285. }
  286. return Status;
  287. }
  288. NTSTATUS
  289. ApmBattQueryStatus (
  290. IN PVOID Context,
  291. IN ULONG BatteryTag,
  292. OUT PBATTERY_STATUS BatteryStatus
  293. )
  294. /*++
  295. Routine Description:
  296. BATTERY CLASS ENTRY
  297. Called by the class driver to retrieve the batteries current status
  298. The battery class driver will serialize all requests it issues to
  299. the miniport for a given battery.
  300. Arguments:
  301. Context - Miniport context value for battery
  302. BatteryTag - Tag of current battery
  303. BatteryStatus - Pointer to structure to return the current battery status
  304. Return Value:
  305. Success if there is a battery currently installed, else no such device.
  306. --*/
  307. {
  308. ULONG BatteryLevel;
  309. PAGED_CODE();
  310. ApmBattPrint ((APMBATT_TRACE | APMBATT_MINI), ("ApmBattQueryStatus\n"));
  311. //
  312. // Call ntapm, it will return a DWORD with the relevent data in it,
  313. // crack this DWORD, and fill this stuff in.
  314. //
  315. if (NtApmGetBatteryLevel) {
  316. BatteryLevel = NtApmGetBatteryLevel();
  317. BatteryStatus->PowerState = ((BatteryLevel & NTAPM_BATTERY_STATE) >> NTAPM_BATTERY_STATE_SHIFT);
  318. BatteryStatus->Capacity = BatteryLevel & NTAPM_POWER_PERCENT;
  319. BatteryStatus->Voltage = UNKNOWN_VOLTAGE;
  320. BatteryStatus->Current = UNKNOWN_RATE;
  321. ApmBattPrint((APMBATT_MINI), ("ApmBattQueryStatus: BatteryLevel = %08lx\n", BatteryLevel));
  322. return STATUS_SUCCESS;
  323. } else {
  324. ApmBattPrint((APMBATT_ERROR), ("ApmBattQueryStatus: failure NtApmGetBatteryLevel == NULL\n"));
  325. //
  326. // return some "safe" values to keep from looping forever
  327. //
  328. BatteryStatus->PowerState = 0;
  329. BatteryStatus->Capacity = 1;
  330. BatteryStatus->Voltage = UNKNOWN_VOLTAGE;
  331. BatteryStatus->Current = UNKNOWN_RATE;
  332. return STATUS_UNSUCCESSFUL;
  333. }
  334. }
  335. NTSTATUS
  336. ApmBattSetStatusNotify (
  337. IN PVOID Context,
  338. IN ULONG BatteryTag,
  339. IN PBATTERY_NOTIFY Notify
  340. )
  341. /*++
  342. Routine Description:
  343. BATTERY CLASS ENTRY
  344. Called by the class driver to set the batteries current notification
  345. setting. When the battery trips the notification, one call to
  346. BatteryClassStatusNotify is issued. If an error is returned, the
  347. class driver will poll the battery status - primarily for capacity
  348. changes. Which is to say the miniport should still issue BatteryClass-
  349. StatusNotify whenever the power state changes.
  350. The class driver will always set the notification level it needs
  351. after each call to BatteryClassStatusNotify.
  352. The battery class driver will serialize all requests it issues to
  353. the miniport for a given battery.
  354. Arguments:
  355. Context - Miniport context value for battery
  356. BatteryTag - Tag of current battery
  357. BatteryNotify - The notification setting
  358. Return Value:
  359. Status
  360. --*/
  361. {
  362. //
  363. // need to fill this in
  364. //
  365. ApmBattPrint (APMBATT_TRACE, ("ApmBattSetStatusNotify\n"));
  366. return STATUS_NOT_IMPLEMENTED;
  367. }
  368. NTSTATUS
  369. ApmBattDisableStatusNotify (
  370. IN PVOID Context
  371. )
  372. /*++
  373. Routine Description:
  374. BATTERY CLASS ENTRY
  375. Called by the class driver to disable the notification setting
  376. for the battery supplied by Context. Note, to disable a setting
  377. does not require the battery tag. Any notification is to be
  378. masked off until a subsequent call to ApmBattSetStatusNotify.
  379. The battery class driver will serialize all requests it issues to
  380. the miniport for a given battery.
  381. Arguments:
  382. Context - Miniport context value for battery
  383. Return Value:
  384. Status
  385. --*/
  386. {
  387. //
  388. // need to fill this in
  389. //
  390. ApmBattPrint (APMBATT_TRACE, ("ApmBattDisableStatusNotify\n"));
  391. return STATUS_NOT_IMPLEMENTED;
  392. }
  393. VOID
  394. ApmBattPowerNotifyHandler (
  395. )
  396. /*++
  397. Routine Description:
  398. NTAPM CALLBACK
  399. This routine fields power device notifications from the APM driver.
  400. Arguments:
  401. Return Value:
  402. None
  403. --*/
  404. {
  405. ApmBattPrint (APMBATT_TRACE, ("ApmBattPowerNotifyHandler\n"));
  406. // DbgBreakPoint();
  407. TagValue++;
  408. BatteryClassStatusNotify(ApmGlobalClass);
  409. }