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