diff options
| -rw-r--r-- | drivers/acpi/battery.c | 329 |
1 files changed, 328 insertions, 1 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 9a2c63b20050..6e7b2a12860d 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
| @@ -36,6 +36,12 @@ | |||
| 36 | #include <linux/suspend.h> | 36 | #include <linux/suspend.h> |
| 37 | #include <asm/unaligned.h> | 37 | #include <asm/unaligned.h> |
| 38 | 38 | ||
| 39 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
| 40 | #include <linux/proc_fs.h> | ||
| 41 | #include <linux/seq_file.h> | ||
| 42 | #include <asm/uaccess.h> | ||
| 43 | #endif | ||
| 44 | |||
| 39 | #include <linux/acpi.h> | 45 | #include <linux/acpi.h> |
| 40 | #include <linux/power_supply.h> | 46 | #include <linux/power_supply.h> |
| 41 | 47 | ||
| @@ -64,6 +70,19 @@ static unsigned int cache_time = 1000; | |||
| 64 | module_param(cache_time, uint, 0644); | 70 | module_param(cache_time, uint, 0644); |
| 65 | MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); | 71 | MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); |
| 66 | 72 | ||
| 73 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
| 74 | extern struct proc_dir_entry *acpi_lock_battery_dir(void); | ||
| 75 | extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); | ||
| 76 | |||
| 77 | enum acpi_battery_files { | ||
| 78 | info_tag = 0, | ||
| 79 | state_tag, | ||
| 80 | alarm_tag, | ||
| 81 | ACPI_BATTERY_NUMFILES, | ||
| 82 | }; | ||
| 83 | |||
| 84 | #endif | ||
| 85 | |||
| 67 | static const struct acpi_device_id battery_device_ids[] = { | 86 | static const struct acpi_device_id battery_device_ids[] = { |
| 68 | {"PNP0C0A", 0}, | 87 | {"PNP0C0A", 0}, |
| 69 | {"", 0}, | 88 | {"", 0}, |
| @@ -299,6 +318,14 @@ static enum power_supply_property energy_battery_props[] = { | |||
| 299 | POWER_SUPPLY_PROP_SERIAL_NUMBER, | 318 | POWER_SUPPLY_PROP_SERIAL_NUMBER, |
| 300 | }; | 319 | }; |
| 301 | 320 | ||
| 321 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
| 322 | inline char *acpi_battery_units(struct acpi_battery *battery) | ||
| 323 | { | ||
| 324 | return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ? | ||
| 325 | "mA" : "mW"; | ||
| 326 | } | ||
| 327 | #endif | ||
| 328 | |||
| 302 | /* -------------------------------------------------------------------------- | 329 | /* -------------------------------------------------------------------------- |
| 303 | Battery Management | 330 | Battery Management |
| 304 | -------------------------------------------------------------------------- */ | 331 | -------------------------------------------------------------------------- */ |
| @@ -717,6 +744,279 @@ static void acpi_battery_refresh(struct acpi_battery *battery) | |||
| 717 | } | 744 | } |
| 718 | 745 | ||
| 719 | /* -------------------------------------------------------------------------- | 746 | /* -------------------------------------------------------------------------- |
| 747 | FS Interface (/proc) | ||
| 748 | -------------------------------------------------------------------------- */ | ||
| 749 | |||
| 750 | #ifdef CONFIG_ACPI_PROCFS_POWER | ||
| 751 | static struct proc_dir_entry *acpi_battery_dir; | ||
| 752 | |||
| 753 | static int acpi_battery_print_info(struct seq_file *seq, int result) | ||
| 754 | { | ||
| 755 | struct acpi_battery *battery = seq->private; | ||
| 756 | |||
| 757 | if (result) | ||
| 758 | goto end; | ||
| 759 | |||
| 760 | seq_printf(seq, "present: %s\n", | ||
| 761 | acpi_battery_present(battery) ? "yes" : "no"); | ||
| 762 | if (!acpi_battery_present(battery)) | ||
| 763 | goto end; | ||
| 764 | if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) | ||
| 765 | seq_printf(seq, "design capacity: unknown\n"); | ||
| 766 | else | ||
| 767 | seq_printf(seq, "design capacity: %d %sh\n", | ||
| 768 | battery->design_capacity, | ||
| 769 | acpi_battery_units(battery)); | ||
| 770 | |||
| 771 | if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN) | ||
| 772 | seq_printf(seq, "last full capacity: unknown\n"); | ||
| 773 | else | ||
| 774 | seq_printf(seq, "last full capacity: %d %sh\n", | ||
| 775 | battery->full_charge_capacity, | ||
| 776 | acpi_battery_units(battery)); | ||
| 777 | |||
| 778 | seq_printf(seq, "battery technology: %srechargeable\n", | ||
| 779 | (!battery->technology)?"non-":""); | ||
| 780 | |||
| 781 | if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) | ||
| 782 | seq_printf(seq, "design voltage: unknown\n"); | ||
| 783 | else | ||
| 784 | seq_printf(seq, "design voltage: %d mV\n", | ||
| 785 | battery->design_voltage); | ||
| 786 | seq_printf(seq, "design capacity warning: %d %sh\n", | ||
| 787 | battery->design_capacity_warning, | ||
| 788 | acpi_battery_units(battery)); | ||
| 789 | seq_printf(seq, "design capacity low: %d %sh\n", | ||
| 790 | battery->design_capacity_low, | ||
| 791 | acpi_battery_units(battery)); | ||
| 792 | seq_printf(seq, "cycle count: %i\n", battery->cycle_count); | ||
| 793 | seq_printf(seq, "capacity granularity 1: %d %sh\n", | ||
| 794 | battery->capacity_granularity_1, | ||
| 795 | acpi_battery_units(battery)); | ||
| 796 | seq_printf(seq, "capacity granularity 2: %d %sh\n", | ||
| 797 | battery->capacity_granularity_2, | ||
| 798 | acpi_battery_units(battery)); | ||
| 799 | seq_printf(seq, "model number: %s\n", battery->model_number); | ||
| 800 | seq_printf(seq, "serial number: %s\n", battery->serial_number); | ||
| 801 | seq_printf(seq, "battery type: %s\n", battery->type); | ||
| 802 | seq_printf(seq, "OEM info: %s\n", battery->oem_info); | ||
| 803 | end: | ||
| 804 | if (result) | ||
| 805 | seq_printf(seq, "ERROR: Unable to read battery info\n"); | ||
| 806 | return result; | ||
| 807 | } | ||
| 808 | |||
| 809 | static int acpi_battery_print_state(struct seq_file *seq, int result) | ||
| 810 | { | ||
| 811 | struct acpi_battery *battery = seq->private; | ||
| 812 | |||
| 813 | if (result) | ||
| 814 | goto end; | ||
| 815 | |||
| 816 | seq_printf(seq, "present: %s\n", | ||
| 817 | acpi_battery_present(battery) ? "yes" : "no"); | ||
| 818 | if (!acpi_battery_present(battery)) | ||
| 819 | goto end; | ||
| 820 | |||
| 821 | seq_printf(seq, "capacity state: %s\n", | ||
| 822 | (battery->state & 0x04) ? "critical" : "ok"); | ||
| 823 | if ((battery->state & 0x01) && (battery->state & 0x02)) | ||
| 824 | seq_printf(seq, | ||
| 825 | "charging state: charging/discharging\n"); | ||
| 826 | else if (battery->state & 0x01) | ||
| 827 | seq_printf(seq, "charging state: discharging\n"); | ||
| 828 | else if (battery->state & 0x02) | ||
| 829 | seq_printf(seq, "charging state: charging\n"); | ||
| 830 | else | ||
| 831 | seq_printf(seq, "charging state: charged\n"); | ||
| 832 | |||
| 833 | if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) | ||
| 834 | seq_printf(seq, "present rate: unknown\n"); | ||
| 835 | else | ||
| 836 | seq_printf(seq, "present rate: %d %s\n", | ||
| 837 | battery->rate_now, acpi_battery_units(battery)); | ||
| 838 | |||
| 839 | if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN) | ||
| 840 | seq_printf(seq, "remaining capacity: unknown\n"); | ||
| 841 | else | ||
| 842 | seq_printf(seq, "remaining capacity: %d %sh\n", | ||
| 843 | battery->capacity_now, acpi_battery_units(battery)); | ||
| 844 | if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN) | ||
| 845 | seq_printf(seq, "present voltage: unknown\n"); | ||
| 846 | else | ||
| 847 | seq_printf(seq, "present voltage: %d mV\n", | ||
| 848 | battery->voltage_now); | ||
| 849 | end: | ||
| 850 | if (result) | ||
| 851 | seq_printf(seq, "ERROR: Unable to read battery state\n"); | ||
| 852 | |||
| 853 | return result; | ||
| 854 | } | ||
| 855 | |||
| 856 | static int acpi_battery_print_alarm(struct seq_file *seq, int result) | ||
| 857 | { | ||
| 858 | struct acpi_battery *battery = seq->private; | ||
| 859 | |||
| 860 | if (result) | ||
| 861 | goto end; | ||
| 862 | |||
| 863 | if (!acpi_battery_present(battery)) { | ||
| 864 | seq_printf(seq, "present: no\n"); | ||
| 865 | goto end; | ||
| 866 | } | ||
| 867 | seq_printf(seq, "alarm: "); | ||
| 868 | if (!battery->alarm) | ||
| 869 | seq_printf(seq, "unsupported\n"); | ||
| 870 | else | ||
| 871 | seq_printf(seq, "%u %sh\n", battery->alarm, | ||
| 872 | acpi_battery_units(battery)); | ||
| 873 | end: | ||
| 874 | if (result) | ||
| 875 | seq_printf(seq, "ERROR: Unable to read battery alarm\n"); | ||
| 876 | return result; | ||
| 877 | } | ||
| 878 | |||
| 879 | static ssize_t acpi_battery_write_alarm(struct file *file, | ||
| 880 | const char __user * buffer, | ||
| 881 | size_t count, loff_t * ppos) | ||
| 882 | { | ||
| 883 | int result = 0; | ||
| 884 | char alarm_string[12] = { '\0' }; | ||
| 885 | struct seq_file *m = file->private_data; | ||
| 886 | struct acpi_battery *battery = m->private; | ||
| 887 | |||
| 888 | |||
