Subject: [PATCH] [acpi fan] Add new-school fan driver - Create drivers/acpi/drivers/fan.c - Populate with necessary driver files - Add compatible proc interface (1 state file) - Add basic sysfs interface (1 file) - No event interface Signed-off-by: Patrick Mochel --- drivers/acpi/drivers/fan/Kconfig | 9 +++++ drivers/acpi/drivers/fan/Makefile | 7 ++++ drivers/acpi/drivers/fan/device.c | 36 +++++++++++++++++++ drivers/acpi/drivers/fan/driver.c | 60 ++++++++++++++++++++++++++++++++ drivers/acpi/drivers/fan/event.c | 12 ++++++ drivers/acpi/drivers/fan/fan.h | 21 +++++++++++ drivers/acpi/drivers/fan/proc.c | 69 +++++++++++++++++++++++++++++++++++++ drivers/acpi/drivers/fan/sysfs.c | 37 ++++++++++++++++++++ 8 files changed, 251 insertions(+), 0 deletions(-) create mode 100644 drivers/acpi/drivers/fan/Kconfig create mode 100644 drivers/acpi/drivers/fan/Makefile create mode 100644 drivers/acpi/drivers/fan/device.c create mode 100644 drivers/acpi/drivers/fan/driver.c create mode 100644 drivers/acpi/drivers/fan/event.c create mode 100644 drivers/acpi/drivers/fan/fan.h create mode 100644 drivers/acpi/drivers/fan/proc.c create mode 100644 drivers/acpi/drivers/fan/sysfs.c applies-to: cd9ba18a6cb3bdb4035c6c91177aeb31b222a086 ecb8e37227456b4af0cc4b460793742728041368 diff --git a/drivers/acpi/drivers/fan/Kconfig b/drivers/acpi/drivers/fan/Kconfig new file mode 100644 index 0000000..c076e95 --- /dev/null +++ b/drivers/acpi/drivers/fan/Kconfig @@ -0,0 +1,9 @@ + +config ACPI_FAN + tristate "Fan" + depends on ACPI_DM + default y + help + This driver adds support for ACPI fan devices, allowing user-mode + applications to perform basic fan control (on, off, status). + diff --git a/drivers/acpi/drivers/fan/Makefile b/drivers/acpi/drivers/fan/Makefile new file mode 100644 index 0000000..a1e0854 --- /dev/null +++ b/drivers/acpi/drivers/fan/Makefile @@ -0,0 +1,7 @@ +obj-$(CONFIG_ACPI_FAN) += fan.o + +fan-y := driver.o device.o event.o + +fan-$(CONFIG_ACPI_DM_PROC) += proc.o +fan-$(CONFIG_ACPI_DM_SYSFS) += sysfs.o + diff --git a/drivers/acpi/drivers/fan/device.c b/drivers/acpi/drivers/fan/device.c new file mode 100644 index 0000000..e60fa58 --- /dev/null +++ b/drivers/acpi/drivers/fan/device.c @@ -0,0 +1,36 @@ +/** + * drivers/acpi/drivers/fan/device.c - Low-level fan access + * + * Copyright (C) 2006 Patrick Mochel + * + * Based on drivers/acpi/fan.c, which was: + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * This file is released under the GPLv2. + */ + +#include +#include "fan.h" + + +int fan_get_state(struct acpi_fan * af) +{ + int ret = 0; + + ret = acpi_bus_get_power(af->f_ad->acpi_device->handle, + &af->f_state); + if (ret) + dbg("Error reading power state"); + return ret; +} + +int fan_set_state(struct acpi_fan * af, unsigned int state) +{ + int ret = 0; + + ret = acpi_bus_set_power(af->f_ad->acpi_device->handle, state); + if (ret) + dbg("Error setting power state"); + return ret; +} diff --git a/drivers/acpi/drivers/fan/driver.c b/drivers/acpi/drivers/fan/driver.c new file mode 100644 index 0000000..6456572 --- /dev/null +++ b/drivers/acpi/drivers/fan/driver.c @@ -0,0 +1,60 @@ +/*** + * drivers/acpi/drivers/fan.c - New-style ACPI driver fan + * + * Copyright (C) 2006 Patrick Mochel + * + * Based on drivers/acpi/button.c, which was + * + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * This file is released under the GPLv2. + */ + +#include +#include "fan.h" + +static int fan_add(struct acpi_dev * ad) +{ + struct acpi_fan * af; + int ret = 0; + + af = kzalloc(sizeof(struct acpi_fan), GFP_KERNEL); + if (!af) + return -ENOMEM; + + af->f_ad = ad; + + ret = fan_get_state(af); + if (ret) { + kfree(af); + return ret; + } + + dev_set_drvdata(&ad->dev, af); + + printk(KERN_INFO PREFIX "fan [%s] (%s)\n", + acpi_dev_bid(ad), !af->f_state ? "on" : "off"); + return ret; +} + +static int fan_remove(struct acpi_dev * ad) +{ + struct acpi_fan * af = dev_get_drvdata(&ad->dev); + + dev_set_drvdata(&ad->dev, NULL); + kfree(af); + return 0; +} + +acpi_no_start(fan); +acpi_no_stop(fan); +acpi_no_shutdown(fan); +acpi_no_suspend(fan); +acpi_no_resume(fan); + +declare_acpi_driver(fan, ACPI_FAN_HID); + +MODULE_AUTHOR("Patrick Mochel"); +MODULE_DESCRIPTION("ACPI Fan Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/acpi/drivers/fan/event.c b/drivers/acpi/drivers/fan/event.c new file mode 100644 index 0000000..5191258 --- /dev/null +++ b/drivers/acpi/drivers/fan/event.c @@ -0,0 +1,12 @@ +/** + * drivers/acpi/drivers/fan/event.c - ACPI Event notification for fan + * + * Copyright (C) 2006 Patrick Mochel + * + * This file is released under the GPLv2. + */ + +#include +#include "fan.h" + +acpi_device_event_none(fan); diff --git a/drivers/acpi/drivers/fan/fan.h b/drivers/acpi/drivers/fan/fan.h new file mode 100644 index 0000000..e02287c --- /dev/null +++ b/drivers/acpi/drivers/fan/fan.h @@ -0,0 +1,21 @@ + +#ifdef DEBUG +#define dbg(fmt, ...) printk(PREFIX "fan: " fmt "\n", ## __VA_ARGS__) +#else +#define dbg(fmt, ...) +#endif + +#define _COMPONENT ACPI_FAN_COMPONENT +ACPI_MODULE_NAME("acpi_fan"); + + +#define ACPI_FAN_HID "PNP0C0B" + + +struct acpi_fan { + struct acpi_dev * f_ad; + unsigned int f_state; +}; + +extern int fan_get_state(struct acpi_fan * af); +extern int fan_set_state(struct acpi_fan * af, unsigned int state); diff --git a/drivers/acpi/drivers/fan/proc.c b/drivers/acpi/drivers/fan/proc.c new file mode 100644 index 0000000..2f62cd4 --- /dev/null +++ b/drivers/acpi/drivers/fan/proc.c @@ -0,0 +1,69 @@ +/** + * drivers/acpi/drivers/fan/proc.c - procfs interface for fan driver + * + * Copyright (C) 2006 Patrick Mochel + * + * Based on drivers/acpi/fan.c, which was: + * Copyright (C) 2001, 2002 Andy Grover + * Copyright (C) 2001, 2002 Paul Diefenbaugh + * + * This file is released under the GPLv2. + */ + +#include +#include "fan.h" + + +static int read_state(struct seq_file * seq, void * offset) +{ + struct acpi_dev * ad = seq->private; + struct acpi_fan * fan = dev_get_drvdata(&ad->dev); + const char * state; + + if (fan_get_state(fan)) { + seq_puts(seq, "ERROR: Unable to read FAN Adapter state\n"); + return 0; + } + + state = !fan->f_state ? "on" : "off"; + + seq_printf(seq, "state: %s\n", state); + return 0; +} + +static ssize_t write_state(struct file *file, const char __user * buffer, + size_t count, loff_t * ppos) +{ + struct seq_file * m = file->private_data; + struct acpi_dev * ad = m->private; + struct acpi_fan * af = dev_get_drvdata(&ad->dev); + + char state_string[12] = ""; + char * end; + unsigned int state; + int ret; + + if (count > sizeof(state_string) - 1) + return -EINVAL; + + if (copy_from_user(state_string, buffer, count)) + return -EFAULT; + + state = simple_strtoul(state_string, &end, 0); + if (*end) + return -EINVAL; + + ret = fan_set_state(af, state); + return ret; +} + +static int open_state(struct inode * inode, struct file * file) +{ + return single_open(file, read_state, PDE(inode)->data); +} + +static struct acpi_proc_file fan_files[] = { + proc_file_rw(state), +}; + +declare_acpi_proc(fan); diff --git a/drivers/acpi/drivers/fan/sysfs.c b/drivers/acpi/drivers/fan/sysfs.c new file mode 100644 index 0000000..1c2d8f8 --- /dev/null +++ b/drivers/acpi/drivers/fan/sysfs.c @@ -0,0 +1,37 @@ +/** + * drivers/acpi/drivers/fan/sysfs.c - sysfs interface for fan driver. + * + * Copyright (C) 2006 Patrick Mochel + * + * This file is released under the GPLv2. + */ + +#include +#include "fan.h" + +static ssize_t state_show(struct acpi_dev * ad, char * buf) +{ + struct acpi_fan * af = dev_get_drvdata(&ad->dev); + return sprintf(buf, "%u", af->f_state); +} + +static ssize_t state_store(struct acpi_dev * ad, const char * buf, size_t count) +{ + struct acpi_fan * af = dev_get_drvdata(&ad->dev); + unsigned int state; + char * end; + int ret = 0; + + state = simple_strtoul(buf, &end, 0); + if (*end != '\0') + ret = fan_set_state(af, state); + else + ret = -EINVAL; + return ret == 0 ? count : ret; +} + +static struct acpi_dev_attr fan_attrs[] = { + acpi_dev_attr_rw(state), +}; + +acpi_driver_sysfs(fan); --- 0.99.9.GIT