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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [acpi/] [battery.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  acpi_battery.c - ACPI Battery Driver ($Revision: 1.1.1.1 $)
3
 *
4
 *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5
 *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6
 *
7
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or (at
12
 *  your option) any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful, but
15
 *  WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 *  General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License along
20
 *  with this program; if not, write to the Free Software Foundation, Inc.,
21
 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22
 *
23
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24
 */
25
 
26
#include <linux/kernel.h>
27
#include <linux/module.h>
28
#include <linux/init.h>
29
#include <linux/types.h>
30
#include <linux/compatmac.h>
31
#include <linux/proc_fs.h>
32
#include <acpi/acpi_bus.h>
33
#include <acpi/acpi_drivers.h>
34
 
35
 
36
#define _COMPONENT              ACPI_BATTERY_COMPONENT
37
ACPI_MODULE_NAME                ("acpi_battery")
38
 
39
MODULE_AUTHOR("Paul Diefenbaugh");
40
MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
41
MODULE_LICENSE("GPL");
42
 
43
#define PREFIX                  "ACPI: "
44
 
45
 
46
#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
47
 
48
#define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS"
49
#define ACPI_BATTERY_FORMAT_BST "NNNN"
50
 
51
static int acpi_battery_add (struct acpi_device *device);
52
static int acpi_battery_remove (struct acpi_device *device, int type);
53
 
54
static struct acpi_driver acpi_battery_driver = {
55
        .name =         ACPI_BATTERY_DRIVER_NAME,
56
        .class =        ACPI_BATTERY_CLASS,
57
        .ids =          ACPI_BATTERY_HID,
58
        .ops =          {
59
                                .add =          acpi_battery_add,
60
                                .remove =       acpi_battery_remove,
61
                        },
62
};
63
 
64
struct acpi_battery_status {
65
        acpi_integer            state;
66
        acpi_integer            present_rate;
67
        acpi_integer            remaining_capacity;
68
        acpi_integer            present_voltage;
69
};
70
 
71
struct acpi_battery_info {
72
        acpi_integer            power_unit;
73
        acpi_integer            design_capacity;
74
        acpi_integer            last_full_capacity;
75
        acpi_integer            battery_technology;
76
        acpi_integer            design_voltage;
77
        acpi_integer            design_capacity_warning;
78
        acpi_integer            design_capacity_low;
79
        acpi_integer            battery_capacity_granularity_1;
80
        acpi_integer            battery_capacity_granularity_2;
81
        acpi_string             model_number;
82
        acpi_string             serial_number;
83
        acpi_string             battery_type;
84
        acpi_string             oem_info;
85
};
86
 
87
struct acpi_battery_flags {
88
        u8                      present:1;      /* Bay occupied? */
89
        u8                      power_unit:1;   /* 0=watts, 1=apms */
90
        u8                      alarm:1;        /* _BTP present? */
91
        u8                      reserved:5;
92
};
93
 
94
struct acpi_battery_trips {
95
        unsigned long           warning;
96
        unsigned long           low;
97
};
98
 
99
struct acpi_battery {
100
        acpi_handle             handle;
101
        struct acpi_battery_flags flags;
102
        struct acpi_battery_trips trips;
103
        unsigned long           alarm;
104
        struct acpi_battery_info *info;
105
};
106
 
107
 
108
/* --------------------------------------------------------------------------
109
                               Battery Management
110
   -------------------------------------------------------------------------- */
111
 
112
static int
113
acpi_battery_get_info (
114
        struct acpi_battery     *battery,
115
        struct acpi_battery_info **bif)
116
{
117
        int                     result = 0;
118
        acpi_status             status = 0;
119
        struct acpi_buffer      buffer = {ACPI_ALLOCATE_BUFFER, NULL};
120
        struct acpi_buffer      format = {sizeof(ACPI_BATTERY_FORMAT_BIF),
121
                                                ACPI_BATTERY_FORMAT_BIF};
122
        struct acpi_buffer      data = {0, NULL};
123
        union acpi_object       *package = NULL;
124
 
125
        ACPI_FUNCTION_TRACE("acpi_battery_get_info");
126
 
127
        if (!battery || !bif)
128
                return_VALUE(-EINVAL);
129
 
130
        /* Evalute _BIF */
131
 
132
        status = acpi_evaluate_object(battery->handle, "_BIF", NULL, &buffer);
133
        if (ACPI_FAILURE(status)) {
134
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BIF\n"));
135
                return_VALUE(-ENODEV);
136
        }
137
 
138
        package = (union acpi_object *) buffer.pointer;
139
 
140
        /* Extract Package Data */
141
 
142
        status = acpi_extract_package(package, &format, &data);
143
        if (status != AE_BUFFER_OVERFLOW) {
144
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n"));
145
                result = -ENODEV;
146
                goto end;
147
        }
148
 
149
        data.pointer = kmalloc(data.length, GFP_KERNEL);
150
        if (!data.pointer) {
151
                result = -ENOMEM;
152
                goto end;
153
        }
154
        memset(data.pointer, 0, data.length);
155
 
156
        status = acpi_extract_package(package, &format, &data);
157
        if (ACPI_FAILURE(status)) {
158
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n"));
159
                kfree(data.pointer);
160
                result = -ENODEV;
161
                goto end;
162
        }
163
 
164
end:
165
        acpi_os_free(buffer.pointer);
166
 
167
        if (!result)
168
                (*bif) = (struct acpi_battery_info *) data.pointer;
169
 
170
        return_VALUE(result);
171
}
172
 
173
static int
174
acpi_battery_get_status (
175
        struct acpi_battery     *battery,
176
        struct acpi_battery_status **bst)
177
{
178
        int                     result = 0;
179
        acpi_status             status = 0;
180
        struct acpi_buffer      buffer = {ACPI_ALLOCATE_BUFFER, NULL};
181
        struct acpi_buffer      format = {sizeof(ACPI_BATTERY_FORMAT_BST),
182
                                                ACPI_BATTERY_FORMAT_BST};
183
        struct acpi_buffer      data = {0, NULL};
184
        union acpi_object       *package = NULL;
185
 
186
        ACPI_FUNCTION_TRACE("acpi_battery_get_status");
187
 
188
        if (!battery || !bst)
189
                return_VALUE(-EINVAL);
190
 
191
        /* Evalute _BST */
192
 
193
        status = acpi_evaluate_object(battery->handle, "_BST", NULL, &buffer);
194
        if (ACPI_FAILURE(status)) {
195
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BST\n"));
196
                return_VALUE(-ENODEV);
197
        }
198
 
199
        package = (union acpi_object *) buffer.pointer;
200
 
201
        /* Extract Package Data */
202
 
203
        status = acpi_extract_package(package, &format, &data);
204
        if (status != AE_BUFFER_OVERFLOW) {
205
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n"));
206
                result = -ENODEV;
207
                goto end;
208
        }
209
 
210
        data.pointer = kmalloc(data.length, GFP_KERNEL);
211
        if (!data.pointer) {
212
                result = -ENOMEM;
213
                goto end;
214
        }
215
        memset(data.pointer, 0, data.length);
216
 
217
        status = acpi_extract_package(package, &format, &data);
218
        if (ACPI_FAILURE(status)) {
219
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n"));
220
                kfree(data.pointer);
221
                result = -ENODEV;
222
                goto end;
223
        }
224
 
225
end:
226
        acpi_os_free(buffer.pointer);
227
 
228
        if (!result)
229
                (*bst) = (struct acpi_battery_status *) data.pointer;
230
 
231
        return_VALUE(result);
232
}
233
 
234
 
235
static int
236
acpi_battery_set_alarm (
237
        struct acpi_battery     *battery,
238
        unsigned long           alarm)
239
{
240
        acpi_status             status = 0;
241
        union acpi_object       arg0 = {ACPI_TYPE_INTEGER};
242
        struct acpi_object_list arg_list = {1, &arg0};
243
 
244
        ACPI_FUNCTION_TRACE("acpi_battery_set_alarm");
245
 
246
        if (!battery)
247
                return_VALUE(-EINVAL);
248
 
249
        if (!battery->flags.alarm)
250
                return_VALUE(-ENODEV);
251
 
252
        arg0.integer.value = alarm;
253
 
254
        status = acpi_evaluate_object(battery->handle, "_BTP", &arg_list, NULL);
255
        if (ACPI_FAILURE(status))
256
                return_VALUE(-ENODEV);
257
 
258
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm));
259
 
