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