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