ac.c revision a6ba5ebef91a59fabd45962e576c02468dbcd33f
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> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/seq_file.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_bus.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_drivers.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_COMPONENT 0x00020000 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_CLASS "ac_adapter" 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_HID "ACPI0003" 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_DRIVER_NAME "ACPI AC Adapter Driver" 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_DEVICE_NAME "AC Adapter" 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_FILE_STATE "state" 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_NOTIFY_STATUS 0x80 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_STATUS_OFFLINE 0x00 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_STATUS_ONLINE 0x01 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ACPI_AC_STATUS_UNKNOWN 0xFF 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _COMPONENT ACPI_AC_COMPONENT 474be44fcd3bf648b782f4460fd06dfae6c42ded4bLen BrownACPI_MODULE_NAME("acpi_ac") 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 494be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown MODULE_AUTHOR("Paul Diefenbaugh"); 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION(ACPI_AC_DRIVER_NAME); 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 534be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_add(struct acpi_device *device); 544be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_remove(struct acpi_device *device, int type); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_ac_open_fs(struct inode *inode, struct file *file); 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct acpi_driver acpi_ac_driver = { 584be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .name = ACPI_AC_DRIVER_NAME, 594be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .class = ACPI_AC_CLASS, 604be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .ids = ACPI_AC_HID, 614be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .ops = { 624be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .add = acpi_ac_add, 634be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .remove = acpi_ac_remove, 644be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown }, 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct acpi_ac { 684be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_handle handle; 69af96179a8298832cc58be212d0e4988d8a1e11bfPatrick Mochel struct acpi_device * device; 704be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown unsigned long state; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct file_operations acpi_ac_fops = { 744be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .open = acpi_ac_open_fs, 754be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .read = seq_read, 764be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .llseek = seq_lseek, 774be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .release = single_release, 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds AC Adapter Management 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 844be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_get_state(struct acpi_ac *ac) 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 864be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_status status = AE_OK; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 90d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 92a6ba5ebef91a59fabd45962e576c02468dbcd33fPatrick Mochel status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ACPI_FAILURE(status)) { 94a6fc67202e0224e6c9d1d285cc0b444bce887ed5Thomas Renninger ACPI_EXCEPTION((AE_INFO, status, "Error reading AC Adapter state")); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ac->state = ACPI_AC_STATUS_UNKNOWN; 96d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 984be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 99d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FS Interface (/proc) 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1064be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic struct proc_dir_entry *acpi_ac_dir; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_ac_seq_show(struct seq_file *seq, void *offset) 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1104be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_ac *ac = (struct acpi_ac *)seq->private; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 114d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acpi_ac_get_state(ac)) { 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "ERROR: Unable to read AC Adapter state\n"); 118d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "state: "); 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ac->state) { 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_STATUS_OFFLINE: 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "off-line\n"); 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_STATUS_ONLINE: 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "on-line\n"); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds seq_puts(seq, "unknown\n"); 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 134d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1364be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int acpi_ac_open_fs(struct inode *inode, struct file *file) 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return single_open(file, acpi_ac_seq_show, PDE(inode)->data); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1424be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_add_fs(struct acpi_device *device) 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1444be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct proc_dir_entry *entry = NULL; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_device_dir(device)) { 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), 1494be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_ac_dir); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_device_dir(device)) 151d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_device_dir(device)->owner = THIS_MODULE; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 'state' [R] */ 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = create_proc_entry(ACPI_AC_FILE_STATE, 1574be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown S_IRUGO, acpi_device_dir(device)); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!entry) 159d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->proc_fops = &acpi_ac_fops; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->data = acpi_driver_data(device); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->owner = THIS_MODULE; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 166d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1694be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_remove_fs(struct acpi_device *device) 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acpi_device_dir(device)) { 1734be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown remove_proc_entry(ACPI_AC_FILE_STATE, acpi_device_dir(device)); 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_proc_entry(acpi_device_bid(device), acpi_ac_dir); 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_device_dir(device) = NULL; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 179d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* -------------------------------------------------------------------------- 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Driver Model 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -------------------------------------------------------------------------- */ 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1864be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic void acpi_ac_notify(acpi_handle handle, u32 event, void *data) 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1884be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_ac *ac = (struct acpi_ac *)data; 1894be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_device *device = NULL; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 193d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 195af96179a8298832cc58be212d0e4988d8a1e11bfPatrick Mochel device = ac->device; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (event) { 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case ACPI_AC_NOTIFY_STATUS: 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_get_state(ac); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_bus_generate_event(device, event, (u32) ac->state); 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_INFO, 2034be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown "Unsupported event [0x%x]\n", event)); 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 207d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2104be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_add(struct acpi_device *device) 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2124be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown int result = 0; 2134be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_status status = AE_OK; 2144be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_ac *ac = NULL; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!device) 218d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ac = kmalloc(sizeof(struct acpi_ac), GFP_KERNEL); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ac) 222d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENOMEM; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(ac, 0, sizeof(struct acpi_ac)); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ac->handle = device->handle; 226af96179a8298832cc58be212d0e4988d8a1e11bfPatrick Mochel ac->device = device; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME); 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(acpi_device_class(device), ACPI_AC_CLASS); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_driver_data(device) = ac; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_ac_get_state(ac); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto end; 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_ac_add_fs(device); 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto end; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 239a6ba5ebef91a59fabd45962e576c02468dbcd33fPatrick Mochel status = acpi_install_notify_handler(device->handle, 2404be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ACPI_DEVICE_NOTIFY, acpi_ac_notify, 2414be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ac); 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ACPI_FAILURE(status)) { 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = -ENODEV; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto end; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2474be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown printk(KERN_INFO PREFIX "%s [%s] (%s)\n", 2484be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_device_name(device), acpi_device_bid(device), 2494be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ac->state ? "on-line" : "off-line"); 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2514be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown end: 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result) { 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_remove_fs(device); 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ac); 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 257d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return result; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2604be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_ac_remove(struct acpi_device *device, int type) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2624be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown acpi_status status = AE_OK; 2634be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_ac *ac = NULL; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!device || !acpi_driver_data(device)) 267d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EINVAL; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2694be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ac = (struct acpi_ac *)acpi_driver_data(device); 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271a6ba5ebef91a59fabd45962e576c02468dbcd33fPatrick Mochel status = acpi_remove_notify_handler(device->handle, 2724be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown ACPI_DEVICE_NOTIFY, acpi_ac_notify); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_remove_fs(device); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(ac); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 278d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2814be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int __init acpi_ac_init(void) 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2834be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown int result = 0; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir); 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!acpi_ac_dir) 288d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_ac_dir->owner = THIS_MODULE; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_bus_register_driver(&acpi_ac_driver); 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (result < 0) { 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); 294d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -ENODEV; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 297d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3004be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic void __exit acpi_ac_exit(void) 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds acpi_bus_unregister_driver(&acpi_ac_driver); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 307d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(acpi_ac_init); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(acpi_ac_exit); 312