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