260
        battery->alarm = alarm;
261
 
262
        return_VALUE(0);
263
}
264
 
265
 
266
static int
267
acpi_battery_check (
268
        struct acpi_battery     *battery)
269
{
270
        int                     result = 0;
271
        acpi_status             status = AE_OK;
272
        acpi_handle             handle = NULL;
273
        struct acpi_device      *device = NULL;
274
        struct acpi_battery_info *bif = NULL;
275
 
276
        ACPI_FUNCTION_TRACE("acpi_battery_check");
277
 
278
        if (!battery)
279
                return_VALUE(-EINVAL);
280
 
281
        result = acpi_bus_get_device(battery->handle, &device);
282
        if (result)
283
                return_VALUE(result);
284
 
285
        result = acpi_bus_get_status(device);
286
        if (result)
287
                return_VALUE(result);
288
 
289
        /* Insertion? */
290
 
291
        if (!battery->flags.present && device->status.battery_present) {
292
 
293
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n"));
294
 
295
                /* Evalute _BIF to get certain static information */
296
 
297
                result = acpi_battery_get_info(battery, &bif);
298
                if (result)
299
                        return_VALUE(result);
300
 
301
                battery->flags.power_unit = bif->power_unit;
302
                battery->trips.warning = bif->design_capacity_warning;
303
                battery->trips.low = bif->design_capacity_low;
304
                kfree(bif);
305
 
306
                /* See if alarms are supported, and if so, set default */
307
 
308
                status = acpi_get_handle(battery->handle, "_BTP", &handle);
309
                if (ACPI_SUCCESS(status)) {
310
                        battery->flags.alarm = 1;
311
                        acpi_battery_set_alarm(battery, battery->trips.warning);
312
                }
313
        }
314
 
315
        /* Removal? */
316
 
317
        else if (battery->flags.present && !device->status.battery_present) {
318
                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n"));
319
        }
320
 
321
        battery->flags.present = device->status.battery_present;
322
 
323
        return_VALUE(result);
324
}
325
 
