1 /* 2 * battery.c - ACPI Battery Driver (Revision: 2.0) 3 * 4 * Copyright (C) 2007 Alexey Starikovskiy <astarikovskiy@suse.de> 5 * Copyright (C) 2004-2007 Vladimir Lebedev <vladimir.p.lebedev@intel.com> 6 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 7 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 8 * 9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or (at 14 * your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, but 17 * WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License along 22 * with this program; if not, write to the Free Software Foundation, Inc., 23 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 24 * 25 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 26 */ 27 28 #include <linux/kernel.h> 29 #include <linux/module.h> 30 #include <linux/init.h> 31 #include <linux/types.h> 32 #include <linux/jiffies.h> 33 34 #ifdef CONFIG_ACPI_PROCFS 35 #include <linux/proc_fs.h> 36 #include <linux/seq_file.h> 37 #include <asm/uaccess.h> 38 #endif 39 40 #include <acpi/acpi_bus.h> 41 #include <acpi/acpi_drivers.h> 42 43 #include <linux/power_supply.h> 44 45 #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF 46 47 #define ACPI_BATTERY_COMPONENT 0x00040000 48 #define ACPI_BATTERY_CLASS "battery" 49 #define ACPI_BATTERY_DEVICE_NAME "Battery" 50 #define ACPI_BATTERY_NOTIFY_STATUS 0x80 51 #define ACPI_BATTERY_NOTIFY_INFO 0x81 52 53 #define _COMPONENT ACPI_BATTERY_COMPONENT 54 55 ACPI_MODULE_NAME("battery"); 56 57 MODULE_AUTHOR("Paul Diefenbaugh"); 58 MODULE_AUTHOR("Alexey Starikovskiy <astarikovskiy@suse.de>"); 59 MODULE_DESCRIPTION("ACPI Battery Driver"); 60 MODULE_LICENSE("GPL"); 61 62 static unsigned int cache_time = 1000; 63 module_param(cache_time, uint, 0644); 64 MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); 65 66 #ifdef CONFIG_ACPI_PROCFS 67 extern struct proc_dir_entry *acpi_lock_battery_dir(void); 68 extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); 69 70 enum acpi_battery_files { 71 info_tag = 0, 72 state_tag, 73 alarm_tag, 74 ACPI_BATTERY_NUMFILES, 75 }; 76 77 #endif 78 79 static const struct acpi_device_id battery_device_ids[] = { 80 {"PNP0C0A", 0}, 81 {"", 0}, 82 }; 83 84 MODULE_DEVICE_TABLE(acpi, battery_device_ids); 85 86 87 struct acpi_battery { 88 struct mutex lock; 89 struct power_supply bat; 90 struct acpi_device *device; 91 unsigned long update_time; 92 int current_now; 93 int capacity_now; 94 int voltage_now; 95 int design_capacity; 96 int full_charge_capacity; 97 int technology; 98 int design_voltage; 99 int design_capacity_warning; 100 int design_capacity_low; 101 int capacity_granularity_1; 102 int capacity_granularity_2; 103 int alarm; 104 char model_number[32]; 105 char serial_number[32]; 106 char type[32]; 107 char oem_info[32]; 108 int state; 109 int power_unit; 110 u8 alarm_present; 111 }; 112 113 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); 114 115 inline int acpi_battery_present(struct acpi_battery *battery) 116 { 117 return battery->device->status.battery_present; 118 } 119 120 static int acpi_battery_technology(struct acpi_battery *battery) 121 { 122 if (!strcasecmp("NiCd", battery->type)) 123 return POWER_SUPPLY_TECHNOLOGY_NiCd; 124 if (!strcasecmp("NiMH", battery->type)) 125 return POWER_SUPPLY_TECHNOLOGY_NiMH; 126 if (!strcasecmp("LION", battery->type)) 127 return POWER_SUPPLY_TECHNOLOGY_LION; 128 if (!strcasecmp("LI-ION", battery->type)) 129 return POWER_SUPPLY_TECHNOLOGY_LION; 130 if (!strcasecmp("LiP", battery->type)) 131 return POWER_SUPPLY_TECHNOLOGY_LIPO; 132 return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; 133 } 134 135 static int acpi_battery_update(struct acpi_battery *battery); 136 137 static int acpi_battery_get_property(struct power_supply *psy, 138 enum power_supply_property psp, 139 union power_supply_propval *val) 140 { 141 struct acpi_battery *battery = to_acpi_battery(psy); 142 143 if ((!acpi_battery_present(battery)) && 144 psp != POWER_SUPPLY_PROP_PRESENT) 145 return -ENODEV; 146 acpi_battery_update(battery); 147 switch (psp) { 148 case POWER_SUPPLY_PROP_STATUS: 149 if (battery->state & 0x01) 150 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; 151 else if (battery->state & 0x02) 152 val->intval = POWER_SUPPLY_STATUS_CHARGING; 153 else if (battery->state == 0) 154 val->intval = POWER_SUPPLY_STATUS_FULL; 155 break; 156 case POWER_SUPPLY_PROP_PRESENT: 157 val->intval = acpi_battery_present(battery); 158 break; 159 case POWER_SUPPLY_PROP_TECHNOLOGY: 160 val->intval = acpi_battery_technology(battery); 161 break; 162 case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: 163 val->intval = battery->design_voltage * 1000; 164 break; 165 case POWER_SUPPLY_PROP_VOLTAGE_NOW: 166 val->intval = battery->voltage_now * 1000; 167 break; 168 case POWER_SUPPLY_PROP_CURRENT_NOW: 169 val->intval = battery->current_now * 1000; 170 break; 171 case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: 172 case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: 173 val->intval = battery->design_capacity * 1000; 174 break; 175 case POWER_SUPPLY_PROP_CHARGE_FULL: 176 case POWER_SUPPLY_PROP_ENERGY_FULL: 177 val->intval = battery->full_charge_capacity * 1000; 178 break; 179 case POWER_SUPPLY_PROP_CHARGE_NOW: 180 case POWER_SUPPLY_PROP_ENERGY_NOW: 181 val->intval = battery->capacity_now * 1000; 182 break; 183 case POWER_SUPPLY_PROP_MODEL_NAME: 184 val->strval = battery->model_number; 185 break; 186 case POWER_SUPPLY_PROP_MANUFACTURER: 187 val->strval = battery->oem_info; 188 break; 189 default: 190 return -EINVAL; 191 } 192 return 0; 193 } 194 195 static enum power_supply_property charge_battery_props[] = { 196 POWER_SUPPLY_PROP_STATUS, 197 POWER_SUPPLY_PROP_PRESENT, 198 POWER_SUPPLY_PROP_TECHNOLOGY, 199 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 200 POWER_SUPPLY_PROP_VOLTAGE_NOW, 201 POWER_SUPPLY_PROP_CURRENT_NOW, 202 POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 203 POWER_SUPPLY_PROP_CHARGE_FULL, 204 POWER_SUPPLY_PROP_CHARGE_NOW, 205 POWER_SUPPLY_PROP_MODEL_NAME, 206 POWER_SUPPLY_PROP_MANUFACTURER, 207 }; 208 209 static enum power_supply_property energy_battery_props[] = { 210 POWER_SUPPLY_PROP_STATUS, 211 POWER_SUPPLY_PROP_PRESENT, 212 POWER_SUPPLY_PROP_TECHNOLOGY, 213 POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, 214 POWER_SUPPLY_PROP_VOLTAGE_NOW, 215 POWER_SUPPLY_PROP_CURRENT_NOW, 216 POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 217 POWER_SUPPLY_PROP_ENERGY_FULL, 218 POWER_SUPPLY_PROP_ENERGY_NOW, 219 POWER_SUPPLY_PROP_MODEL_NAME, 220 POWER_SUPPLY_PROP_MANUFACTURER, 221 }; 222 223 #ifdef CONFIG_ACPI_PROCFS 224 inline char *acpi_battery_units(struct acpi_battery *battery) 225 { 226 return (battery->power_unit)?"mA":"mW"; 227 } 228 #endif 229 230 /* -------------------------------------------------------------------------- 231 Battery Management 232 -------------------------------------------------------------------------- */ 233 struct acpi_offsets { 234 size_t offset; /* offset inside struct acpi_sbs_battery */ 235 u8 mode; /* int or string? */ 236 }; 237 238 static struct acpi_offsets state_offsets[] = { 239 {offsetof(struct acpi_battery, state), 0}, 240 {offsetof(struct acpi_battery, current_now), 0}, 241 {offsetof(struct acpi_battery, capacity_now), 0}, 242 {offsetof(struct acpi_battery, voltage_now), 0}, 243 }; 244 245 static struct acpi_offsets info_offsets[] = { 246 {offsetof(struct acpi_battery, power_unit), 0}, 247 {offsetof(struct acpi_battery, design_capacity), 0}, 248 {offsetof(struct acpi_battery, full_charge_capacity), 0}, 249 {offsetof(struct acpi_battery, technology), 0}, 250 {offsetof(struct acpi_battery, design_voltage), 0}, 251 {offsetof(struct acpi_battery, design_capacity_warning), 0}, 252 {offsetof(struct acpi_battery, design_capacity_low), 0}, 253 {offsetof(struct acpi_battery, capacity_granularity_1), 0}, 254 {offsetof(struct acpi_battery, capacity_granularity_2), 0}, 255 {offsetof(struct acpi_battery, model_number), 1}, 256 {offsetof(struct acpi_battery, serial_number), 1}, 257 {offsetof(struct acpi_battery, type), 1}, 258 {offsetof(struct acpi_battery, oem_info), 1}, 259 }; 260 261 static int extract_package(struct acpi_battery *battery, 262 union acpi_object *package, 263 struct acpi_offsets *offsets, int num) 264 { 265 int i; 266 union acpi_object *element; 267 if (package->type != ACPI_TYPE_PACKAGE) 268 return -EFAULT; 269 for (i = 0; i < num; ++i) { 270 if (package->package.count <= i) 271 return -EFAULT; 272 element = &package->package.elements[i]; 273 if (offsets[i].mode) { 274 u8 *ptr = (u8 *)battery + offsets[i].offset; 275 if (element->type == ACPI_TYPE_STRING || 276 element->type == ACPI_TYPE_BUFFER) 277 strncpy(ptr, element->string.pointer, 32); 278 else if (element->type == ACPI_TYPE_INTEGER) { 279 strncpy(ptr, (u8 *)&element->integer.value, 280 sizeof(acpi_integer)); 281 ptr[sizeof(acpi_integer)] = 0; 282 } else return -EFAULT; 283 } else { 284 if (element->type == ACPI_TYPE_INTEGER) { 285 int *x = (int *)((u8 *)battery + 286 offsets[i].offset); 287 *x = element->integer.value; 288 } else return -EFAULT; 289 } 290 } 291 return 0; 292 } 293 294 static int acpi_battery_get_status(struct acpi_battery *battery) 295 { 296 if (acpi_bus_get_status(battery->device)) { 297 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA")); 298 return -ENODEV; 299 } 300 return 0; 301 } 302 303 static int acpi_battery_get_info(struct acpi_battery *battery) 304 { 305 int result = -EFAULT; 306 acpi_status status = 0; 307 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 308 309 if (!acpi_battery_present(battery)) 310 return 0; 311 mutex_lock(&battery->lock); 312 status = acpi_evaluate_object(battery->device->handle, "_BIF", 313 NULL, &buffer); 314 mutex_unlock(&battery->lock); 315 316 if (ACPI_FAILURE(status)) { 317 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); 318 return -ENODEV; 319 } 320 321 result = extract_package(battery, buffer.pointer, 322 info_offsets, ARRAY_SIZE(info_offsets)); 323 kfree(buffer.pointer); 324 return result; 325 } 326 327 static int acpi_battery_get_state(struct acpi_battery *battery) 328 { 329 int result = 0; 330 acpi_status status = 0; 331 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 332 333 if (!acpi_battery_present(battery)) 334 return 0; 335 336 if (battery->update_time && 337 time_before(jiffies, battery->update_time + 338 msecs_to_jiffies(cache_time))) 339 return 0; 340 341 mutex_lock(&battery->lock); 342 status = acpi_evaluate_object(battery->device->handle, "_BST", 343 NULL, &buffer); 344 mutex_unlock(&battery->lock); 345 346 if (ACPI_FAILURE(status)) { 347 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); 348 return -ENODEV; 349 } 350 351 result = extract_package(battery, buffer.pointer, 352 state_offsets, ARRAY_SIZE(state_offsets)); 353 battery->update_time = jiffies; 354 kfree(buffer.pointer); 355 return result; 356 } 357 358 static int acpi_battery_set_alarm(struct acpi_battery *battery) 359 { 360 acpi_status status = 0; 361 union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER }; 362 struct acpi_object_list arg_list = { 1, &arg0 }; 363 364 if (!acpi_battery_present(battery)|| !battery->alarm_present) 365 return -ENODEV; 366 367 arg0.integer.value = battery->alarm; 368 369 mutex_lock(&battery->lock); 370 status = acpi_evaluate_object(battery->device->handle, "_BTP", 371 &arg_list, NULL); 372 mutex_unlock(&battery->lock); 373 374 if (ACPI_FAILURE(status)) 375 return -ENODEV; 376 377 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm)); 378 return 0; 379 } 380 381 static int acpi_battery_init_alarm(struct acpi_battery *battery) 382 { 383 acpi_status status = AE_OK; 384 acpi_handle handle = NULL; 385 386 /* See if alarms are supported, and if so, set default */ 387 status = acpi_get_handle(battery->device->handle, "_BTP", &handle); 388 if (ACPI_FAILURE(status)) { 389 battery->alarm_present = 0; 390 return 0; 391 } 392 battery->alarm_present = 1; 393 if (!battery->alarm) 394 battery->alarm = battery->design_capacity_warning; 395 return acpi_battery_set_alarm(battery); 396 } 397 398 static ssize_t acpi_battery_alarm_show(struct device *dev, 399 struct device_attribute *attr, 400 char *buf) 401 { 402 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); 403 return sprintf(buf, "%d\n", battery->alarm * 1000); 404 } 405 406 static ssize_t acpi_battery_alarm_store(struct device *dev, 407 struct device_attribute *attr, 408 const char *buf, size_t count) 409 { 410 unsigned long x; 411 struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); 412 if (sscanf(buf, "%ld\n", &x) == 1) 413 battery->alarm = x/1000; 414 if (acpi_battery_present(battery)) 415 acpi_battery_set_alarm(battery); 416 return count; 417 } 418 419 static struct device_attribute alarm_attr = { 420 .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE}, 421 .show = acpi_battery_alarm_show, 422 .store = acpi_battery_alarm_store, 423 }; 424 425 static int sysfs_add_battery(struct acpi_battery *battery) 426 { 427 int result; 428 429 battery->update_time = 0; 430 result = acpi_battery_get_info(battery); 431 acpi_battery_init_alarm(battery); 432 if (result) 433 return result; 434 if (battery->power_unit) { 435 battery->bat.properties = charge_battery_props; 436 battery->bat.num_properties = 437 ARRAY_SIZE(charge_battery_props); 438 } else { 439 battery->bat.properties = energy_battery_props; 440 battery->bat.num_properties = 441 ARRAY_SIZE(energy_battery_props); 442 } 443 444 battery->bat.name = acpi_device_bid(battery->device); 445 battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; 446 battery->bat.get_property = acpi_battery_get_property; 447 448 result = power_supply_register(&battery->device->dev, &battery->bat); 449 if (result) 450 return result; 451 return device_create_file(battery->bat.dev, &alarm_attr); 452 } 453 454 static void sysfs_remove_battery(struct acpi_battery *battery) 455 { 456 if (!battery->bat.dev) 457 return; 458 device_remove_file(battery->bat.dev, &alarm_attr); 459 power_supply_unregister(&battery->bat); 460 } 461 462 static int acpi_battery_update(struct acpi_battery *battery) 463 { 464 int result = acpi_battery_get_status(battery); 465 if (result) 466 return result; 467 if (!acpi_battery_present(battery)) { 468 sysfs_remove_battery(battery); 469 return 0; 470 } 471 if (!battery->bat.dev) 472 sysfs_add_battery(battery); 473 return acpi_battery_get_state(battery); 474 } 475 476 /* -------------------------------------------------------------------------- 477 FS Interface (/proc) 478 -------------------------------------------------------------------------- */ 479 480 #ifdef CONFIG_ACPI_PROCFS 481 static struct proc_dir_entry *acpi_battery_dir; 482 483 static int acpi_battery_print_info(struct seq_file *seq, int result) 484 { 485 struct acpi_battery *battery = seq->private; 486 487 if (result) 488 goto end; 489 490 seq_printf(seq, "present: %s\n", 491 acpi_battery_present(battery)?"yes":"no"); 492 if (!acpi_battery_present(battery)) 493 goto end; 494 if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) 495 seq_printf(seq, "design capacity: unknown\n"); 496 else 497 seq_printf(seq, "design capacity: %d %sh\n", 498 battery->design_capacity, 499 acpi_battery_units(battery)); 500 501 if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN) 502 seq_printf(seq, "last full capacity: unknown\n"); 503 else 504 seq_printf(seq, "last full capacity: %d %sh\n", 505 battery->full_charge_capacity, 506 acpi_battery_units(battery)); 507 508 seq_printf(seq, "battery technology: %srechargeable\n", 509 (!battery->technology)?"non-":""); 510 511 if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) 512 seq_printf(seq, "design voltage: unknown\n"); 513 else 514 seq_printf(seq, "design voltage: %d mV\n", 515 battery->design_voltage); 516 seq_printf(seq, "design capacity warning: %d %sh\n", 517 battery->design_capacity_warning, 518 acpi_battery_units(battery)); 519 seq_printf(seq, "design capacity low: %d %sh\n", 520 battery->design_capacity_low, 521 acpi_battery_units(battery)); 522 seq_printf(seq, "capacity granularity 1: %d %sh\n", 523 battery->capacity_granularity_1, 524 acpi_battery_units(battery)); 525 seq_printf(seq, "capacity granularity 2: %d %sh\n", 526 battery->capacity_granularity_2, 527 acpi_battery_units(battery)); 528 seq_printf(seq, "model number: %s\n", battery->model_number); 529 seq_printf(seq, "serial number: %s\n", battery->serial_number); 530 seq_printf(seq, "battery type: %s\n", battery->type); 531 seq_printf(seq, "OEM info: %s\n", battery->oem_info); 532 end: 533 if (result) 534 seq_printf(seq, "ERROR: Unable to read battery info\n"); 535 return result; 536 } 537 538 static int acpi_battery_print_state(struct seq_file *seq, int result) 539 { 540 struct acpi_battery *battery = seq->private; 541 542 if (result) 543 goto end; 544 545 seq_printf(seq, "present: %s\n", 546 acpi_battery_present(battery)?"yes":"no"); 547 if (!acpi_battery_present(battery)) 548 goto end; 549 550 seq_printf(seq, "capacity state: %s\n", 551 (battery->state & 0x04)?"critical":"ok"); 552 if ((battery->state & 0x01) && (battery->state & 0x02)) 553 seq_printf(seq, 554 "charging state: charging/discharging\n"); 555 else if (battery->state & 0x01) 556 seq_printf(seq, "charging state: discharging\n"); 557 else if (battery->state & 0x02) 558 seq_printf(seq, "charging state: charging\n"); 559 else 560 seq_printf(seq, "charging state: charged\n"); 561 562 if (battery->current_now == ACPI_BATTERY_VALUE_UNKNOWN) 563 seq_printf(seq, "present rate: unknown\n"); 564 else 565 seq_printf(seq, "present rate: %d %s\n", 566 battery->current_now, acpi_battery_units(battery)); 567 568 if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN) 569 seq_printf(seq, "remaining capacity: unknown\n"); 570 else 571 seq_printf(seq, "remaining capacity: %d %sh\n", 572 battery->capacity_now, acpi_battery_units(battery)); 573 if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN) 574 seq_printf(seq, "present voltage: unknown\n"); 575 else 576 seq_printf(seq, "present voltage: %d mV\n", 577 battery->voltage_now); 578 end: 579 if (result) 580 seq_printf(seq, "ERROR: Unable to read battery state\n"); 581 582 return result; 583 } 584 585 static int acpi_battery_print_alarm(struct seq_file *seq, int result) 586 { 587 struct acpi_battery *battery = seq->private; 588 589 if (result) 590 goto end; 591 592 if (!acpi_battery_present(battery)) { 593 seq_printf(seq, "present: no\n"); 594 goto end; 595 } 596 seq_printf(seq, "alarm: "); 597 if (!battery->alarm) 598 seq_printf(seq, "unsupported\n"); 599 else 600 seq_printf(seq, "%u %sh\n", battery->alarm, 601 acpi_battery_units(battery)); 602 end: 603 if (result) 604 seq_printf(seq, "ERROR: Unable to read battery alarm\n"); 605 return result; 606 } 607 608 static ssize_t acpi_battery_write_alarm(struct file *file, 609 const char __user * buffer, 610 size_t count, loff_t * ppos) 611 { 612 int result = 0; 613 char alarm_string[12] = { '\0' }; 614 struct seq_file *m = file->private_data; 615 struct acpi_battery *battery = m->private; 616 617 if (!battery || (count > sizeof(alarm_string) - 1)) 618 return -EINVAL; 619 if (!acpi_battery_present(battery)) { 620 result = -ENODEV; 621 goto end; 622 } 623 if (copy_from_user(alarm_string, buffer, count)) { 624 result = -EFAULT; 625 goto end; 626 } 627 alarm_string[count] = '\0'; 628 battery->alarm = simple_strtol(alarm_string, NULL, 0); 629 result = acpi_battery_set_alarm(battery); 630 end: 631 if (!result) 632 return count; 633 return result; 634 } 635 636 typedef int(*print_func)(struct seq_file *seq, int result); 637 638 static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = { 639 acpi_battery_print_info, 640 acpi_battery_print_state, 641 acpi_battery_print_alarm, 642 }; 643 644 static int acpi_battery_read(int fid, struct seq_file *seq) 645 { 646 struct acpi_battery *battery = seq->private; 647 int result = acpi_battery_update(battery); 648 return acpi_print_funcs[fid](seq, result); 649 } 650 651 #define DECLARE_FILE_FUNCTIONS(_name) \ 652 static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \ 653 { \ 654 return acpi_battery_read(_name##_tag, seq); \ 655 } \ 656 static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \ 657 { \ 658 return single_open(file, acpi_battery_read_##_name, PDE(inode)->data); \ 659 } 660 661 DECLARE_FILE_FUNCTIONS(info); 662 DECLARE_FILE_FUNCTIONS(state); 663 DECLARE_FILE_FUNCTIONS(alarm); 664 665 #undef DECLARE_FILE_FUNCTIONS 666 667 #define FILE_DESCRIPTION_RO(_name) \ 668 { \ 669 .name = __stringify(_name), \ 670 .mode = S_IRUGO, \ 671 .ops = { \ 672 .open = acpi_battery_##_name##_open_fs, \ 673 .read = seq_read, \ 674 .llseek = seq_lseek, \ 675 .release = single_release, \ 676 .owner = THIS_MODULE, \ 677 }, \ 678 } 679 680 #define FILE_DESCRIPTION_RW(_name) \ 681 { \ 682 .name = __stringify(_name), \ 683 .mode = S_IFREG | S_IRUGO | S_IWUSR, \ 684 .ops = { \ 685 .open = acpi_battery_##_name##_open_fs, \ 686 .read = seq_read, \ 687 .llseek = seq_lseek, \ 688 .write = acpi_battery_write_##_name, \ 689 .release = single_release, \ 690 .owner = THIS_MODULE, \ 691 }, \ 692 } 693 694 static struct battery_file { 695 struct file_operations ops; 696 mode_t mode; 697 char *name; 698 } acpi_battery_file[] = { 699 FILE_DESCRIPTION_RO(info), 700 FILE_DESCRIPTION_RO(state), 701 FILE_DESCRIPTION_RW(alarm), 702 }; 703 704 #undef FILE_DESCRIPTION_RO 705 #undef FILE_DESCRIPTION_RW 706 707 static int acpi_battery_add_fs(struct acpi_device *device) 708 { 709 struct proc_dir_entry *entry = NULL; 710 int i; 711 712 if (!acpi_device_dir(device)) { 713 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), 714 acpi_battery_dir); 715 if (!acpi_device_dir(device)) 716 return -ENODEV; 717 acpi_device_dir(device)->owner = THIS_MODULE; 718 } 719 720 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { 721 entry = create_proc_entry(acpi_battery_file[i].name, 722 acpi_battery_file[i].mode, acpi_device_dir(device)); 723 if (!entry) 724 return -ENODEV; 725 else { 726 entry->proc_fops = &acpi_battery_file[i].ops; 727 entry->data = acpi_driver_data(device); 728 entry->owner = THIS_MODULE; 729 } 730 } 731 return 0; 732 } 733 734 static void acpi_battery_remove_fs(struct acpi_device *device) 735 { 736 int i; 737 if (!acpi_device_dir(device)) 738 return; 739 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) 740 remove_proc_entry(acpi_battery_file[i].name, 741 acpi_device_dir(device)); 742 743 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); 744 acpi_device_dir(device) = NULL; 745 } 746 747 #endif 748 749 /* -------------------------------------------------------------------------- 750 Driver Interface 751 -------------------------------------------------------------------------- */ 752 753 static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) 754 { 755 struct acpi_battery *battery = data; 756 struct acpi_device *device; 757 if (!battery) 758 return; 759 device = battery->device; 760 acpi_battery_update(battery); 761 acpi_bus_generate_proc_event(device, event, 762 acpi_battery_present(battery)); 763 acpi_bus_generate_netlink_event(device->pnp.device_class, 764 device->dev.bus_id, event, 765 acpi_battery_present(battery)); 766 /* acpi_batter_update could remove power_supply object */ 767 if (battery->bat.dev) 768 kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); 769 } 770 771 static int acpi_battery_add(struct acpi_device *device) 772 { 773 int result = 0; 774 acpi_status status = 0; 775 struct acpi_battery *battery = NULL; 776 if (!device) 777 return -EINVAL; 778 battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL); 779 if (!battery) 780 return -ENOMEM; 781 battery->device = device; 782 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); 783 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); 784 acpi_driver_data(device) = battery; 785 mutex_init(&battery->lock); 786 acpi_battery_update(battery); 787 #ifdef CONFIG_ACPI_PROCFS 788 result = acpi_battery_add_fs(device); 789 if (result) 790 goto end; 791 #endif 792 status = acpi_install_notify_handler(device->handle, 793 ACPI_ALL_NOTIFY, 794 acpi_battery_notify, battery); 795 if (ACPI_FAILURE(status)) { 796 ACPI_EXCEPTION((AE_INFO, status, "Installing notify handler")); 797 result = -ENODEV; 798 goto end; 799 } 800 printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", 801 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), 802 device->status.battery_present ? "present" : "absent"); 803 end: 804 if (result) { 805 #ifdef CONFIG_ACPI_PROCFS 806 acpi_battery_remove_fs(device); 807 #endif 808 kfree(battery); 809 } 810 return result; 811 } 812 813 static int acpi_battery_remove(struct acpi_device *device, int type) 814 { 815 acpi_status status = 0; 816 struct acpi_battery *battery = NULL; 817 818 if (!device || !acpi_driver_data(device)) 819 return -EINVAL; 820 battery = acpi_driver_data(device); 821 status = acpi_remove_notify_handler(device->handle, 822 ACPI_ALL_NOTIFY, 823 acpi_battery_notify); 824 #ifdef CONFIG_ACPI_PROCFS 825 acpi_battery_remove_fs(device); 826 #endif 827 sysfs_remove_battery(battery); 828 mutex_destroy(&battery->lock); 829 kfree(battery); 830 return 0; 831 } 832 833 /* this is needed to learn about changes made in suspended state */ 834 static int acpi_battery_resume(struct acpi_device *device) 835 { 836 struct acpi_battery *battery; 837 if (!device) 838 return -EINVAL; 839 battery = acpi_driver_data(device); 840 battery->update_time = 0; 841 acpi_battery_update(battery); 842 return 0; 843 } 844 845 static struct acpi_driver acpi_battery_driver = { 846 .name = "battery", 847 .class = ACPI_BATTERY_CLASS, 848 .ids = battery_device_ids, 849 .ops = { 850 .add = acpi_battery_add, 851 .resume = acpi_battery_resume, 852 .remove = acpi_battery_remove, 853 }, 854 }; 855 856 static int __init acpi_battery_init(void) 857 { 858 if (acpi_disabled) 859 return -ENODEV; 860 #ifdef CONFIG_ACPI_PROCFS 861 acpi_battery_dir = acpi_lock_battery_dir(); 862 if (!acpi_battery_dir) 863 return -ENODEV; 864 #endif 865 if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { 866 #ifdef CONFIG_ACPI_PROCFS 867 acpi_unlock_battery_dir(acpi_battery_dir); 868 #endif 869 return -ENODEV; 870 } 871 return 0; 872 } 873 874 static void __exit acpi_battery_exit(void) 875 { 876 acpi_bus_unregister_driver(&acpi_battery_driver); 877 #ifdef CONFIG_ACPI_PROCFS 878 acpi_unlock_battery_dir(acpi_battery_dir); 879 #endif 880 } 881 882 module_init(acpi_battery_init); 883 module_exit(acpi_battery_exit); 884