#define ACPI_BATTERY_CLASS "battery"
#define ACPI_BATTERY_HID "PNP0C0A"
#define ACPI_BATTERY_DEVICE_NAME "Battery"
-#define ACPI_BATTERY_FILE_INFO "info"
-#define ACPI_BATTERY_FILE_STATE "state"
-#define ACPI_BATTERY_FILE_ALARM "alarm"
#define ACPI_BATTERY_NOTIFY_STATUS 0x80
#define ACPI_BATTERY_NOTIFY_INFO 0x81
#define ACPI_BATTERY_UNITS_WATTS "mW"
acpi_string oem_info;
};
+enum acpi_battery_files{
+ ACPI_BATTERY_INFO = 0,
+ ACPI_BATTERY_STATE,
+ ACPI_BATTERY_ALARM,
+ ACPI_BATTERY_NUMFILES,
+};
+
struct acpi_battery_flags {
u8 battery_present_prev;
u8 alarm_present;
u8 init_update;
- u8 info_update;
- u8 state_update;
- u8 alarm_update;
+ u8 update[ACPI_BATTERY_NUMFILES];
u8 power_unit;
};
struct acpi_buffer bif_data;
struct acpi_buffer bst_data;
unsigned long alarm;
- unsigned long info_update_time;
- unsigned long state_update_time;
- unsigned long alarm_update_time;
+ unsigned long update_time[ACPI_BATTERY_NUMFILES];
};
-#define acpi_battery_present(battery) battery->device->status.battery_present
-#define acpi_battery_present_prev(battery) battery->flags.battery_present_prev
-#define acpi_battery_alarm_present(battery) battery->flags.alarm_present
-#define acpi_battery_init_update_flag(battery) battery->flags.init_update
-#define acpi_battery_info_update_flag(battery) battery->flags.info_update
-#define acpi_battery_state_update_flag(battery) battery->flags.state_update
-#define acpi_battery_alarm_update_flag(battery) battery->flags.alarm_update
-#define acpi_battery_power_units(battery) battery->flags.power_unit ? \
- ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS
-#define acpi_battery_handle(battery) battery->device->handle
-#define acpi_battery_inserted(battery) (!acpi_battery_present_prev(battery) & acpi_battery_present(battery))
-#define acpi_battery_removed(battery) (acpi_battery_present_prev(battery) & !acpi_battery_present(battery))
-#define acpi_battery_bid(battery) acpi_device_bid(battery->device)
-#define acpi_battery_status_str(battery) acpi_battery_present(battery) ? "present" : "absent"
-
-/* --------------------------------------------------------------------------
- Battery Management
- -------------------------------------------------------------------------- */
-
-static void acpi_battery_mutex_lock(struct acpi_battery *battery)
+inline int acpi_battery_present(struct acpi_battery *battery)
{
- mutex_lock(&battery->mutex);
+ return battery->device->status.battery_present;
+}
+inline char *acpi_battery_power_units(struct acpi_battery *battery)
+{
+ if (battery->flags.power_unit)
+ return ACPI_BATTERY_UNITS_AMPS;
+ else
+ return ACPI_BATTERY_UNITS_WATTS;
}
-static void acpi_battery_mutex_unlock(struct acpi_battery *battery)
+inline acpi_handle acpi_battery_handle(struct acpi_battery *battery)
{
- mutex_unlock(&battery->mutex);
+ return battery->device->handle;
}
+/* --------------------------------------------------------------------------
+ Battery Management
+ -------------------------------------------------------------------------- */
+
static void acpi_battery_check_result(struct acpi_battery *battery, int result)
{
if (!battery)
return;
if (result) {
- acpi_battery_init_update_flag(battery) = 1;
+ battery->flags.init_update = 1;
}
}
}
if (data_null.length != data->length) {
- if (data->pointer) {
- kfree(data->pointer);
- }
+ kfree(data->pointer);
data->pointer = kzalloc(data_null.length, GFP_KERNEL);
if (!data->pointer) {
ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "kzalloc()"));
struct acpi_buffer *data = NULL;
struct acpi_battery_info *bif = NULL;
- battery->info_update_time = get_seconds();
+ battery->update_time[ACPI_BATTERY_INFO] = get_seconds();
if (!acpi_battery_present(battery))
return 0;
- /* Evalute _BIF */
+ /* Evaluate _BIF */
status =
acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL,
end:
- if (buffer.pointer) {
- kfree(buffer.pointer);
- }
+ kfree(buffer.pointer);
if (!result) {
bif = data->pointer;
union acpi_object *package = NULL;
struct acpi_buffer *data = NULL;
- battery->state_update_time = get_seconds();
+ battery->update_time[ACPI_BATTERY_STATE] = get_seconds();
if (!acpi_battery_present(battery))
return 0;
- /* Evalute _BST */
+ /* Evaluate _BST */
status =
acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL,
goto end;
end:
- if (buffer.pointer) {
- kfree(buffer.pointer);
- }
+ kfree(buffer.pointer);
return result;
}
static int acpi_battery_get_alarm(struct acpi_battery *battery)
{
- battery->alarm_update_time = get_seconds();
+ battery->update_time[ACPI_BATTERY_ALARM] = get_seconds();
return 0;
}
union acpi_object arg0 = { ACPI_TYPE_INTEGER };
struct acpi_object_list arg_list = { 1, &arg0 };
- battery->alarm_update_time = get_seconds();
+ battery->update_time[ACPI_BATTERY_ALARM] = get_seconds();
if (!acpi_battery_present(battery))
return -ENODEV;
- if (!acpi_battery_alarm_present(battery))
+ if (!battery->flags.alarm_present)
return -ENODEV;
arg0.integer.value = alarm;
status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle);
if (ACPI_SUCCESS(status)) {
- acpi_battery_alarm_present(battery) = 1;
+ battery->flags.alarm_present = 1;
if (!alarm && bif) {
alarm = bif->design_capacity_warning;
}
if (result)
goto end;
} else {
- acpi_battery_alarm_present(battery) = 0;
+ battery->flags.alarm_present = 0;
}
end:
if (result)
return result;
- acpi_battery_present_prev(battery) = acpi_battery_present(battery);
+ battery->flags.battery_present_prev = acpi_battery_present(battery);
if (acpi_battery_present(battery)) {
result = acpi_battery_get_info(battery);
update = 1;
}
- if (acpi_battery_init_update_flag(battery)) {
+ if (battery->flags.init_update) {
result = acpi_battery_init_update(battery);
if (result)
- goto end;;
+ goto end;
update_result = ACPI_BATTERY_INIT_UPDATE;
} else if (update) {
result = acpi_battery_get_status(battery);
if (result)
- goto end;;
- if (acpi_battery_inserted(battery)
- || acpi_battery_removed(battery)) {
+ goto end;
+ if ((!battery->flags.battery_present_prev & acpi_battery_present(battery))
+ || (battery->flags.battery_present_prev & !acpi_battery_present(battery))) {
result = acpi_battery_init_update(battery);
if (result)
- goto end;;
+ goto end;
update_result = ACPI_BATTERY_INIT_UPDATE;
} else {
update_result = ACPI_BATTERY_EASY_UPDATE;
end:
- acpi_battery_init_update_flag(battery) = (result != 0);
+ battery->flags.init_update = (result != 0);
*update_result_ptr = update_result;
{
acpi_battery_get_status(battery);
- if (acpi_battery_init_update_flag(battery)) {
+ if (battery->flags.init_update) {
return;
}
- if (acpi_battery_inserted(battery) || acpi_battery_removed(battery)) {
- acpi_battery_init_update_flag(battery) = 1;
+ if ((!battery->flags.battery_present_prev &
+ acpi_battery_present(battery)) ||
+ (battery->flags.battery_present_prev &
+ !acpi_battery_present(battery))) {
+ battery->flags.init_update = 1;
} else {
- acpi_battery_info_update_flag(battery) = 1;
- acpi_battery_state_update_flag(battery) = 1;
- acpi_battery_alarm_update_flag(battery) = 1;
+ battery->flags.update[ACPI_BATTERY_INFO] = 1;
+ battery->flags.update[ACPI_BATTERY_STATE] = 1;
+ battery->flags.update[ACPI_BATTERY_ALARM] = 1;
}
}
static struct proc_dir_entry *acpi_battery_dir;
-static int acpi_battery_read_info_print(struct seq_file *seq, int result)
+static int acpi_battery_print_info(struct seq_file *seq, int result)
{
struct acpi_battery *battery = seq->private;
struct acpi_battery_info *bif = NULL;
return result;
}
-static int acpi_battery_read_info(struct seq_file *seq, void *offset)
-{
- struct acpi_battery *battery = seq->private;
- int result = 0;
- int update_result = ACPI_BATTERY_NONE_UPDATE;
- int update = 0;
-
- acpi_battery_mutex_lock(battery);
-
- update = (get_seconds() - battery->info_update_time >= update_time);
- update = (update | acpi_battery_info_update_flag(battery));
-
- result = acpi_battery_update(battery, update, &update_result);
- if (result)
- goto end;
-
- /* Battery Info (_BIF) */
-
- if (update_result == ACPI_BATTERY_EASY_UPDATE) {
- result = acpi_battery_get_info(battery);
- if (result)
- goto end;
- }
-
- end:
-
- result = acpi_battery_read_info_print(seq, result);
-
- acpi_battery_check_result(battery, result);
-
- acpi_battery_info_update_flag(battery) = result;
-
- acpi_battery_mutex_unlock(battery);
-
- return result;
-}
-
-static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
-{
- return single_open(file, acpi_battery_read_info, PDE(inode)->data);
-}
-
-static int acpi_battery_read_state_print(struct seq_file *seq, int result)
+static int acpi_battery_print_state(struct seq_file *seq, int result)
{
struct acpi_battery *battery = seq->private;
struct acpi_battery_state *bst = NULL;
return result;
}
-static int acpi_battery_read_state(struct seq_file *seq, void *offset)
-{
- struct acpi_battery *battery = seq->private;
- int result = 0;
- int update_result = ACPI_BATTERY_NONE_UPDATE;
- int update = 0;
-
- acpi_battery_mutex_lock(battery);
-
- update = (get_seconds() - battery->state_update_time >= update_time);
- update = (update | acpi_battery_state_update_flag(battery));
-
- result = acpi_battery_update(battery, update, &update_result);
- if (result)
- goto end;
-
- /* Battery State (_BST) */
-
- if (update_result == ACPI_BATTERY_EASY_UPDATE) {
- result = acpi_battery_get_state(battery);
- if (result)
- goto end;
- }
-
- end:
-
- result = acpi_battery_read_state_print(seq, result);
-
- acpi_battery_check_result(battery, result);
-
- acpi_battery_state_update_flag(battery) = result;
-
- acpi_battery_mutex_unlock(battery);
-
- return result;
-}
-
-static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
-{
- return single_open(file, acpi_battery_read_state, PDE(inode)->data);
-}
-
-static int acpi_battery_read_alarm_print(struct seq_file *seq, int result)
+static int acpi_battery_print_alarm(struct seq_file *seq, int result)
{
struct acpi_battery *battery = seq->private;
char *units = "?";
return result;
}
-static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
-{
- struct acpi_battery *battery = seq->private;
- int result = 0;
- int update_result = ACPI_BATTERY_NONE_UPDATE;
- int update = 0;
-
- acpi_battery_mutex_lock(battery);
-
- update = (get_seconds() - battery->alarm_update_time >= update_time);
- update = (update | acpi_battery_alarm_update_flag(battery));
-
- result = acpi_battery_update(battery, update, &update_result);
- if (result)
- goto end;
-
- /* Battery Alarm */
-
- if (update_result == ACPI_BATTERY_EASY_UPDATE) {
- result = acpi_battery_get_alarm(battery);
- if (result)
- goto end;
- }
-
- end:
-
- result = acpi_battery_read_alarm_print(seq, result);
-
- acpi_battery_check_result(battery, result);
-
- acpi_battery_alarm_update_flag(battery) = result;
-
- acpi_battery_mutex_unlock(battery);
-
- return result;
-}
-
static ssize_t
acpi_battery_write_alarm(struct file *file,
const char __user * buffer,
if (!battery || (count > sizeof(alarm_string) - 1))
return -EINVAL;
- acpi_battery_mutex_lock(battery);
+ mutex_lock(&battery->mutex);
result = acpi_battery_update(battery, 1, &update_result);
if (result) {
if (!result)
result = count;
- acpi_battery_mutex_unlock(battery);
+ mutex_unlock(&battery->mutex);
+
+ return result;
+}
+
+typedef int(*print_func)(struct seq_file *seq, int result);
+typedef int(*get_func)(struct acpi_battery *battery);
+
+static struct acpi_read_mux {
+ print_func print;
+ get_func get;
+} acpi_read_funcs[ACPI_BATTERY_NUMFILES] = {
+ {.get = acpi_battery_get_info, .print = acpi_battery_print_info},
+ {.get = acpi_battery_get_state, .print = acpi_battery_print_state},
+ {.get = acpi_battery_get_alarm, .print = acpi_battery_print_alarm},
+};
+static int acpi_battery_read(int fid, struct seq_file *seq)
+{
+ struct acpi_battery *battery = seq->private;
+ int result = 0;
+ int update_result = ACPI_BATTERY_NONE_UPDATE;
+ int update = 0;
+
+ mutex_lock(&battery->mutex);
+
+ update = (get_seconds() - battery->update_time[fid] >= update_time);
+ update = (update | battery->flags.update[fid]);
+
+ result = acpi_battery_update(battery, update, &update_result);
+ if (result)
+ goto end;
+
+ if (update_result == ACPI_BATTERY_EASY_UPDATE) {
+ result = acpi_read_funcs[fid].get(battery);
+ if (result)
+ goto end;
+ }
+
+ end:
+ result = acpi_read_funcs[fid].print(seq, result);
+ acpi_battery_check_result(battery, result);
+ battery->flags.update[fid] = result;
+ mutex_unlock(&battery->mutex);
return result;
}
+static int acpi_battery_read_info(struct seq_file *seq, void *offset)
+{
+ return acpi_battery_read(ACPI_BATTERY_INFO, seq);
+}
+
+static int acpi_battery_read_state(struct seq_file *seq, void *offset)
+{
+ return acpi_battery_read(ACPI_BATTERY_STATE, seq);
+}
+
+static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
+{
+ return acpi_battery_read(ACPI_BATTERY_ALARM, seq);
+}
+
+static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
+{
+ return single_open(file, acpi_battery_read_info, PDE(inode)->data);
+}
+
+static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
+{
+ return single_open(file, acpi_battery_read_state, PDE(inode)->data);
+}
+
static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
{
return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
}
-static const struct file_operations acpi_battery_info_ops = {
+static struct battery_file {
+ struct file_operations ops;
+ mode_t mode;
+ char *name;
+} acpi_battery_file[] = {
+ {
+ .name = "info",
+ .mode = S_IRUGO,
+ .ops = {
.open = acpi_battery_info_open_fs,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.owner = THIS_MODULE,
-};
-
-static const struct file_operations acpi_battery_state_ops = {
+ },
+ },
+ {
+ .name = "state",
+ .mode = S_IRUGO,
+ .ops = {
.open = acpi_battery_state_open_fs,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.owner = THIS_MODULE,
-};
-
-static const struct file_operations acpi_battery_alarm_ops = {
+ },
+ },
+ {
+ .name = "alarm",
+ .mode = S_IFREG | S_IRUGO | S_IWUSR,
+ .ops = {
.open = acpi_battery_alarm_open_fs,
.read = seq_read,
.write = acpi_battery_write_alarm,
.llseek = seq_lseek,
.release = single_release,
.owner = THIS_MODULE,
+ },
+ },
};
static int acpi_battery_add_fs(struct acpi_device *device)
{
struct proc_dir_entry *entry = NULL;
+ int i;
if (!acpi_device_dir(device)) {
acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
acpi_device_dir(device)->owner = THIS_MODULE;
}
- /* 'info' [R] */
- entry = create_proc_entry(ACPI_BATTERY_FILE_INFO,
- S_IRUGO, acpi_device_dir(device));
- if (!entry)
- return -ENODEV;
- else {
- entry->proc_fops = &acpi_battery_info_ops;
- entry->data = acpi_driver_data(device);
- entry->owner = THIS_MODULE;
- }
-
- /* 'status' [R] */
- entry = create_proc_entry(ACPI_BATTERY_FILE_STATE,
- S_IRUGO, acpi_device_dir(device));
- if (!entry)
- return -ENODEV;
- else {
- entry->proc_fops = &acpi_battery_state_ops;
- entry->data = acpi_driver_data(device);
- entry->owner = THIS_MODULE;
- }
-
- /* 'alarm' [R/W] */
- entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM,
- S_IFREG | S_IRUGO | S_IWUSR,
- acpi_device_dir(device));
- if (!entry)
- return -ENODEV;
- else {
- entry->proc_fops = &acpi_battery_alarm_ops;
- entry->data = acpi_driver_data(device);
- entry->owner = THIS_MODULE;
+ for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
+ entry = create_proc_entry(acpi_battery_file[i].name,
+ acpi_battery_file[i].mode, acpi_device_dir(device));
+ if (!entry)
+ return -ENODEV;
+ else {
+ entry->proc_fops = &acpi_battery_file[i].ops;
+ entry->data = acpi_driver_data(device);
+ entry->owner = THIS_MODULE;
+ }
}
return 0;
static int acpi_battery_remove_fs(struct acpi_device *device)
{
+ int i;
if (acpi_device_dir(device)) {
- remove_proc_entry(ACPI_BATTERY_FILE_ALARM,
- acpi_device_dir(device));
- remove_proc_entry(ACPI_BATTERY_FILE_STATE,
- acpi_device_dir(device));
- remove_proc_entry(ACPI_BATTERY_FILE_INFO,
+ for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
+ remove_proc_entry(acpi_battery_file[i].name,
acpi_device_dir(device));
-
+ }
remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
acpi_device_dir(device) = NULL;
}
mutex_init(&battery->mutex);
- acpi_battery_mutex_lock(battery);
+ mutex_lock(&battery->mutex);
battery->device = device;
strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
if (result)
goto end;
- acpi_battery_init_update_flag(battery) = 1;
+ battery->flags.init_update = 1;
result = acpi_battery_add_fs(device);
if (result)
kfree(battery);
}
- acpi_battery_mutex_unlock(battery);
+ mutex_unlock(&battery->mutex);
return result;
}
battery = acpi_driver_data(device);
- acpi_battery_mutex_lock(battery);
+ mutex_lock(&battery->mutex);
status = acpi_remove_notify_handler(device->handle,
ACPI_ALL_NOTIFY,
acpi_battery_remove_fs(device);
- if (battery->bif_data.pointer)
- kfree(battery->bif_data.pointer);
+ kfree(battery->bif_data.pointer);
- if (battery->bst_data.pointer)
- kfree(battery->bst_data.pointer);
+ kfree(battery->bst_data.pointer);
- acpi_battery_mutex_unlock(battery);
+ mutex_unlock(&battery->mutex);
mutex_destroy(&battery->mutex);
battery = device->driver_data;
- acpi_battery_init_update_flag(battery) = 1;
+ battery->flags.init_update = 1;
return 0;
}