Updated work of Nicolas Trangez to support INPUT layer inasus-laptop driver in git branch. Initial discussion can be found here:http://article.gmane.org/gmane.linux.acpi.acpi4asus.user/217 --- drivers/misc/asus-laptop.c | 183 +++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 182 insertions(+), 1 deletions(-) diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.cindex 8fb8b35..46db3b0 100644--- a/drivers/misc/asus-laptop.c+++ b/drivers/misc/asus-laptop.c@@ -24,6 +24,7 @@ * http://sourceforge.net/projects/acpi4asus/ * * Credits:+ * Nicolas Trangez - Initial work to let ACPI buttons work over INPUT layer * Pontus Fuchs - Helper functions, cleanup * Johann Wiesner - Small compile fixes * John Belmonte - ACPI code for Toshiba laptop was a good starting point.@@ -46,6 +47,8 @@ #include <acpi/acpi_drivers.h> #include <acpi/acpi_bus.h> #include <asm/uaccess.h>+#include <linux/input.h>+#include <linux/pci_ids.h> #define ASUS_LAPTOP_VERSION "0.42" @@ -250,6 +253,12 @@ ASUS_LED(rled, "record"); ASUS_LED(pled, "phone"); ASUS_LED(gled, "gaming"); +/* Input layer variables */+static u16 *hotk_keycode_map;+static int hotk_keycode_map_size;+static struct input_dev *asus_hotk_inputdev;+static int asus_hotk_inputdev_registered;+ /* * This function evaluates an ACPI method, given an int as parameter, the * method is searched within the scope of the handle, can be NULL. The output@@ -722,6 +731,8 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr, static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) {+ int keycode;+ /* TODO Find a better way to handle events count. */ if (!hotk) return;@@ -738,7 +749,28 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) lcd_blank(FB_BLANK_POWERDOWN); } - acpi_bus_generate_proc_event(hotk->device, event,+ if (event < hotk_keycode_map_size) {+ keycode = hotk_keycode_map[event];+ printk("Keycode: %04x (%d)\n", keycode, keycode);+ } else {+ keycode = KEY_UNKNOWN;+ printk("Scancode %d out of keymap\n", event);+ }++ if (keycode != KEY_RESERVED) {+ input_report_key(asus_hotk_inputdev, keycode, 1);+ if (keycode == KEY_UNKNOWN)+ input_event(asus_hotk_inputdev, EV_MSC, MSC_SCAN, event);+ input_sync(asus_hotk_inputdev);++ input_report_key(asus_hotk_inputdev, keycode, 0);+ if (keycode == KEY_UNKNOWN)+ input_event(asus_hotk_inputdev, EV_MSC, MSC_SCAN, event);+ input_sync(asus_hotk_inputdev);+ }++ if (keycode == KEY_RESERVED || keycode == KEY_UNKNOWN)+ acpi_bus_generate_proc_event(hotk->device, event, hotk->event_count[event % 128]++); return;@@ -1071,6 +1103,16 @@ static int asus_hotk_remove(struct acpi_device *device, int type) return 0; } +static void asus_hotk_exit(void)+{+ if (asus_hotk_inputdev) {+ if (asus_hotk_inputdev_registered)+ input_unregister_device(asus_hotk_inputdev);+ else+ input_free_device(asus_hotk_inputdev);+ }+}+ static void asus_backlight_exit(void) { if (asus_backlight_device)@@ -1095,6 +1137,7 @@ static void __exit asus_laptop_exit(void) { asus_backlight_exit(); asus_led_exit();+ asus_hotk_exit(); acpi_bus_unregister_driver(&asus_hotk_driver); sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group);@@ -1102,6 +1145,138 @@ static void __exit asus_laptop_exit(void) platform_driver_unregister(&asuspf_driver); } +static int asus_hotk_init(void)+{+ int ret, i;++ static u16 keycode_map_1[] __initdata = {+ KEY_UNKNOWN, /* 0 */+ KEY_UNKNOWN, /* 1 */+ KEY_UNKNOWN, /* 2 */+ KEY_UNKNOWN, /* 3 */+ KEY_UNKNOWN, /* 4 */+ KEY_UNKNOWN, /* 5 */+ KEY_UNKNOWN, /* 6 */+ KEY_UNKNOWN, /* 7 */+ KEY_UNKNOWN, /* 8 */+ KEY_UNKNOWN, /* 9 */+ KEY_UNKNOWN, /* 10 */+ KEY_UNKNOWN, /* 11 */+ KEY_UNKNOWN, /* 12 */+ KEY_UNKNOWN, /* 13 */+ KEY_UNKNOWN, /* 14 */+ KEY_UNKNOWN, /* 15 */+ KEY_UNKNOWN, /* 16 */+ KEY_UNKNOWN, /* 17 */+ KEY_UNKNOWN, /* 18 */+ KEY_UNKNOWN, /* 19 */+ KEY_UNKNOWN, /* 20 */+ KEY_UNKNOWN, /* 21 */+ KEY_UNKNOWN, /* 22 */+ KEY_UNKNOWN, /* 23 */+ KEY_UNKNOWN, /* 24 */+ KEY_UNKNOWN, /* 25 */+ KEY_UNKNOWN, /* 26 */+ KEY_UNKNOWN, /* 27 */+ KEY_UNKNOWN, /* 28 */+ KEY_UNKNOWN, /* 29 */+ KEY_UNKNOWN, /* 30 */+ KEY_UNKNOWN, /* 31 */+ KEY_UNKNOWN, /* 32 */+ KEY_UNKNOWN, /* 33 */+ KEY_UNKNOWN, /* 34 */+ KEY_UNKNOWN, /* 35 */+ KEY_UNKNOWN, /* 36 */+ KEY_UNKNOWN, /* 37 */+ KEY_UNKNOWN, /* 38 */+ KEY_UNKNOWN, /* 39 */+ KEY_UNKNOWN, /* 40 */+ KEY_UNKNOWN, /* 41 */+ KEY_UNKNOWN, /* 42 */+ KEY_UNKNOWN, /* 43 */+ KEY_UNKNOWN, /* 44 */+ KEY_UNKNOWN, /* 45 */+ KEY_UNKNOWN, /* 46 */+ KEY_UNKNOWN, /* 47 */+ KEY_UNKNOWN, /* 48 */+ KEY_UNKNOWN, /* 49 */+ KEY_UNKNOWN, /* 50 */+ KEY_UNKNOWN, /* 51 */+ KEY_UNKNOWN, /* 52 */+ KEY_UNKNOWN, /* 53 */+ KEY_UNKNOWN, /* 54 */+ KEY_UNKNOWN, /* 55 */+ KEY_UNKNOWN, /* 56 */+ KEY_UNKNOWN, /* 57 */+ KEY_UNKNOWN, /* 58 */+ KEY_UNKNOWN, /* 59 */+ KEY_UNKNOWN, /* 60 */+ KEY_UNKNOWN, /* 61 */+ KEY_UNKNOWN, /* 62 */+ KEY_UNKNOWN, /* 63 */+ KEY_PREVIOUSSONG, /* 64 */+ KEY_NEXTSONG, /* 65 */+ KEY_UNKNOWN, /* 66 */+ KEY_STOP, /* 67 */+ KEY_UNKNOWN, /* 68 */+ KEY_PLAYPAUSE, /* 69 */+ KEY_UNKNOWN, /* 70 */+ };++#define ASUS_HOTK_MAP_LEN ARRAY_SIZE(keycode_map_1)+#define ASUS_HOTK_MAP_SIZE sizeof(keycode_map_1)+#define ASUS_HOTK_MAP_TYPESIZE sizeof(keycode_map_1[0])++ /* Always use first keymap. TODO make this model-specific */+ hotk_keycode_map = kmalloc(ASUS_HOTK_MAP_SIZE, GFP_KERNEL);+ hotk_keycode_map_size = ASUS_HOTK_MAP_LEN;+ if (!hotk_keycode_map) {+ printk(ASUS_ERR "failed to allocate memory for keymap\n");+ return -ENOMEM;+ }+ printk(ASUS_NOTICE "using keycode_map_1\n");+ memcpy(hotk_keycode_map, &keycode_map_1, ASUS_HOTK_MAP_SIZE);+ /* TODO make sure no ACPI events are sent on known keycodes */++ asus_hotk_inputdev = input_allocate_device();+ if (!asus_hotk_inputdev) {+ printk(ASUS_ERR "unable to allocate input device\n");+ return -ENOMEM;+ }+ asus_hotk_inputdev->name = "Asus Extra Buttons";+ asus_hotk_inputdev->phys = ASUS_HOTK_FILE "/input0";+ asus_hotk_inputdev->id.bustype = BUS_HOST;+ asus_hotk_inputdev->id.vendor = PCI_VENDOR_ID_ASUSTEK;+ /* TODO+ asus_hotk_inputdev->id.product =+ asus_hotk_inputdev->id.version =+ */++ set_bit(EV_KEY, asus_hotk_inputdev->evbit);+ set_bit(EV_MSC, asus_hotk_inputdev->evbit);+ set_bit(MSC_SCAN, asus_hotk_inputdev->mscbit);+ asus_hotk_inputdev->keycodesize = ASUS_HOTK_MAP_TYPESIZE;+ asus_hotk_inputdev->keycodemax = ASUS_HOTK_MAP_LEN;+ asus_hotk_inputdev->keycode = hotk_keycode_map;+ for (i = 0; i < ASUS_HOTK_MAP_LEN; i++) {+ if (hotk_keycode_map[i] != KEY_RESERVED) {+ set_bit(hotk_keycode_map[i], asus_hotk_inputdev->keybit);+ } /*else {+ if (i < sizeof(hotk_reserved_mask)*8)+ hotk_reserved_mask |= 1 << i;+ }*/+ }++ ret = input_register_device(asus_hotk_inputdev);+ if (ret < 0) {+ printk(ASUS_ERR "unable to register input device\n");+ return ret;+ }+ asus_hotk_inputdev_registered = 1;++ return 0;+}+ static int asus_backlight_init(struct device *dev) { struct backlight_device *bd;@@ -1208,6 +1383,10 @@ static int __init asus_laptop_init(void) dev = acpi_get_physical_device(hotk->device->handle); + result = asus_hotk_init();+ if (result)+ goto fail_hotk;+ if (!acpi_video_backlight_support()) { result = asus_backlight_init(dev); if (result)@@ -1259,6 +1438,8 @@ static int __init asus_laptop_init(void) fail_backlight: + fail_hotk:+ return result; } -- 1.5.6 ÿôèº{.nÇ+?·?®??+%?Ëÿ±éݶ¥?wÿº{.nÇ+?·¥?{±ý§)?ø§¶?¡Ü¨}©?²Æ zÚ&j:+v?¨þø¯ù®w¥þ?à2?Þ?¨èÚ&¢)ß¡«a¶Úÿÿûàz¿äz¹Þ?ú+?ù???Ý¢jÿ?wèþf