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