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.

444 lines
14 KiB

  1. /*++
  2. Copyright (c) 2000,2001 Microsoft Corporation
  3. Module Name:
  4. battinfo.c
  5. Abstract: SMBus Smart Battery Information Property Sheet module.
  6. Environment:
  7. User mode
  8. Author:
  9. Michael Tsang (MikeTs) 23-Jan-2001
  10. Revision History:
  11. --*/
  12. #include "pch.h"
  13. #ifdef BATTINFO
  14. char gszUnitmV[] = "mV";
  15. char gszUnitmA[] = "mA";
  16. char gszUnitPercent[] = "%";
  17. char gszReserved[] = "Reserved";
  18. PSZ gapszBattModeNames[] =
  19. {
  20. "ReportWatt",
  21. "DisableBroadcastToCharger",
  22. "PrimaryBatt",
  23. "ChargerCtrlEnabled",
  24. "CondCycleReq'd",
  25. "PrimaryBattSupport",
  26. "IntChargeCtrler"
  27. };
  28. PSZ gapszBattStatusNames[] =
  29. {
  30. "OverCharged",
  31. "TerminateCharge",
  32. "OverTemp",
  33. "TerminateDischarge",
  34. "RemainCapAlarm",
  35. "RemainTimeAlarm",
  36. "Init'd",
  37. "Discharging",
  38. "Full",
  39. "Empty"
  40. };
  41. SMBCMD_INFO gBattCmds[] =
  42. {
  43. BATTCMD_MANUFACTURER_ACCESS, SMB_READ_WORD, WHX, sizeof(WORD),
  44. " ManufacturerAcc", NULL, 0, NULL,
  45. BATTCMD_REMAININGCAP_ALARM, SMB_READ_WORD, CAP, sizeof(WORD),
  46. " RemainCapAlarm", NULL, 0, NULL,
  47. BATTCMD_REMAININGTIME_ALARM, SMB_READ_WORD, TIM, sizeof(WORD),
  48. " RemainTimeAlarm", NULL, 0, NULL,
  49. BATTCMD_BATTERY_MODE, SMB_READ_WORD, WBT, sizeof(WORD),
  50. " BatteryMode", NULL, 0xc383, gapszBattModeNames,
  51. BATTCMD_ATRATE, SMB_READ_WORD, RAT, sizeof(WORD),
  52. " AtRate", NULL, 0, NULL,
  53. BATTCMD_ATRATE_TIMETOFULL, SMB_READ_WORD, TIM, sizeof(WORD),
  54. " AtRateTimeToFull", NULL, 0, NULL,
  55. BATTCMD_ATRATE_TIMETOEMPTY, SMB_READ_WORD, TIM, sizeof(WORD),
  56. "AtRateTimeToEmpty", NULL, 0, NULL,
  57. BATTCMD_ATRATE_OK, SMB_READ_WORD, WDC, sizeof(WORD),
  58. " AtRateOK", NULL, 0, NULL,
  59. BATTCMD_TEMPERATURE, SMB_READ_WORD, TMP, sizeof(WORD),
  60. " Temperature", NULL, 0, NULL,
  61. BATTCMD_VOLTAGE, SMB_READ_WORD, WDC, sizeof(WORD),
  62. " Voltage", gszUnitmV, 0, NULL,
  63. BATTCMD_CURRENT, SMB_READ_WORD, WSN, sizeof(WORD),
  64. " Current", gszUnitmA, 0, NULL,
  65. BATTCMD_AVG_CURRENT, SMB_READ_WORD, WSN, sizeof(WORD),
  66. " AvgCurrent", gszUnitmA, 0, NULL,
  67. BATTCMD_MAX_ERROR, SMB_READ_WORD, WDC, sizeof(WORD),
  68. " MaxError", gszUnitPercent, 0, NULL,
  69. BATTCMD_REL_STATEOFCHARGE, SMB_READ_WORD, WDC, sizeof(WORD),
  70. " RelStateOfCharge", gszUnitPercent, 0, NULL,
  71. BATTCMD_ABS_STATEOFCHARGE, SMB_READ_WORD, WDC, sizeof(WORD),
  72. " AbsStateOfCharge", gszUnitPercent, 0, NULL,
  73. BATTCMD_REMAININGCAP, SMB_READ_WORD, CAP, sizeof(WORD),
  74. " RemainCap", NULL, 0, NULL,
  75. BATTCMD_FULLCHARGECAP, SMB_READ_WORD, CAP, sizeof(WORD),
  76. " FullChargeCap", NULL, 0, NULL,
  77. BATTCMD_RUNTIMETOEMPTY, SMB_READ_WORD, TIM, sizeof(WORD),
  78. " RunTimeToEmpty", NULL, 0, NULL,
  79. BATTCMD_AVGTIMETOEMPTY, SMB_READ_WORD, TIM, sizeof(WORD),
  80. " AvgTimeToEmpty", NULL, 0, NULL,
  81. BATTCMD_AVGTIMETOFULL, SMB_READ_WORD, TIM, sizeof(WORD),
  82. " AvgTimeToFull", NULL, 0, NULL,
  83. BATTCMD_CHARGING_CURRENT, SMB_READ_WORD, WDC, sizeof(WORD),
  84. " ChargingCurrent", gszUnitmA, 0, NULL,
  85. BATTCMD_CHARGING_VOLTAGE, SMB_READ_WORD, WDC, sizeof(WORD),
  86. " ChargingVoltage", gszUnitmV, 0, NULL,
  87. BATTCMD_BATTERY_STATUS, SMB_READ_WORD, STA, sizeof(WORD),
  88. " BatteryStatus", NULL, 0xdbf0, gapszBattStatusNames,
  89. BATTCMD_CYCLE_COUNT, SMB_READ_WORD, WDC, sizeof(WORD),
  90. " CycleCount", NULL, 0, NULL,
  91. BATTCMD_DESIGN_CAP, SMB_READ_WORD, CAP, sizeof(WORD),
  92. " DesignCap", NULL, 0, NULL,
  93. BATTCMD_DESIGN_VOLTAGE, SMB_READ_WORD, WDC, sizeof(WORD),
  94. " DesignVoltage", gszUnitmV, 0, NULL,
  95. BATTCMD_SPEC_INFO, SMB_READ_WORD, SPI, sizeof(WORD),
  96. " SpecInfo", NULL, 0, NULL,
  97. BATTCMD_MANUFACTURE_DATE, SMB_READ_WORD, DAT, sizeof(WORD),
  98. " ManufactureDate", NULL, 0, NULL,
  99. BATTCMD_SERIAL_NUM, SMB_READ_WORD, WDC, sizeof(WORD),
  100. " SerialNumber", NULL, 0, NULL,
  101. BATTCMD_MANUFACTURER_NAME, SMB_READ_BLOCK,STR, sizeof(BLOCK_DATA),
  102. " ManufacturerName", NULL, 0, NULL,
  103. BATTCMD_DEVICE_NAME, SMB_READ_BLOCK,STR, sizeof(BLOCK_DATA),
  104. " DeviceName", NULL, 0, NULL,
  105. BATTCMD_DEVICE_CHEMISTRY, SMB_READ_BLOCK,STR, sizeof(BLOCK_DATA),
  106. " DeviceChemistry", NULL, 0, NULL,
  107. BATTCMD_MANUFACTURER_DATA, SMB_READ_BLOCK,MAN, sizeof(BLOCK_DATA),
  108. " ManufacturerData", NULL, 0, NULL,
  109. };
  110. #define NUM_BATT_CMDS (sizeof(gBattCmds)/sizeof(SMBCMD_INFO))
  111. BATT_INFO gBattInfo = {0};
  112. /*++
  113. @doc EXTERNAL
  114. @func INT_PTR | BatteryDlgProc |
  115. Dialog procedure for the battery page.
  116. @parm IN HWND | hwnd | Window handle.
  117. @parm IN UINT | uMsg | Message.
  118. @parm IN WPARAM | wParam | Word Parameter.
  119. @parm IN LPARAM | lParam | Long Parameter.
  120. @rvalue Return value depends on the message.
  121. --*/
  122. INT_PTR APIENTRY
  123. BatteryDlgProc(
  124. IN HWND hwnd,
  125. IN UINT uMsg,
  126. IN WPARAM wParam,
  127. IN LPARAM lParam
  128. )
  129. {
  130. TRACEPROC("BatteryDlgProc", 2)
  131. INT_PTR rc = FALSE;
  132. TRACEENTER(("(hwnd=%p,Msg=%s,wParam=%x,lParam=%x)\n",
  133. hwnd, LookupName(uMsg, WMMsgNames) , wParam, lParam));
  134. switch (uMsg)
  135. {
  136. case WM_INITDIALOG:
  137. rc = InitBatteryPage(hwnd);
  138. if (!rc)
  139. {
  140. EnableWindow(hwnd, FALSE);
  141. }
  142. break;
  143. case WM_NOTIFY:
  144. {
  145. NMHDR FAR *lpnm = (NMHDR FAR *)lParam;
  146. switch (lpnm->code)
  147. {
  148. case PSN_QUERYINITIALFOCUS:
  149. {
  150. SetWindowLong(hwnd,
  151. DWL_MSGRESULT,
  152. (LONG)GetDlgItem(hwnd, IDC_BATTINFO_REFRESH));
  153. rc = TRUE;
  154. break;
  155. }
  156. }
  157. break;
  158. }
  159. case WM_COMMAND:
  160. switch (LOWORD(wParam))
  161. {
  162. case IDC_BATTINFO_REFRESH:
  163. RefreshBatteryInfo(GetDlgItem(hwnd, IDC_BATTINFO_TEXT));
  164. break;
  165. }
  166. break;
  167. }
  168. TRACEEXIT(("=%x\n", rc));
  169. return rc;
  170. } //BatteryDlgProc
  171. /*++
  172. @doc INTERNAL
  173. @func BOOL | InitBatteryPage |
  174. Initialize the battery property page.
  175. @parm IN HWND | hwnd | Window handle.
  176. @rvalue Always returns TRUE.
  177. --*/
  178. BOOL
  179. InitBatteryPage(
  180. IN HWND hwnd
  181. )
  182. {
  183. TRACEPROC("InitBatteryPage", 2)
  184. HWND hwndEdit;
  185. TRACEENTER(("(hwnd=%x)\n", hwnd));
  186. hwndEdit = GetDlgItem(hwnd, IDC_BATTINFO_TEXT);
  187. SendMessage(hwndEdit, WM_SETFONT, (WPARAM)ghFont, MAKELONG(FALSE, 0));
  188. RefreshBatteryInfo(hwndEdit);
  189. TRACEEXIT(("=1\n"));
  190. return TRUE;
  191. } //InitBatteryPage
  192. /*++
  193. @doc INTERNAL
  194. @func VOID | RefreshBatteryInfo | Refresh battery information.
  195. @parm IN HWND | hwndEdit | Handle to edit control.
  196. @rvalue None.
  197. --*/
  198. VOID
  199. RefreshBatteryInfo(
  200. IN HWND hwndEdit
  201. )
  202. {
  203. TRACEPROC("RefreshBatteryInfo", 3)
  204. int i;
  205. PBYTE pbBuff;
  206. BOOL fWatt = FALSE;
  207. TRACEENTER(("(hwndEdit=%x)\n", hwndEdit));
  208. //
  209. // Erase edit control.
  210. //
  211. SendMessage(hwndEdit, EM_SETSEL, 0, -1);
  212. SendMessage(hwndEdit, EM_REPLACESEL, 0, (LPARAM)"");
  213. memset(&gBattInfo, 0, sizeof(gBattInfo));
  214. pbBuff = (PBYTE)&gBattInfo.wBatteryMode;
  215. if (GetSMBDevInfo(SMB_BATTERY_ADDRESS,
  216. &gBattCmds[BATTCMD_BATTERY_MODE],
  217. pbBuff))
  218. {
  219. fWatt = (gBattInfo.wBatteryMode & BATTMODE_CAPMODE_POWER) != 0;
  220. }
  221. else
  222. {
  223. TRACEWARN(("failed to get battery mode.\n"));
  224. }
  225. for (i = 0, pbBuff = (PBYTE)&gBattInfo; i < NUM_BATT_CMDS; ++i)
  226. {
  227. if (GetSMBDevInfo(SMB_BATTERY_ADDRESS, &gBattCmds[i], pbBuff))
  228. {
  229. DisplayBatteryInfo(hwndEdit, &gBattCmds[i], pbBuff, fWatt);
  230. }
  231. else
  232. {
  233. TRACEWARN(("failed to get battery info. for %s.\n",
  234. gBattCmds[i].pszLabel));
  235. }
  236. pbBuff += gBattCmds[i].iDataSize;
  237. }
  238. //
  239. // Scroll back to the top.
  240. //
  241. SendMessage(hwndEdit, EM_SETSEL, 0, 0);
  242. SendMessage(hwndEdit, EM_SCROLLCARET, 0, 0);
  243. TRACEEXIT(("!\n"));
  244. return;
  245. } //RefreshBatteryInfo
  246. /*++
  247. @doc INTERNAL
  248. @func BOOL | DisplayBatteryInfo | Display battery info.
  249. @parm IN HWND | hwndEdit | Edit window handle.
  250. @parm IN PSMBCMD_INFO | BattCmd | Points to the battery command.
  251. @parm IN PBYTE | pbBuff | Battery data to display.
  252. @parm IN BOOL | fWatt | If TRUE, Battery is in mW mode
  253. @rvalue SUCCESS | Returns TRUE if it handles it.
  254. @rvalue FAILURE | Returns FALSE if it doesn't handle it.
  255. --*/
  256. BOOL
  257. DisplayBatteryInfo(
  258. IN HWND hwndEdit,
  259. IN PSMBCMD_INFO BattCmd,
  260. IN PBYTE pbBuff,
  261. IN BOOL fWatt
  262. )
  263. {
  264. TRACEPROC("DisplayBatteryInfo", 3)
  265. BOOL rc = TRUE;
  266. WORD wData = *((PWORD)pbBuff);
  267. TRACEENTER(("(hwndEdit=%x,BattCmd=%p,Cmd=%s,pbBuff=%p,fWatt=%x)\n",
  268. hwndEdit, BattCmd, BattCmd->pszLabel, pbBuff, fWatt));
  269. EditPrintf(hwndEdit, "%s=", BattCmd->pszLabel);
  270. switch (BattCmd->bType)
  271. {
  272. case TYPEF_WORD_CAP:
  273. EditPrintf(hwndEdit,
  274. "%6d %s\r\n",
  275. fWatt? wData*10: wData,
  276. fWatt? "mWH": "mAH");
  277. break;
  278. case TYPEF_WORD_RATE:
  279. EditPrintf(hwndEdit,
  280. "%6d %s\r\n",
  281. (SHORT)(fWatt? wData*10: wData),
  282. fWatt? "mW": "mA");
  283. break;
  284. case TYPEF_WORD_STATUS:
  285. EditPrintf(hwndEdit, "0x%04x", wData);
  286. DisplayDevBits(hwndEdit,
  287. BattCmd->dwData,
  288. (PSZ *)BattCmd->pvData,
  289. (DWORD)wData);
  290. EditPrintf(hwndEdit,
  291. ",ErrCode:%x\r\n",
  292. wData & BATTSTATUS_ERRCODE_MASK);
  293. break;
  294. case TYPEF_WORD_TEMP:
  295. EditPrintf(hwndEdit, "%4d.%1d \xb0K\r\n", wData/10, wData%10);
  296. break;
  297. case TYPEF_WORD_SPECINFO:
  298. EditPrintf(hwndEdit,
  299. "Rev:%d,Ver:%d,VScale:%d,IPScale:%d\r\n",
  300. SPECINFO_REVISION(wData),
  301. SPECINFO_VERSION(wData),
  302. SPECINFO_VSCALE(wData),
  303. SPECINFO_IPSCALE(wData));
  304. break;
  305. case TYPEF_WORD_DATE:
  306. EditPrintf(hwndEdit,
  307. "%02d/%02d/%04d\r\n",
  308. MANUDATE_MONTH(wData),
  309. MANUDATE_DAY(wData),
  310. MANUDATE_YEAR(wData));
  311. break;
  312. case TYPEF_WORD_TIME:
  313. if (wData == 0xffff)
  314. {
  315. EditPrintf(hwndEdit, "%6s\r\n", "n/a");
  316. }
  317. else if ((wData/60) == 0)
  318. {
  319. EditPrintf(hwndEdit, "%6d minutes\r\n", wData);
  320. }
  321. else
  322. {
  323. EditPrintf(hwndEdit, "%3d:%02d hours\r\n",
  324. wData/60, wData%60);
  325. }
  326. break;
  327. case TYPEF_MANU_DATA:
  328. {
  329. static PSZ pszManuModeNames[] =
  330. {
  331. "AutoOffsetCal",
  332. "ShelfSleep",
  333. "CalMode",
  334. "VCellReport",
  335. "LEDDesign",
  336. "ForceAutoOffsetCal"
  337. };
  338. static char szUnitMOhms[] = "mOhm";
  339. static SMBCMD_INFO ManuData[] =
  340. {0, 0, WDC, sizeof(WORD), " CFVolt", NULL, 0, NULL,
  341. 0, 0, WDC, sizeof(WORD), " CFCurr", NULL, 0, NULL,
  342. 0, 0, WDC, sizeof(WORD), " CFTemp", NULL, 0, NULL,
  343. 0, 0, TPC, sizeof(WORD), " AlarmHiTemp", NULL, 0, NULL,
  344. 0, 0, TPC, sizeof(WORD), " TMax", NULL, 0, NULL,
  345. 0, 0, WDC, sizeof(WORD), " ITFOver", NULL, 0, NULL,
  346. 0, 0, RES, sizeof(WORD), " PackRes", szUnitMOhms, 0, NULL,
  347. 0, 0, RES, sizeof(WORD), " ShuntRes", szUnitMOhms, 0, NULL,
  348. 0, 0, BDC, sizeof(BYTE), " Cells", NULL, 0, NULL,
  349. 0, 0, BDC, sizeof(BYTE), " COVolt", NULL, 0, NULL,
  350. 0, 0, BDC, sizeof(BYTE), " COCurr", NULL, 0, NULL,
  351. 0, 0, BDC, sizeof(BYTE), " COD", NULL, 0, NULL,
  352. 0, 0, BBT, sizeof(BYTE), " ManufMode", NULL, 0xfc, pszManuModeNames};
  353. #define NUM_MANU_DATA (sizeof(ManuData)/sizeof(SMBCMD_INFO))
  354. int i;
  355. TRACEASSERT(((PBLOCK_DATA)pbBuff)->bBlockLen == 21);
  356. EditPrintf(hwndEdit, "PS331...\r\n");
  357. pbBuff = ((PBLOCK_DATA)pbBuff)->BlockData;
  358. for (i = 0; i < NUM_MANU_DATA; ++i)
  359. {
  360. DisplayBatteryInfo(hwndEdit, &ManuData[i], pbBuff, fWatt);
  361. pbBuff += ManuData[i].iDataSize;
  362. }
  363. break;
  364. }
  365. case TYPEF_TEMP_CELSIUS:
  366. wData = *((PWORD)pbBuff);
  367. EditPrintf(hwndEdit, "%6d " "\xb0" "C\r\n", (wData - 150 + 5)/11);
  368. break;
  369. case TYPEF_WORD_RESISTOR:
  370. {
  371. DWORD dwData = (DWORD)(*((PWORD)pbBuff)*10000/65536 + 5);
  372. dwData /= 10;
  373. EditPrintf(hwndEdit, "%6d mOhm\r\n", dwData);
  374. break;
  375. }
  376. default:
  377. rc = DisplaySMBDevInfo(hwndEdit, BattCmd, pbBuff);
  378. }
  379. TRACEEXIT(("=%x\n", rc));
  380. return rc;
  381. } //DisplayBatteryInfo
  382. #endif //ifdef BATTINFO