All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Oliveira Nascimento <dnascimento@gmail.com>
To: linux-acpi@vger.kernel.org, Nicolas Trangez <ikke@nicolast.be>
Subject: [PATCH 01/02] Initial work to let ACPI buttons work over INPUT layer
Date: Sat, 29 Nov 2008 18:34:43 -0200	[thread overview]
Message-ID: <200811291834.46109.dnascimento@gmail.com> (raw)

Updated work of Nicolas Trangez to support INPUT layer in
asus-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.c
index 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

\0

             reply	other threads:[~2008-11-29 20:36 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-11-29 20:34 Daniel Oliveira Nascimento [this message]
2008-12-10  9:26 ` [PATCH 01/02] Initial work to let ACPI buttons work over INPUT layer Timo Hoenig
2008-12-10 10:31   ` Corentin Chary
2008-12-10 10:45     ` Timo Hoenig
2008-12-19 16:34 ` Fwd: " Daniel Nascimento
2009-01-07 11:38   ` Timo Hoenig
2009-01-12 11:59     ` Corentin Chary
2009-01-12 12:00       ` Corentin Chary
2009-01-14  9:57         ` Corentin Chary
2009-01-14 12:05           ` Daniel Nascimento
2009-01-15 12:31           ` Fabien Crespel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200811291834.46109.dnascimento@gmail.com \
    --to=dnascimento@gmail.com \
    --cc=ikke@nicolast.be \
    --cc=linux-acpi@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.