diff options
Diffstat (limited to 'drivers/acpi/power.c')
-rw-r--r-- | drivers/acpi/power.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c new file mode 100644 index 000000000..0422bf94d --- /dev/null +++ b/drivers/acpi/power.c @@ -0,0 +1,137 @@ +/* + * power.c - Overall power driver. Also handles AC adapter device. + * + * Copyright (C) 2000 Andrew Grover + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/proc_fs.h> +#include "acpi.h" +#include "driver.h" + +#define _COMPONENT OS_DEPENDENT + MODULE_NAME ("power") + +int acpi_cmbatt_init(void); +int acpi_cmbatt_terminate(void); + +/* ACPI-specific defines */ +#define ACPI_AC_ADAPTER_HID "ACPI0003" + +static int ac_count = 0; +static ACPI_HANDLE ac_handle = 0; + +/* + * We found a device with the correct HID + */ +static ACPI_STATUS +acpi_found_ac_adapter(ACPI_HANDLE handle, u32 level, void *ctx, void **value) +{ + ACPI_DEVICE_INFO info; + + if (ac_count > 0) { + printk(KERN_ERR "AC Adapter: more than one!\n"); + return (AE_OK); + } + + if (!ACPI_SUCCESS(acpi_get_object_info(handle, &info))) { + printk(KERN_ERR "AC Adapter: Could not get AC Adapter object info\n"); + return (AE_OK); + } + + if (!(info.valid & ACPI_VALID_STA)) { + printk(KERN_ERR "AC Adapter: Battery _STA invalid\n"); + return AE_OK; + } + + printk(KERN_INFO "AC Adapter: found\n"); + + ac_handle = handle; + + ac_count++; + + return AE_OK; +} + +static int +proc_read_ac_adapter_status(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + ACPI_OBJECT obj; + ACPI_BUFFER buf; + + char *p = page; + int len; + + buf.length = sizeof(obj); + buf.pointer = &obj; + if (!ACPI_SUCCESS(acpi_evaluate_object(ac_handle, "_PSR", NULL, &buf)) + || obj.type != ACPI_TYPE_NUMBER) { + p += sprintf(p, "Could not read AC status\n"); + goto end; + } + + if (obj.number.value) + p += sprintf(p, "on-line\n"); + else + p += sprintf(p, "off-line\n"); + +end: + len = (p - page); + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + return len; +} + +int +acpi_power_init(void) +{ + acpi_get_devices(ACPI_AC_ADAPTER_HID, + acpi_found_ac_adapter, + NULL, + NULL); + + if (!proc_mkdir("power", NULL)) + return 0; + + if (ac_handle) { + create_proc_read_entry("power/ac", 0, NULL, + proc_read_ac_adapter_status, NULL); + } + + acpi_cmbatt_init(); + + return 0; +} + +int +acpi_power_terminate(void) +{ + acpi_cmbatt_terminate(); + + if (ac_handle) { + remove_proc_entry("power/ac", NULL); + } + + remove_proc_entry("power", NULL); + + return 0; +} |