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