ac.c revision 8a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08c
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> 308a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#ifdef CONFIG_ACPI_PROCFS 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/seq_file.h> 338a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 34d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy#include <linux/power_supply.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_bus.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_drivers.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_COMPONENT 0x00020000 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_CLASS "ac_adapter" 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_DEVICE_NAME "AC Adapter" 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_FILE_STATE "state" 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_NOTIFY_STATUS 0x80 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_STATUS_OFFLINE 0x00 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_STATUS_ONLINE 0x01 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_STATUS_UNKNOWN 0xFF 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _COMPONENT ACPI_AC_COMPONENT 48f52fd66d2ea794010c2d7536cf8e6abed0ac4947Len BrownACPI_MODULE_NAME("ac"); 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 50f52fd66d2ea794010c2d7536cf8e6abed0ac4947Len BrownMODULE_AUTHOR("Paul Diefenbaugh"); 517cda93e008e1a477970adbf82dba81a5d4f0ae40Len BrownMODULE_DESCRIPTION("ACPI AC Adapter Driver"); 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 548a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#ifdef CONFIG_ACPI_PROCFS 553f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendextern struct proc_dir_entry *acpi_lock_ac_dir(void); 563f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsendextern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); 578a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkovstatic int acpi_ac_open_fs(struct inode *inode, struct file *file); 588a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 593f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend 604be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_add(struct acpi_device *device); 614be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_remove(struct acpi_device *device, int type); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renningerconst static struct acpi_device_id ac_device_ids[] = { 641ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger {"ACPI0003", 0}, 651ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger {"", 0}, 661ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger}; 671ba90e3a87c46500623afdc3898573e4a5ebb21bThomas RenningerMODULE_DEVICE_TABLE(acpi, ac_device_ids); 681ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct acpi_driver acpi_ac_driver = { 70c2b6705b75d9c7aff98a4602a32230639e10891cLen Brown .name = "ac", 714be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .class = ACPI_AC_CLASS, 721ba90e3a87c46500623afdc3898573e4a5ebb21bThomas Renninger .ids = ac_device_ids, 734be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .ops = { 744be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .add = acpi_ac_add, 754be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .remove = acpi_ac_remove, 764be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown }, 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct acpi_ac { 80d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy struct power_supply charger; 81af96179a8298832cc58be212d0e4988d8a1e11bfPatrick Mochel struct acpi_device * device; 824be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown unsigned long state; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 85d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger); 86d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy 878a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#ifdef CONFIG_ACPI_PROCFS 88d75080328affb4b268da430b7074cc8139cc662aArjan van de Venstatic const struct file_operations acpi_ac_fops = { 894be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .open = acpi_ac_open_fs, 904be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .read = seq_read, 914be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .llseek = seq_lseek, 924be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .release = single_release, 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 948a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 958a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov 96d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiystatic int get_ac_property(struct power_supply *psy, 97d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy enum power_supply_property psp, 98d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy union power_supply_propval *val) 99d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy{ 100d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy struct acpi_ac *ac = to_acpi_ac(psy); 101d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy switch (psp) { 102d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy case POWER_SUPPLY_PROP_ONLINE: 103d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy val->intval = ac->state; 104d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy break; 105d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy default: 106d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy return -EINVAL; 107d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy } 108d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy return 0; 109d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy} 110d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy 111d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiystatic enum power_supply_property ac_props[] = { 112d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy POWER_SUPPLY_PROP_ONLINE, 113d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy}; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AC Adapter Management 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1194be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_get_state(struct acpi_ac *ac) 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1214be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_status status = AE_OK; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 125d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 127a6ba5ebef91a59fabd45962e576c02468dbcd33fPatrick Mochel status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ACPI_FAILURE(status)) { 129a6fc67202e0224e6c9d1d285cc0b444bce887ed5Thomas Renninger ACPI_EXCEPTION((AE_INFO, status, "Error reading AC Adapter state")); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ac->state = ACPI_AC_STATUS_UNKNOWN; 131d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1334be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 134d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1378a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#ifdef CONFIG_ACPI_PROCFS 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FS Interface (/proc) 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1424be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic struct proc_dir_entry *acpi_ac_dir; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_ac_seq_show(struct seq_file *seq, void *offset) 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14650dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt struct acpi_ac *ac = seq->private; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 150d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acpi_ac_get_state(ac)) { 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "ERROR: Unable to read AC Adapter state\n"); 154d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "state: "); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ac->state) { 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_STATUS_OFFLINE: 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "off-line\n"); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_STATUS_ONLINE: 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "on-line\n"); 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "unknown\n"); 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 170d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1724be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_ac_open_fs(struct inode *inode, struct file *file) 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return single_open(file, acpi_ac_seq_show, PDE(inode)->data); 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1784be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_add_fs(struct acpi_device *device) 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1804be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct proc_dir_entry *entry = NULL; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_device_dir(device)) { 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), 1854be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_ac_dir); 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_device_dir(device)) 187d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_device_dir(device)->owner = THIS_MODULE; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 'state' [R] */ 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = create_proc_entry(ACPI_AC_FILE_STATE, 1934be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown S_IRUGO, acpi_device_dir(device)); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!entry) 195d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->proc_fops = &acpi_ac_fops; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->data = acpi_driver_data(device); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->owner = THIS_MODULE; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 202d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2054be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_remove_fs(struct acpi_device *device) 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acpi_device_dir(device)) { 2094be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown remove_proc_entry(ACPI_AC_FILE_STATE, acpi_device_dir(device)); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_proc_entry(acpi_device_bid(device), acpi_ac_dir); 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_device_dir(device) = NULL; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 215d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2178a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Driver Model 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2234be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic void acpi_ac_notify(acpi_handle handle, u32 event, void *data) 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 22550dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt struct acpi_ac *ac = data; 2264be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_device *device = NULL; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 230d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 232af96179a8298832cc58be212d0e4988d8a1e11bfPatrick Mochel device = ac->device; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (event) { 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_NOTIFY_STATUS: 23503d782524e2d0511317769521c8d5daadbab8482Christian Lupien case ACPI_NOTIFY_BUS_CHECK: 23603d782524e2d0511317769521c8d5daadbab8482Christian Lupien case ACPI_NOTIFY_DEVICE_CHECK: 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_get_state(ac); 23814e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown acpi_bus_generate_proc_event(device, event, (u32) ac->state); 239962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui acpi_bus_generate_netlink_event(device->pnp.device_class, 240962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui device->dev.bus_id, event, 241962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui (u32) ac->state); 242d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_INFO, 2464be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown "Unsupported event [0x%x]\n", event)); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 250d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2534be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_add(struct acpi_device *device) 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2554be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown int result = 0; 2564be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_status status = AE_OK; 2574be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_ac *ac = NULL; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!device) 261d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26336bcbec7ce21e2e8b3143b11a05747330abeca70Burman Yan ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL); 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 265d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENOMEM; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 267af96179a8298832cc58be212d0e4988d8a1e11bfPatrick Mochel ac->device = device; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(acpi_device_class(device), ACPI_AC_CLASS); 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_driver_data(device) = ac; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_ac_get_state(ac); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto end; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2768a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#ifdef CONFIG_ACPI_PROCFS 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_ac_add_fs(device); 2788a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto end; 281d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.name = acpi_device_bid(device); 282d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.type = POWER_SUPPLY_TYPE_MAINS; 283d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.properties = ac_props; 284d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.num_properties = ARRAY_SIZE(ac_props); 285d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy ac->charger.get_property = get_ac_property; 286d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy power_supply_register(&ac->device->dev, &ac->charger); 287a6ba5ebef91a59fabd45962e576c02468dbcd33fPatrick Mochel status = acpi_install_notify_handler(device->handle, 28803d782524e2d0511317769521c8d5daadbab8482Christian Lupien ACPI_ALL_NOTIFY, acpi_ac_notify, 2894be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ac); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ACPI_FAILURE(status)) { 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = -ENODEV; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto end; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2954be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown printk(KERN_INFO PREFIX "%s [%s] (%s)\n", 2964be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_device_name(device), acpi_device_bid(device), 2974be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ac->state ? "on-line" : "off-line"); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2994be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown end: 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 3018a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#ifdef CONFIG_ACPI_PROCFS 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_remove_fs(device); 3038a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ac); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 307d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return result; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3104be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_remove(struct acpi_device *device, int type) 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3124be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_status status = AE_OK; 3134be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_ac *ac = NULL; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!device || !acpi_driver_data(device)) 317d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31950dd096973f1d95aa03c6a6d9e148d706b62b68eJan Engelhardt ac = acpi_driver_data(device); 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321a6ba5ebef91a59fabd45962e576c02468dbcd33fPatrick Mochel status = acpi_remove_notify_handler(device->handle, 32203d782524e2d0511317769521c8d5daadbab8482Christian Lupien ACPI_ALL_NOTIFY, acpi_ac_notify); 323d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy if (ac->charger.dev) 324d5b4a3d0efa36de31b86d5677dad6c36cb8735d7Alexey Starikovskiy power_supply_unregister(&ac->charger); 3258a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#ifdef CONFIG_ACPI_PROCFS 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_remove_fs(device); 3278a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ac); 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3344be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int __init acpi_ac_init(void) 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3363f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend int result; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3384d8316d5ea4dcf0bf15d8a06d539ed7c99e9cfbePavel Machek if (acpi_disabled) 3394d8316d5ea4dcf0bf15d8a06d539ed7c99e9cfbePavel Machek return -ENODEV; 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3418a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#ifdef CONFIG_ACPI_PROCFS 3423f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_ac_dir = acpi_lock_ac_dir(); 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_ac_dir) 344d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 3458a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_bus_register_driver(&acpi_ac_driver); 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result < 0) { 3498a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#ifdef CONFIG_ACPI_PROCFS 3503f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_unlock_ac_dir(acpi_ac_dir); 3518a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 352d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 355d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3584be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic void __exit acpi_ac_exit(void) 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_bus_unregister_driver(&acpi_ac_driver); 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3638a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#ifdef CONFIG_ACPI_PROCFS 3643f86b83243d59bb50caf5938d284d22e10d082a4Rich Townsend acpi_unlock_ac_dir(acpi_ac_dir); 3658a246ee43f4b1df3fa5cbf9c4a3d3dcad0b1e08cAndrey Borzenkov#endif 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 367d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(acpi_ac_init); 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(acpi_ac_exit); 372