bt.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:14k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  *
  3.  * Module Name: bt.c
  4.  *   $Revision: 29 $
  5.  *
  6.  *****************************************************************************/
  7. /*
  8.  *  Copyright (C) 2000, 2001 Andrew Grover
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23.  */
  24. #include <acpi.h>
  25. #include "bt.h"
  26. #define _COMPONENT ACPI_BATTERY
  27. MODULE_NAME  ("bt")
  28. /****************************************************************************
  29.  *                            Internal Functions
  30.  ****************************************************************************/
  31. /****************************************************************************
  32.  *
  33.  * FUNCTION: bt_print
  34.  *
  35.  * PARAMETERS:
  36.  *
  37.  * RETURN:
  38.  *
  39.  * DESCRIPTION: Prints out information on a specific battery.
  40.  *
  41.  ****************************************************************************/
  42. void
  43. bt_print (
  44. BT_CONTEXT *battery)
  45. {
  46. #ifdef ACPI_DEBUG
  47. acpi_buffer  buffer;
  48. PROC_NAME("bt_print");
  49. if (!battery) {
  50. return;
  51. }
  52. buffer.length = 256;
  53. buffer.pointer = acpi_os_callocate(buffer.length);
  54. if (!buffer.pointer) {
  55. return;
  56. }
  57. /*
  58.  * Get the full pathname for this ACPI object.
  59.  */
  60. acpi_get_name(battery->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
  61. /*
  62.  * Print out basic battery information.
  63.  */
  64. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------n"));
  65. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "| Battery[%02x]:[%p] %sn", battery->device_handle, battery->acpi_handle, (char*)buffer.pointer));
  66. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "|   uid[%s] is_present[%d] power_units[%s]n", battery->uid, battery->is_present, battery->power_units));
  67. ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, "+------------------------------------------------------------n"));
  68. acpi_os_free(buffer.pointer);
  69. #endif /*ACPI_DEBUG*/
  70. return;
  71. }
  72. /****************************************************************************
  73.  *
  74.  * FUNCTION: bt_get_info
  75.  *
  76.  * PARAMETERS:
  77.  *
  78.  * RETURN:
  79.  *
  80.  * DESCRIPTION:
  81.  *
  82.  * NOTES: Allocates battery_info - which must be freed by the caller.
  83.  *
  84.  ****************************************************************************/
  85. acpi_status
  86. bt_get_info (
  87. BT_CONTEXT *battery,
  88. BT_BATTERY_INFO  **battery_info)
  89. {
  90. acpi_status  status = AE_OK;
  91. acpi_buffer  bif_buffer, package_format, package_data;
  92. acpi_object  *package = NULL;
  93. FUNCTION_TRACE("bt_get_info");
  94. if (!battery || !battery_info || *battery_info) {
  95. return_ACPI_STATUS(AE_BAD_PARAMETER);
  96. }
  97. memset(&bif_buffer, 0, sizeof(acpi_buffer));
  98. /*
  99.  * Evalute _BIF:
  100.  * -------------
  101.  * And be sure to deallocate bif_buffer.pointer!
  102.  */
  103. status = bm_evaluate_object(battery->acpi_handle, "_BIF", NULL,
  104. &bif_buffer);
  105. if (ACPI_FAILURE(status)) {
  106. return_ACPI_STATUS(status);
  107. }
  108. /*
  109.  * Extract Package Data:
  110.  * ---------------------
  111.  * Type-cast this bif_buffer to a package and use helper
  112.  * functions to convert results into BT_BATTERY_INFO structure.
  113.  * The first attempt is just to get the size of the package
  114.  * data; the second gets the data (once we know the required
  115.  * bif_buffer size).
  116.  */
  117. status = bm_cast_buffer(&bif_buffer, (void**)&package,
  118. sizeof(acpi_object));
  119. if (ACPI_FAILURE(status)) {
  120. goto end;
  121. }
  122. package_format.length = sizeof("NNNNNNNNNSSSS");
  123. package_format.pointer = "NNNNNNNNNSSSS";
  124. memset(&package_data, 0, sizeof(acpi_buffer));
  125. status = bm_extract_package_data(package, &package_format,
  126. &package_data);
  127. if (status != AE_BUFFER_OVERFLOW) {
  128. if (status == AE_OK) {
  129. status = AE_ERROR;
  130. }
  131. goto end;
  132. }
  133. package_data.pointer = acpi_os_callocate(package_data.length);
  134. if (!package_data.pointer) {
  135. return_ACPI_STATUS(AE_NO_MEMORY);
  136. }
  137. status = bm_extract_package_data(package, &package_format,
  138. &package_data);
  139. if (ACPI_FAILURE(status)) {
  140. acpi_os_free(package_data.pointer);
  141. goto end;
  142. }
  143. *battery_info = package_data.pointer;
  144. end:
  145. acpi_os_free(bif_buffer.pointer);
  146. return_ACPI_STATUS(status);
  147. }
  148. /****************************************************************************
  149.  *
  150.  * FUNCTION: bt_get_status
  151.  *
  152.  * PARAMETERS:
  153.  *
  154.  * RETURN:
  155.  *
  156.  * DESCRIPTION:
  157.  *
  158.  ****************************************************************************/
  159. acpi_status
  160. bt_get_status (
  161. BT_CONTEXT *battery,
  162. BT_BATTERY_STATUS **battery_status)
  163. {
  164. acpi_status  status = AE_OK;
  165. acpi_buffer  bst_buffer, package_format, package_data;
  166. acpi_object  *package = NULL;
  167. FUNCTION_TRACE("bt_get_status");
  168. if (!battery || !battery_status || *battery_status) {
  169. return_ACPI_STATUS(AE_BAD_PARAMETER);
  170. }
  171. memset(&bst_buffer, 0, sizeof(acpi_buffer));
  172. /*
  173.  * Evalute _BST:
  174.  * -------------
  175.  * And be sure to deallocate bst_buffer.pointer!
  176.  */
  177. status = bm_evaluate_object(battery->acpi_handle, "_BST",
  178. NULL, &bst_buffer);
  179. if (ACPI_FAILURE(status)) {
  180. return_ACPI_STATUS(status);
  181. }
  182. /*
  183.  * Extract Package Data:
  184.  * ---------------------
  185.  * Type-cast this bst_buffer to a package and use helper
  186.  * functions to convert results into BT_BATTERY_STATUS structure.
  187.  * The first attempt is just to get the size of the package data;
  188.  * the second gets the data (once we know the required bst_buffer
  189.  * size).
  190.  */
  191. status = bm_cast_buffer(&bst_buffer, (void**)&package,
  192. sizeof(acpi_object));
  193. if (ACPI_FAILURE(status)) {
  194. goto end;
  195. }
  196. package_format.length = sizeof("NNNN");
  197. package_format.pointer = "NNNN";
  198. memset(&package_data, 0, sizeof(acpi_buffer));
  199. status = bm_extract_package_data(package, &package_format,
  200. &package_data);
  201. if (status != AE_BUFFER_OVERFLOW) {
  202. if (status == AE_OK) {
  203. status = AE_ERROR;
  204. }
  205. goto end;
  206. }
  207. package_data.pointer = acpi_os_callocate(package_data.length);
  208. if (!package_data.pointer) {
  209. return_ACPI_STATUS(AE_NO_MEMORY);
  210. }
  211. status = bm_extract_package_data(package, &package_format,
  212. &package_data);
  213. if (ACPI_FAILURE(status)) {
  214. acpi_os_free(package_data.pointer);
  215. goto end;
  216. }
  217. *battery_status = package_data.pointer;
  218. end:
  219. acpi_os_free(bst_buffer.pointer);
  220. return_ACPI_STATUS(status);
  221. }
  222. /****************************************************************************
  223.  *
  224.  * FUNCTION: bt_check_device
  225.  *
  226.  * PARAMETERS:
  227.  *
  228.  * RETURN:
  229.  *
  230.  * DESCRIPTION:
  231.  *
  232.  ****************************************************************************/
  233. acpi_status
  234. bt_check_device (
  235. BT_CONTEXT *battery)
  236. {
  237. acpi_status  status = AE_OK;
  238. BM_DEVICE_STATUS battery_status = BM_STATUS_UNKNOWN;
  239. u32  was_present = FALSE;
  240. BT_BATTERY_INFO  *battery_info = NULL;
  241. FUNCTION_TRACE("bt_check_device");
  242. if (!battery) {
  243. return_ACPI_STATUS(AE_BAD_PARAMETER);
  244. }
  245. was_present = battery->is_present;
  246. /*
  247.  * Battery Present?
  248.  * ----------------
  249.  * Get the device status and check if battery slot is occupied.
  250.  */
  251. status = bm_get_device_status(battery->device_handle, &battery_status);
  252. if (ACPI_FAILURE(status)) {
  253. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Unable to get battery status.n"));
  254. return_ACPI_STATUS(status);
  255. }
  256. if (battery_status & BM_STATUS_BATTERY_PRESENT) {
  257. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Battery socket occupied.n"));
  258. battery->is_present = TRUE;
  259. }
  260. else {
  261. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Battery socket not occupied.n"));
  262. battery->is_present = FALSE;
  263. }
  264. /*
  265.  * Battery Appeared?
  266.  * -----------------
  267.  */
  268. if (!was_present && battery->is_present) {
  269. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Battery insertion detected.n"));
  270. /*
  271.  * Units of Power?
  272.  * ---------------
  273.  * Get the 'units of power', as we'll need this to report
  274.  * status information.
  275.  */
  276. status = bt_get_info(battery, &battery_info);
  277. if (ACPI_SUCCESS(status)) {
  278. battery->power_units = (battery_info->power_unit)
  279. ? BT_POWER_UNITS_AMPS : BT_POWER_UNITS_WATTS;
  280. acpi_os_free(battery_info);
  281. }
  282. }
  283. /*
  284.  * Battery Disappeared?
  285.  * --------------------
  286.  */
  287. else if (was_present && !battery->is_present) {
  288. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Battery removal detected.n"));
  289. battery->power_units = BT_POWER_UNITS_DEFAULT;
  290. }
  291. return_ACPI_STATUS(status);
  292. }
  293. /*****************************************************************************
  294.  *
  295.  * FUNCTION: bt_add_device
  296.  *
  297.  * PARAMETERS:
  298.  *
  299.  * RETURN:
  300.  *
  301.  * DESCRIPTION:
  302.  *
  303.  ****************************************************************************/
  304. acpi_status
  305. bt_add_device (
  306. BM_HANDLE device_handle,
  307. void **context)
  308. {
  309. acpi_status  status = AE_OK;
  310. BM_DEVICE *device = NULL;
  311. BT_CONTEXT *battery = NULL;
  312. FUNCTION_TRACE("bt_add_device");
  313. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Adding battery device [%02x].n", device_handle));
  314. if (!context || *context) {
  315. return_ACPI_STATUS(AE_BAD_PARAMETER);
  316. }
  317. /*
  318.  * Get information on this device.
  319.  */
  320. status = bm_get_device_info(device_handle, &device);
  321. if (ACPI_FAILURE(status)) {
  322. return_ACPI_STATUS(status);
  323. }
  324. /*
  325.  * Allocate a new BT_CONTEXT structure.
  326.  */
  327. battery = acpi_os_callocate(sizeof(BT_CONTEXT));
  328. if (!battery) {
  329. return_ACPI_STATUS(AE_NO_MEMORY);
  330. }
  331. battery->device_handle = device->handle;
  332. battery->acpi_handle = device->acpi_handle;
  333. strncpy(battery->uid, device->id.uid, sizeof(battery->uid));
  334. battery->power_units = BT_POWER_UNITS_DEFAULT;
  335. battery->is_present = FALSE;
  336. /*
  337.  * See if battery is really present.
  338.  */
  339. status = bt_check_device(battery);
  340. if (ACPI_FAILURE(status)) {
  341. goto end;
  342. }
  343. status = bt_osl_add_device(battery);
  344. if (ACPI_FAILURE(status)) {
  345. goto end;
  346. }
  347. *context = battery;
  348. bt_print(battery);
  349. end:
  350. if (ACPI_FAILURE(status)) {
  351. acpi_os_free(battery);
  352. }
  353. return_ACPI_STATUS(status);
  354. }
  355. /*****************************************************************************
  356.  *
  357.  * FUNCTION: bt_remove_device
  358.  *
  359.  * PARAMETERS:
  360.  *
  361.  * RETURN:
  362.  *
  363.  * DESCRIPTION:
  364.  *
  365.  ****************************************************************************/
  366. acpi_status
  367. bt_remove_device (
  368. void **context)
  369. {
  370. acpi_status  status = AE_OK;
  371. BT_CONTEXT *battery = NULL;
  372. FUNCTION_TRACE("bt_remove_device");
  373. if (!context || !*context) {
  374. return_ACPI_STATUS(AE_BAD_PARAMETER);
  375. }
  376. battery = (BT_CONTEXT*)*context;
  377. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing battery device [%02x].n", battery->device_handle));
  378. bt_osl_remove_device(battery);
  379. acpi_os_free(battery);
  380. *context = NULL;
  381. return_ACPI_STATUS(status);
  382. }
  383. /*****************************************************************************
  384.  *                               External Functions
  385.  *****************************************************************************/
  386. /*****************************************************************************
  387.  *
  388.  * FUNCTION: bt_initialize
  389.  *
  390.  * PARAMETERS: <none>
  391.  *
  392.  * RETURN:
  393.  *
  394.  * DESCRIPTION:
  395.  *
  396.  ****************************************************************************/
  397. acpi_status
  398. bt_initialize (void)
  399. {
  400. acpi_status status = AE_OK;
  401. BM_DEVICE_ID criteria;
  402. BM_DRIVER driver;
  403. FUNCTION_TRACE("bt_initialize");
  404. memset(&criteria, 0, sizeof(BM_DEVICE_ID));
  405. memset(&driver, 0, sizeof(BM_DRIVER));
  406. /*
  407.  * Register driver for driver method battery devices.
  408.  */
  409. MEMCPY(criteria.hid, BT_HID_CM_BATTERY, sizeof(BT_HID_CM_BATTERY));
  410. driver.notify = &bt_notify;
  411. driver.request = &bt_request;
  412. status = bm_register_driver(&criteria, &driver);
  413. return_ACPI_STATUS(status);
  414. }
  415. /****************************************************************************
  416.  *
  417.  * FUNCTION: bt_terminate
  418.  *
  419.  * PARAMETERS: <none>
  420.  *
  421.  * RETURN:
  422.  *
  423.  * DESCRIPTION:
  424.  *
  425.  ****************************************************************************/
  426. acpi_status
  427. bt_terminate (void)
  428. {
  429. acpi_status status = AE_OK;
  430. BM_DEVICE_ID criteria;
  431. BM_DRIVER driver;
  432. FUNCTION_TRACE("bt_terminate");
  433. memset(&criteria, 0, sizeof(BM_DEVICE_ID));
  434. memset(&driver, 0, sizeof(BM_DRIVER));
  435. /*
  436.  * Unregister driver for driver method battery devices.
  437.  */
  438. MEMCPY(criteria.hid, BT_HID_CM_BATTERY, sizeof(BT_HID_CM_BATTERY));
  439. driver.notify = &bt_notify;
  440. driver.request = &bt_request;
  441. status = bm_unregister_driver(&criteria, &driver);
  442. return_ACPI_STATUS(status);
  443. }
  444. /****************************************************************************
  445.  *
  446.  * FUNCTION: bt_notify
  447.  *
  448.  * PARAMETERS: <none>
  449.  *
  450.  * RETURN:
  451.  *
  452.  * DESCRIPTION:
  453.  *
  454.  ****************************************************************************/
  455. acpi_status
  456. bt_notify (
  457. BM_NOTIFY notify_type,
  458. BM_HANDLE device_handle,
  459. void **context)
  460. {
  461. acpi_status  status = AE_OK;
  462. FUNCTION_TRACE("bt_notify");
  463. if (!context) {
  464. return_ACPI_STATUS(AE_BAD_PARAMETER);
  465. }
  466. switch (notify_type) {
  467. case BM_NOTIFY_DEVICE_ADDED:
  468. status = bt_add_device(device_handle, context);
  469. break;
  470. case BM_NOTIFY_DEVICE_REMOVED:
  471. status = bt_remove_device(context);
  472. break;
  473. case BT_NOTIFY_STATUS_CHANGE:
  474. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Status change (_BST) event detected.n"));
  475. status = bt_osl_generate_event(notify_type,
  476. ((BT_CONTEXT*)*context));
  477. break;
  478. case BT_NOTIFY_INFORMATION_CHANGE:
  479. ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Information change (_BIF) event detected.n"));
  480. status = bt_check_device((BT_CONTEXT*)*context);
  481. if (ACPI_SUCCESS(status)) {
  482. status = bt_osl_generate_event(notify_type,
  483. ((BT_CONTEXT*)*context));
  484. }
  485. break;
  486. default:
  487. status = AE_SUPPORT;
  488. break;
  489. }
  490. return_ACPI_STATUS(status);
  491. }
  492. /****************************************************************************
  493.  *
  494.  * FUNCTION: bt_request
  495.  *
  496.  * PARAMETERS:
  497.  *
  498.  * RETURN:
  499.  *
  500.  * DESCRIPTION:
  501.  *
  502.  ****************************************************************************/
  503. acpi_status
  504. bt_request (
  505. BM_REQUEST *request,
  506. void *context)
  507. {
  508. acpi_status  status = AE_OK;
  509. FUNCTION_TRACE("bt_request");
  510. /*
  511.  * Must have a valid request structure and context.
  512.  */
  513. if (!request || !context)
  514. return_ACPI_STATUS(AE_BAD_PARAMETER);
  515. /*
  516.  * Handle request:
  517.  * ---------------
  518.  */
  519. switch (request->command) {
  520. default:
  521. status = AE_SUPPORT;
  522. break;
  523. }
  524. request->status = status;
  525. return_ACPI_STATUS(status);
  526. }