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.

486 lines
14 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. smblite.c
  5. Abstract:
  6. SMBus LCD Back Light Driver
  7. Environment:
  8. Kernel mode
  9. Author:
  10. Michael Tsang (MikeTs) 20-Nov-2000
  11. Revision History:
  12. --*/
  13. #include "pch.h"
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text(INIT, DriverEntry)
  16. #pragma alloc_text(PAGE, SmbLiteAddDevice)
  17. #pragma alloc_text(PAGE, RemoveDevice)
  18. #pragma alloc_text(PAGE, SmbLiteUnload)
  19. #pragma alloc_text(PAGE, SmbLiteCreateClose)
  20. #pragma alloc_text(PAGE, HookPowerStateCallback)
  21. #endif //ifdef ALLOC_PRAGMA
  22. const WCHAR gcwstrACBrightness[] = L"ACBrightness";
  23. const WCHAR gcwstrDCBrightness[] = L"DCBrightness";
  24. const WCHAR gcwstrDeviceName[] = L"\\Device\\SMBusBackLight";
  25. const WCHAR gcwstrDosDeviceName[] = L"\\DosDevices\\SMBusBackLight";
  26. NTSYSAPI
  27. NTSTATUS
  28. NTAPI
  29. ZwPowerInformation(
  30. IN POWER_INFORMATION_LEVEL InformationLevel,
  31. IN PVOID InputBuffer OPTIONAL,
  32. IN ULONG InputBufferLength,
  33. OUT PVOID OutputBuffer OPTIONAL,
  34. IN ULONG OutputBufferLength
  35. );
  36. /*++
  37. @doc EXTERNAL
  38. @func NTSTATUS | DriverEntry |
  39. Installable driver initialization entry point.
  40. This entry point is called directly by the I/O system.
  41. @parm IN PDRIVER_OBJECT | DrvObj | Points to the driver object.
  42. @parm IN PUNICODE_STRINT | RegPath | Points to the registry path.
  43. @rvalue SUCCESS | returns STATUS_SUCCESS
  44. @rvalue FAILURE | returns NT status code
  45. --*/
  46. NTSTATUS EXTERNAL
  47. DriverEntry(
  48. IN PDRIVER_OBJECT DrvObj,
  49. IN PUNICODE_STRING RegPath
  50. )
  51. {
  52. PROCNAME("DriverEntry")
  53. NTSTATUS status = STATUS_SUCCESS;
  54. ENTER(1, ("(DrvObj=%p,RegPath=%p)\n", DrvObj, RegPath));
  55. DrvObj->DriverExtension->AddDevice = SmbLiteAddDevice;
  56. DrvObj->DriverUnload = SmbLiteUnload;
  57. DrvObj->MajorFunction[IRP_MJ_CREATE] =
  58. DrvObj->MajorFunction[IRP_MJ_CLOSE] = SmbLiteCreateClose;
  59. DrvObj->MajorFunction[IRP_MJ_PNP] = SmbLitePnp;
  60. DrvObj->MajorFunction[IRP_MJ_POWER] = SmbLitePower;
  61. DrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SmbLiteIoctl;
  62. EXIT(1, ("=%x\n", status));
  63. return status;
  64. } //DriverEntry
  65. /*++
  66. @doc EXTERNAL
  67. @func NTSTATUS | SmbLiteAddDevice |
  68. Add the new backlite device.
  69. @parm IN PDRIVER_OBJECT | DrvObj | Points to the driver object.
  70. @parm IN PDEVICE_OBJECT | DevObj |
  71. Points to a functional device object created by hidclass.
  72. @rvalue SUCCESS | Returns STATUS_SUCCESS.
  73. @rvalue FAILURE | Returns NT status code.
  74. --*/
  75. NTSTATUS EXTERNAL
  76. SmbLiteAddDevice(
  77. IN PDRIVER_OBJECT DrvObj,
  78. IN PDEVICE_OBJECT DevObj
  79. )
  80. {
  81. PROCNAME("SmbLiteAddDevice")
  82. NTSTATUS status;
  83. PDEVICE_OBJECT fdo = NULL;
  84. UNICODE_STRING UnicodeString;
  85. PSMBLITE_DEVEXT devext = NULL;
  86. PAGED_CODE ();
  87. ENTER(1, ("(DrvObj=%p,DevObj=%p)\n", DrvObj, DevObj));
  88. ASSERT(DevObj != NULL);
  89. RtlInitUnicodeString(&UnicodeString, gcwstrDeviceName);
  90. status = IoCreateDevice(DrvObj,
  91. sizeof(SMBLITE_DEVEXT),
  92. &UnicodeString,
  93. FILE_DEVICE_UNKNOWN,
  94. 0,
  95. FALSE,
  96. &fdo);
  97. if (NT_SUCCESS(status))
  98. {
  99. devext = (PSMBLITE_DEVEXT)fdo->DeviceExtension;
  100. RtlZeroMemory(devext, sizeof(*devext));
  101. fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
  102. fdo->Flags &= ~DO_DEVICE_INITIALIZING;
  103. IoInitializeRemoveLock(&devext->RemoveLock,
  104. SMBLITE_POOLTAG,
  105. 1,
  106. 64);
  107. devext->FDO = fdo;
  108. devext->PDO = DevObj;
  109. devext->LowerDevice = IoAttachDeviceToDeviceStack(fdo, DevObj);
  110. if (devext->LowerDevice == NULL)
  111. {
  112. ERRPRINT(("failed to attach to lower device\n"));
  113. status = STATUS_UNSUCCESSFUL;
  114. }
  115. else
  116. {
  117. RtlInitUnicodeString(&devext->SymbolicName, gcwstrDosDeviceName);
  118. status = IoCreateSymbolicLink(&devext->SymbolicName,
  119. &UnicodeString);
  120. if (!NT_SUCCESS(status))
  121. {
  122. ERRPRINT(("failed to create device symbolic name (status=%x).\n",
  123. status));
  124. }
  125. else
  126. {
  127. devext->dwfSmbLite |= SMBLITEF_SYM_LINK_CREATED;
  128. status = HookPowerStateCallback(devext);
  129. if (!NT_SUCCESS(status))
  130. {
  131. ERRPRINT(("failed to hook power state callback (status=%x).\n",
  132. status));
  133. }
  134. else
  135. {
  136. SYSTEM_BATTERY_STATE BatteryState;
  137. status = ZwPowerInformation(SystemBatteryState,
  138. NULL,
  139. 0,
  140. &BatteryState,
  141. sizeof(BatteryState));
  142. if (!NT_SUCCESS(status))
  143. {
  144. ERRPRINT(("failed to query power information (status=%x).\n",
  145. status));
  146. }
  147. else
  148. {
  149. if (BatteryState.AcOnLine)
  150. {
  151. devext->dwfSmbLite |= SMBLITEF_SYSTEM_ON_AC;
  152. DBGPRINT(1, ("System is on AC.\n"));
  153. }
  154. else
  155. {
  156. devext->dwfSmbLite &= ~SMBLITEF_SYSTEM_ON_AC;
  157. DBGPRINT(1, ("System is on DC.\n"));
  158. }
  159. if (RegQueryDeviceParam(
  160. DevObj,
  161. gcwstrACBrightness,
  162. &devext->BackLightBrightness.bACValue,
  163. sizeof(devext->BackLightBrightness.bACValue))
  164. != STATUS_SUCCESS)
  165. {
  166. devext->BackLightBrightness.bACValue =
  167. DEF_ACBRIGHTNESS;
  168. }
  169. if (RegQueryDeviceParam(
  170. DevObj,
  171. gcwstrDCBrightness,
  172. &devext->BackLightBrightness.bDCValue,
  173. sizeof(devext->BackLightBrightness.bDCValue))
  174. != STATUS_SUCCESS)
  175. {
  176. devext->BackLightBrightness.bDCValue =
  177. DEF_DCBRIGHTNESS;
  178. }
  179. status = SetBackLightBrightness(devext,
  180. &devext->BackLightBrightness,
  181. FALSE);
  182. if (!NT_SUCCESS(status))
  183. {
  184. ERRPRINT(("failed to set backlight to initial brightness (status=%x).\n",
  185. status));
  186. }
  187. }
  188. }
  189. }
  190. }
  191. }
  192. else
  193. {
  194. ERRPRINT(("failed to create FDO (status=%x)\n", status));
  195. }
  196. if (!NT_SUCCESS(status) && (fdo != NULL) && (devext != NULL))
  197. {
  198. RemoveDevice(devext);
  199. }
  200. EXIT(1, ("=%x\n", status));
  201. return status;
  202. } //SmbLiteAddDevice
  203. /*++
  204. @doc INTERNAL
  205. @func VOID | RemoveDevice | Clean up.
  206. @parm IN PSMBLITE_DEVEXT | devext | Points to device extension.
  207. @rvalue None.
  208. --*/
  209. VOID INTERNAL
  210. RemoveDevice(
  211. IN PSMBLITE_DEVEXT devext
  212. )
  213. {
  214. PROCNAME("RemoveDevice")
  215. NTSTATUS status;
  216. PAGED_CODE ();
  217. ENTER(2, ("(devext=%p)\n", devext));
  218. ASSERT(devext != NULL);
  219. if (devext->dwfSmbLite & SMBLITEF_SYM_LINK_CREATED)
  220. {
  221. status = IoDeleteSymbolicLink(&devext->SymbolicName);
  222. if (!NT_SUCCESS(status))
  223. {
  224. WARNPRINT(("failed to delete device symbolic name (status=%x).\n",
  225. status));
  226. }
  227. }
  228. if (devext->hPowerStateCallback)
  229. {
  230. ExUnregisterCallback(devext->hPowerStateCallback);
  231. }
  232. if (devext->LowerDevice != NULL)
  233. {
  234. IoDetachDevice(devext->LowerDevice);
  235. }
  236. if (devext->FDO != NULL)
  237. {
  238. IoDeleteDevice(devext->FDO);
  239. }
  240. EXIT(2, ("!\n"));
  241. return;
  242. } //RemoveDevice
  243. /*++
  244. @doc EXTERNAL
  245. @func void | SmbLiteUnload | Free all the allocated resources, etc.
  246. @parm IN PDRIVER_OBJECT | DrvObj | Points to the driver object.
  247. @rvalue None.
  248. --*/
  249. VOID EXTERNAL
  250. SmbLiteUnload(
  251. IN PDRIVER_OBJECT DrvObj
  252. )
  253. {
  254. PROCNAME("SmbLiteUnload")
  255. PAGED_CODE();
  256. ENTER(1, ("(DrvObj=%p)\n", DrvObj));
  257. ASSERT(DrvObj->DeviceObject == NULL);
  258. UNREFERENCED_PARAMETER(DrvObj);
  259. EXIT(1, ("!\n"));
  260. return;
  261. } //SmbLiteUnload
  262. /*++
  263. @doc EXTERNAL
  264. @func NTSTATUS | SmbLiteCreateClose |
  265. Process the create and close IRPs sent to this device.
  266. @parm IN PDEVICE_OBJECT | DevObj | Points to the device object.
  267. @parm IN PIRP | Irp | Points to an I/O Request Packet.
  268. @rvalue SUCCESS | Returns STATUS_SUCCESS
  269. @rvalue FAILURE | Returns NT status code
  270. --*/
  271. NTSTATUS EXTERNAL
  272. SmbLiteCreateClose(
  273. IN PDEVICE_OBJECT DevObj,
  274. IN PIRP Irp
  275. )
  276. {
  277. PROCNAME("SmbLiteCreateClose")
  278. NTSTATUS status;
  279. PSMBLITE_DEVEXT devext;
  280. PIO_STACK_LOCATION irpsp;
  281. PAGED_CODE ();
  282. devext = DevObj->DeviceExtension;
  283. irpsp = IoGetCurrentIrpStackLocation(Irp);
  284. ENTER(1, ("(DevObj=%p,Irp=%p,IrpStack=%p,Major=%s)\n",
  285. DevObj, Irp, irpsp,
  286. LookupName(irpsp->MajorFunction, MajorFnNames)));
  287. if (irpsp->MajorFunction == IRP_MJ_CREATE)
  288. {
  289. status = IoAcquireRemoveLock(&devext->RemoveLock,
  290. irpsp->FileObject);
  291. }
  292. else
  293. {
  294. ASSERT(irpsp->MajorFunction == IRP_MJ_CLOSE);
  295. IoReleaseRemoveLock(&devext->RemoveLock, irpsp->FileObject);
  296. }
  297. Irp->IoStatus.Status = status;
  298. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  299. EXIT(1, ("=%x\n", status));
  300. return status;
  301. } //SmbLiteCreateClose
  302. /*++
  303. @doc INTERNAL
  304. @func NTSTATUS | HookPowerStateCallback | Hook system power state
  305. callback to monitor if AC power is plugged in or not.
  306. @parm IN PSMBLITE_DEVEXT | devext | Points to the device extension.
  307. @rvalue SUCCESS | Returns STATUS_SUCCESS
  308. @rvalue FAILURE | Returns NT status code
  309. --*/
  310. NTSTATUS INTERNAL
  311. HookPowerStateCallback(
  312. IN PSMBLITE_DEVEXT devext
  313. )
  314. {
  315. PROCNAME("HookPowerStateCallback")
  316. NTSTATUS status;
  317. UNICODE_STRING CallbackName;
  318. OBJECT_ATTRIBUTES ObjAttrib;
  319. PCALLBACK_OBJECT PowerStateCallbackObj;
  320. PAGED_CODE();
  321. ENTER(2, ("(devext=%p)\n", devext));
  322. RtlInitUnicodeString(&CallbackName, L"\\Callback\\PowerState");
  323. InitializeObjectAttributes(&ObjAttrib,
  324. &CallbackName,
  325. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
  326. NULL,
  327. NULL);
  328. status = ExCreateCallback(&PowerStateCallbackObj,
  329. &ObjAttrib,
  330. FALSE,
  331. TRUE);
  332. if (NT_SUCCESS(status))
  333. {
  334. devext->hPowerStateCallback = ExRegisterCallback(
  335. PowerStateCallbackObj,
  336. PowerStateCallbackProc,
  337. devext);
  338. if (devext->hPowerStateCallback == NULL)
  339. {
  340. ERRPRINT(("failed to register battery power callback function.\n"));
  341. status = STATUS_UNSUCCESSFUL;
  342. }
  343. ObDereferenceObject(PowerStateCallbackObj);
  344. }
  345. else
  346. {
  347. ERRPRINT(("failed to create battery power callback object (status=%x).\n",
  348. status));
  349. }
  350. EXIT(2, ("=%x\n", status));
  351. return status;
  352. } //HookPowerStateCallback
  353. /*++
  354. @doc INTERNAL
  355. @func VOID | PowerStateCallbackProc | Power state callback.
  356. @parm IN PVOID | CallbackContext | Callback context.
  357. @parm IN PVOID | Arg1 | Action.
  358. @parm IN PVOID | Arg2 | Value.
  359. @rvalue None.
  360. --*/
  361. VOID
  362. PowerStateCallbackProc(
  363. IN PVOID CallbackContext,
  364. IN PVOID Arg1,
  365. IN PVOID Arg2
  366. )
  367. {
  368. PROCNAME("PowerStateCallback")
  369. ENTER(2, ("(Context=%p,Arg1=%p,Arg2=%p)\n", CallbackContext, Arg1, Arg2));
  370. //
  371. // This callback must be non-pageable because it could be called at
  372. // DISPATCH level.
  373. //
  374. if ((ULONG)Arg1 == PO_CB_AC_STATUS)
  375. {
  376. PSMBLITE_DEVEXT devext = (PSMBLITE_DEVEXT)CallbackContext;
  377. ULONG dwfOnAC = (Arg2 == 0)? 0: SMBLITEF_SYSTEM_ON_AC;
  378. DBGPRINT(1, ("System is on %s, previous state is %s.\n",
  379. dwfOnAC? "AC": "DC",
  380. (devext->dwfSmbLite & SMBLITEF_SYSTEM_ON_AC)? "AC": "DC"));
  381. if ((devext->dwfSmbLite & SMBLITEF_SYSTEM_ON_AC)^dwfOnAC)
  382. {
  383. NTSTATUS status;
  384. //
  385. // AC/DC status has changed.
  386. //
  387. devext->dwfSmbLite &= ~SMBLITEF_SYSTEM_ON_AC;
  388. devext->dwfSmbLite |= dwfOnAC;
  389. status = SetBackLightBrightness(devext,
  390. &devext->BackLightBrightness,
  391. FALSE);
  392. if (!NT_SUCCESS(status))
  393. {
  394. WARNPRINT(("failed to set %s backlight brightness (status=%x).\n",
  395. dwfOnAC? "AC": "DC", status));
  396. }
  397. }
  398. }
  399. EXIT(2, ("!\n"));
  400. return;
  401. } //PowerStateCallbackProc