diff options
Diffstat (limited to 'drivers/acpi/ac.c')
| -rw-r--r-- | drivers/acpi/ac.c | 130 | 
1 files changed, 128 insertions, 2 deletions
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index c67f6f5ad611..36b0e61f9c09 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -30,6 +30,10 @@  #include <linux/types.h>  #include <linux/dmi.h>  #include <linux/delay.h> +#ifdef CONFIG_ACPI_PROCFS_POWER +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#endif  #include <linux/platform_device.h>  #include <linux/power_supply.h>  #include <linux/acpi.h> @@ -52,6 +56,7 @@ MODULE_AUTHOR("Paul Diefenbaugh");  MODULE_DESCRIPTION("ACPI AC Adapter Driver");  MODULE_LICENSE("GPL"); +  static int acpi_ac_add(struct acpi_device *device);  static int acpi_ac_remove(struct acpi_device *device);  static void acpi_ac_notify(struct acpi_device *device, u32 event); @@ -67,6 +72,13 @@ static int acpi_ac_resume(struct device *dev);  #endif  static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume); +#ifdef CONFIG_ACPI_PROCFS_POWER +extern struct proc_dir_entry *acpi_lock_ac_dir(void); +extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); +static int acpi_ac_open_fs(struct inode *inode, struct file *file); +#endif + +  static int ac_sleep_before_get_state_ms;  static struct acpi_driver acpi_ac_driver = { @@ -91,6 +103,16 @@ struct acpi_ac {  #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger) +#ifdef CONFIG_ACPI_PROCFS_POWER +static const struct file_operations acpi_ac_fops = { +	.owner = THIS_MODULE, +	.open = acpi_ac_open_fs, +	.read = seq_read, +	.llseek = seq_lseek, +	.release = single_release, +}; +#endif +  /* --------------------------------------------------------------------------                                 AC Adapter Management     -------------------------------------------------------------------------- */ @@ -143,6 +165,83 @@ static enum power_supply_property ac_props[] = {  	POWER_SUPPLY_PROP_ONLINE,  }; +#ifdef CONFIG_ACPI_PROCFS_POWER +/* -------------------------------------------------------------------------- +                              FS Interface (/proc) +   -------------------------------------------------------------------------- */ + +static struct proc_dir_entry *acpi_ac_dir; + +static int acpi_ac_seq_show(struct seq_file *seq, void *offset) +{ +	struct acpi_ac *ac = seq->private; + + +	if (!ac) +		return 0; + +	if (acpi_ac_get_state(ac)) { +		seq_puts(seq, "ERROR: Unable to read AC Adapter state\n"); +		return 0; +	} + +	seq_puts(seq, "state:                   "); +	switch (ac->state) { +	case ACPI_AC_STATUS_OFFLINE: +		seq_puts(seq, "off-line\n"); +		break; +	case ACPI_AC_STATUS_ONLINE: +		seq_puts(seq, "on-line\n"); +		break; +	default: +		seq_puts(seq, "unknown\n"); +		break; +	} + +	return 0; +} + +static int acpi_ac_open_fs(struct inode *inode, struct file *file) +{ +	return single_open(file, acpi_ac_seq_show, PDE_DATA(inode)); +} + +static int acpi_ac_add_fs(struct acpi_ac *ac) +{ +	struct proc_dir_entry *entry = NULL; + +	printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded," +			" please retry with CONFIG_ACPI_PROCFS_POWER cleared\n"); +	if (!acpi_device_dir(ac->device)) { +		acpi_device_dir(ac->device) = +			proc_mkdir(acpi_device_bid(ac->device), acpi_ac_dir); +		if (!acpi_device_dir(ac->device)) +			return -ENODEV; +	} + +	/* 'state' [R] */ +	entry = proc_create_data(ACPI_AC_FILE_STATE, +				 S_IRUGO, acpi_device_dir(ac->device), +				 &acpi_ac_fops, ac); +	if (!entry) +		return -ENODEV; +	return 0; +} + +static int acpi_ac_remove_fs(struct acpi_ac *ac) +{ + +	if (acpi_device_dir(ac->device)) { +		remove_proc_entry(ACPI_AC_FILE_STATE, +				  acpi_device_dir(ac->device)); +		remove_proc_entry(acpi_device_bid(ac->device), acpi_ac_dir); +		acpi_device_dir(ac->device) = NULL; +	} + +	return 0; +} +#endif +  /* --------------------------------------------------------------------------                                     Driver Model     -------------------------------------------------------------------------- */ @@ -243,6 +342,11 @@ static int acpi_ac_add(struct acpi_device *device)  		goto end;  	ac->charger.name = acpi_device_bid(device); +#ifdef CONFIG_ACPI_PROCFS_POWER +	result = acpi_ac_add_fs(ac); +	if (result) +		goto end; +#endif  	ac->charger.type = POWER_SUPPLY_TYPE_MAINS;  	ac->charger.properties = ac_props;  	ac->charger.num_properties = ARRAY_SIZE(ac_props); @@ -258,8 +362,12 @@ static int acpi_ac_add(struct acpi_device *device)  	ac->battery_nb.notifier_call = acpi_ac_battery_notify;  	register_acpi_notifier(&ac->battery_nb);  end: -	if (result) +	if (result) { +#ifdef CONFIG_ACPI_PROCFS_POWER +		acpi_ac_remove_fs(ac); +#endif  		kfree(ac); +	}  	dmi_check_system(ac_dmi_table);  	return result; @@ -303,6 +411,10 @@ static int acpi_ac_remove(struct acpi_device *device)  		power_supply_unregister(&ac->charger);  	unregister_acpi_notifier(&ac->battery_nb); +#ifdef CONFIG_ACPI_PROCFS_POWER +	acpi_ac_remove_fs(ac); +#endif +  	kfree(ac);  	return 0; @@ -315,9 +427,20 @@ static int __init acpi_ac_init(void)  	if (acpi_disabled)  		return -ENODEV; +#ifdef CONFIG_ACPI_PROCFS_POWER +	acpi_ac_dir = acpi_lock_ac_dir(); +	if (!acpi_ac_dir) +		return -ENODEV; +#endif + +  	result = acpi_bus_register_driver(&acpi_ac_driver); -	if (result < 0) +	if (result < 0) { +#ifdef CONFIG_ACPI_PROCFS_POWER +		acpi_unlock_ac_dir(acpi_ac_dir); +#endif  		return -ENODEV; +	}  	return 0;  } @@ -325,6 +448,9 @@ static int __init acpi_ac_init(void)  static void __exit acpi_ac_exit(void)  {  	acpi_bus_unregister_driver(&acpi_ac_driver); +#ifdef CONFIG_ACPI_PROCFS_POWER +	acpi_unlock_ac_dir(acpi_ac_dir); +#endif  }  module_init(acpi_ac_init);  module_exit(acpi_ac_exit);  |