PageRenderTime 45ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/libsmbios-2.2.28/src/bin/dellLEDCtl.cpp

#
C++ | 659 lines | 344 code | 73 blank | 242 comment | 27 complexity | 3c5f1f89a147d605d5cc565275d56ba8 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-3.0
  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. * vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=c:cindent:textwidth=0:
  3. *
  4. * Copyright (C) 2007 Dell Inc.
  5. * by Ed H <eah1@yahoo.com>
  6. * based on dellWirelessCtl by Michael E Brown <Michael_E_Brown@Dell.com>
  7. * Licensed under the Open Software License version 2.1
  8. *
  9. * Alternatively, you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published
  11. * by the Free Software Foundation; either version 2 of the License,
  12. * or (at your option) any later version.
  13. * This program is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  16. * See the GNU General Public License for more details.
  17. */
  18. // compat header should always be first header if including system headers
  19. #include "smbios/compat.h"
  20. #include <string>
  21. #include <iostream>
  22. #include <iomanip>
  23. #include <stdlib.h>
  24. #include <ctype.h>
  25. //#define SHOW_STROBE_PERF
  26. #if defined(SHOW_STROBE_PERF)
  27. #include <sys/time.h>
  28. #endif
  29. #include <time.h>
  30. #include <string.h>
  31. #include "smbios/ISmi.h"
  32. #include "smbios/IToken.h"
  33. #include "smbios/SystemInfo.h"
  34. #include "getopts.h"
  35. // always include last if included.
  36. #include "smbios/message.h"
  37. using namespace std;
  38. #define LIST_DELL_LED_COLORS(_) \
  39. _(Off) \
  40. _(Ruby) \
  41. _(Citrine) \
  42. _(Amber) \
  43. _(Peridot) \
  44. _(Emerald) \
  45. _(Jade) \
  46. _(Topaz) \
  47. _(Tanzanite) \
  48. _(Aquamarine) \
  49. _(Sapphire) \
  50. _(Iolite) \
  51. _(Amythest) \
  52. _(Kunzite) \
  53. _(Rhodolite) \
  54. _(Coral) \
  55. _(Diamond)
  56. #define MK_DELL_LED_COLOR_ENUM(x) DELL_LED_COLOR_##x,
  57. typedef enum { LIST_DELL_LED_COLORS(MK_DELL_LED_COLOR_ENUM) NUM_DELL_LED_COLORS } DELL_LED_COLOR;
  58. #define MK_STRING(x) #x,
  59. static const char *dell_led_color[] = { LIST_DELL_LED_COLORS(MK_STRING) };
  60. struct options opts[] =
  61. {
  62. { 1, "info", "Get LED info", "i", 0 },
  63. { 2, "zone1", "Set zone 1 color", "z1", 1 },
  64. { 3, "zone2", "Set zone 2 color", "z2", 1 },
  65. { 4, "zone3", "Set zone 3 color", "z3", 1 },
  66. { 5, "zone4", "Set zone 4 color", "z4", 1 },
  67. { 6, "level", "Set intensity level [0..7]", "l", 1 },
  68. { 7, "colors", "Show color list", "c", 0 },
  69. { 8, "boot", "Preserve colors across reboots", "b", 0 },
  70. { 9, "strobe", "Firetruck mode", "s", 0 },
  71. { 252, "password", "BIOS setup password", "p", 1 },
  72. { 249, "rawpassword", "Do not auto-convert password to scancodes", NULL, 0 },
  73. { 255, "version", "Display libsmbios version information", NULL, 0 },
  74. { 0, NULL, NULL, NULL, 0 }
  75. };
  76. #define DELL_LED_CTL_VERSION "0.1.0"
  77. static void printLEDInfo()
  78. {
  79. u32 args[4] = {0, 0, 0, 0};
  80. u32 res[4];
  81. // cbClass: 4
  82. // cbSelect: 7
  83. // name: Get LED Settings
  84. //
  85. // On return:
  86. // cbRES1 Return code
  87. // 0 Completed successfully
  88. // -1 Completed with error
  89. // -2 Function not supported
  90. // cbRES2 Current LED Settings
  91. // byte 0 LED Color for Zone 1
  92. // byte 1 LED Color for Zone 2
  93. // byte 2 LED Color for Zone 3
  94. // byte 3 bit [2:0] have the Intensity Level
  95. // Bits 3-7 Reserved
  96. // cbRES3 CMOS LED Settings
  97. // byte 0 LED Color for Zone 1
  98. // byte 1 LED Color for Zone 2
  99. // byte 2 LED Color for Zone 3
  100. // byte 3 bit [2:0] have the Intensity Level
  101. // bits 3-7 Reserved
  102. //
  103. // cbRES4 Zone4 LED Settings
  104. // byte 0 Zone4 current led setting
  105. // byte 1 Zone4 CMOS led setting
  106. //
  107. // Note : The Mapping of Zones like Zone 1 is Fans, Zone 2 is Speakers,etc
  108. // will be defined in the system specific BIOS Document.
  109. try
  110. {
  111. smi::doSimpleCallingInterfaceSmi(4, 7, args, res);
  112. cout << "LED Info:" << endl;
  113. u8 *p2 = (u8 *)&res[smi::cbRES2];
  114. u8 *p3 = (u8 *)&res[smi::cbRES3];
  115. u8 *p4 = (u8 *)&res[smi::cbRES4];
  116. cout << "\tCurrent zone 1: " << dell_led_color[p2[0]] << endl;
  117. cout << "\tCurrent zone 2: " << dell_led_color[p2[1]] << endl;
  118. cout << "\tCurrent zone 3: " << dell_led_color[p2[2]] << endl;
  119. cout << "\tCurrent zone 4: " << dell_led_color[p4[0]] << endl;
  120. cout << "\tCurrent intensity " << u32(p2[3] & 0x7) << endl;
  121. cout << "\tCMOS zone 1: " << dell_led_color[p3[0]] << endl;
  122. cout << "\tCMOS zone 2: " << dell_led_color[p3[1]] << endl;
  123. cout << "\tCMOS zone 3: " << dell_led_color[p3[2]] << endl;
  124. cout << "\tCMOS zone 4: " << dell_led_color[p4[1]] << endl;
  125. cout << "\tCMOS intensity " << u32(p3[3] & 0x7) << endl;
  126. }
  127. catch(smi::UnsupportedSmi)
  128. {
  129. cout << "LED Info not supported on this system." << endl;
  130. return;
  131. }
  132. // cbClass: 17
  133. // cbSelect: 12
  134. // Name: Touchpad (TP) & Media Board (MB) LED Control
  135. //
  136. // On entry:
  137. // cbARG1, byte1 Subcommand:
  138. // 0 Get config
  139. // 1 Set config
  140. // cbARG2, byte1 Control bits (if cbARG1==1):
  141. // 0 LED Inactive State:
  142. // 0=Off
  143. // 1=Low intensity
  144. // 1 TP LED Active State:
  145. // 0=No change (stay off or low)
  146. // 1=Turn on for 3 seconds
  147. // 2 MB LED Active State:
  148. // 0=No change (stay off or low)
  149. // 1=Turn on for 3 seconds
  150. // 3-7 Reserved (0)
  151. //
  152. // On return:
  153. // cbRES1 Return code
  154. // 0 Completed successfully
  155. // -1 Completed with error
  156. // -2 Function not supported
  157. // cbRES2 Error code (if cbRES1==-1)
  158. // -1 Non-specific error
  159. // cbARG3, byte1 Config bits:
  160. // 0 LED Inactive State:
  161. // 0=Off
  162. // 1=Low intensity
  163. // 1 TP LED Active State:
  164. // 0=No change (stay off or low)
  165. // 1=Turn on for 3 seconds
  166. // 2 MB LED Active State:
  167. // 0=No change (stay off or low)
  168. // 1=Turn on for 3 seconds
  169. // 3-7 Reserved (0)
  170. //
  171. // NOTE: The LED Inactive State bit controls both the Touchpad LED and the
  172. // Media Board LED. When this bit is clear (0), neither LED will be on when
  173. // their respective control is inactive. When this bit is set (1), both LEDs
  174. // will be on at low intensity when their respective control is inactive. The
  175. // control for the touchpad LED is the touchpad, and that control is active
  176. // when the touchpad is being touched. The control for the media board LED is
  177. // the media button, and that control is active when the media button is being
  178. // pressed. The responses to activity by the touchpad and media board LEDs are
  179. // controlled individually. Each of these LEDs can be set to remain in its
  180. // inactive state (off or low intensity) even when activity is detected, or to
  181. // turn on at normal intensity and stay on for 3 seconds when activity is
  182. // detected.
  183. try
  184. {
  185. memset( args, 0, sizeof(args) );
  186. u8 *p1 = (u8 *)&args[smi::cbARG1];
  187. // HACK HACK HACK I suspect this is really byte 0 (doc error?) - Ed
  188. p1[1] = 0;
  189. smi::doSimpleCallingInterfaceSmi(17, 12, args, res);
  190. cout << "Touchpad/Media Key LED Info:" << endl;
  191. u8 *p3 = (u8 *)&res[smi::cbRES3];
  192. cout << "\tInactive level: " << ((p3[0] & 1) ? "Low" : "Off") << endl;
  193. cout << "\tTouchpad action: " << ((p3[0] & 2) ? "Brighten" : "Unchanged") << endl;
  194. cout << "\tMedia key action: " << ((p3[0] & 4) ? "Brighten" : "Unchanged") << endl;
  195. }
  196. catch(smi::UnsupportedSmi)
  197. {
  198. cout << "Touchpad/Media Key LED Info not supported on this system." << endl;
  199. return;
  200. }
  201. }
  202. static inline bool zoneIsSet( DELL_LED_COLOR z )
  203. {
  204. return( (z >= DELL_LED_COLOR_Off) || (z < NUM_DELL_LED_COLORS) );
  205. }
  206. static void setAllLEDs( int level, DELL_LED_COLOR zone[], bool preserve )
  207. {
  208. u32 args[4] = {0, 0, 0, 0};
  209. u32 res[4];
  210. // cbClass: 4
  211. // cbClass: 6
  212. // name: Set LED Settings
  213. // On entry:
  214. // cbARG1:
  215. // byte 0 LED Color for Zone 1
  216. // byte 1 LED Color for Zone 2
  217. // byte 2 LED Color for Zone 3
  218. // byte 3 bit [2:0] have the Intensity Level
  219. // bits 3-7 Reserved
  220. // cbARG2:
  221. // byte0 bit [0] - Make change Permanent Bit
  222. //
  223. // If bit 0 is 1, change the LED colors and save the setting to CMOS;
  224. // otherwise, change the LED colors but dont save to CMOS
  225. //
  226. // cbARG3:
  227. // byte 0 LED Color for Zone 4
  228. //
  229. // On return:
  230. // cbRES1 Return code
  231. // 0 Completed successfully
  232. // -1 Completed with error
  233. // -2 Function not supported
  234. //
  235. // Note : The Mapping of Zones like Zone 1 is Fans, Zone 2 is Speakers,etc
  236. // will be defined in the system specific BIOS Document.
  237. try
  238. {
  239. u8 *p1 = (u8 *)&args[smi::cbARG1];
  240. u8 *p2 = (u8 *)&args[smi::cbARG2];
  241. u8 *p3 = (u8 *)&args[smi::cbARG3];
  242. p1[0] = u8(zone[0]);
  243. p1[1] = u8(zone[1]);
  244. p1[2] = u8(zone[2]);
  245. p1[3] = level;
  246. p2[0] = preserve ? 1 : 0;
  247. p3[0] = u8(zone[3]);
  248. smi::doSimpleCallingInterfaceSmi(4, 6, args, res);
  249. }
  250. catch(smi::UnsupportedSmi)
  251. {
  252. cout << "Setting LED colors not supported on this system." << endl;
  253. return;
  254. }
  255. }
  256. static void setLEDs( int level, DELL_LED_COLOR zone[], bool preserve )
  257. {
  258. u32 args[4] = {0, 0, 0, 0};
  259. u32 res[4];
  260. // first get current state (see printLEDInfo)...
  261. try
  262. {
  263. smi::doSimpleCallingInterfaceSmi(4, 7, args, res);
  264. u8 *p2 = (u8 *)&res[smi::cbRES2];
  265. //u8 *p3 = (u8 *)&res[smi::cbRES3];
  266. u8 *p4 = (u8 *)&res[smi::cbRES4];
  267. if (!zoneIsSet( zone[0] )) zone[0] = DELL_LED_COLOR(p2[0]);
  268. if (!zoneIsSet( zone[1] )) zone[1] = DELL_LED_COLOR(p2[1]);
  269. if (!zoneIsSet( zone[2] )) zone[2] = DELL_LED_COLOR(p2[2]);
  270. if (!zoneIsSet( zone[3] )) zone[3] = DELL_LED_COLOR(p4[0]);
  271. if ((level < 0) || (level > 7)) level = p2[3] & 0x7;
  272. }
  273. catch(smi::UnsupportedSmi)
  274. {
  275. cout << "LED Info not supported on this system." << endl;
  276. return;
  277. }
  278. // ...then set all the merged-in changes (see setAllLEDs)
  279. setAllLEDs( level, zone, preserve );
  280. }
  281. // just for fun...
  282. static void strobeLEDs()
  283. {
  284. int level;
  285. DELL_LED_COLOR zone[4];
  286. u32 args[4] = {0, 0, 0, 0};
  287. u32 res[4];
  288. // save the current state (see printLEDInfo)
  289. try
  290. {
  291. smi::doSimpleCallingInterfaceSmi(4, 7, args, res);
  292. u8 *p2 = (u8 *)&res[smi::cbRES2];
  293. //u8 *p3 = (u8 *)&res[smi::cbRES3];
  294. u8 *p4 = (u8 *)&res[smi::cbRES4];
  295. zone[0] = DELL_LED_COLOR(p2[0]);
  296. zone[1] = DELL_LED_COLOR(p2[1]);
  297. zone[2] = DELL_LED_COLOR(p2[2]);
  298. zone[3] = DELL_LED_COLOR(p4[0]);
  299. level = p2[3] & 0x7;
  300. }
  301. catch(smi::UnsupportedSmi)
  302. {
  303. cout << "LED Info not supported on this system." << endl;
  304. return;
  305. }
  306. // 3ms per change
  307. struct timespec nsleep = { 0, 3000000 };
  308. int cnt = 0;
  309. #if defined(SHOW_STROBE_PERF)
  310. struct timeval start;
  311. gettimeofday( &start, NULL );
  312. nsleep.tv_nsec = 0;
  313. #endif
  314. for (int z = DELL_LED_COLOR_Off + 1; z < NUM_DELL_LED_COLORS; ++z)
  315. {
  316. DELL_LED_COLOR t[4];
  317. t[0] = t[1] = t[2] = t[3] = DELL_LED_COLOR(z);
  318. for (int new_level = 0; new_level < 7; ++new_level)
  319. {
  320. setAllLEDs( new_level, t, false );
  321. nanosleep( &nsleep, NULL );
  322. ++cnt;
  323. }
  324. for (int new_level = 7; new_level > 0; --new_level)
  325. {
  326. setAllLEDs( new_level, t, false );
  327. nanosleep( &nsleep, NULL );
  328. ++cnt;
  329. }
  330. }
  331. for (int z = NUM_DELL_LED_COLORS - 2; z > DELL_LED_COLOR_Off + 1; --z)
  332. {
  333. DELL_LED_COLOR t[4];
  334. t[0] = t[1] = t[2] = t[3] = DELL_LED_COLOR(z);
  335. for (int new_level = 0; new_level < 7; ++new_level)
  336. {
  337. setAllLEDs( new_level, t, false );
  338. nanosleep( &nsleep, NULL );
  339. ++cnt;
  340. }
  341. for (int new_level = 7; new_level > 0; --new_level)
  342. {
  343. setAllLEDs( new_level, t, false );
  344. nanosleep( &nsleep, NULL );
  345. ++cnt;
  346. }
  347. }
  348. #if defined(SHOW_STROBE_PERF)
  349. struct timeval end;
  350. gettimeofday( &end, NULL );
  351. float elapsed_millis = (end.tv_sec - start.tv_sec) * 1000.0f + (end.tv_usec - start.tv_usec) / 1000.0f;
  352. cout << elapsed_millis << "ms for " << cnt << " updates (" << elapsed_millis / cnt << "ms/update)" << endl;
  353. #endif
  354. // restore everything
  355. setAllLEDs( level, zone, false );
  356. }
  357. int main (int argc, char **argv)
  358. {
  359. int retval = 0;
  360. string password("");
  361. bool rawPassword = false;
  362. bool printInfo = false;
  363. bool setColors = false;
  364. bool strobe = false;
  365. bool preserve = false;
  366. int level = -1;
  367. DELL_LED_COLOR zone[4] =
  368. {
  369. NUM_DELL_LED_COLORS,
  370. NUM_DELL_LED_COLORS,
  371. NUM_DELL_LED_COLORS,
  372. NUM_DELL_LED_COLORS
  373. };
  374. try
  375. {
  376. char *args = 0;
  377. int c=0;
  378. while ( (c=getopts(argc, argv, opts, &args)) != 0 )
  379. {
  380. switch(c)
  381. {
  382. case 1:
  383. cout << "Libsmbios version : " << SMBIOSGetLibraryVersionString() << endl;
  384. cout << "dellLEDCtl version: " << DELL_LED_CTL_VERSION << endl;
  385. printInfo = true;
  386. break;
  387. case 2: case 3: case 4: case 5:
  388. if (isdigit( args[0] ))
  389. {
  390. zone[c - 2] = DELL_LED_COLOR(atoi( args ));
  391. setColors = true;
  392. }
  393. else
  394. {
  395. for (int i = 0; i < NUM_DELL_LED_COLORS; ++i)
  396. {
  397. if (strcasecmp( args, dell_led_color[i] ) == 0)
  398. {
  399. zone[c - 2] = DELL_LED_COLOR(i);
  400. setColors = true;
  401. break;
  402. }
  403. }
  404. }
  405. break;
  406. case 6:
  407. level = atoi( args );
  408. setColors = true;
  409. break;
  410. case 7:
  411. cout << "Color values:" << endl;
  412. for (int i = 0; i < NUM_DELL_LED_COLORS; ++i)
  413. {
  414. cout << dell_led_color[i] << " = " << i << endl;
  415. }
  416. break;
  417. case 8:
  418. preserve = true;
  419. break;
  420. case 9:
  421. strobe = true;
  422. break;
  423. case 249:
  424. rawPassword = true;
  425. break;
  426. case 252:
  427. password = args;
  428. break;
  429. case 255:
  430. cout << "Libsmbios version: " << SMBIOSGetLibraryVersionString() << endl;
  431. cout << "dellLEDCtl version: " << DELL_LED_CTL_VERSION << endl;
  432. exit(0);
  433. break;
  434. default:
  435. break;
  436. }
  437. free(args);
  438. }
  439. if ((!rawPassword) && (1 == SMBIOSGetSmiPasswordCoding()) && strlen(password.c_str())>0)
  440. {
  441. cerr << endl;
  442. cerr << "BIOS Password encoding has been detected as SCAN CODE format." << endl;
  443. cerr << "Automatically changing password from ASCII coding to en_US scancode format." << endl;
  444. cerr << "Use the --rawpassword option to disable this, for example, if you have " << endl;
  445. cerr << "another language keyboard, then manually convert the ASCII password to" << endl;
  446. cerr << "scan code format." << endl;
  447. cerr << endl;
  448. char *codedPass = new char[strlen(password.c_str())+1];
  449. memset(codedPass, 0, strlen(password.c_str())+1);
  450. SMBIOSMapAsciiTo_en_US_ScanCode(codedPass, password.c_str(), strlen(password.c_str()));
  451. password = codedPass;
  452. delete []codedPass;
  453. }
  454. if (printInfo)
  455. {
  456. printLEDInfo();
  457. cout << endl;
  458. }
  459. if (setColors)
  460. {
  461. setLEDs( level, zone, preserve );
  462. }
  463. if (strobe)
  464. {
  465. strobeLEDs();
  466. }
  467. }
  468. catch( const exception &e )
  469. {
  470. cerr << "An Error occurred. The Error message is: " << endl << e.what() << endl;
  471. retval = 1;
  472. }
  473. catch ( ... )
  474. {
  475. cerr << "An Unknown Error occurred. Aborting." << endl;
  476. retval = 2;
  477. }
  478. return retval;
  479. }
  480. // cbClass: 4
  481. // cbSelect: 7
  482. // name: Get LED Settings
  483. //
  484. // On return:
  485. // cbRES1 Return code
  486. // 0 Completed successfully
  487. // -1 Completed with error
  488. // -2 Function not supported
  489. // cbRES2 Current LED Settings
  490. // byte 0 LED Color for Zone 1
  491. // byte 1 LED Color for Zone 2
  492. // byte 2 LED Color for Zone 3
  493. // byte 3 bit [2:0] have the Intensity Level
  494. // Bits 3-7 Reserved
  495. // cbRES3 CMOS LED Settings
  496. // byte 0 LED Color for Zone 1
  497. // byte 1 LED Color for Zone 2
  498. // byte 2 LED Color for Zone 3
  499. // byte 3 bit [2:0] have the Intensity Level
  500. // bits 3-7 Reserved
  501. //
  502. // cbRES4 Zone4 LED Settings
  503. // byte 0 Zone4 current led setting
  504. // byte 1 Zone4 CMOS led setting
  505. //
  506. // Note : The Mapping of Zones like Zone 1 is Fans, Zone 2 is Speakers,etc
  507. // will be defined in the system specific BIOS Document.
  508. // cbClass: 4
  509. // cbClass: 6
  510. // name: Set LED Settings
  511. // On entry:
  512. // cbARG1:
  513. // byte 0 LED Color for Zone 1
  514. // byte 1 LED Color for Zone 2
  515. // byte 2 LED Color for Zone 3
  516. // byte 3 bit [2:0] have the Intensity Level
  517. // bits 3-7 Reserved
  518. // cbARG2:
  519. // byte0 bit [0] - Make change Permanent Bit
  520. //
  521. // If bit 0 is 1, change the LED colors and save the setting to CMOS;
  522. // otherwise, change the LED colors but dont save to CMOS
  523. //
  524. // cbARG3:
  525. // byte 0 LED Color for Zone 4
  526. //
  527. // On return:
  528. // cbRES1 Return code
  529. // 0 Completed successfully
  530. // -1 Completed with error
  531. // -2 Function not supported
  532. //
  533. // Note : The Mapping of Zones like Zone 1 is Fans, Zone 2 is Speakers,etc
  534. // will be defined in the system specific BIOS Document.
  535. // cbClass: 17
  536. // cbSelect: 12
  537. // Name: Touchpad (TP) & Media Board (MB) LED Control
  538. //
  539. // On entry:
  540. // cbARG1, byte1 Subcommand:
  541. // 0 Get config
  542. // 1 Set config
  543. // cbARG2, byte1 Control bits (if cbARG1==1):
  544. // 0 LED Inactive State:
  545. // 0=Off
  546. // 1=Low intensity
  547. // 1 TP LED Active State:
  548. // 0=No change (stay off or low)
  549. // 1=Turn on for 3 seconds
  550. // 2 MB LED Active State:
  551. // 0=No change (stay off or low)
  552. // 1=Turn on for 3 seconds
  553. // 3-7 Reserved (0)
  554. //
  555. // On return:
  556. // cbRES1 Return code
  557. // 0 Completed successfully
  558. // -1 Completed with error
  559. // -2 Function not supported
  560. // cbRES2 Error code (if cbRES1==-1)
  561. // -1 Non-specific error
  562. // cbARG3, byte1 Config bits:
  563. // 0 LED Inactive State:
  564. // 0=Off
  565. // 1=Low intensity
  566. // 1 TP LED Active State:
  567. // 0=No change (stay off or low)
  568. // 1=Turn on for 3 seconds
  569. // 2 MB LED Active State:
  570. // 0=No change (stay off or low)
  571. // 1=Turn on for 3 seconds
  572. // 3-7 Reserved (0)
  573. //
  574. // NOTE: The LED Inactive State bit controls both the Touchpad LED and the
  575. // Media Board LED. When this bit is clear (0), neither LED will be on when
  576. // their respective control is inactive. When this bit is set (1), both LEDs
  577. // will be on at low intensity when their respective control is inactive. The
  578. // control for the touchpad LED is the touchpad, and that control is active
  579. // when the touchpad is being touched. The control for the media board LED is
  580. // the media button, and that control is active when the media button is being
  581. // pressed. The responses to activity by the touchpad and media board LEDs are
  582. // controlled individually. Each of these LEDs can be set to remain in its
  583. // inactive state (off or low intensity) even when activity is detected, or to
  584. // turn on at normal intensity and stay on for 3 seconds when activity is
  585. // detected.