Loading drivers/staging/pcc-acpi/pcc-acpi.c +309 −231 Original line number Diff line number Diff line Loading @@ -94,20 +94,21 @@ * */ #define ACPI_PCC_VERSION "0.9" #define ACPI_PCC_VERSION "0.9+hy" #include <linux/version.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> #include <asm/uaccess.h> #include <linux/ctype.h> #include <linux/init.h> #include <linux/input.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/types.h> #include <linux/proc_fs.h> #include <linux/ctype.h> #include <linux/seq_file.h> #include <asm/uaccess.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> #include <linux/input.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/version.h> /************************************************************************* Loading Loading @@ -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: " Loading @@ -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 Loading @@ -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 */ Loading @@ -209,11 +216,7 @@ 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}, Loading @@ -222,14 +225,23 @@ static const struct acpi_device_id pcc_device_ids[] = { }; 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 }, }; Loading @@ -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[] = { Loading @@ -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) Loading Loading @@ -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++) { Loading @@ -322,47 +338,42 @@ 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); Loading @@ -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); Loading @@ -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); Loading Loading @@ -441,7 +453,8 @@ static ssize_t acpi_pcc_write_single_flag (struct file *file, } 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); } Loading @@ -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]) { 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, return_VALUE(acpi_pcc_write_brightness(file, buffer, count, SINF_AC_MIN_BRIGHT, SINF_AC_MAX_BRIGHT, SINF_AC_CUR_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, return_VALUE(acpi_pcc_write_brightness(file, buffer, count, SINF_DC_MIN_BRIGHT, SINF_DC_MAX_BRIGHT, SINF_DC_CUR_BRIGHT); SINF_DC_CUR_BRIGHT)); } static ssize_t acpi_pcc_write_no_brightness(struct file *file, const char __user *buffer, Loading @@ -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, Loading @@ -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; Loading Loading @@ -640,9 +676,9 @@ void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data) return_VOID; } /* -------------------------------------------------------------------------- /* ************************************************************************* 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); Loading Loading @@ -681,8 +717,7 @@ typedef struct _ProcItem } ProcItem; /* Note: These functions map *exactly* to the SINF/SSET functions */ ProcItem pcc_proc_items_sifr[] = { 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 }, Loading @@ -696,22 +731,21 @@ ProcItem pcc_proc_items_sifr[] = { 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 }, { NULL, NULL, 0 }, }; static int acpi_pcc_add_device(struct acpi_device *device, 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); Loading @@ -724,13 +758,13 @@ 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); Loading @@ -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; Loading @@ -759,7 +793,7 @@ static int acpi_pcc_proc_init(struct acpi_device *device) return_VALUE(status); } static void acpi_pcc_remove_device(struct acpi_device *device, static void __devexit acpi_pcc_remove_device(struct acpi_device *device, ProcItem *proc_items, int num) { Loading @@ -771,39 +805,58 @@ 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 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); 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); Loading @@ -819,71 +872,87 @@ static int acpi_pcc_init_input(struct acpi_hotkey *hotkey) 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.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->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->num_sifr = num_sifr; Loading @@ -891,8 +960,7 @@ static int acpi_pcc_hotkey_add (struct acpi_device *device) strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PCC_CLASS); status = acpi_install_notify_handler ( hotkey->handle, status = acpi_install_notify_handler(hotkey->handle, ACPI_DEVICE_NOTIFY, acpi_pcc_hotkey_notify, hotkey); Loading @@ -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); Loading @@ -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); 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); Loading
drivers/staging/pcc-acpi/pcc-acpi.c +309 −231 Original line number Diff line number Diff line Loading @@ -94,20 +94,21 @@ * */ #define ACPI_PCC_VERSION "0.9" #define ACPI_PCC_VERSION "0.9+hy" #include <linux/version.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> #include <asm/uaccess.h> #include <linux/ctype.h> #include <linux/init.h> #include <linux/input.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/types.h> #include <linux/proc_fs.h> #include <linux/ctype.h> #include <linux/seq_file.h> #include <asm/uaccess.h> #include <acpi/acpi_bus.h> #include <acpi/acpi_drivers.h> #include <linux/input.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/version.h> /************************************************************************* Loading Loading @@ -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: " Loading @@ -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 Loading @@ -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 */ Loading @@ -209,11 +216,7 @@ 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}, Loading @@ -222,14 +225,23 @@ static const struct acpi_device_id pcc_device_ids[] = { }; 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 }, }; Loading @@ -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[] = { Loading @@ -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) Loading Loading @@ -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++) { Loading @@ -322,47 +338,42 @@ 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); Loading @@ -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); Loading @@ -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); Loading Loading @@ -441,7 +453,8 @@ static ssize_t acpi_pcc_write_single_flag (struct file *file, } 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); } Loading @@ -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]) { 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, return_VALUE(acpi_pcc_write_brightness(file, buffer, count, SINF_AC_MIN_BRIGHT, SINF_AC_MAX_BRIGHT, SINF_AC_CUR_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, return_VALUE(acpi_pcc_write_brightness(file, buffer, count, SINF_DC_MIN_BRIGHT, SINF_DC_MAX_BRIGHT, SINF_DC_CUR_BRIGHT); SINF_DC_CUR_BRIGHT)); } static ssize_t acpi_pcc_write_no_brightness(struct file *file, const char __user *buffer, Loading @@ -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, Loading @@ -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; Loading Loading @@ -640,9 +676,9 @@ void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data) return_VOID; } /* -------------------------------------------------------------------------- /* ************************************************************************* 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); Loading Loading @@ -681,8 +717,7 @@ typedef struct _ProcItem } ProcItem; /* Note: These functions map *exactly* to the SINF/SSET functions */ ProcItem pcc_proc_items_sifr[] = { 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 }, Loading @@ -696,22 +731,21 @@ ProcItem pcc_proc_items_sifr[] = { 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 }, { NULL, NULL, 0 }, }; static int acpi_pcc_add_device(struct acpi_device *device, 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); Loading @@ -724,13 +758,13 @@ 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); Loading @@ -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; Loading @@ -759,7 +793,7 @@ static int acpi_pcc_proc_init(struct acpi_device *device) return_VALUE(status); } static void acpi_pcc_remove_device(struct acpi_device *device, static void __devexit acpi_pcc_remove_device(struct acpi_device *device, ProcItem *proc_items, int num) { Loading @@ -771,39 +805,58 @@ 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 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); 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); Loading @@ -819,71 +872,87 @@ static int acpi_pcc_init_input(struct acpi_hotkey *hotkey) 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.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->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->num_sifr = num_sifr; Loading @@ -891,8 +960,7 @@ static int acpi_pcc_hotkey_add (struct acpi_device *device) strcpy(acpi_device_name(device), ACPI_PCC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PCC_CLASS); status = acpi_install_notify_handler ( hotkey->handle, status = acpi_install_notify_handler(hotkey->handle, ACPI_DEVICE_NOTIFY, acpi_pcc_hotkey_notify, hotkey); Loading @@ -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); Loading @@ -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); 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);