1 /* 2 * acpi_battery.c - ACPI Battery Driver ($Revision: 37 $) 3 * 4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 6 * 7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or (at 12 * your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write to the Free Software Foundation, Inc., 21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 22 * 23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 24 */ 25 26 #include <linux/kernel.h> 27 #include <linux/module.h> 28 #include <linux/init.h> 29 #include <linux/types.h> 30 #include <linux/proc_fs.h> 31 #include <linux/seq_file.h> 32 #include <asm/uaccess.h> 33 34 #include <acpi/acpi_bus.h> 35 #include <acpi/acpi_drivers.h> 36 37 38 #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF 39 40 #define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS" 41 #define ACPI_BATTERY_FORMAT_BST "NNNN" 42 43 #define ACPI_BATTERY_COMPONENT 0x00040000 44 #define ACPI_BATTERY_CLASS "battery" 45 #define ACPI_BATTERY_HID "PNP0C0A" 46 #define ACPI_BATTERY_DRIVER_NAME "ACPI Battery Driver" 47 #define ACPI_BATTERY_DEVICE_NAME "Battery" 48 #define ACPI_BATTERY_FILE_INFO "info" 49 #define ACPI_BATTERY_FILE_STATUS "state" 50 #define ACPI_BATTERY_FILE_ALARM "alarm" 51 #define ACPI_BATTERY_NOTIFY_STATUS 0x80 52 #define ACPI_BATTERY_NOTIFY_INFO 0x81 53 #define ACPI_BATTERY_UNITS_WATTS "mW" 54 #define ACPI_BATTERY_UNITS_AMPS "mA" 55 56 57 #define _COMPONENT ACPI_BATTERY_COMPONENT 58 ACPI_MODULE_NAME ("acpi_battery") 59 60 MODULE_AUTHOR("Paul Diefenbaugh"); 61 MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME); 62 MODULE_LICENSE("GPL"); 63 64 static int acpi_battery_add (struct acpi_device *device); 65 static int acpi_battery_remove (struct acpi_device *device, int type); 66 67 static struct acpi_driver acpi_battery_driver = { 68 .name = ACPI_BATTERY_DRIVER_NAME, 69 .class = ACPI_BATTERY_CLASS, 70 .ids = ACPI_BATTERY_HID, 71 .ops = { 72 .add = acpi_battery_add, 73 .remove = acpi_battery_remove, 74 }, 75 }; 76 77 struct acpi_battery_status { 78 acpi_integer state; 79 acpi_integer present_rate; 80 acpi_integer remaining_capacity; 81 acpi_integer present_voltage; 82 }; 83 84 struct acpi_battery_info { 85 acpi_integer power_unit; 86 acpi_integer design_capacity; 87 acpi_integer last_full_capacity; 88 acpi_integer battery_technology; 89 acpi_integer design_voltage; 90 acpi_integer design_capacity_warning; 91 acpi_integer design_capacity_low; 92 acpi_integer battery_capacity_granularity_1; 93 acpi_integer battery_capacity_granularity_2; 94 acpi_string model_number; 95 acpi_string serial_number; 96 acpi_string battery_type; 97 acpi_string oem_info; 98 }; 99 100 struct acpi_battery_flags { 101 u8 present:1; /* Bay occupied? */ 102 u8 power_unit:1; /* 0=watts, 1=apms */ 103 u8 alarm:1; /* _BTP present? */ 104 u8 reserved:5; 105 }; 106 107 struct acpi_battery_trips { 108 unsigned long warning; 109 unsigned long low; 110 }; 111 112 struct acpi_battery { 113 acpi_handle handle; 114 struct acpi_battery_flags flags; 115 struct acpi_battery_trips trips; 116 unsigned long alarm; 117 struct acpi_battery_info *info; 118 }; 119 120 121 /* -------------------------------------------------------------------------- 122 Battery Management 123 -------------------------------------------------------------------------- */ 124 125 static int 126 acpi_battery_get_info ( 127 struct acpi_battery *battery, 128 struct acpi_battery_info **bif) 129 { 130 int result = 0; 131 acpi_status status = 0; 132 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 133 struct acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BIF), 134 ACPI_BATTERY_FORMAT_BIF}; 135 struct acpi_buffer data = {0, NULL}; 136 union acpi_object *package = NULL; 137 138 ACPI_FUNCTION_TRACE("acpi_battery_get_info"); 139 140 if (!battery || !bif) 141 return_VALUE(-EINVAL); 142 143 /* Evalute _BIF */ 144 145 status = acpi_evaluate_object(battery->handle, "_BIF", NULL, &buffer); 146 if (ACPI_FAILURE(status)) { 147 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BIF\n")); 148 return_VALUE(-ENODEV); 149 } 150 151 package = (union acpi_object *) buffer.pointer; 152 153 /* Extract Package Data */ 154 155 status = acpi_extract_package(package, &format, &data); 156 if (status != AE_BUFFER_OVERFLOW) { 157 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n")); 158 result = -ENODEV; 159 goto end; 160 } 161 162 data.pointer = kmalloc(data.length, GFP_KERNEL); 163 if (!data.pointer) { 164 result = -ENOMEM; 165 goto end; 166 } 167 memset(data.pointer, 0, data.length); 168 169 status = acpi_extract_package(package, &format, &data); 170 if (ACPI_FAILURE(status)) { 171 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n")); 172 kfree(data.pointer); 173 result = -ENODEV; 174 goto end; 175 } 176 177 end: 178 acpi_os_free(buffer.pointer); 179 180 if (!result) 181 (*bif) = (struct acpi_battery_info *) data.pointer; 182 183 return_VALUE(result); 184 } 185 186 static int 187 acpi_battery_get_status ( 188 struct acpi_battery *battery, 189 struct acpi_battery_status **bst) 190 { 191 int result = 0; 192 acpi_status status = 0; 193 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 194 struct acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BST), 195 ACPI_BATTERY_FORMAT_BST}; 196 struct acpi_buffer data = {0, NULL}; 197 union acpi_object *package = NULL; 198 199 ACPI_FUNCTION_TRACE("acpi_battery_get_status"); 200 201 if (!battery || !bst) 202 return_VALUE(-EINVAL); 203 204 /* Evalute _BST */ 205 206 status = acpi_evaluate_object(battery->handle, "_BST", NULL, &buffer); 207 if (ACPI_FAILURE(status)) { 208 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BST\n")); 209 return_VALUE(-ENODEV); 210 } 211 212 package = (union acpi_object *) buffer.pointer; 213 214 /* Extract Package Data */ 215 216 status = acpi_extract_package(package, &format, &data); 217 if (status != AE_BUFFER_OVERFLOW) { 218 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n")); 219 result = -ENODEV; 220 goto end; 221 } 222 223 data.pointer = kmalloc(data.length, GFP_KERNEL); 224 if (!data.pointer) { 225 result = -ENOMEM; 226 goto end; 227 } 228 memset(data.pointer, 0, data.length); 229 230 status = acpi_extract_package(package, &format, &data); 231 if (ACPI_FAILURE(status)) { 232 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n")); 233 kfree(data.pointer); 234 result = -ENODEV; 235 goto end; 236 } 237 238 end: 239 acpi_os_free(buffer.pointer); 240 241 if (!result) 242 (*bst) = (struct acpi_battery_status *) data.pointer; 243 244 return_VALUE(result); 245 } 246 247 248 static int 249 acpi_battery_set_alarm ( 250 struct acpi_battery *battery, 251 unsigned long alarm) 252 { 253 acpi_status status = 0; 254 union acpi_object arg0 = {ACPI_TYPE_INTEGER}; 255 struct acpi_object_list arg_list = {1, &arg0}; 256 257 ACPI_FUNCTION_TRACE("acpi_battery_set_alarm"); 258 259 if (!battery) 260 return_VALUE(-EINVAL); 261 262 if (!battery->flags.alarm) 263 return_VALUE(-ENODEV); 264 265 arg0.integer.value = alarm; 266 267 status = acpi_evaluate_object(battery->handle, "_BTP", &arg_list, NULL); 268 if (ACPI_FAILURE(status)) 269 return_VALUE(-ENODEV); 270 271 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm)); 272 273 battery->alarm = alarm; 274 275 return_VALUE(0); 276 } 277 278 279 static int 280 acpi_battery_check ( 281 struct acpi_battery *battery) 282 { 283 int result = 0; 284 acpi_status status = AE_OK; 285 acpi_handle handle = NULL; 286 struct acpi_device *device = NULL; 287 struct acpi_battery_info *bif = NULL; 288 289 ACPI_FUNCTION_TRACE("acpi_battery_check"); 290 291 if (!battery) 292 return_VALUE(-EINVAL); 293 294 result = acpi_bus_get_device(battery->handle, &device); 295 if (result) 296 return_VALUE(result); 297 298 result = acpi_bus_get_status(device); 299 if (result) 300 return_VALUE(result); 301 302 /* Insertion? */ 303 304 if (!battery->flags.present && device->status.battery_present) { 305 306 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n")); 307 308 /* Evalute _BIF to get certain static information */ 309 310 result = acpi_battery_get_info(battery, &bif); 311 if (result) 312 return_VALUE(result); 313 314 battery->flags.power_unit = bif->power_unit; 315 battery->trips.warning = bif->design_capacity_warning; 316 battery->trips.low = bif->design_capacity_low; 317 kfree(bif); 318 319 /* See if alarms are supported, and if so, set default */ 320 321 status = acpi_get_handle(battery->handle, "_BTP", &handle); 322 if (ACPI_SUCCESS(status)) { 323 battery->flags.alarm = 1; 324 acpi_battery_set_alarm(battery, battery->trips.warning); 325 } 326 } 327 328 /* Removal? */ 329 330 else if (battery->flags.present && !device->status.battery_present) { 331 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n")); 332 } 333 334 battery->flags.present = device->status.battery_present; 335 336 return_VALUE(result); 337 } 338 339 340 /* -------------------------------------------------------------------------- 341 FS Interface (/proc) 342 -------------------------------------------------------------------------- */ 343 344 static struct proc_dir_entry *acpi_battery_dir; 345 static int acpi_battery_read_info(struct seq_file *seq, void *offset) 346 { 347 int result = 0; 348 struct acpi_battery *battery = (struct acpi_battery *) seq->private; 349 struct acpi_battery_info *bif = NULL; 350 char *units = "?"; 351 352 ACPI_FUNCTION_TRACE("acpi_battery_read_info"); 353 354 if (!battery) 355 goto end; 356 357 if (battery->flags.present) 358 seq_printf(seq, "present: yes\n"); 359 else { 360 seq_printf(seq, "present: no\n"); 361 goto end; 362 } 363 364 /* Battery Info (_BIF) */ 365 366 result = acpi_battery_get_info(battery, &bif); 367 if (result || !bif) { 368 seq_printf(seq, "ERROR: Unable to read battery information\n"); 369 goto end; 370 } 371 372 units = bif->power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; 373 374 if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) 375 seq_printf(seq, "design capacity: unknown\n"); 376 else 377 seq_printf(seq, "design capacity: %d %sh\n", 378 (u32) bif->design_capacity, units); 379 380 if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) 381 seq_printf(seq, "last full capacity: unknown\n"); 382 else 383 seq_printf(seq, "last full capacity: %d %sh\n", 384 (u32) bif->last_full_capacity, units); 385 386 switch ((u32) bif->battery_technology) { 387 case 0: 388 seq_printf(seq, "battery technology: non-rechargeable\n"); 389 break; 390 case 1: 391 seq_printf(seq, "battery technology: rechargeable\n"); 392 break; 393 default: 394 seq_printf(seq, "battery technology: unknown\n"); 395 break; 396 } 397 398 if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) 399 seq_printf(seq, "design voltage: unknown\n"); 400 else 401 seq_printf(seq, "design voltage: %d mV\n", 402 (u32) bif->design_voltage); 403 404 seq_printf(seq, "design capacity warning: %d %sh\n", 405 (u32) bif->design_capacity_warning, units); 406 seq_printf(seq, "design capacity low: %d %sh\n", 407 (u32) bif->design_capacity_low, units); 408 seq_printf(seq, "capacity granularity 1: %d %sh\n", 409 (u32) bif->battery_capacity_granularity_1, units); 410 seq_printf(seq, "capacity granularity 2: %d %sh\n", 411 (u32) bif->battery_capacity_granularity_2, units); 412 seq_printf(seq, "model number: %s\n", 413 bif->model_number); 414 seq_printf(seq, "serial number: %s\n", 415 bif->serial_number); 416 seq_printf(seq, "battery type: %s\n", 417 bif->battery_type); 418 seq_printf(seq, "OEM info: %s\n", 419 bif->oem_info); 420 421 end: 422 kfree(bif); 423 424 return_VALUE(0); 425 } 426 427 static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) 428 { 429 return single_open(file, acpi_battery_read_info, PDE(inode)->data); 430 } 431 432 433 static int 434 acpi_battery_read_state (struct seq_file *seq, void *offset) 435 { 436 int result = 0; 437 struct acpi_battery *battery = (struct acpi_battery *) seq->private; 438 struct acpi_battery_status *bst = NULL; 439 char *units = "?"; 440 441 ACPI_FUNCTION_TRACE("acpi_battery_read_state"); 442 443 if (!battery) 444 goto end; 445 446 if (battery->flags.present) 447 seq_printf(seq, "present: yes\n"); 448 else { 449 seq_printf(seq, "present: no\n"); 450 goto end; 451 } 452 453 /* Battery Units */ 454 455 units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; 456 457 /* Battery Status (_BST) */ 458 459 result = acpi_battery_get_status(battery, &bst); 460 if (result || !bst) { 461 seq_printf(seq, "ERROR: Unable to read battery status\n"); 462 goto end; 463 } 464 465 if (!(bst->state & 0x04)) 466 seq_printf(seq, "capacity state: ok\n"); 467 else 468 seq_printf(seq, "capacity state: critical\n"); 469 470 if ((bst->state & 0x01) && (bst->state & 0x02)){ 471 seq_printf(seq, "charging state: charging/discharging\n"); 472 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, 473 "Battery Charging and Discharging?\n")); 474 } 475 else if (bst->state & 0x01) 476 seq_printf(seq, "charging state: discharging\n"); 477 else if (bst->state & 0x02) 478 seq_printf(seq, "charging state: charging\n"); 479 else { 480 seq_printf(seq, "charging state: charged\n"); 481 } 482 483 if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN) 484 seq_printf(seq, "present rate: unknown\n"); 485 else 486 seq_printf(seq, "present rate: %d %s\n", 487 (u32) bst->present_rate, units); 488 489 if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN) 490 seq_printf(seq, "remaining capacity: unknown\n"); 491 else 492 seq_printf(seq, "remaining capacity: %d %sh\n", 493 (u32) bst->remaining_capacity, units); 494 495 if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN) 496 seq_printf(seq, "present voltage: unknown\n"); 497 else 498 seq_printf(seq, "present voltage: %d mV\n", 499 (u32) bst->present_voltage); 500 501 end: 502 kfree(bst); 503 504 return_VALUE(0); 505 } 506 507 static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) 508 { 509 return single_open(file, acpi_battery_read_state, PDE(inode)->data); 510 } 511 512 513 static int 514 acpi_battery_read_alarm (struct seq_file *seq, void *offset) 515 { 516 struct acpi_battery *battery = (struct acpi_battery *) seq->private; 517 char *units = "?"; 518 519 ACPI_FUNCTION_TRACE("acpi_battery_read_alarm"); 520 521 if (!battery) 522 goto end; 523 524 if (!battery->flags.present) { 525 seq_printf(seq, "present: no\n"); 526 goto end; 527 } 528 529 /* Battery Units */ 530 531 units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; 532 533 /* Battery Alarm */ 534 535 seq_printf(seq, "alarm: "); 536 if (!battery->alarm) 537 seq_printf(seq, "unsupported\n"); 538 else 539 seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units); 540 541 end: 542 return_VALUE(0); 543 } 544 545 546 static ssize_t 547 acpi_battery_write_alarm ( 548 struct file *file, 549 const char __user *buffer, 550 size_t count, 551 loff_t *ppos) 552 { 553 int result = 0; 554 char alarm_string[12] = {'\0'}; 555 struct seq_file *m = (struct seq_file *)file->private_data; 556 struct acpi_battery *battery = (struct acpi_battery *)m->private; 557 558 ACPI_FUNCTION_TRACE("acpi_battery_write_alarm"); 559 560 if (!battery || (count > sizeof(alarm_string) - 1)) 561 return_VALUE(-EINVAL); 562 563 if (!battery->flags.present) 564 return_VALUE(-ENODEV); 565 566 if (copy_from_user(alarm_string, buffer, count)) 567 return_VALUE(-EFAULT); 568 569 alarm_string[count] = '\0'; 570 571 result = acpi_battery_set_alarm(battery, 572 simple_strtoul(alarm_string, NULL, 0)); 573 if (result) 574 return_VALUE(result); 575 576 return_VALUE(count); 577 } 578 579 static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) 580 { 581 return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); 582 } 583 584 static struct file_operations acpi_battery_info_ops = { 585 .open = acpi_battery_info_open_fs, 586 .read = seq_read, 587 .llseek = seq_lseek, 588 .release = single_release, 589 .owner = THIS_MODULE, 590 }; 591 592 static struct file_operations acpi_battery_state_ops = { 593 .open = acpi_battery_state_open_fs, 594 .read = seq_read, 595 .llseek = seq_lseek, 596 .release = single_release, 597 .owner = THIS_MODULE, 598 }; 599 600 static struct file_operations acpi_battery_alarm_ops = { 601 .open = acpi_battery_alarm_open_fs, 602 .read = seq_read, 603 .write = acpi_battery_write_alarm, 604 .llseek = seq_lseek, 605 .release = single_release, 606 .owner = THIS_MODULE, 607 }; 608 609 static int 610 acpi_battery_add_fs ( 611 struct acpi_device *device) 612 { 613 struct proc_dir_entry *entry = NULL; 614 615 ACPI_FUNCTION_TRACE("acpi_battery_add_fs"); 616 617 if (!acpi_device_dir(device)) { 618 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), 619 acpi_battery_dir); 620 if (!acpi_device_dir(device)) 621 return_VALUE(-ENODEV); 622 acpi_device_dir(device)->owner = THIS_MODULE; 623 } 624 625 /* 'info' [R] */ 626 entry = create_proc_entry(ACPI_BATTERY_FILE_INFO, 627 S_IRUGO, acpi_device_dir(device)); 628 if (!entry) 629 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 630 "Unable to create '%s' fs entry\n", 631 ACPI_BATTERY_FILE_INFO)); 632 else { 633 entry->proc_fops = &acpi_battery_info_ops; 634 entry->data = acpi_driver_data(device); 635 entry->owner = THIS_MODULE; 636 } 637 638 /* 'status' [R] */ 639 entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS, 640 S_IRUGO, acpi_device_dir(device)); 641 if (!entry) 642 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 643 "Unable to create '%s' fs entry\n", 644 ACPI_BATTERY_FILE_STATUS)); 645 else { 646 entry->proc_fops = &acpi_battery_state_ops; 647 entry->data = acpi_driver_data(device); 648 entry->owner = THIS_MODULE; 649 } 650 651 /* 'alarm' [R/W] */ 652 entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM, 653 S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device)); 654 if (!entry) 655 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 656 "Unable to create '%s' fs entry\n", 657 ACPI_BATTERY_FILE_ALARM)); 658 else { 659 entry->proc_fops = &acpi_battery_alarm_ops; 660 entry->data = acpi_driver_data(device); 661 entry->owner = THIS_MODULE; 662 } 663 664 return_VALUE(0); 665 } 666 667 668 static int 669 acpi_battery_remove_fs ( 670 struct acpi_device *device) 671 { 672 ACPI_FUNCTION_TRACE("acpi_battery_remove_fs"); 673 674 if (acpi_device_dir(device)) { 675 remove_proc_entry(ACPI_BATTERY_FILE_ALARM, 676 acpi_device_dir(device)); 677 remove_proc_entry(ACPI_BATTERY_FILE_STATUS, 678 acpi_device_dir(device)); 679 remove_proc_entry(ACPI_BATTERY_FILE_INFO, 680 acpi_device_dir(device)); 681 682 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); 683 acpi_device_dir(device) = NULL; 684 } 685 686 return_VALUE(0); 687 } 688 689 690 /* -------------------------------------------------------------------------- 691 Driver Interface 692 -------------------------------------------------------------------------- */ 693 694 static void 695 acpi_battery_notify ( 696 acpi_handle handle, 697 u32 event, 698 void *data) 699 { 700 struct acpi_battery *battery = (struct acpi_battery *) data; 701 struct acpi_device *device = NULL; 702 703 ACPI_FUNCTION_TRACE("acpi_battery_notify"); 704 705 if (!battery) 706 return_VOID; 707 708 if (acpi_bus_get_device(handle, &device)) 709 return_VOID; 710 711 switch (event) { 712 case ACPI_BATTERY_NOTIFY_STATUS: 713 case ACPI_BATTERY_NOTIFY_INFO: 714 acpi_battery_check(battery); 715 acpi_bus_generate_event(device, event, battery->flags.present); 716 break; 717 default: 718 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 719 "Unsupported event [0x%x]\n", event)); 720 break; 721 } 722 723 return_VOID; 724 } 725 726 727 static int 728 acpi_battery_add ( 729 struct acpi_device *device) 730 { 731 int result = 0; 732 acpi_status status = 0; 733 struct acpi_battery *battery = NULL; 734 735 ACPI_FUNCTION_TRACE("acpi_battery_add"); 736 737 if (!device) 738 return_VALUE(-EINVAL); 739 740 battery = kmalloc(sizeof(struct acpi_battery), GFP_KERNEL); 741 if (!battery) 742 return_VALUE(-ENOMEM); 743 memset(battery, 0, sizeof(struct acpi_battery)); 744 745 battery->handle = device->handle; 746 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); 747 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); 748 acpi_driver_data(device) = battery; 749 750 result = acpi_battery_check(battery); 751 if (result) 752 goto end; 753 754 result = acpi_battery_add_fs(device); 755 if (result) 756 goto end; 757 758 status = acpi_install_notify_handler(battery->handle, 759 ACPI_DEVICE_NOTIFY, acpi_battery_notify, battery); 760 if (ACPI_FAILURE(status)) { 761 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 762 "Error installing notify handler\n")); 763 result = -ENODEV; 764 goto end; 765 } 766 767 printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", 768 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), 769 device->status.battery_present?"present":"absent"); 770 771 end: 772 if (result) { 773 acpi_battery_remove_fs(device); 774 kfree(battery); 775 } 776 777 return_VALUE(result); 778 } 779 780 781 static int 782 acpi_battery_remove ( 783 struct acpi_device *device, 784 int type) 785 { 786 acpi_status status = 0; 787 struct acpi_battery *battery = NULL; 788 789 ACPI_FUNCTION_TRACE("acpi_battery_remove"); 790 791 if (!device || !acpi_driver_data(device)) 792 return_VALUE(-EINVAL); 793 794 battery = (struct acpi_battery *) acpi_driver_data(device); 795 796 status = acpi_remove_notify_handler(battery->handle, 797 ACPI_DEVICE_NOTIFY, acpi_battery_notify); 798 if (ACPI_FAILURE(status)) 799 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 800 "Error removing notify handler\n")); 801 802 acpi_battery_remove_fs(device); 803 804 kfree(battery); 805 806 return_VALUE(0); 807 } 808 809 810 static int __init 811 acpi_battery_init (void) 812 { 813 int result = 0; 814 815 ACPI_FUNCTION_TRACE("acpi_battery_init"); 816 817 acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir); 818 if (!acpi_battery_dir) 819 return_VALUE(-ENODEV); 820 acpi_battery_dir->owner = THIS_MODULE; 821 822 result = acpi_bus_register_driver(&acpi_battery_driver); 823 if (result < 0) { 824 remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); 825 return_VALUE(-ENODEV); 826 } 827 828 return_VALUE(0); 829 } 830 831 832 static void __exit 833 acpi_battery_exit (void) 834 { 835 ACPI_FUNCTION_TRACE("acpi_battery_exit"); 836 837 acpi_bus_unregister_driver(&acpi_battery_driver); 838 839 remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir); 840 841 return_VOID; 842 } 843 844 845 module_init(acpi_battery_init); 846 module_exit(acpi_battery_exit); 847