326
 
327
/* --------------------------------------------------------------------------
328
                              FS Interface (/proc)
329
   -------------------------------------------------------------------------- */
330
 
331
struct proc_dir_entry           *acpi_battery_dir;
332
 
333
static int
334
acpi_battery_read_info (
335
        char                    *page,
336
        char                    **start,
337
        off_t                   off,
338
        int                     count,
339
        int                     *eof,
340
        void                    *data)
341
{
342
        int                     result = 0;
343
        struct acpi_battery     *battery = (struct acpi_battery *) data;
344
        struct acpi_battery_info *bif = NULL;
345
        char                    *units = "?";
346
        char                    *p = page;
347
        int                     len = 0;
348
 
349
        ACPI_FUNCTION_TRACE("acpi_battery_read_info");
350
 
351
        if (!battery || (off != 0))
352
                goto end;
353
 
354
        if (battery->flags.present)
355
                p += sprintf(p, "present:                 yes\n");
356
        else {
357
                p += sprintf(p, "present:                 no\n");
358
                goto end;
359
        }
360
 
361
        /* Battery Info (_BIF) */
362
 
363
        result = acpi_battery_get_info(battery, &bif);
364
        if (result || !bif) {
365
                p += sprintf(p, "ERROR: Unable to read battery information\n");
366
                goto end;
367
        }
368
 
369
        units = bif->power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
370
 
371
        if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
372
                p += sprintf(p, "design capacity:         unknown\n");
373
        else
374
                p += sprintf(p, "design capacity:         %d %sh\n",
375
                        (u32) bif->design_capacity, units);
376
 
377
        if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
378
                p += sprintf(p, "last full capacity:      unknown\n");
379
        else
380
                p += sprintf(p, "last full capacity:      %d %sh\n",
381
                        (u32) bif->last_full_capacity, units);
382
 
383
        switch ((u32) bif->battery_technology) {
384
        case 0:
385
                p += sprintf(p, "battery technology:      non-rechargeable\n");
386
                break;
387
        case 1:
388
                p += sprintf(p, "battery technology:      rechargeable\n");
389
                break;
390
        default:
391
                p += sprintf(p, "battery technology:      unknown\n");
392
                break;
393
        }
394
 
395
        if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
396
                p += sprintf(p, "design voltage:          unknown\n");
397
        else
398
                p += sprintf(p, "design voltage:          %d mV\n",
399
                        (u32) bif->design_voltage);
400
 
401
        p += sprintf(p, "design capacity warning: %d %sh\n",
402
                (u32) bif->design_capacity_warning, units);
403
        p += sprintf(p, "design capacity low:     %d %sh\n",
404
                (u32) bif->design_capacity_low, units);
405
        p += sprintf(p, "capacity granularity 1:  %d %sh\n",
406
                (u32) bif->battery_capacity_granularity_1, units);
407
        p += sprintf(p, "capacity granularity 2:  %d %sh\n",
408
                (u32) bif->battery_capacity_granularity_2, units);
409
        p += sprintf(p, "model number:            %s\n",
410
                bif->model_number);
411
        p += sprintf(p, "serial number:           %s\n",
412
                bif->serial_number);
413
        p += sprintf(p, "battery type:            %s\n",
414
                bif->battery_type);
415
        p += sprintf(p, "OEM info:                %s\n",
416
                bif->oem_info);
417
 
418
end:
419
        kfree(bif);
420
 
421
        len = (p - page);
422
        if (len <= off+count) *eof = 1;
423
        *start = page + off;
424
        len -= off;
425
        if (len>count) len = count;
426
        if (len<0) len = 0;
427
 
428
        return_VALUE(len);
429
}
430
 
431
 
432
static int
433
acpi_battery_read_state (
434
        char                    *page,
435
        char                    **start,
436
        off_t                   off,
437
        int                     count,
438
        int                     *eof,
439
        void                    *data)
440
{
441
        int                     result = 0;
442
        struct acpi_battery     *battery = (struct acpi_battery *) data;
443
        struct acpi_battery_status *bst = NULL;
444
        char                    *units = "?";
445
        char                    *p = page;
446
        int                     len = 0;
447
 
448
        ACPI_FUNCTION_TRACE("acpi_battery_read_state");
449
 
450
        if (!battery || (off != 0))
451
                goto end;
452
 
453
        if (battery->flags.present)
454
                p += sprintf(p, "present:                 yes\n");
455
        else {
456
                p += sprintf(p, "present:                 no\n");
457
                goto end;
458
        }
459
 
460
        /* Battery Units */
461
 
462
        units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
463
 
464
        /* Battery Status (_BST) */
465
 
466
        result = acpi_battery_get_status(battery, &bst);
467
        if (result || !bst) {
468
                p += sprintf(p, "ERROR: Unable to read battery status\n");
469
                goto end;
470
        }
471
 
472
        if (!(bst->state & 0x04))
473
                p += sprintf(p, "capacity state:          ok\n");
474
        else
475
                p += sprintf(p, "capacity state:          critical\n");
476
 
477
        if ((bst->state & 0x01) && (bst->state & 0x02))
478
                p += sprintf(p, "charging state:          charging/discharging\n");
479
        else if (bst->state & 0x01)
480
                p += sprintf(p, "charging state:          discharging\n");
481
        else if (bst->state & 0x02)
482
                p += sprintf(p, "charging state:          charging\n");
483
        else
484
                p += sprintf(p, "charging state:          unknown\n");
485
 
486
        if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN)
487
                p += sprintf(p, "present rate:            unknown\n");
488
        else
489
                p += sprintf(p, "present rate:            %d %s\n",
490
                        (u32) bst->present_rate, units);
491
 
492
        if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
493
                p += sprintf(p, "remaining capacity:      unknown\n");
494
        else
495
                p += sprintf(p, "remaining capacity:      %d %sh\n",
496
                        (u32) bst->remaining_capacity, units);
497
 
498
        if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
499
                p += sprintf(p, "present voltage:         unknown\n");
500
        else
501
                p += sprintf(p, "present voltage:         %d mV\n",
502
                        (u32) bst->present_voltage);
503
 
504
end:
505
        kfree(bst);
506
 
507
        len = (p - page);
508
        if (len <= off+count) *eof = 1;
509
        *start = page + off;
510
        len -= off;
511
        if (len>count) len = count;
512
        if (len<0) len = 0;
513
 
514
        return_VALUE(len);
515
}
516
 
517
 
518
static int
519
acpi_battery_read_alarm (
520
        char                    *page,
521
        char                    **start,
522
        off_t                   off,
523
        int                     count,
524
        int                     *eof,
525
        void                    *data)
