From: Greg Kroah-Hartman Date: Wed, 22 Oct 2008 05:21:51 +0000 (-0700) Subject: Staging: pcc-acpi: update to latest version X-Git-Tag: v2.6.28-rc1~34^2~12 X-Git-Url: http://www.pilppa.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=f2d86100d95274bd85a36b7b7c0efa9af0d82b2b;p=linux-2.6-omap-h63xx.git Staging: pcc-acpi: update to latest version Import the changes from the upstream driver into this version to keep things up to date. Cc: Yokota Hiroshi Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/pcc-acpi/pcc-acpi.c b/drivers/staging/pcc-acpi/pcc-acpi.c index ffda32a1030..e44181ead26 100644 --- a/drivers/staging/pcc-acpi/pcc-acpi.c +++ b/drivers/staging/pcc-acpi/pcc-acpi.c @@ -94,20 +94,21 @@ * */ -#define ACPI_PCC_VERSION "0.9" +#define ACPI_PCC_VERSION "0.9+hy" -#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include #include -#include #include -#include -#include -#include -#include +#include +#include +#include /************************************************************************* @@ -152,10 +153,10 @@ static int _open_func_name_(struct inode *inode, struct file *file) \ #endif #define _COMPONENT ACPI_HOTKEY_COMPONENT -ACPI_MODULE_NAME("pcc_acpi") +ACPI_MODULE_NAME("pcc_acpi"); -MODULE_AUTHOR("Hiroshi Miura"); -MODULE_DESCRIPTION("ACPI HotKey driver for Panasonic Lets Note laptops"); +MODULE_AUTHOR("Hiroshi Miura, Hiroshi Yokota"); +MODULE_DESCRIPTION("ACPI HotKey driver for Panasonic Let's Note laptops"); MODULE_LICENSE("GPL"); #define LOGPREFIX "pcc_acpi: " @@ -182,7 +183,7 @@ MODULE_LICENSE("GPL"); * definitions for /proc/ interface * *******************************************************************/ -#define ACPI_PCC_DRIVER_NAME "PCC Extra Driver" +#define ACPI_PCC_DRIVER_NAME "pcc_acpi" #define ACPI_PCC_DEVICE_NAME "PCCExtra" #define ACPI_PCC_CLASS "pcc" #define PROC_PCC ACPI_PCC_CLASS @@ -196,6 +197,12 @@ MODULE_LICENSE("GPL"); #define PROC_STR_MAX_LEN 8 +#define BUS_PCC_HOTKEY BUS_I8042 /*0x1a*/ /* FIXME: BUS_I8042? */ + +/* Fn+F4/F5 confricts with Shift+F1/F2 */ +/* This hack avoids key number confrict */ +#define PCC_KEYINPUT_MODE (0) + /* LCD_TYPEs: 0 = Normal, 1 = Semi-transparent ENV_STATEs: Normal temp=0x01, High temp=0x81, N/A=0x00 */ @@ -209,27 +216,32 @@ enum SINF_BITS { SINF_NUM_BATTERIES = 0, SINF_STICKY_KEY = 0x80, }; -static int acpi_pcc_hotkey_add(struct acpi_device *device); -static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type); -static int acpi_pcc_hotkey_resume(struct acpi_device *device); - -static const struct acpi_device_id pcc_device_ids[] = { +static struct acpi_device_id pcc_device_ids[] = { {"MAT0012", 0}, {"MAT0013", 0}, {"MAT0018", 0}, {"MAT0019", 0}, - {"", 0}, + {"", 0}, }; MODULE_DEVICE_TABLE(acpi, pcc_device_ids); + +static int __devinit acpi_pcc_hotkey_add(struct acpi_device *device); +static int __devexit acpi_pcc_hotkey_remove(struct acpi_device *device, int type); +static int acpi_pcc_hotkey_resume(struct acpi_device *device); + + static struct acpi_driver acpi_pcc_driver = { .name = ACPI_PCC_DRIVER_NAME, .class = ACPI_PCC_CLASS, .ids = pcc_device_ids, .ops = { .add = acpi_pcc_hotkey_add, - .remove = acpi_pcc_hotkey_remove, + .remove = __devexit_p(acpi_pcc_hotkey_remove), +#ifdef CONFIG_PM + /*.suspend = acpi_pcc_hotkey_suspend,*/ .resume = acpi_pcc_hotkey_resume, +#endif }, }; @@ -248,9 +260,12 @@ struct pcc_keyinput { int key_mode; }; -/* -------------------------------------------------------------------------- +/* ************************************************************************* + Hotkey driver core + ************************************************************************* */ +/* ------------------------------------------------------------------------- method access functions - -------------------------------------------------------------------------- */ + ------------------------------------------------------------------------- */ static int acpi_pcc_write_sset(struct acpi_hotkey *hotkey, int func, int val) { union acpi_object in_objs[] = { @@ -263,13 +278,13 @@ static int acpi_pcc_write_sset(struct acpi_hotkey *hotkey, int func, int val) .count = ARRAY_SIZE(in_objs), .pointer = in_objs, }; - acpi_status status = AE_OK; + acpi_status status; ACPI_FUNCTION_TRACE("acpi_pcc_write_sset"); status = acpi_evaluate_object(hotkey->handle, METHOD_HKEY_SSET, ¶ms, NULL); - return_VALUE(status == AE_OK); + return_VALUE(status == AE_OK ? AE_OK : AE_ERROR); } static inline int acpi_pcc_get_sqty(struct acpi_device *device) @@ -301,19 +316,20 @@ static int acpi_pcc_retrieve_biosdata(struct acpi_hotkey *hotkey, u32* sinf) status = acpi_evaluate_object(hotkey->handle, METHOD_HKEY_SINF, 0 , &buffer); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "evaluation error HKEY.SINF\n")); - return_VALUE(0); + status = AE_ERROR; + return_VALUE(status); } hkey = buffer.pointer; if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n")); - goto end; + goto free_buffer; } if (hotkey->num_sifr < hkey->package.count) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "SQTY reports bad SINF length\n")); status = AE_ERROR; - goto end; + goto free_buffer; } for (i = 0; i < hkey->package.count; i++) { @@ -322,59 +338,54 @@ static int acpi_pcc_retrieve_biosdata(struct acpi_hotkey *hotkey, u32* sinf) sinf[i] = element->integer.value; } else { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF data\n")); + status = AE_ERROR; + break; } } sinf[hkey->package.count] = -1; -end: + free_buffer: kfree(buffer.pointer); - return_VALUE(status == AE_OK); + return_VALUE(status == AE_OK ? AE_OK : AE_ERROR); } static int acpi_pcc_read_sinf_field(struct seq_file *seq, int field) { struct acpi_hotkey *hotkey = (struct acpi_hotkey *) seq->private; - u32* sinf = kmalloc(sizeof(u32) * (hotkey->num_sifr + 1), GFP_KERNEL); + u32 sinf[hotkey->num_sifr + 1]; ACPI_FUNCTION_TRACE("acpi_pcc_read_sinf_field"); - if (!sinf) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate %li bytes\n", - sizeof(u32) * hotkey->num_sifr)); - return_VALUE(0); - } - - if (acpi_pcc_retrieve_biosdata(hotkey, sinf)) { + if (ACPI_SUCCESS(acpi_pcc_retrieve_biosdata(hotkey, sinf))) { seq_printf(seq, "%u\n", sinf[field]); } else { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't retrieve BIOS data\n")); } - kfree(sinf); - return_VALUE(0); + return_VALUE(AE_OK); } -/* -------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- user interface functions - -------------------------------------------------------------------------- */ + ------------------------------------------------------------------------- */ /* read methods */ /* Sinf read methods */ #define PCC_SINF_READ_F(_name_, FUNC) \ static int _name_ (struct seq_file *seq, void *offset) \ { \ - return acpi_pcc_read_sinf_field(seq, (FUNC)); \ + return_VALUE(ACPI_SUCCESS(acpi_pcc_read_sinf_field(seq, (FUNC))) ? 0 : -EINVAL); \ } -PCC_SINF_READ_F(acpi_pcc_numbatteries_show, SINF_NUM_BATTERIES); -PCC_SINF_READ_F(acpi_pcc_lcdtype_show, SINF_LCD_TYPE); +PCC_SINF_READ_F(acpi_pcc_numbatteries_show, SINF_NUM_BATTERIES); +PCC_SINF_READ_F(acpi_pcc_lcdtype_show, SINF_LCD_TYPE); PCC_SINF_READ_F(acpi_pcc_ac_brightness_max_show, SINF_AC_MAX_BRIGHT); PCC_SINF_READ_F(acpi_pcc_ac_brightness_min_show, SINF_AC_MIN_BRIGHT); -PCC_SINF_READ_F(acpi_pcc_ac_brightness_show, SINF_AC_CUR_BRIGHT); +PCC_SINF_READ_F(acpi_pcc_ac_brightness_show, SINF_AC_CUR_BRIGHT); PCC_SINF_READ_F(acpi_pcc_dc_brightness_max_show, SINF_DC_MAX_BRIGHT); PCC_SINF_READ_F(acpi_pcc_dc_brightness_min_show, SINF_DC_MIN_BRIGHT); -PCC_SINF_READ_F(acpi_pcc_dc_brightness_show, SINF_DC_CUR_BRIGHT); -PCC_SINF_READ_F(acpi_pcc_brightness_show, SINF_AC_CUR_BRIGHT); -PCC_SINF_READ_F(acpi_pcc_mute_show, SINF_MUTE); +PCC_SINF_READ_F(acpi_pcc_dc_brightness_show, SINF_DC_CUR_BRIGHT); +PCC_SINF_READ_F(acpi_pcc_brightness_show, SINF_AC_CUR_BRIGHT); +PCC_SINF_READ_F(acpi_pcc_mute_show, SINF_MUTE); static int acpi_pcc_sticky_key_show(struct seq_file *seq, void *offset) { @@ -383,7 +394,7 @@ static int acpi_pcc_sticky_key_show(struct seq_file *seq, void *offset) ACPI_FUNCTION_TRACE("acpi_pcc_sticky_key_show"); if (!hotkey || !hotkey->device) { - return_VALUE(0); + return_VALUE(-EINVAL); } seq_printf(seq, "%d\n", hotkey->sticky_mode); @@ -410,8 +421,9 @@ static int acpi_pcc_version_show(struct seq_file *seq, void *offset) ACPI_FUNCTION_TRACE("acpi_pcc_version_show"); - if (!hotkey || !hotkey->device) - return 0; + if (!hotkey || !hotkey->device) { + return_VALUE(-EINVAL); + } seq_printf(seq, "%s version %s\n", ACPI_PCC_DRIVER_NAME, ACPI_PCC_VERSION); seq_printf(seq, "%li functions\n", hotkey->num_sifr); @@ -421,27 +433,28 @@ static int acpi_pcc_version_show(struct seq_file *seq, void *offset) /* write methods */ static ssize_t acpi_pcc_write_single_flag (struct file *file, - const char __user *buffer, - size_t count, - int sinf_func) + const char __user *buffer, + size_t count, + int sinf_func) { struct seq_file *seq = file->private_data; struct acpi_hotkey *hotkey = seq->private; char write_string[PROC_STR_MAX_LEN]; - u32 val; + u32 val; ACPI_FUNCTION_TRACE("acpi_pcc_write_single_flag"); if (!hotkey || (count > sizeof(write_string) - 1)) { return_VALUE(-EINVAL); - } + } if (copy_from_user(write_string, buffer, count)) { return_VALUE(-EFAULT); - } + } write_string[count] = '\0'; - if (sscanf(write_string, "%i", &val) == 1 && (val == 0 || val == 1)) { + if ((sscanf(write_string, "%3i", &val) == 1) && + (val == 0 || val == 1)) { acpi_pcc_write_sset(hotkey, sinf_func, val); } @@ -457,53 +470,51 @@ static unsigned long acpi_pcc_write_brightness(struct file *file, const char __u struct acpi_hotkey *hotkey = (struct acpi_hotkey *)seq->private; char write_string[PROC_STR_MAX_LEN]; u32 bright; - u32* sinf = kmalloc(sizeof(u32) * (hotkey->num_sifr + 1), GFP_KERNEL); + u32 sinf[hotkey->num_sifr + 1]; ACPI_FUNCTION_TRACE("acpi_pcc_write_brightness"); - if (!hotkey || (count > sizeof(write_string) - 1)) + if (!hotkey || (count > sizeof(write_string) - 1)) { return_VALUE(-EINVAL); - - if (!sinf) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate %li bytes\n", - sizeof(u32) * hotkey->num_sifr)); - return_VALUE(-EFAULT); } - if (copy_from_user(write_string, buffer, count)) + if (copy_from_user(write_string, buffer, count)) { return_VALUE(-EFAULT); + } write_string[count] = '\0'; - if (!acpi_pcc_retrieve_biosdata(hotkey, sinf)) { + if (ACPI_FAILURE(acpi_pcc_retrieve_biosdata(hotkey, sinf))) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't retrieve BIOS data\n")); goto end; } - if (sscanf(write_string, "%i", &bright) == 1 && - bright >= sinf[min_index] && bright <= sinf[max_index]) { - acpi_pcc_write_sset(hotkey, cur_index, bright); + if ((sscanf(write_string, "%4i", &bright) == 1) && + (bright >= sinf[min_index] ) && + (bright <= sinf[max_index] )) { + acpi_pcc_write_sset(hotkey, cur_index, bright); } end: - kfree(sinf); return_VALUE(count); } static ssize_t acpi_pcc_write_ac_brightness(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - return acpi_pcc_write_brightness(file, buffer, count, SINF_AC_MIN_BRIGHT, - SINF_AC_MAX_BRIGHT, - SINF_AC_CUR_BRIGHT); + return_VALUE(acpi_pcc_write_brightness(file, buffer, count, + SINF_AC_MIN_BRIGHT, + SINF_AC_MAX_BRIGHT, + SINF_AC_CUR_BRIGHT)); } static ssize_t acpi_pcc_write_dc_brightness(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - return acpi_pcc_write_brightness(file, buffer, count, SINF_DC_MIN_BRIGHT, - SINF_DC_MAX_BRIGHT, - SINF_DC_CUR_BRIGHT); + return_VALUE(acpi_pcc_write_brightness(file, buffer, count, + SINF_DC_MIN_BRIGHT, + SINF_DC_MAX_BRIGHT, + SINF_DC_CUR_BRIGHT)); } static ssize_t acpi_pcc_write_no_brightness(struct file *file, const char __user *buffer, @@ -518,14 +529,36 @@ static ssize_t acpi_pcc_write_mute (struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - return acpi_pcc_write_single_flag(file, buffer, count, SINF_MUTE); + return_VALUE(acpi_pcc_write_single_flag(file, buffer, count, SINF_MUTE)); } static ssize_t acpi_pcc_write_sticky_key (struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { - return acpi_pcc_write_single_flag(file, buffer, count, SINF_STICKY_KEY); + struct seq_file *seq = (struct seq_file *)file->private_data; + struct acpi_hotkey *hotkey = (struct acpi_hotkey *)seq->private; + char write_string[PROC_STR_MAX_LEN]; + int mode; + + ACPI_FUNCTION_TRACE("acpi_pcc_write_sticky_key"); + + if (!hotkey || (count > sizeof(write_string) - 1)) { + return_VALUE(-EINVAL); + } + + if (copy_from_user(write_string, buffer, count)) { + return_VALUE(-EFAULT); + } + write_string[count] = '\0'; + + if ((sscanf(write_string, "%3i", &mode) == 1) && + (mode == 0 || mode == 1)) { + acpi_pcc_write_sset(hotkey, SINF_STICKY_KEY, mode); + hotkey->sticky_mode = mode; + } + + return_VALUE(count); } static ssize_t acpi_pcc_write_keyinput(struct file *file, const char __user *buffer, @@ -539,25 +572,28 @@ static ssize_t acpi_pcc_write_keyinput(struct file *file, const char __user *buf ACPI_FUNCTION_TRACE("acpi_pcc_write_keyinput"); - if (!hotkey || (count > sizeof(write_string) - 1)) + if (!hotkey || (count > (sizeof(write_string) - 1))) { return_VALUE(-EINVAL); + } - if (copy_from_user(write_string, buffer, count)) + if (copy_from_user(write_string, buffer, count)) { return_VALUE(-EFAULT); + } write_string[count] = '\0'; - if (sscanf(write_string, "%i", &key_mode) == 1 && (key_mode == 0 || key_mode == 1)) { - keyinput = (struct pcc_keyinput *)input_get_drvdata(hotkey->input_dev); + if ((sscanf(write_string, "%4i", &key_mode) == 1) && + (key_mode == 0 || key_mode == 1)) { + keyinput = input_get_drvdata(hotkey->input_dev); keyinput->key_mode = key_mode; } return_VALUE(count); } -/* -------------------------------------------------------------------------- +/* ------------------------------------------------------------------------- hotkey driver - -------------------------------------------------------------------------- */ + ------------------------------------------------------------------------- */ static void acpi_pcc_generete_keyinput(struct acpi_hotkey *hotkey) { struct input_dev *hotk_input_dev = hotkey->input_dev; @@ -640,38 +676,38 @@ void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data) return_VOID; } -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ +/* ************************************************************************* + FS Interface (/proc) + ************************************************************************* */ /* oepn proc file fs*/ -SEQ_OPEN_FS(acpi_pcc_dc_brightness_open_fs, acpi_pcc_dc_brightness_show); -SEQ_OPEN_FS(acpi_pcc_numbatteries_open_fs, acpi_pcc_numbatteries_show); -SEQ_OPEN_FS(acpi_pcc_lcdtype_open_fs, acpi_pcc_lcdtype_show); +SEQ_OPEN_FS(acpi_pcc_dc_brightness_open_fs, acpi_pcc_dc_brightness_show); +SEQ_OPEN_FS(acpi_pcc_numbatteries_open_fs, acpi_pcc_numbatteries_show); +SEQ_OPEN_FS(acpi_pcc_lcdtype_open_fs, acpi_pcc_lcdtype_show); SEQ_OPEN_FS(acpi_pcc_ac_brightness_max_open_fs, acpi_pcc_ac_brightness_max_show); -SEQ_OPEN_FS(acpi_pcc_ac_brightness_min_open_fs, acpi_pcc_ac_brightness_min_show); -SEQ_OPEN_FS(acpi_pcc_ac_brightness_open_fs, acpi_pcc_ac_brightness_show); +SEQ_OPEN_FS(acpi_pcc_ac_brightness_min_open_fs, acpi_pcc_ac_brightness_min_show); +SEQ_OPEN_FS(acpi_pcc_ac_brightness_open_fs, acpi_pcc_ac_brightness_show); SEQ_OPEN_FS(acpi_pcc_dc_brightness_max_open_fs, acpi_pcc_dc_brightness_max_show); SEQ_OPEN_FS(acpi_pcc_dc_brightness_min_open_fs, acpi_pcc_dc_brightness_min_show); -SEQ_OPEN_FS(acpi_pcc_brightness_open_fs, acpi_pcc_brightness_show); -SEQ_OPEN_FS(acpi_pcc_mute_open_fs, acpi_pcc_mute_show); -SEQ_OPEN_FS(acpi_pcc_version_open_fs, acpi_pcc_version_show); -SEQ_OPEN_FS(acpi_pcc_keyinput_open_fs, acpi_pcc_keyinput_show); -SEQ_OPEN_FS(acpi_pcc_sticky_key_open_fs, acpi_pcc_sticky_key_show); +SEQ_OPEN_FS(acpi_pcc_brightness_open_fs, acpi_pcc_brightness_show); +SEQ_OPEN_FS(acpi_pcc_mute_open_fs, acpi_pcc_mute_show); +SEQ_OPEN_FS(acpi_pcc_version_open_fs, acpi_pcc_version_show); +SEQ_OPEN_FS(acpi_pcc_keyinput_open_fs, acpi_pcc_keyinput_show); +SEQ_OPEN_FS(acpi_pcc_sticky_key_open_fs, acpi_pcc_sticky_key_show); typedef struct file_operations fops_t; -static fops_t acpi_pcc_numbatteries_fops = SEQ_FILEOPS_R (acpi_pcc_numbatteries_open_fs); -static fops_t acpi_pcc_lcdtype_fops = SEQ_FILEOPS_R (acpi_pcc_lcdtype_open_fs); -static fops_t acpi_pcc_mute_fops = SEQ_FILEOPS_RW(acpi_pcc_mute_open_fs, acpi_pcc_write_mute); -static fops_t acpi_pcc_ac_brightness_fops = SEQ_FILEOPS_RW(acpi_pcc_ac_brightness_open_fs, acpi_pcc_write_ac_brightness); -static fops_t acpi_pcc_ac_brightness_max_fops = SEQ_FILEOPS_R(acpi_pcc_ac_brightness_max_open_fs); -static fops_t acpi_pcc_ac_brightness_min_fops = SEQ_FILEOPS_R(acpi_pcc_ac_brightness_min_open_fs); -static fops_t acpi_pcc_dc_brightness_fops = SEQ_FILEOPS_RW(acpi_pcc_dc_brightness_open_fs, acpi_pcc_write_dc_brightness); -static fops_t acpi_pcc_dc_brightness_max_fops = SEQ_FILEOPS_R(acpi_pcc_dc_brightness_max_open_fs); -static fops_t acpi_pcc_dc_brightness_min_fops = SEQ_FILEOPS_R(acpi_pcc_dc_brightness_min_open_fs); -static fops_t acpi_pcc_brightness_fops = SEQ_FILEOPS_RW(acpi_pcc_brightness_open_fs, acpi_pcc_write_no_brightness); -static fops_t acpi_pcc_sticky_key_fops = SEQ_FILEOPS_RW(acpi_pcc_sticky_key_open_fs, acpi_pcc_write_sticky_key); -static fops_t acpi_pcc_keyinput_fops = SEQ_FILEOPS_RW(acpi_pcc_keyinput_open_fs, acpi_pcc_write_keyinput); -static fops_t acpi_pcc_version_fops = SEQ_FILEOPS_R (acpi_pcc_version_open_fs); +static fops_t acpi_pcc_numbatteries_fops = SEQ_FILEOPS_R (acpi_pcc_numbatteries_open_fs); +static fops_t acpi_pcc_lcdtype_fops = SEQ_FILEOPS_R (acpi_pcc_lcdtype_open_fs); +static fops_t acpi_pcc_mute_fops = SEQ_FILEOPS_RW(acpi_pcc_mute_open_fs, acpi_pcc_write_mute); +static fops_t acpi_pcc_ac_brightness_fops = SEQ_FILEOPS_RW(acpi_pcc_ac_brightness_open_fs, acpi_pcc_write_ac_brightness); +static fops_t acpi_pcc_ac_brightness_max_fops = SEQ_FILEOPS_R (acpi_pcc_ac_brightness_max_open_fs); +static fops_t acpi_pcc_ac_brightness_min_fops = SEQ_FILEOPS_R (acpi_pcc_ac_brightness_min_open_fs); +static fops_t acpi_pcc_dc_brightness_fops = SEQ_FILEOPS_RW(acpi_pcc_dc_brightness_open_fs, acpi_pcc_write_dc_brightness); +static fops_t acpi_pcc_dc_brightness_max_fops = SEQ_FILEOPS_R (acpi_pcc_dc_brightness_max_open_fs); +static fops_t acpi_pcc_dc_brightness_min_fops = SEQ_FILEOPS_R (acpi_pcc_dc_brightness_min_open_fs); +static fops_t acpi_pcc_brightness_fops = SEQ_FILEOPS_RW(acpi_pcc_brightness_open_fs, acpi_pcc_write_no_brightness); +static fops_t acpi_pcc_sticky_key_fops = SEQ_FILEOPS_RW(acpi_pcc_sticky_key_open_fs, acpi_pcc_write_sticky_key); +static fops_t acpi_pcc_keyinput_fops = SEQ_FILEOPS_RW(acpi_pcc_keyinput_open_fs, acpi_pcc_write_keyinput); +static fops_t acpi_pcc_version_fops = SEQ_FILEOPS_R (acpi_pcc_version_open_fs); typedef struct _ProcItem { @@ -681,37 +717,35 @@ typedef struct _ProcItem } ProcItem; /* Note: These functions map *exactly* to the SINF/SSET functions */ -ProcItem pcc_proc_items_sifr[] = -{ - { "num_batteries", &acpi_pcc_numbatteries_fops, S_IRUGO }, - { "lcd_type", &acpi_pcc_lcdtype_fops, S_IRUGO }, +ProcItem acpi_pcc_proc_items_sifr[] = { + { "num_batteries", &acpi_pcc_numbatteries_fops, S_IRUGO }, + { "lcd_type", &acpi_pcc_lcdtype_fops, S_IRUGO }, { "ac_brightness_max" , &acpi_pcc_ac_brightness_max_fops,S_IRUGO }, { "ac_brightness_min" , &acpi_pcc_ac_brightness_min_fops,S_IRUGO }, - { "ac_brightness" , &acpi_pcc_ac_brightness_fops, S_IFREG | S_IRUGO | S_IWUSR }, + { "ac_brightness" , &acpi_pcc_ac_brightness_fops, S_IFREG | S_IRUGO | S_IWUSR }, { "dc_brightness_max" , &acpi_pcc_dc_brightness_max_fops,S_IRUGO }, { "dc_brightness_min" , &acpi_pcc_dc_brightness_min_fops,S_IRUGO }, - { "dc_brightness" , &acpi_pcc_dc_brightness_fops, S_IFREG | S_IRUGO | S_IWUSR }, - { "brightness" , &acpi_pcc_brightness_fops, S_IFREG | S_IRUGO | S_IWUSR }, - { "mute", &acpi_pcc_mute_fops, S_IFREG | S_IRUGO | S_IWUSR }, + { "dc_brightness" , &acpi_pcc_dc_brightness_fops, S_IFREG | S_IRUGO | S_IWUSR }, + { "brightness" , &acpi_pcc_brightness_fops, S_IFREG | S_IRUGO | S_IWUSR }, + { "mute", &acpi_pcc_mute_fops, S_IFREG | S_IRUGO | S_IWUSR }, { NULL, NULL, 0 }, }; -ProcItem pcc_proc_items[] = -{ +ProcItem acpi_pcc_proc_items[] = { { "sticky_key", &acpi_pcc_sticky_key_fops, S_IFREG | S_IRUGO | S_IWUSR }, - { "keyinput", &acpi_pcc_keyinput_fops, S_IFREG | S_IRUGO | S_IWUSR }, - { "version", &acpi_pcc_version_fops, S_IRUGO }, + { "keyinput", &acpi_pcc_keyinput_fops, S_IFREG | S_IRUGO | S_IWUSR }, + { "version", &acpi_pcc_version_fops, S_IRUGO }, { NULL, NULL, 0 }, }; -static int acpi_pcc_add_device(struct acpi_device *device, - ProcItem *proc_items, - int num) +static int __devinit acpi_pcc_add_device(struct acpi_device *device, + ProcItem *proc_items, + int num) { + struct acpi_hotkey *hotkey = (struct acpi_hotkey*)acpi_driver_data(device); struct proc_dir_entry* proc; ProcItem* item; int i; - struct acpi_hotkey *hotkey = (struct acpi_hotkey*)acpi_driver_data(device); for (item = proc_items, i = 0; item->name && i < num; ++item, ++i) { proc = create_proc_entry(item->name, item->flag, hotkey->proc_dir_entry); @@ -724,16 +758,16 @@ static int acpi_pcc_add_device(struct acpi_device *device, item--; remove_proc_entry(item->name, hotkey->proc_dir_entry); } - return -ENODEV; + return_VALUE(-ENODEV); } } - return 0; + return_VALUE(0); } -static int acpi_pcc_proc_init(struct acpi_device *device) +static int __devinit acpi_pcc_proc_init(struct acpi_device *device) { - struct proc_dir_entry* acpi_pcc_dir; - struct acpi_hotkey *hotkey = (struct acpi_hotkey*)acpi_driver_data(device); + struct proc_dir_entry *acpi_pcc_dir; + struct acpi_hotkey *hotkey = (struct acpi_hotkey*)acpi_driver_data(device); acpi_status status; ACPI_FUNCTION_TRACE("acpi_pcc_proc_init"); @@ -748,8 +782,8 @@ static int acpi_pcc_proc_init(struct acpi_device *device) acpi_pcc_dir->owner = THIS_MODULE; hotkey->proc_dir_entry = acpi_pcc_dir; - status = acpi_pcc_add_device(device, pcc_proc_items_sifr, hotkey->num_sifr); - status |= acpi_pcc_add_device(device, pcc_proc_items, sizeof(pcc_proc_items)/sizeof(ProcItem)); + status = acpi_pcc_add_device(device, acpi_pcc_proc_items_sifr, hotkey->num_sifr); + status |= acpi_pcc_add_device(device, acpi_pcc_proc_items, ARRAY_SIZE(acpi_pcc_proc_items)); if (unlikely(status)) { remove_proc_entry(PROC_PCC, acpi_root_dir); hotkey->proc_dir_entry = NULL; @@ -759,9 +793,9 @@ static int acpi_pcc_proc_init(struct acpi_device *device) return_VALUE(status); } -static void acpi_pcc_remove_device(struct acpi_device *device, - ProcItem *proc_items, - int num) +static void __devexit acpi_pcc_remove_device(struct acpi_device *device, + ProcItem *proc_items, + int num) { struct acpi_hotkey *hotkey = (struct acpi_hotkey*)acpi_driver_data(device); ProcItem* item; @@ -771,131 +805,165 @@ static void acpi_pcc_remove_device(struct acpi_device *device, remove_proc_entry(item->name, hotkey->proc_dir_entry); } - return; + return_VOID; +} + +/* ************************************************************************* + Power Management + ************************************************************************* */ +#ifdef CONFIG_PM +static int acpi_pcc_hotkey_resume(struct acpi_device *device) +{ + struct acpi_hotkey *hotkey = acpi_driver_data(device); + acpi_status status = AE_OK; + + ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_resume"); + + if (device == NULL || hotkey == NULL) { return_VALUE(-EINVAL); } + + if (hotkey->num_sifr != 0) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Sticky mode restore: %d\n", hotkey->sticky_mode)); + + status = acpi_pcc_write_sset(hotkey, SINF_STICKY_KEY, hotkey->sticky_mode); + } + if (status != AE_OK) { return_VALUE(-EINVAL); } + + return_VALUE(0); } +#endif -/* -------------------------------------------------------------------------- - input init - -------------------------------------------------------------------------- */ -static int acpi_pcc_init_input(struct acpi_hotkey *hotkey) +/* ************************************************************************* + Module init/remove + ************************************************************************* */ +/* ------------------------------------------------------------------------- + input + ------------------------------------------------------------------------- */ +static int __devinit acpi_pcc_init_input(struct acpi_hotkey *hotkey) { - struct input_dev *hotk_input_dev; + struct input_dev *hotk_input_dev; struct pcc_keyinput *pcc_keyinput; + int error; ACPI_FUNCTION_TRACE("acpi_pcc_init_input"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) hotk_input_dev = input_allocate_device(); - if (!hotk_input_dev) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate input device for hotkey")); - return_VALUE(-ENOMEM); - } -#else - hotk_input_dev = kcalloc(1, sizeof(struct input_dev),GFP_KERNEL); if (hotk_input_dev == NULL) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate mem for hotkey")); - return_VALUE(-ENOMEM); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate input device for hotkey")); + goto err_input; } -#endif - pcc_keyinput = kcalloc(1,sizeof(struct pcc_keyinput),GFP_KERNEL); + pcc_keyinput = kcalloc(1, sizeof(struct pcc_keyinput), GFP_KERNEL); if (pcc_keyinput == NULL) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate mem for hotkey")); - input_unregister_device(hotk_input_dev); - return_VALUE(-ENOMEM); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate mem for private data")); + goto err_pcc; } hotk_input_dev->evbit[0] = BIT(EV_KEY); set_bit(KEY_BRIGHTNESSDOWN, hotk_input_dev->keybit); - set_bit(KEY_BRIGHTNESSUP, hotk_input_dev->keybit); - set_bit(KEY_MUTE, hotk_input_dev->keybit); - set_bit(KEY_VOLUMEDOWN, hotk_input_dev->keybit); - set_bit(KEY_VOLUMEUP, hotk_input_dev->keybit); - set_bit(KEY_SLEEP, hotk_input_dev->keybit); - set_bit(KEY_BATT, hotk_input_dev->keybit); - set_bit(KEY_SUSPEND, hotk_input_dev->keybit); - - hotk_input_dev->name = ACPI_PCC_DRIVER_NAME; - hotk_input_dev->phys = ACPI_PCC_INPUT_PHYS; - hotk_input_dev->id.bustype = 0x1a; /* XXX FIXME: BUS_I8042? */ - hotk_input_dev->id.vendor = 0x0001; + set_bit(KEY_BRIGHTNESSUP, hotk_input_dev->keybit); + set_bit(KEY_MUTE, hotk_input_dev->keybit); + set_bit(KEY_VOLUMEDOWN, hotk_input_dev->keybit); + set_bit(KEY_VOLUMEUP, hotk_input_dev->keybit); + set_bit(KEY_SLEEP, hotk_input_dev->keybit); + set_bit(KEY_BATT, hotk_input_dev->keybit); + set_bit(KEY_SUSPEND, hotk_input_dev->keybit); + + hotk_input_dev->name = ACPI_PCC_DRIVER_NAME; + hotk_input_dev->phys = ACPI_PCC_INPUT_PHYS; + hotk_input_dev->id.bustype = BUS_PCC_HOTKEY; + hotk_input_dev->id.vendor = 0x0001; hotk_input_dev->id.product = 0x0001; hotk_input_dev->id.version = 0x0100; - pcc_keyinput->key_mode = 1; /* default on */ - pcc_keyinput->hotkey = hotkey; + pcc_keyinput->key_mode = PCC_KEYINPUT_MODE; + pcc_keyinput->hotkey = hotkey; input_set_drvdata(hotk_input_dev, pcc_keyinput); hotkey->input_dev = hotk_input_dev; + error = input_register_device(hotk_input_dev); - input_register_device(hotk_input_dev); + if (error) { + goto err_pcc; + } return_VALUE(0); -} -/* -------------------------------------------------------------------------- - module init - -------------------------------------------------------------------------- */ + err_pcc: + input_unregister_device(hotk_input_dev); + err_input: + return_VALUE(-ENOMEM); +} -static int acpi_pcc_hotkey_resume(struct acpi_device *device) +static void __devexit acpi_pcc_remove_input(struct acpi_hotkey *hotkey) { - struct acpi_hotkey *hotkey = acpi_driver_data(device); - acpi_status status = AE_OK; + struct input_dev *hotk_input_dev; + struct pcc_keyinput *pcc_keyinput; - ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_resume"); + ACPI_FUNCTION_TRACE("acpi_pcc_remove_input"); - if (device == NULL || hotkey == NULL) { return_VALUE(-EINVAL); } + if (hotkey == NULL) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Can't free memory")); + return_VOID; + } - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Sticky mode restore: %d\n", hotkey->sticky_mode)); + hotk_input_dev = hotkey->input_dev; + pcc_keyinput = input_get_drvdata(hotk_input_dev); - status = acpi_pcc_write_sset(hotkey, SINF_STICKY_KEY, hotkey->sticky_mode); + input_unregister_device(hotk_input_dev); - return_VALUE(status == AE_OK ? 0 : -EINVAL); + kfree(pcc_keyinput); } -static int acpi_pcc_hotkey_add (struct acpi_device *device) +/* ------------------------------------------------------------------------- + ACPI + ------------------------------------------------------------------------- */ +static int __devinit acpi_pcc_hotkey_add (struct acpi_device *device) { acpi_status status = AE_OK; struct acpi_hotkey *hotkey = NULL; - int num_sifr, result; + int sifr_status, num_sifr, result; ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_add"); - if (!device) { + if (device == NULL) { return_VALUE(-EINVAL); } - num_sifr = acpi_pcc_get_sqty(device); + sifr_status = acpi_pcc_get_sqty(device); - if (num_sifr > 255) { + if (sifr_status > 255) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "num_sifr too large")); return_VALUE(-ENODEV); } - hotkey = kmalloc(sizeof(struct acpi_hotkey), GFP_KERNEL); - if (!hotkey) { + if (sifr_status < 0) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "not support SQTY")); + num_sifr = 0; + } else { + num_sifr = sifr_status; + } + + hotkey = kcalloc(1, sizeof(struct acpi_hotkey), GFP_KERNEL); + if (hotkey == NULL) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate mem for hotkey")); return_VALUE(-ENOMEM); } - memset(hotkey, 0, sizeof(struct acpi_hotkey)); - - hotkey->device = device; - hotkey->handle = device->handle; + hotkey->device = device; + hotkey->handle = device->handle; hotkey->num_sifr = num_sifr; acpi_driver_data(device) = hotkey; - strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME); + strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PCC_CLASS); - status = acpi_install_notify_handler ( - hotkey->handle, - ACPI_DEVICE_NOTIFY, - acpi_pcc_hotkey_notify, - hotkey); + status = acpi_install_notify_handler(hotkey->handle, + ACPI_DEVICE_NOTIFY, + acpi_pcc_hotkey_notify, + hotkey); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing notify handler\n")); @@ -904,7 +972,7 @@ static int acpi_pcc_hotkey_add (struct acpi_device *device) } result = acpi_pcc_init_input(hotkey); - if (result) { + if (result != 0) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error installing keyinput handler\n")); kfree(hotkey); return_VALUE(result); @@ -913,62 +981,72 @@ static int acpi_pcc_hotkey_add (struct acpi_device *device) return_VALUE(acpi_pcc_proc_init(device)); } -static int __init acpi_pcc_init(void) -{ - int result = 0; - - ACPI_FUNCTION_TRACE("acpi_pcc_init"); - - if (acpi_disabled) { - return_VALUE(-ENODEV); - } - - result = acpi_bus_register_driver(&acpi_pcc_driver); - if (result < 0) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error registering hotkey driver\n")); - return_VALUE(-ENODEV); - } - - return_VALUE(0); -} - -module_init(acpi_pcc_init); - -static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type) +static int __devexit acpi_pcc_hotkey_remove(struct acpi_device *device, int type) { acpi_status status = AE_OK; struct acpi_hotkey *hotkey = acpi_driver_data(device); ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_remove"); - if (!device || !hotkey) + if (!device || !hotkey) { return_VALUE(-EINVAL); + } if (hotkey->proc_dir_entry) { - acpi_pcc_remove_device(device, pcc_proc_items_sifr, hotkey->num_sifr); - acpi_pcc_remove_device(device, pcc_proc_items, sizeof(pcc_proc_items)/sizeof(ProcItem)); + acpi_pcc_remove_device(device, acpi_pcc_proc_items_sifr, hotkey->num_sifr); + acpi_pcc_remove_device(device, acpi_pcc_proc_items, ARRAY_SIZE(acpi_pcc_proc_items)); remove_proc_entry(PROC_PCC, acpi_root_dir); } status = acpi_remove_notify_handler(hotkey->handle, ACPI_DEVICE_NOTIFY, acpi_pcc_hotkey_notify); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error removing notify handler\n")); + } - input_unregister_device(hotkey->input_dev); - - kfree(hotkey); + acpi_pcc_remove_input(hotkey); + if (hotkey != NULL) { + kfree(hotkey); + } return_VALUE(status == AE_OK); } +/* ********************************************************************* + Module entry point + ********************************************************************* */ +static int __init acpi_pcc_init(void) +{ + int result; + + ACPI_FUNCTION_TRACE("acpi_pcc_init"); + + printk(KERN_INFO LOGPREFIX "loading...\n"); + + if (acpi_disabled) { + printk(KERN_INFO LOGPREFIX "ACPI disabled.\n"); + return_VALUE(-ENODEV); + } + + result = acpi_bus_register_driver(&acpi_pcc_driver); + if (result < 0) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error registering hotkey driver\n")); + return_VALUE(-ENODEV); + } + + return_VALUE(result); +} + static void __exit acpi_pcc_exit(void) { ACPI_FUNCTION_TRACE("acpi_pcc_exit"); + printk(KERN_INFO LOGPREFIX "unloading...\n"); + acpi_bus_unregister_driver(&acpi_pcc_driver); return_VOID; } +module_init(acpi_pcc_init); module_exit(acpi_pcc_exit);