ac.c revision 97749cd9adbb2985e4b2aee1a59d6b970fe9c3a7
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * acpi_ac.c - ACPI AC Adapter Driver ($Revision: 27 $) 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or (at 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * your option) any later version. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, but 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * General Public License for more details. 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License along 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with this program; if not, write to the Free Software Foundation, Inc., 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 30fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/seq_file.h> 338a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3497749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#ifdef CONFIG_ACPI_SYSFS_POWER 35d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy#include <linux/power_supply.h> 3697749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#endif 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_bus.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_drivers.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_COMPONENT 0x00020000 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_CLASS "ac_adapter" 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_DEVICE_NAME "AC Adapter" 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_FILE_STATE "state" 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_NOTIFY_STATUS 0x80 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_STATUS_OFFLINE 0x00 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_STATUS_ONLINE 0x01 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_STATUS_UNKNOWN 0xFF 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _COMPONENT ACPI_AC_COMPONENT 50f52fd66d2ea794010c2d7536cf8e6abed0ac4947Len BrownACPI_MODULE_NAME("ac"); 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 52f52fd66d2ea794010c2d7536cf8e6abed0ac4947Len BrownMODULE_AUTHOR("Paul Diefenbaugh"); 537cda93e008e1a477970adbf82dba81a5d4f0ae40Len BrownMODULE_DESCRIPTION("ACPI AC Adapter Driver"); 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 56fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 573f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendextern struct proc_dir_entry *acpi_lock_ac_dir(void); 583f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendextern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); 598a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkovstatic int acpi_ac_open_fs(struct inode *inode, struct file *file); 608a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 613f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 624be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_add(struct acpi_device *device); 634be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_remove(struct acpi_device *device, int type); 645bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiystatic int acpi_ac_resume(struct acpi_device *device); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renningerconst static struct acpi_device_id ac_device_ids[] = { 671ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger {"ACPI0003", 0}, 681ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger {"", 0}, 691ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger}; 701ba90e3a87c46500623afdc3898573e4a5ebb21bThomas RenningerMODULE_DEVICE_TABLE(acpi, ac_device_ids); 711ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct acpi_driver acpi_ac_driver = { 73c2b6705b75d9c7aff98a4602a32230639e10891cLen Brown .name = "ac", 744be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .class = ACPI_AC_CLASS, 751ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger .ids = ac_device_ids, 764be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .ops = { 774be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .add = acpi_ac_add, 784be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .remove = acpi_ac_remove, 795bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy .resume = acpi_ac_resume, 804be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown }, 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct acpi_ac { 8497749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#ifdef CONFIG_ACPI_SYSFS_POWER 85d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy struct power_supply charger; 8697749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#endif 87af96179a8298832cc58be212d0e4988d8a1e11bfPatrick Mochel struct acpi_device * device; 884be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown unsigned long state; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger); 92d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy 93fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 94d75080328affb4b268da430b7074cc8139cc662aArjan van de Venstatic const struct file_operations acpi_ac_fops = { 954be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .open = acpi_ac_open_fs, 964be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .read = seq_read, 974be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .llseek = seq_lseek, 984be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .release = single_release, 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1008a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 10197749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#ifdef CONFIG_ACPI_SYSFS_POWER 102d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiystatic int get_ac_property(struct power_supply *psy, 103d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy enum power_supply_property psp, 104d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy union power_supply_propval *val) 105d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy{ 106d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy struct acpi_ac *ac = to_acpi_ac(psy); 107d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy switch (psp) { 108d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy case POWER_SUPPLY_PROP_ONLINE: 109d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy val->intval = ac->state; 110d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy break; 111d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy default: 112d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy return -EINVAL; 113d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy } 114d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy return 0; 115d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy} 116d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy 117d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiystatic enum power_supply_property ac_props[] = { 118d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy POWER_SUPPLY_PROP_ONLINE, 119d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy}; 12097749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#endif 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AC Adapter Management 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1254be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_get_state(struct acpi_ac *ac) 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1274be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_status status = AE_OK; 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 131d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 133a6ba5ebef91a59fabd45962e576c02468dbcd33fPatrick Mochel status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ACPI_FAILURE(status)) { 135a6fc67202e0224e6c9d1d285cc0b444bce887ed5Thomas Renninger ACPI_EXCEPTION((AE_INFO, status, "Error reading AC Adapter state")); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ac->state = ACPI_AC_STATUS_UNKNOWN; 137d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1394be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 140d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 143fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FS Interface (/proc) 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1484be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic struct proc_dir_entry *acpi_ac_dir; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_ac_seq_show(struct seq_file *seq, void *offset) 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 15250dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt struct acpi_ac *ac = seq->private; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 156d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acpi_ac_get_state(ac)) { 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "ERROR: Unable to read AC Adapter state\n"); 160d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "state: "); 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ac->state) { 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_STATUS_OFFLINE: 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "off-line\n"); 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_STATUS_ONLINE: 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "on-line\n"); 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "unknown\n"); 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 176d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1784be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_ac_open_fs(struct inode *inode, struct file *file) 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return single_open(file, acpi_ac_seq_show, PDE(inode)->data); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1844be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_add_fs(struct acpi_device *device) 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1864be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct proc_dir_entry *entry = NULL; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_device_dir(device)) { 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), 1914be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_ac_dir); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_device_dir(device)) 193d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_device_dir(device)->owner = THIS_MODULE; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 'state' [R] */ 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = create_proc_entry(ACPI_AC_FILE_STATE, 1994be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown S_IRUGO, acpi_device_dir(device)); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!entry) 201d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->proc_fops = &acpi_ac_fops; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->data = acpi_driver_data(device); 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->owner = THIS_MODULE; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 208d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2114be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_remove_fs(struct acpi_device *device) 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acpi_device_dir(device)) { 2154be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown remove_proc_entry(ACPI_AC_FILE_STATE, acpi_device_dir(device)); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_proc_entry(acpi_device_bid(device), acpi_ac_dir); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_device_dir(device) = NULL; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2238a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Driver Model 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2294be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic void acpi_ac_notify(acpi_handle handle, u32 event, void *data) 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 23150dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt struct acpi_ac *ac = data; 2324be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_device *device = NULL; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 236d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 238af96179a8298832cc58be212d0e4988d8a1e11bfPatrick Mochel device = ac->device; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (event) { 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_NOTIFY_STATUS: 24103d782524e2d0511317769521c8d5daadbab8482Christian Lupien case ACPI_NOTIFY_BUS_CHECK: 24203d782524e2d0511317769521c8d5daadbab8482Christian Lupien case ACPI_NOTIFY_DEVICE_CHECK: 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_get_state(ac); 24414e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown acpi_bus_generate_proc_event(device, event, (u32) ac->state); 245962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui acpi_bus_generate_netlink_event(device->pnp.device_class, 246962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui device->dev.bus_id, event, 247962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui (u32) ac->state); 24897749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#ifdef CONFIG_ACPI_SYSFS_POWER 249d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); 25097749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#endif 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_INFO, 2544be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown "Unsupported event [0x%x]\n", event)); 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 258d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2614be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_add(struct acpi_device *device) 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2634be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown int result = 0; 2644be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_status status = AE_OK; 2654be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_ac *ac = NULL; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!device) 269d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27136bcbec7ce21e2e8b3143b11a05747330abeca70Burman Yan ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 273d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENOMEM; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 275af96179a8298832cc58be212d0e4988d8a1e11bfPatrick Mochel ac->device = device; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(acpi_device_class(device), ACPI_AC_CLASS); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_driver_data(device) = ac; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_ac_get_state(ac); 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto end; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 284fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_ac_add_fs(device); 2868a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto end; 28997749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#ifdef CONFIG_ACPI_SYSFS_POWER 290d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.name = acpi_device_bid(device); 291d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.type = POWER_SUPPLY_TYPE_MAINS; 292d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.properties = ac_props; 293d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.num_properties = ARRAY_SIZE(ac_props); 294d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.get_property = get_ac_property; 295d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy power_supply_register(&ac->device->dev, &ac->charger); 29697749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#endif 297a6ba5ebef91a59fabd45962e576c02468dbcd33fPatrick Mochel status = acpi_install_notify_handler(device->handle, 29803d782524e2d0511317769521c8d5daadbab8482Christian Lupien ACPI_ALL_NOTIFY, acpi_ac_notify, 2994be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ac); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ACPI_FAILURE(status)) { 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = -ENODEV; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto end; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3054be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown printk(KERN_INFO PREFIX "%s [%s] (%s)\n", 3064be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_device_name(device), acpi_device_bid(device), 3074be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ac->state ? "on-line" : "off-line"); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3094be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown end: 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 311fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_remove_fs(device); 3138a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ac); 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 317d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return result; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3205bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiystatic int acpi_ac_resume(struct acpi_device *device) 3215bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy{ 3225bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy struct acpi_ac *ac; 3235bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy unsigned old_state; 3245bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy if (!device || !acpi_driver_data(device)) 3255bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy return -EINVAL; 3265bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy ac = acpi_driver_data(device); 3275bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy old_state = ac->state; 3285bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy if (acpi_ac_get_state(ac)) 3295bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy return 0; 33097749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#ifdef CONFIG_ACPI_SYSFS_POWER 3315bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy if (old_state != ac->state) 3325bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); 33397749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#endif 3345bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy return 0; 3355bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy} 3365bfeca3138a6031e38c566d57128ff592eb009a8Alexey Starikovskiy 3374be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_remove(struct acpi_device *device, int type) 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3394be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_status status = AE_OK; 3404be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_ac *ac = NULL; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!device || !acpi_driver_data(device)) 344d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 34650dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt ac = acpi_driver_data(device); 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 348a6ba5ebef91a59fabd45962e576c02468dbcd33fPatrick Mochel status = acpi_remove_notify_handler(device->handle, 34903d782524e2d0511317769521c8d5daadbab8482Christian Lupien ACPI_ALL_NOTIFY, acpi_ac_notify); 35097749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#ifdef CONFIG_ACPI_SYSFS_POWER 351d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy if (ac->charger.dev) 352d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy power_supply_unregister(&ac->charger); 35397749cd9adbb2985e4b2aee1a59d6b970fe9c3a7Alexey Starikovskiy#endif 354fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_remove_fs(device); 3568a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ac); 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 360d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3634be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int __init acpi_ac_init(void) 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3653f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend int result; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3674d8316d5ea4dcf0bf15d8a06d539ed7c99e9cfbePavel Machek if (acpi_disabled) 3684d8316d5ea4dcf0bf15d8a06d539ed7c99e9cfbePavel Machek return -ENODEV; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 370fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3713f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_ac_dir = acpi_lock_ac_dir(); 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_ac_dir) 373d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 3748a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_bus_register_driver(&acpi_ac_driver); 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result < 0) { 378fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3793f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_unlock_ac_dir(acpi_ac_dir); 3808a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 381d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 384d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3874be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic void __exit acpi_ac_exit(void) 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_bus_unregister_driver(&acpi_ac_driver); 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 392fdcedbba2f98c94bfbac9f6e712ab765f997b8dcAlexey Starikovskiy#ifdef CONFIG_ACPI_PROCFS_POWER 3933f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_unlock_ac_dir(acpi_ac_dir); 3948a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 396d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(acpi_ac_init); 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(acpi_ac_exit); 401