📄 battery.c
字号:
/* * acpi_battery.c - ACPI Battery Driver ($Revision: 37 $) * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * * 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/module.h>#include <linux/init.h>#include <linux/types.h>#include <linux/proc_fs.h>#include <asm/uaccess.h>#include <acpi/acpi_bus.h>#include <acpi/acpi_drivers.h>#define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF#define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS"#define ACPI_BATTERY_FORMAT_BST "NNNN"#define ACPI_BATTERY_COMPONENT 0x00040000#define ACPI_BATTERY_CLASS "battery"#define ACPI_BATTERY_HID "PNP0C0A"#define ACPI_BATTERY_DRIVER_NAME "ACPI Battery Driver"#define ACPI_BATTERY_DEVICE_NAME "Battery"#define ACPI_BATTERY_FILE_INFO "info"#define ACPI_BATTERY_FILE_STATUS "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"#define ACPI_BATTERY_UNITS_AMPS "mA"#define _COMPONENT ACPI_BATTERY_COMPONENTACPI_MODULE_NAME ("acpi_battery")MODULE_AUTHOR("Paul Diefenbaugh");MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);MODULE_LICENSE("GPL");static int acpi_battery_add (struct acpi_device *device);static int acpi_battery_remove (struct acpi_device *device, int type);static struct acpi_driver acpi_battery_driver = { .name = ACPI_BATTERY_DRIVER_NAME, .class = ACPI_BATTERY_CLASS, .ids = ACPI_BATTERY_HID, .ops = { .add = acpi_battery_add, .remove = acpi_battery_remove, },};struct acpi_battery_status { acpi_integer state; acpi_integer present_rate; acpi_integer remaining_capacity; acpi_integer present_voltage;};struct acpi_battery_info { acpi_integer power_unit; acpi_integer design_capacity; acpi_integer last_full_capacity; acpi_integer battery_technology; acpi_integer design_voltage; acpi_integer design_capacity_warning; acpi_integer design_capacity_low; acpi_integer battery_capacity_granularity_1; acpi_integer battery_capacity_granularity_2; acpi_string model_number; acpi_string serial_number; acpi_string battery_type; acpi_string oem_info;};struct acpi_battery_flags { u8 present:1; /* Bay occupied? */ u8 power_unit:1; /* 0=watts, 1=apms */ u8 alarm:1; /* _BTP present? */ u8 reserved:5;};struct acpi_battery_trips { unsigned long warning; unsigned long low;};struct acpi_battery { acpi_handle handle; struct acpi_battery_flags flags; struct acpi_battery_trips trips; unsigned long alarm; struct acpi_battery_info *info;};/* -------------------------------------------------------------------------- Battery Management -------------------------------------------------------------------------- */static intacpi_battery_get_info ( struct acpi_battery *battery, struct acpi_battery_info **bif){ int result = 0; acpi_status status = 0; struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; struct acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BIF), ACPI_BATTERY_FORMAT_BIF}; struct acpi_buffer data = {0, NULL}; union acpi_object *package = NULL; ACPI_FUNCTION_TRACE("acpi_battery_get_info"); if (!battery || !bif) return_VALUE(-EINVAL); /* Evalute _BIF */ status = acpi_evaluate_object(battery->handle, "_BIF", NULL, &buffer); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BIF\n")); return_VALUE(-ENODEV); } package = (union acpi_object *) buffer.pointer; /* Extract Package Data */ status = acpi_extract_package(package, &format, &data); if (status != AE_BUFFER_OVERFLOW) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n")); result = -ENODEV; goto end; } data.pointer = kmalloc(data.length, GFP_KERNEL); if (!data.pointer) { result = -ENOMEM; goto end; } memset(data.pointer, 0, data.length); status = acpi_extract_package(package, &format, &data); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BIF\n")); kfree(data.pointer); result = -ENODEV; goto end; }end: acpi_os_free(buffer.pointer); if (!result) (*bif) = (struct acpi_battery_info *) data.pointer; return_VALUE(result);}static intacpi_battery_get_status ( struct acpi_battery *battery, struct acpi_battery_status **bst){ int result = 0; acpi_status status = 0; struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; struct acpi_buffer format = {sizeof(ACPI_BATTERY_FORMAT_BST), ACPI_BATTERY_FORMAT_BST}; struct acpi_buffer data = {0, NULL}; union acpi_object *package = NULL; ACPI_FUNCTION_TRACE("acpi_battery_get_status"); if (!battery || !bst) return_VALUE(-EINVAL); /* Evalute _BST */ status = acpi_evaluate_object(battery->handle, "_BST", NULL, &buffer); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error evaluating _BST\n")); return_VALUE(-ENODEV); } package = (union acpi_object *) buffer.pointer; /* Extract Package Data */ status = acpi_extract_package(package, &format, &data); if (status != AE_BUFFER_OVERFLOW) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n")); result = -ENODEV; goto end; } data.pointer = kmalloc(data.length, GFP_KERNEL); if (!data.pointer) { result = -ENOMEM; goto end; } memset(data.pointer, 0, data.length); status = acpi_extract_package(package, &format, &data); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error extracting _BST\n")); kfree(data.pointer); result = -ENODEV; goto end; }end: acpi_os_free(buffer.pointer); if (!result) (*bst) = (struct acpi_battery_status *) data.pointer; return_VALUE(result);}static intacpi_battery_set_alarm ( struct acpi_battery *battery, unsigned long alarm){ acpi_status status = 0; union acpi_object arg0 = {ACPI_TYPE_INTEGER}; struct acpi_object_list arg_list = {1, &arg0}; ACPI_FUNCTION_TRACE("acpi_battery_set_alarm"); if (!battery) return_VALUE(-EINVAL); if (!battery->flags.alarm) return_VALUE(-ENODEV); arg0.integer.value = alarm; status = acpi_evaluate_object(battery->handle, "_BTP", &arg_list, NULL); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm)); battery->alarm = alarm; return_VALUE(0);}static intacpi_battery_check ( struct acpi_battery *battery){ int result = 0; acpi_status status = AE_OK; acpi_handle handle = NULL; struct acpi_device *device = NULL; struct acpi_battery_info *bif = NULL; ACPI_FUNCTION_TRACE("acpi_battery_check"); if (!battery) return_VALUE(-EINVAL); result = acpi_bus_get_device(battery->handle, &device); if (result) return_VALUE(result); result = acpi_bus_get_status(device); if (result) return_VALUE(result); /* Insertion? */ if (!battery->flags.present && device->status.battery_present) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n")); /* Evalute _BIF to get certain static information */ result = acpi_battery_get_info(battery, &bif); if (result) return_VALUE(result); battery->flags.power_unit = bif->power_unit; battery->trips.warning = bif->design_capacity_warning; battery->trips.low = bif->design_capacity_low; kfree(bif); /* See if alarms are supported, and if so, set default */ status = acpi_get_handle(battery->handle, "_BTP", &handle); if (ACPI_SUCCESS(status)) { battery->flags.alarm = 1; acpi_battery_set_alarm(battery, battery->trips.warning); } } /* Removal? */ else if (battery->flags.present && !device->status.battery_present) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n")); } battery->flags.present = device->status.battery_present; return_VALUE(result);}/* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */struct proc_dir_entry *acpi_battery_dir;static intacpi_battery_read_info ( char *page, char **start, off_t off, int count, int *eof, void *data){ int result = 0; struct acpi_battery *battery = (struct acpi_battery *) data; struct acpi_battery_info *bif = NULL; char *units = "?"; char *p = page; int len = 0; ACPI_FUNCTION_TRACE("acpi_battery_read_info"); if (!battery || (off != 0)) goto end; if (battery->flags.present) p += sprintf(p, "present: yes\n"); else { p += sprintf(p, "present: no\n"); goto end; } /* Battery Info (_BIF) */ result = acpi_battery_get_info(battery, &bif); if (result || !bif) { p += sprintf(p, "ERROR: Unable to read battery information\n"); goto end; } units = bif->power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) p += sprintf(p, "design capacity: unknown\n"); else p += sprintf(p, "design capacity: %d %sh\n", (u32) bif->design_capacity, units); if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) p += sprintf(p, "last full capacity: unknown\n"); else p += sprintf(p, "last full capacity: %d %sh\n", (u32) bif->last_full_capacity, units); switch ((u32) bif->battery_technology) { case 0: p += sprintf(p, "battery technology: non-rechargeable\n"); break; case 1: p += sprintf(p, "battery technology: rechargeable\n"); break; default: p += sprintf(p, "battery technology: unknown\n"); break; } if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) p += sprintf(p, "design voltage: unknown\n"); else p += sprintf(p, "design voltage: %d mV\n", (u32) bif->design_voltage); p += sprintf(p, "design capacity warning: %d %sh\n", (u32) bif->design_capacity_warning, units); p += sprintf(p, "design capacity low: %d %sh\n", (u32) bif->design_capacity_low, units); p += sprintf(p, "capacity granularity 1: %d %sh\n", (u32) bif->battery_capacity_granularity_1, units); p += sprintf(p, "capacity granularity 2: %d %sh\n", (u32) bif->battery_capacity_granularity_2, units); p += sprintf(p, "model number: %s\n", bif->model_number); p += sprintf(p, "serial number: %s\n", bif->serial_number); p += sprintf(p, "battery type: %s\n", bif->battery_type); p += sprintf(p, "OEM info: %s\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -