OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [acpi/] [battery.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.