2 * acpi_battery.c - ACPI Battery Driver ($Revision: 37 $)
4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
7 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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.
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.
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.
23 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/types.h>
30 #include <linux/jiffies.h>
31 #include <linux/proc_fs.h>
32 #include <linux/seq_file.h>
33 #include <asm/uaccess.h>
35 #include <acpi/acpi_bus.h>
36 #include <acpi/acpi_drivers.h>
38 #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
40 #define ACPI_BATTERY_COMPONENT 0x00040000
41 #define ACPI_BATTERY_CLASS "battery"
42 #define ACPI_BATTERY_DEVICE_NAME "Battery"
43 #define ACPI_BATTERY_NOTIFY_STATUS 0x80
44 #define ACPI_BATTERY_NOTIFY_INFO 0x81
46 #define _COMPONENT ACPI_BATTERY_COMPONENT
48 ACPI_MODULE_NAME("battery");
50 MODULE_AUTHOR("Paul Diefenbaugh");
51 MODULE_DESCRIPTION("ACPI Battery Driver");
52 MODULE_LICENSE("GPL");
54 static unsigned int cache_time
= 1000;
55 module_param(cache_time
, uint
, 0644);
56 MODULE_PARM_DESC(cache_time
, "cache time in milliseconds");
58 extern struct proc_dir_entry
*acpi_lock_battery_dir(void);
59 extern void *acpi_unlock_battery_dir(struct proc_dir_entry
*acpi_battery_dir
);
61 static int acpi_battery_add(struct acpi_device
*device
);
62 static int acpi_battery_remove(struct acpi_device
*device
, int type
);
63 static int acpi_battery_resume(struct acpi_device
*device
);
65 static const struct acpi_device_id battery_device_ids
[] = {
69 MODULE_DEVICE_TABLE(acpi
, battery_device_ids
);
71 static struct acpi_driver acpi_battery_driver
= {
73 .class = ACPI_BATTERY_CLASS
,
74 .ids
= battery_device_ids
,
76 .add
= acpi_battery_add
,
77 .resume
= acpi_battery_resume
,
78 .remove
= acpi_battery_remove
,
82 enum acpi_battery_files
{
83 ACPI_BATTERY_INFO
= 0,
86 ACPI_BATTERY_NUMFILES
,
91 struct acpi_device
*device
;
92 unsigned long update_time
;
94 int remaining_capacity
;
97 int last_full_capacity
;
100 int design_capacity_warning
;
101 int design_capacity_low
;
102 int capacity_granularity_1
;
103 int capacity_granularity_2
;
105 char model_number
[32];
106 char serial_number
[32];
114 inline int acpi_battery_present(struct acpi_battery
*battery
)
116 return battery
->device
->status
.battery_present
;
119 inline char *acpi_battery_units(struct acpi_battery
*battery
)
121 return (battery
->power_unit
)?"mA":"mW";
124 /* --------------------------------------------------------------------------
126 -------------------------------------------------------------------------- */
128 struct acpi_offsets
{
129 size_t offset
; /* offset inside struct acpi_sbs_battery */
130 u8 mode
; /* int or string? */
133 static struct acpi_offsets state_offsets
[] = {
134 {offsetof(struct acpi_battery
, state
), 0},
135 {offsetof(struct acpi_battery
, present_rate
), 0},
136 {offsetof(struct acpi_battery
, remaining_capacity
), 0},
137 {offsetof(struct acpi_battery
, present_voltage
), 0},
140 static struct acpi_offsets info_offsets
[] = {
141 {offsetof(struct acpi_battery
, power_unit
), 0},
142 {offsetof(struct acpi_battery
, design_capacity
), 0},
143 {offsetof(struct acpi_battery
, last_full_capacity
), 0},
144 {offsetof(struct acpi_battery
, technology
), 0},
145 {offsetof(struct acpi_battery
, design_voltage
), 0},
146 {offsetof(struct acpi_battery
, design_capacity_warning
), 0},
147 {offsetof(struct acpi_battery
, design_capacity_low
), 0},
148 {offsetof(struct acpi_battery
, capacity_granularity_1
), 0},
149 {offsetof(struct acpi_battery
, capacity_granularity_2
), 0},
150 {offsetof(struct acpi_battery
, model_number
), 1},
151 {offsetof(struct acpi_battery
, serial_number
), 1},
152 {offsetof(struct acpi_battery
, type
), 1},
153 {offsetof(struct acpi_battery
, oem_info
), 1},
156 static int extract_package(struct acpi_battery
*battery
,
157 union acpi_object
*package
,
158 struct acpi_offsets
*offsets
, int num
)
161 union acpi_object
*element
;
162 if (package
->type
!= ACPI_TYPE_PACKAGE
)
164 for (i
= 0; i
< num
; ++i
) {
165 if (package
->package
.count
<= i
)
167 element
= &package
->package
.elements
[i
];
168 if (offsets
[i
].mode
) {
169 if (element
->type
!= ACPI_TYPE_STRING
&&
170 element
->type
!= ACPI_TYPE_BUFFER
)
172 strncpy((u8
*)battery
+ offsets
[i
].offset
,
173 element
->string
.pointer
, 32);
175 if (element
->type
!= ACPI_TYPE_INTEGER
)
177 x
= (int *)((u8
*)battery
+ offsets
[i
].offset
);
178 *x
= element
->integer
.value
;
184 static int acpi_battery_get_status(struct acpi_battery
*battery
)
188 result
= acpi_bus_get_status(battery
->device
);
190 ACPI_EXCEPTION((AE_INFO
, AE_ERROR
, "Evaluating _STA"));
196 static int acpi_battery_get_info(struct acpi_battery
*battery
)
199 acpi_status status
= 0;
200 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
202 if (!acpi_battery_present(battery
))
204 mutex_lock(&battery
->lock
);
205 status
= acpi_evaluate_object(battery
->device
->handle
, "_BIF",
207 mutex_unlock(&battery
->lock
);
208 if (ACPI_FAILURE(status
)) {
209 ACPI_EXCEPTION((AE_INFO
, status
, "Evaluating _BIF"));
212 result
= extract_package(battery
, buffer
.pointer
,
213 info_offsets
, ARRAY_SIZE(info_offsets
));
214 kfree(buffer
.pointer
);
218 static int acpi_battery_get_state(struct acpi_battery
*battery
)
221 acpi_status status
= 0;
222 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
224 if (!acpi_battery_present(battery
))
227 if (battery
->update_time
&&
228 time_before(jiffies
, battery
->update_time
+
229 msecs_to_jiffies(cache_time
)))
232 mutex_lock(&battery
->lock
);
233 status
= acpi_evaluate_object(battery
->device
->handle
, "_BST",
235 mutex_unlock(&battery
->lock
);
237 if (ACPI_FAILURE(status
)) {
238 ACPI_EXCEPTION((AE_INFO
, status
, "Evaluating _BST"));
241 result
= extract_package(battery
, buffer
.pointer
,
242 state_offsets
, ARRAY_SIZE(state_offsets
));
243 battery
->update_time
= jiffies
;
244 kfree(buffer
.pointer
);
248 static int acpi_battery_get_alarm(struct acpi_battery
*battery
)
253 static int acpi_battery_set_alarm(struct acpi_battery
*battery
,
256 acpi_status status
= 0;
257 union acpi_object arg0
= { ACPI_TYPE_INTEGER
};
258 struct acpi_object_list arg_list
= { 1, &arg0
};
260 if (!acpi_battery_present(battery
))
263 if (!battery
->alarm_present
)
266 arg0
.integer
.value
= alarm
;
268 mutex_lock(&battery
->lock
);
269 status
= acpi_evaluate_object(battery
->device
->handle
, "_BTP",
271 mutex_unlock(&battery
->lock
);
272 if (ACPI_FAILURE(status
))
275 ACPI_DEBUG_PRINT((ACPI_DB_INFO
, "Alarm set to %d\n", (u32
) alarm
));
277 battery
->alarm
= alarm
;
282 static int acpi_battery_init_alarm(struct acpi_battery
*battery
)
284 acpi_status status
= AE_OK
;
285 acpi_handle handle
= NULL
;
287 /* See if alarms are supported, and if so, set default */
288 status
= acpi_get_handle(battery
->device
->handle
, "_BTP", &handle
);
289 if (ACPI_FAILURE(status
)) {
290 battery
->alarm_present
= 0;
293 battery
->alarm_present
= 1;
295 battery
->alarm
= battery
->design_capacity_warning
;
296 return acpi_battery_set_alarm(battery
, battery
->alarm
);
299 static int acpi_battery_update(struct acpi_battery
*battery
)
301 int saved_present
= acpi_battery_present(battery
);
302 int result
= acpi_battery_get_status(battery
);
303 if (result
|| !acpi_battery_present(battery
))
305 if (saved_present
!= acpi_battery_present(battery
) ||
306 !battery
->update_time
) {
307 battery
->update_time
= 0;
308 result
= acpi_battery_get_info(battery
);
311 acpi_battery_init_alarm(battery
);
313 return acpi_battery_get_state(battery
);
316 /* --------------------------------------------------------------------------
318 -------------------------------------------------------------------------- */
320 static struct proc_dir_entry
*acpi_battery_dir
;
322 static int acpi_battery_print_info(struct seq_file
*seq
, int result
)
324 struct acpi_battery
*battery
= seq
->private;
330 if (acpi_battery_present(battery
))
331 seq_printf(seq
, "present: yes\n");
333 seq_printf(seq
, "present: no\n");
339 units
= acpi_battery_units(battery
);
341 if (battery
->design_capacity
== ACPI_BATTERY_VALUE_UNKNOWN
)
342 seq_printf(seq
, "design capacity: unknown\n");
344 seq_printf(seq
, "design capacity: %d %sh\n",
345 (u32
) battery
->design_capacity
, units
);
347 if (battery
->last_full_capacity
== ACPI_BATTERY_VALUE_UNKNOWN
)
348 seq_printf(seq
, "last full capacity: unknown\n");
350 seq_printf(seq
, "last full capacity: %d %sh\n",
351 (u32
) battery
->last_full_capacity
, units
);
353 switch ((u32
) battery
->technology
) {
355 seq_printf(seq
, "battery technology: non-rechargeable\n");
358 seq_printf(seq
, "battery technology: rechargeable\n");
361 seq_printf(seq
, "battery technology: unknown\n");
365 if (battery
->design_voltage
== ACPI_BATTERY_VALUE_UNKNOWN
)
366 seq_printf(seq
, "design voltage: unknown\n");
368 seq_printf(seq
, "design voltage: %d mV\n",
369 (u32
) battery
->design_voltage
);
370 seq_printf(seq
, "design capacity warning: %d %sh\n",
371 (u32
) battery
->design_capacity_warning
, units
);
372 seq_printf(seq
, "design capacity low: %d %sh\n",
373 (u32
) battery
->design_capacity_low
, units
);
374 seq_printf(seq
, "capacity granularity 1: %d %sh\n",
375 (u32
) battery
->capacity_granularity_1
, units
);
376 seq_printf(seq
, "capacity granularity 2: %d %sh\n",
377 (u32
) battery
->capacity_granularity_2
, units
);
378 seq_printf(seq
, "model number: %s\n", battery
->model_number
);
379 seq_printf(seq
, "serial number: %s\n", battery
->serial_number
);
380 seq_printf(seq
, "battery type: %s\n", battery
->type
);
381 seq_printf(seq
, "OEM info: %s\n", battery
->oem_info
);
386 seq_printf(seq
, "ERROR: Unable to read battery info\n");
391 static int acpi_battery_print_state(struct seq_file
*seq
, int result
)
393 struct acpi_battery
*battery
= seq
->private;
399 if (acpi_battery_present(battery
))
400 seq_printf(seq
, "present: yes\n");
402 seq_printf(seq
, "present: no\n");
408 units
= acpi_battery_units(battery
);
410 if (!(battery
->state
& 0x04))
411 seq_printf(seq
, "capacity state: ok\n");
413 seq_printf(seq
, "capacity state: critical\n");
415 if ((battery
->state
& 0x01) && (battery
->state
& 0x02)) {
417 "charging state: charging/discharging\n");
418 } else if (battery
->state
& 0x01)
419 seq_printf(seq
, "charging state: discharging\n");
420 else if (battery
->state
& 0x02)
421 seq_printf(seq
, "charging state: charging\n");
423 seq_printf(seq
, "charging state: charged\n");
426 if (battery
->present_rate
== ACPI_BATTERY_VALUE_UNKNOWN
)
427 seq_printf(seq
, "present rate: unknown\n");
429 seq_printf(seq
, "present rate: %d %s\n",
430 (u32
) battery
->present_rate
, units
);
432 if (battery
->remaining_capacity
== ACPI_BATTERY_VALUE_UNKNOWN
)
433 seq_printf(seq
, "remaining capacity: unknown\n");
435 seq_printf(seq
, "remaining capacity: %d %sh\n",
436 (u32
) battery
->remaining_capacity
, units
);
438 if (battery
->present_voltage
== ACPI_BATTERY_VALUE_UNKNOWN
)
439 seq_printf(seq
, "present voltage: unknown\n");
441 seq_printf(seq
, "present voltage: %d mV\n",
442 (u32
) battery
->present_voltage
);
447 seq_printf(seq
, "ERROR: Unable to read battery state\n");
453 static int acpi_battery_print_alarm(struct seq_file
*seq
, int result
)
455 struct acpi_battery
*battery
= seq
->private;
461 if (!acpi_battery_present(battery
)) {
462 seq_printf(seq
, "present: no\n");
468 units
= acpi_battery_units(battery
);
470 seq_printf(seq
, "alarm: ");
472 seq_printf(seq
, "unsupported\n");
474 seq_printf(seq
, "%u %sh\n", battery
->alarm
, units
);
479 seq_printf(seq
, "ERROR: Unable to read battery alarm\n");
484 static ssize_t
acpi_battery_write_alarm(struct file
*file
,
485 const char __user
* buffer
,
486 size_t count
, loff_t
* ppos
)
489 char alarm_string
[12] = { '\0' };
490 struct seq_file
*m
= file
->private_data
;
491 struct acpi_battery
*battery
= m
->private;
493 if (!battery
|| (count
> sizeof(alarm_string
) - 1))
499 if (!acpi_battery_present(battery
)) {
503 if (copy_from_user(alarm_string
, buffer
, count
)) {
507 alarm_string
[count
] = '\0';
508 battery
->alarm
= simple_strtol(alarm_string
, NULL
, 0);
509 result
= acpi_battery_set_alarm(battery
, battery
->alarm
);
516 typedef int(*print_func
)(struct seq_file
*seq
, int result
);
517 typedef int(*get_func
)(struct acpi_battery
*battery
);
519 static struct acpi_read_mux
{
522 } acpi_read_funcs
[ACPI_BATTERY_NUMFILES
] = {
523 {.get
= acpi_battery_get_info
, .print
= acpi_battery_print_info
},
524 {.get
= acpi_battery_get_state
, .print
= acpi_battery_print_state
},
525 {.get
= acpi_battery_get_alarm
, .print
= acpi_battery_print_alarm
},
528 static int acpi_battery_read(int fid
, struct seq_file
*seq
)
530 struct acpi_battery
*battery
= seq
->private;
531 int result
= acpi_battery_update(battery
);
532 return acpi_read_funcs
[fid
].print(seq
, result
);
535 static int acpi_battery_read_info(struct seq_file
*seq
, void *offset
)
537 return acpi_battery_read(ACPI_BATTERY_INFO
, seq
);
540 static int acpi_battery_read_state(struct seq_file
*seq
, void *offset
)
542 return acpi_battery_read(ACPI_BATTERY_STATE
, seq
);
545 static int acpi_battery_read_alarm(struct seq_file
*seq
, void *offset
)
547 return acpi_battery_read(ACPI_BATTERY_ALARM
, seq
);
550 static int acpi_battery_info_open_fs(struct inode
*inode
, struct file
*file
)
552 return single_open(file
, acpi_battery_read_info
, PDE(inode
)->data
);
555 static int acpi_battery_state_open_fs(struct inode
*inode
, struct file
*file
)
557 return single_open(file
, acpi_battery_read_state
, PDE(inode
)->data
);
560 static int acpi_battery_alarm_open_fs(struct inode
*inode
, struct file
*file
)
562 return single_open(file
, acpi_battery_read_alarm
, PDE(inode
)->data
);
565 static struct battery_file
{
566 struct file_operations ops
;
569 } acpi_battery_file
[] = {
574 .open
= acpi_battery_info_open_fs
,
577 .release
= single_release
,
578 .owner
= THIS_MODULE
,
585 .open
= acpi_battery_state_open_fs
,
588 .release
= single_release
,
589 .owner
= THIS_MODULE
,
594 .mode
= S_IFREG
| S_IRUGO
| S_IWUSR
,
596 .open
= acpi_battery_alarm_open_fs
,
598 .write
= acpi_battery_write_alarm
,
600 .release
= single_release
,
601 .owner
= THIS_MODULE
,
606 static int acpi_battery_add_fs(struct acpi_device
*device
)
608 struct proc_dir_entry
*entry
= NULL
;
611 if (!acpi_device_dir(device
)) {
612 acpi_device_dir(device
) = proc_mkdir(acpi_device_bid(device
),
614 if (!acpi_device_dir(device
))
616 acpi_device_dir(device
)->owner
= THIS_MODULE
;
619 for (i
= 0; i
< ACPI_BATTERY_NUMFILES
; ++i
) {
620 entry
= create_proc_entry(acpi_battery_file
[i
].name
,
621 acpi_battery_file
[i
].mode
, acpi_device_dir(device
));
625 entry
->proc_fops
= &acpi_battery_file
[i
].ops
;
626 entry
->data
= acpi_driver_data(device
);
627 entry
->owner
= THIS_MODULE
;
634 static int acpi_battery_remove_fs(struct acpi_device
*device
)
637 if (acpi_device_dir(device
)) {
638 for (i
= 0; i
< ACPI_BATTERY_NUMFILES
; ++i
) {
639 remove_proc_entry(acpi_battery_file
[i
].name
,
640 acpi_device_dir(device
));
642 remove_proc_entry(acpi_device_bid(device
), acpi_battery_dir
);
643 acpi_device_dir(device
) = NULL
;
649 /* --------------------------------------------------------------------------
651 -------------------------------------------------------------------------- */
653 static void acpi_battery_notify(acpi_handle handle
, u32 event
, void *data
)
655 struct acpi_battery
*battery
= data
;
656 struct acpi_device
*device
;
659 device
= battery
->device
;
660 acpi_battery_update(battery
);
661 acpi_bus_generate_proc_event(device
, event
,
662 acpi_battery_present(battery
));
663 acpi_bus_generate_netlink_event(device
->pnp
.device_class
,
664 device
->dev
.bus_id
, event
,
665 acpi_battery_present(battery
));
668 static int acpi_battery_add(struct acpi_device
*device
)
671 acpi_status status
= 0;
672 struct acpi_battery
*battery
= NULL
;
677 battery
= kzalloc(sizeof(struct acpi_battery
), GFP_KERNEL
);
681 battery
->device
= device
;
682 strcpy(acpi_device_name(device
), ACPI_BATTERY_DEVICE_NAME
);
683 strcpy(acpi_device_class(device
), ACPI_BATTERY_CLASS
);
684 acpi_driver_data(device
) = battery
;
685 mutex_init(&battery
->lock
);
686 acpi_battery_update(battery
);
687 result
= acpi_battery_add_fs(device
);
691 status
= acpi_install_notify_handler(device
->handle
,
693 acpi_battery_notify
, battery
);
694 if (ACPI_FAILURE(status
)) {
695 ACPI_EXCEPTION((AE_INFO
, status
, "Installing notify handler"));
700 printk(KERN_INFO PREFIX
"%s Slot [%s] (battery %s)\n",
701 ACPI_BATTERY_DEVICE_NAME
, acpi_device_bid(device
),
702 device
->status
.battery_present
? "present" : "absent");
707 acpi_battery_remove_fs(device
);
714 static int acpi_battery_remove(struct acpi_device
*device
, int type
)
716 acpi_status status
= 0;
717 struct acpi_battery
*battery
= NULL
;
719 if (!device
|| !acpi_driver_data(device
))
722 battery
= acpi_driver_data(device
);
724 status
= acpi_remove_notify_handler(device
->handle
,
726 acpi_battery_notify
);
728 acpi_battery_remove_fs(device
);
729 mutex_destroy(&battery
->lock
);
735 /* this is needed to learn about changes made in suspended state */
736 static int acpi_battery_resume(struct acpi_device
*device
)
738 struct acpi_battery
*battery
;
741 battery
= acpi_driver_data(device
);
742 battery
->update_time
= 0;
746 static int __init
acpi_battery_init(void)
753 acpi_battery_dir
= acpi_lock_battery_dir();
754 if (!acpi_battery_dir
)
757 result
= acpi_bus_register_driver(&acpi_battery_driver
);
759 acpi_unlock_battery_dir(acpi_battery_dir
);
766 static void __exit
acpi_battery_exit(void)
768 acpi_bus_unregister_driver(&acpi_battery_driver
);
770 acpi_unlock_battery_dir(acpi_battery_dir
);
775 module_init(acpi_battery_init
);
776 module_exit(acpi_battery_exit
);