526
{
527
        struct acpi_battery     *battery = (struct acpi_battery *) data;
528
        char                    *units = "?";
529
        char                    *p = page;
530
        int                     len = 0;
531
 
532
        ACPI_FUNCTION_TRACE("acpi_battery_read_alarm");
533
 
534
        if (!battery || (off != 0))
535
                goto end;
536
 
537
        if (!battery->flags.present) {
538
                p += sprintf(p, "present:                 no\n");
539
                goto end;
540
        }
541
 
542
        /* Battery Units */
543
 
544
        units = battery->flags.power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
545
 
546
        /* Battery Alarm */
547
 
548
        p += sprintf(p, "alarm:                   ");
549
        if (!battery->alarm)
550
                p += sprintf(p, "unsupported\n");
551
        else
552
                p += sprintf(p, "%d %sh\n", (u32) battery->alarm, units);
553
 
554
end:
555
        len = (p - page);
556
        if (len <= off+count) *eof = 1;
557
        *start = page + off;
558
        len -= off;
559
        if (len>count) len = count;
560
        if (len<0) len = 0;
561
 
562
        return_VALUE(len);
563
}
564
 
565
 
566
static int
567
acpi_battery_write_alarm (
568
        struct file             *file,
569
        const char              *buffer,
570
        unsigned long           count,
571
        void                    *data)
572
{
573
        int                     result = 0;
574
        struct acpi_battery     *battery = (struct acpi_battery *) data;
575
        char                    alarm_string[12] = {'\0'};
576
 
577
        ACPI_FUNCTION_TRACE("acpi_battery_write_alarm");
578
 
579
        if (!battery || (count > sizeof(alarm_string) - 1))
580
                return_VALUE(-EINVAL);
581
 
582
        if (!battery->flags.present)
583
                return_VALUE(-ENODEV);
584
 
585
        if (copy_from_user(alarm_string, buffer, count))
586
                return_VALUE(-EFAULT);
587
 
588
        alarm_string[count] = '\0';
589
 
590
        result = acpi_battery_set_alarm(battery,
591
                simple_strtoul(alarm_string, NULL, 0));
592
        if (result)
593
                return_VALUE(result);
594
 
595
        return_VALUE(count);
596
}
597
 
598
 
599
static int
600
acpi_battery_add_fs (
601
        struct acpi_device      *device)
602
{
603
        struct proc_dir_entry   *entry = NULL;
604
 
605
        ACPI_FUNCTION_TRACE("acpi_battery_add_fs");
606
 
607
        if (!acpi_device_dir(device)) {
608
                acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
609
                        acpi_battery_dir);
610
                if (!acpi_device_dir(device))
611
                        return_VALUE(-ENODEV);
612
        }
613
 
614
        /* 'info' [R] */
615
        entry = create_proc_entry(ACPI_BATTERY_FILE_INFO,
616
                S_IRUGO, acpi_device_dir(device));
617
        if (!entry)
618
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
619
                        "Unable to create '%s' fs entry\n",
620
                        ACPI_BATTERY_FILE_INFO));
621
        else {
622
                entry->read_proc = acpi_battery_read_info;
623
                entry->data = acpi_driver_data(device);
624
        }
625
 
626
        /* 'status' [R] */
627
        entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS,
628
                S_IRUGO, acpi_device_dir(device));
629
        if (!entry)
630
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
631
                        "Unable to create '%s' fs entry\n",
632
                        ACPI_BATTERY_FILE_STATUS));
633
        else {
634
                entry->read_proc = acpi_battery_read_state;
635
                entry->data = acpi_driver_data(device);
636
        }
637
 
638
        /* 'alarm' [R/W] */
639
        entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM,
640
                S_IFREG|S_IRUGO|S_IWUSR, acpi_device_dir(device));
641
        if (!entry)
642
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
643
                        "Unable to create '%s' fs entry\n",
644
                        ACPI_BATTERY_FILE_ALARM));
645
        else {
646
                entry->read_proc = acpi_battery_read_alarm;
647
                entry->write_proc = acpi_battery_write_alarm;
648
                entry->data = acpi_driver_data(device);
649
        }
650
 
651
        return_VALUE(0);
652
}
653
 
654
 
655
static int
656
acpi_battery_remove_fs (
657
        struct acpi_device      *device)
658
{
659
        ACPI_FUNCTION_TRACE("acpi_battery_remove_fs");
660
 
661
        if (acpi_device_dir(device)) {
662
                remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
663
                acpi_device_dir(device) = NULL;
664
        }
665
 
666
        return_VALUE(0);
667
}
668
 
669
 
670
/* --------------------------------------------------------------------------
671
                                 Driver Interface
672
   -------------------------------------------------------------------------- */
673
 
674
static void
675
acpi_battery_notify (
676
        acpi_handle             handle,
677
        u32                     event,
678
        void                    *data)
