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