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