679
{
680
        struct acpi_battery     *battery = (struct acpi_battery *) data;
681
        struct acpi_device      *device = NULL;
682
 
683
        ACPI_FUNCTION_TRACE("acpi_battery_notify");
684
 
685
        if (!battery)
686
                return_VOID;
687
 
688
        if (acpi_bus_get_device(handle, &device))
689
                return_VOID;
690
 
691
        switch (event) {
692
        case ACPI_BATTERY_NOTIFY_STATUS:
693
        case ACPI_BATTERY_NOTIFY_INFO:
694
                acpi_battery_check(battery);
695
                acpi_bus_generate_event(device, event, battery->flags.present);
696
                break;
697
        default:
698
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
699
                        "Unsupported event [0x%x]\n", event));
700
                break;
701
        }
702
 
703
        return_VOID;
704
}
705
 
706
 
707
static int
708
acpi_battery_add (
709
        struct acpi_device      *device)
710
{
711
        int                     result = 0;
712
        acpi_status             status = 0;
713
        struct acpi_battery     *battery = NULL;
714
 
715
        ACPI_FUNCTION_TRACE("acpi_battery_add");
716
 
717
        if (!device)
718
                return_VALUE(-EINVAL);
719
 
720
        battery = kmalloc(sizeof(struct acpi_battery), GFP_KERNEL);
721
        if (!battery)
722
                return_VALUE(-ENOMEM);
723
        memset(battery, 0, sizeof(struct acpi_battery));
724
 
725
        battery->handle = device->handle;
726
        sprintf(acpi_device_name(device), "%s", ACPI_BATTERY_DEVICE_NAME);
727
        sprintf(acpi_device_class(device), "%s", ACPI_BATTERY_CLASS);
728
        acpi_driver_data(device) = battery;
729
 
730
        result = acpi_battery_check(battery);
731
        if (result)
732
                goto end;
733
 
734
        result = acpi_battery_add_fs(device);
735
        if (result)
736
                goto end;
737
 
738
        status = acpi_install_notify_handler(battery->handle,
739
                ACPI_DEVICE_NOTIFY, acpi_battery_notify, battery);
740
        if (ACPI_FAILURE(status)) {
741
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
742
                        "Error installing notify handler\n"));
743
                result = -ENODEV;
744
                goto end;
745
        }
746
 
747
        printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
748
                ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
749
                device->status.battery_present?"present":"absent");
750
 
751
end:
752
        if (result) {
753
                acpi_battery_remove_fs(device);
754
                kfree(battery);
755
        }
756
 
757
        return_VALUE(result);
758
}
759
 
760
 
761
static int
762
acpi_battery_remove (
763
        struct acpi_device      *device,
764
        int                     type)
765
{
766
        acpi_status             status = 0;
767
        struct acpi_battery     *battery = NULL;
768
 
769
        ACPI_FUNCTION_TRACE("acpi_battery_remove");
770
 
771
        if (!device || !acpi_driver_data(device))
772
                return_VALUE(-EINVAL);
773
 
774
        battery = (struct acpi_battery *) acpi_driver_data(device);
775
 
776
        status = acpi_remove_notify_handler(battery->handle,
777
                ACPI_DEVICE_NOTIFY, acpi_battery_notify);
778
        if (ACPI_FAILURE(status))
779
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
780
                        "Error removing notify handler\n"));
781
 
782
        acpi_battery_remove_fs(device);
783
 
784
        kfree(battery);
785
 
786
        return_VALUE(0);
787
}
788
 
789
 
790
static int __init
791
acpi_battery_init (void)
792
{
793
        int                     result = 0;
794
 
795
        ACPI_FUNCTION_TRACE("acpi_battery_init");
796
 
797
        acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
798
        if (!acpi_battery_dir)
799
                return_VALUE(-ENODEV);
800
 
801
        result = acpi_bus_register_driver(&acpi_battery_driver);
802
        if (result < 0) {
803
                remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
804
                return_VALUE(-ENODEV);
805
        }
806
 
807
        return_VALUE(0);
808
}
809
 
810
 
811
static void __exit
812
acpi_battery_exit (void)
813
{
814
        ACPI_FUNCTION_TRACE("acpi_battery_exit");
815
 
816
        acpi_bus_unregister_driver(&acpi_battery_driver);
817
 
818
        remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
819
 
820
        return_VOID;
821
}
822
 
823
 
824
module_init(acpi_battery_init);
825
module_exit(acpi_battery_exit);

powered by: WebSVN 2.1.0

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