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