All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/9] Implement sparse keymap library
@ 2009-12-04  6:11 Dmitry Torokhov
  2009-12-04  6:11 ` [PATCH 1/9] Input: add generic support for sparse keymaps Dmitry Torokhov
                   ` (8 more replies)
  0 siblings, 9 replies; 22+ messages in thread
From: Dmitry Torokhov @ 2009-12-04  6:11 UTC (permalink / raw)
  To: linux-input, Len Brown
  Cc: linux-acpi, Herton Ronaldo Krzesinski, Harald Welte,
	Corentin Chary, Carlos Corbacho, Wu Zhangjin, Anisse Astier

It seems that almost everty platform driver out there copied the keymap
implementation from wistron button driver... That's a lot of duplicated code
and I think it is high time we split it into a library module that can be
shared between all these drivers.

Changes since v1: added sparse_keymap_report_event() and
sparse_keymap_report_entry() to furger reduce code in the drivers.

Len, what would be the best way to merge this? The patches touch a few of
the platform drivers and I would like to get it done sooner than later
because teh patch converting EVIOCGKEYCODE and EVIOCSKEYCODE to use
unisgned int instead of signed int scancodes depends on it.

Thanks.

-- 
Dmitry


^ permalink raw reply	[flat|nested] 22+ messages in thread

* [PATCH 1/9] Input: add generic support for sparse keymaps
  2009-12-04  6:11 [PATCH v2 0/9] Implement sparse keymap library Dmitry Torokhov
@ 2009-12-04  6:11 ` Dmitry Torokhov
  2009-12-04  8:02   ` Wu Zhangjin
                     ` (2 more replies)
  2009-12-04  6:12 ` [PATCH 2/9] Input: wistron_btns - switch to using sparse keymap library Dmitry Torokhov
                   ` (7 subsequent siblings)
  8 siblings, 3 replies; 22+ messages in thread
From: Dmitry Torokhov @ 2009-12-04  6:11 UTC (permalink / raw)
  To: linux-input, Len Brown
  Cc: linux-acpi, Herton Ronaldo Krzesinski, Harald Welte,
	Corentin Chary, Carlos Corbacho, Wu Zhangjin, Anisse Astier

More and more devices choose to reimplement support for sparse keymaps
first introduced by wistron driver. Move it into a library module so it
can be easily used by interested parties.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---

 Documentation/DocBook/device-drivers.tmpl |    4 
 drivers/input/Kconfig                     |   28 ++-
 drivers/input/Makefile                    |    1 
 drivers/input/input-polldev.c             |   14 +-
 drivers/input/sparse-keymap.c             |  251 +++++++++++++++++++++++++++++
 include/linux/input/sparse-keymap.h       |   62 +++++++
 6 files changed, 348 insertions(+), 12 deletions(-)
 create mode 100644 drivers/input/sparse-keymap.c
 create mode 100644 include/linux/input/sparse-keymap.h

diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index e994d1d..f9a6e2c 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -306,6 +306,10 @@ X!Idrivers/video/console/fonts.c
      <sect1><title>Matrix keyboars/keypads</title>
 !Iinclude/linux/input/matrix_keypad.h
      </sect1>
+     <sect1><title>Sparse keymap support</title>
+!Iinclude/linux/input/sparse-keymap.h
+!Edrivers/input/sparse-keymap.c
+     </sect1>
   </chapter>
 
   <chapter id="spi">
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index cd50c00..50af91e 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -8,7 +8,7 @@ menu "Input device support"
 config INPUT
 	tristate "Generic input layer (needed for keyboard, mouse, ...)" if EMBEDDED
 	default y
-	---help---
+	help
 	  Say Y here if you have any input device (mouse, keyboard, tablet,
 	  joystick, steering wheel ...) connected to your system and want
 	  it to be available to applications. This includes standard PS/2
@@ -27,8 +27,7 @@ if INPUT
 
 config INPUT_FF_MEMLESS
 	tristate "Support for memoryless force-feedback devices"
-	default n
-	---help---
+	help
 	  Say Y here if you have memoryless force-feedback input device
 	  such as Logitech WingMan Force 3D, ThrustMaster FireStorm Dual
 	  Power 2, or similar. You will also need to enable hardware-specific
@@ -52,12 +51,25 @@ config INPUT_POLLDEV
 	  To compile this driver as a module, choose M here: the
 	  module will be called input-polldev.
 
+config INPUT_SPARSEKMAP
+	tristate "Sparse keymap support library"
+	help
+	  Say Y here if you are using a driver for an input
+	  device that uses sparse keymap. This option is only
+	  useful for out-of-tree drivers since in-tree drivers
+	  select it automatically.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called sparse-keymap.
+
 comment "Userland interfaces"
 
 config INPUT_MOUSEDEV
 	tristate "Mouse interface" if EMBEDDED
 	default y
-	---help---
+	help
 	  Say Y here if you want your mouse to be accessible as char devices
 	  13:32+ - /dev/input/mouseX and 13:63 - /dev/input/mice as an
 	  emulated IntelliMouse Explorer PS/2 mouse. That way, all user space
@@ -73,7 +85,7 @@ config INPUT_MOUSEDEV_PSAUX
 	bool "Provide legacy /dev/psaux device"
 	default y
 	depends on INPUT_MOUSEDEV
-	---help---
+	help
 	  Say Y here if you want your mouse also be accessible as char device
 	  10:1 - /dev/psaux. The data available through /dev/psaux is exactly
 	  the same as the data from /dev/input/mice.
@@ -103,7 +115,7 @@ config INPUT_MOUSEDEV_SCREEN_Y
 
 config INPUT_JOYDEV
 	tristate "Joystick interface"
-	---help---
+	help
 	  Say Y here if you want your joystick or gamepad to be
 	  accessible as char device 13:0+ - /dev/input/jsX device.
 
@@ -125,7 +137,7 @@ config INPUT_EVDEV
 
 config INPUT_EVBUG
 	tristate "Event debugging"
-	---help---
+	help
 	  Say Y here if you have a problem with the input subsystem and
 	  want all events (keypresses, mouse movements), to be output to
 	  the system log. While this is useful for debugging, it's also
@@ -140,7 +152,7 @@ config INPUT_EVBUG
 config INPUT_APMPOWER
 	tristate "Input Power Event -> APM Bridge" if EMBEDDED
 	depends on INPUT && APM_EMULATION
-	---help---
+	help
 	  Say Y here if you want suspend key events to trigger a user
 	  requested suspend through APM. This is useful on embedded
 	  systems where such behaviour is desired without userspace
diff --git a/drivers/input/Makefile b/drivers/input/Makefile
index 4c9c745..7ad212d 100644
--- a/drivers/input/Makefile
+++ b/drivers/input/Makefile
@@ -9,6 +9,7 @@ input-core-objs := input.o input-compat.o ff-core.o
 
 obj-$(CONFIG_INPUT_FF_MEMLESS)	+= ff-memless.o
 obj-$(CONFIG_INPUT_POLLDEV)	+= input-polldev.o
+obj-$(CONFIG_INPUT_SPARSEKMAP)	+= sparse-keymap.o
 
 obj-$(CONFIG_INPUT_MOUSEDEV)	+= mousedev.o
 obj-$(CONFIG_INPUT_JOYDEV)	+= joydev.o
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c
index 6a2eb39..aa6713b 100644
--- a/drivers/input/input-polldev.c
+++ b/drivers/input/input-polldev.c
@@ -212,7 +212,7 @@ EXPORT_SYMBOL(input_allocate_polled_device);
  * @dev: device to free
  *
  * The function frees memory allocated for polling device and drops
- * reference to the associated input device (if present).
+ * reference to the associated input device.
  */
 void input_free_polled_device(struct input_polled_dev *dev)
 {
@@ -258,6 +258,15 @@ int input_register_polled_device(struct input_polled_dev *dev)
 		return error;
 	}
 
+	/*
+	 * Take extra reference to the underlying input device so
+	 * that it survives call to input_unregister_polled_device()
+	 * and is deleted only after input_free_polled_device()
+	 * has been invoked. This is needed to ease task of freeing
+	 * sparse keymaps.
+	 */
+	input_get_device(input);
+
 	return 0;
 }
 EXPORT_SYMBOL(input_register_polled_device);
@@ -269,8 +278,6 @@ EXPORT_SYMBOL(input_register_polled_device);
  * The function unregisters previously registered polled input
  * device from input layer. Polling is stopped and device is
  * ready to be freed with call to input_free_polled_device().
- * Callers should not attempt to access dev->input pointer
- * after calling this function.
  */
 void input_unregister_polled_device(struct input_polled_dev *dev)
 {
@@ -278,7 +285,6 @@ void input_unregister_polled_device(struct input_polled_dev *dev)
 			   &input_polldev_attribute_group);
 
 	input_unregister_device(dev->input);
-	dev->input = NULL;
 }
 EXPORT_SYMBOL(input_unregister_polled_device);
 
diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c
new file mode 100644
index 0000000..4655c56
--- /dev/null
+++ b/drivers/input/sparse-keymap.c
@@ -0,0 +1,251 @@
+/*
+ * Generic support for sparse keymaps
+ *
+ * Copyright (c) 2009 Dmitry Torokhov
+ *
+ * Derived from wistron button driver:
+ * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
+ * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
+ * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+
+MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
+MODULE_DESCRIPTION("Generic support for sparse keymaps");
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("0.1");
+
+/**
+ * sparse_keymap_entry_from_scancode - perform sparse keymap lookup
+ * @dev: Input device using sparse keymap
+ * @code: Scan code
+ *
+ * This function is used to perform &struct key_entry lookup in an
+ * input device using sparse keymap.
+ */
+struct key_entry *sparse_keymap_entry_from_scancode(struct input_dev *dev,
+						    unsigned int code)
+{
+	struct key_entry *key;
+
+	for (key = dev->keycode; key->type != KE_END; key++)
+		if (code == key->code)
+			return key;
+
+	return NULL;
+}
+EXPORT_SYMBOL(sparse_keymap_entry_from_scancode);
+
+/**
+ * sparse_keymap_entry_from_keycode - perform sparse keymap lookup
+ * @dev: Input device using sparse keymap
+ * @keycode: Key code
+ *
+ * This function is used to perform &struct key_entry lookup in an
+ * input device using sparse keymap.
+ */
+struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev,
+						   unsigned int keycode)
+{
+	struct key_entry *key;
+
+	for (key = dev->keycode; key->type != KE_END; key++)
+		if (key->type == KE_KEY && keycode == key->keycode)
+			return key;
+
+	return NULL;
+}
+EXPORT_SYMBOL(sparse_keymap_entry_from_keycode);
+
+static int sparse_keymap_getkeycode(struct input_dev *dev,
+				    int scancode, int *keycode)
+{
+	const struct key_entry *key =
+			sparse_keymap_entry_from_scancode(dev, scancode);
+
+	if (key && key->type == KE_KEY) {
+		*keycode = key->keycode;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int sparse_keymap_setkeycode(struct input_dev *dev,
+				    int scancode, int keycode)
+{
+	struct key_entry *key;
+	int old_keycode;
+
+	if (keycode < 0 || keycode > KEY_MAX)
+		return -EINVAL;
+
+	key = sparse_keymap_entry_from_scancode(dev, scancode);
+	if (key && key->type == KE_KEY) {
+		old_keycode = key->keycode;
+		key->keycode = keycode;
+		set_bit(keycode, dev->keybit);
+		if (!sparse_keymap_entry_from_keycode(dev, old_keycode))
+			clear_bit(old_keycode, dev->keybit);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(sparse_keymap_setkeycode);
+
+/**
+ * sparse_keymap_setup - set up sparse keymap for an input device
+ * @dev: Input device
+ * @keymap: Keymap in form of array of &key_entry structures ending
+ *	with %KE_END type entry
+ * @setup: Function that can be used to adjust keymap entries
+ *	depending on device's deeds, may be %NULL
+ *
+ * The function calculates size and allocates copy of the original
+ * keymap after which sets up input device event bits appropriately.
+ * Before detsroying input device allocated keymap should be freed
+ * with a call to sparse_keymap_free().
+ */
+int sparse_keymap_setup(struct input_dev *dev,
+			const struct key_entry *keymap,
+			int (*setup)(struct input_dev *, struct key_entry *))
+{
+	size_t map_size = 1; /* to account for the last KE_END entry */
+	const struct key_entry *e;
+	struct key_entry *map, *entry;
+	int i;
+	int error;
+
+	for (e = keymap; e->type != KE_END; e++)
+		map_size++;
+
+	map = kcalloc(map_size, sizeof (struct key_entry), GFP_KERNEL);
+	if (!map)
+		return -ENOMEM;
+
+	memcpy(map, keymap, map_size * sizeof (struct key_entry));
+
+	for (i = 0; i < map_size; i++) {
+		entry = &map[i];
+
+		if (setup) {
+			error = setup(dev, entry);
+			if (error)
+				goto err_out;
+		}
+
+		switch (entry->type) {
+		case KE_KEY:
+			__set_bit(EV_KEY, dev->evbit);
+			__set_bit(entry->keycode, dev->keybit);
+			break;
+
+		case KE_SW:
+			__set_bit(EV_SW, dev->evbit);
+			__set_bit(entry->sw.code, dev->swbit);
+			break;
+		}
+	}
+
+	dev->keycode = map;
+	dev->keycodemax = map_size;
+	dev->getkeycode = sparse_keymap_getkeycode;
+	dev->setkeycode = sparse_keymap_setkeycode;
+
+	return 0;
+
+ err_out:
+	kfree(keymap);
+	return error;
+
+}
+EXPORT_SYMBOL(sparse_keymap_setup);
+
+/**
+ * sparse_keymap_free - free memory allocated for sparse keymap
+ * @dev: Input device using sparse keymap
+ *
+ * This function is used to free memory allocated by sparse keymap
+ * in an input device that was set up by sparse_keymap_setup().
+ */
+void sparse_keymap_free(struct input_dev *dev)
+{
+	kfree(dev->keycode);
+	dev->keycode = NULL;
+	dev->keycodemax = 0;
+	dev->getkeycode = NULL;
+	dev->setkeycode = NULL;
+}
+EXPORT_SYMBOL(sparse_keymap_free);
+
+/**
+ * sparse_keymap_report_event - report event corresponding to given key entry
+ * @dev: Input device for which event should be reported
+ * @ke: key entry describing event
+ * @value: Value that should be reported (ignored by %KE_SW entries)
+ * @autorelease: Signals whether release event should be emitted for %KE_KEY
+ *	entries right after reporting press event, ignored by all other
+ *	entries
+ *
+ * This function is used to report input event described by given
+ * &struct key_entry.
+ */
+void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *ke,
+				unsigned int value, bool autorelease)
+{
+	switch (ke->type) {
+	case KE_KEY:
+		input_report_key(dev, ke->keycode, value);
+		input_sync(dev);
+		if (value && autorelease) {
+			input_report_key(dev, ke->keycode, 0);
+			input_sync(dev);
+		}
+		break;
+
+	case KE_SW:
+		value = ke->sw.value;
+		/* fall through */
+
+	case KE_VSW:
+		input_report_switch(dev, ke->sw.code, value);
+		break;
+	}
+}
+EXPORT_SYMBOL(sparse_keymap_report_entry);
+
+/**
+ * sparse_keymap_report_event - report event corresponding to given scancode
+ * @dev: Input device using sparse keymap
+ * @code: Scan code
+ * @value: Value that should be reported (ignored by %KE_SW entries)
+ * @autorelease: Signals whether release event should be emitted for %KE_KEY
+ *	entries right after reporting press event, ignored by all other
+ *	entries
+ *
+ * This function is used to perform lookup in an input device using sparse
+ * keymap and report corresponding event. Returns %true if lookup was
+ * successful and %false otherwise.
+ */
+bool sparse_keymap_report_event(struct input_dev *dev, unsigned int code,
+				unsigned int value, bool autorelease)
+{
+	const struct key_entry *ke =
+		sparse_keymap_entry_from_scancode(dev, code);
+
+	if (ke) {
+		sparse_keymap_report_entry(dev, ke, value, autorelease);
+		return true;
+	}
+
+	return false;
+}
+EXPORT_SYMBOL(sparse_keymap_report_event);
+
diff --git a/include/linux/input/sparse-keymap.h b/include/linux/input/sparse-keymap.h
new file mode 100644
index 0000000..52db620
--- /dev/null
+++ b/include/linux/input/sparse-keymap.h
@@ -0,0 +1,62 @@
+#ifndef _SPARSE_KEYMAP_H
+#define _SPARSE_KEYMAP_H
+
+/*
+ * Copyright (c) 2009 Dmitry Torokhov
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#define KE_END		0	/* Indicates end of keymap */
+#define KE_KEY		1	/* Ordinary key/button */
+#define KE_SW		2	/* Switch (predetermined value) */
+#define KE_VSW		3	/* Switch (value supplied at runtime) */
+#define KE_IGNORE	4	/* Known entry that should be ignored */
+#define KE_LAST		KE_IGNORE
+
+/**
+ * struct key_entry - keymap entry for use in sparse keymap
+ * @type: Type of the key entry (KE_KEY, KE_SW, KE_VSW, KE_END);
+ *	drivers are allowed to extend the list with their own
+ *	private definitions.
+ * @code: Device-specific data identifying the button/switch
+ * @keycode: KEY_* code assigned to a key/button
+ * @sw.code: SW_* code assigned to a switch
+ * @sw.value: Value that should be sent in an input even when KE_SW
+ *	switch is toggled. KE_VSW switches ignore this field and
+ *	expect driver to supply value for the event.
+ *
+ * This structure defines an entry in a sparse keymap used by some
+ * input devices for which traditional table-based approach is not
+ * suitable.
+ */
+struct key_entry {
+	int type;		/* See KE_* above */
+	u32 code;
+	union {
+		u16 keycode;		/* For KE_KEY */
+		struct {		/* For KE_SW, KE_VSW */
+			u8 code;
+			u8 value;	/* For KE_SW, ignored by KE_VSW */
+		} sw;
+	};
+};
+
+struct key_entry *sparse_keymap_entry_from_scancode(struct input_dev *dev,
+						    unsigned int code);
+struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev,
+						   unsigned int code);
+int sparse_keymap_setup(struct input_dev *dev,
+			const struct key_entry *keymap,
+			int (*setup)(struct input_dev *, struct key_entry *));
+void sparse_keymap_free(struct input_dev *dev);
+
+void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *ke,
+				unsigned int value, bool autorelease);
+
+bool sparse_keymap_report_event(struct input_dev *dev, unsigned int code,
+				unsigned int value, bool autorelease);
+
+#endif /* _SPARSE_KEYMAP_H */


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 2/9] Input: wistron_btns - switch to using sparse keymap library
  2009-12-04  6:11 [PATCH v2 0/9] Implement sparse keymap library Dmitry Torokhov
  2009-12-04  6:11 ` [PATCH 1/9] Input: add generic support for sparse keymaps Dmitry Torokhov
@ 2009-12-04  6:12 ` Dmitry Torokhov
  2009-12-04  6:12 ` [PATCH 3/9] Input: dm355evm_kbd " Dmitry Torokhov
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 22+ messages in thread
From: Dmitry Torokhov @ 2009-12-04  6:12 UTC (permalink / raw)
  To: linux-input, Len Brown
  Cc: linux-acpi, Herton Ronaldo Krzesinski, Harald Welte,
	Corentin Chary, Carlos Corbacho, Wu Zhangjin, Anisse Astier

The keymap manipulation code was split into a library module,
so let's make us of it.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---

 drivers/input/misc/Kconfig        |    1 
 drivers/input/misc/wistron_btns.c |  178 +++++++++----------------------------
 2 files changed, 45 insertions(+), 134 deletions(-)

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index a9bb254..d25ecbb 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -80,6 +80,7 @@ config INPUT_WISTRON_BTNS
 	tristate "x86 Wistron laptop button interface"
 	depends on X86 && !X86_64
 	select INPUT_POLLDEV
+	select INPUT_SPARSEKMAP
 	select NEW_LEDS
 	select LEDS_CLASS
 	select CHECK_SIGNATURE
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c
index 00eb9d6..b70c066 100644
--- a/drivers/input/misc/wistron_btns.c
+++ b/drivers/input/misc/wistron_btns.c
@@ -21,6 +21,7 @@
 #include <linux/dmi.h>
 #include <linux/init.h>
 #include <linux/input-polldev.h>
+#include <linux/input/sparse-keymap.h>
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
@@ -224,19 +225,8 @@ static void bios_set_state(u8 subsys, int enable)
 
 /* Hardware database */
 
-struct key_entry {
-	char type;		/* See KE_* below */
-	u8 code;
-	union {
-		u16 keycode;		/* For KE_KEY */
-		struct {		/* For KE_SW */
-			u8 code;
-			u8 value;
-		} sw;
-	};
-};
-
-enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH };
+#define KE_WIFI		(KE_LAST + 1)
+#define KE_BLUETOOTH	(KE_LAST + 2)
 
 #define FE_MAIL_LED 0x01
 #define FE_WIFI_LED 0x02
@@ -1037,21 +1027,6 @@ static unsigned long jiffies_last_press;
 static bool wifi_enabled;
 static bool bluetooth_enabled;
 
-static void report_key(struct input_dev *dev, unsigned int keycode)
-{
-	input_report_key(dev, keycode, 1);
-	input_sync(dev);
-	input_report_key(dev, keycode, 0);
-	input_sync(dev);
-}
-
-static void report_switch(struct input_dev *dev, unsigned int code, int value)
-{
-	input_report_switch(dev, code, value);
-	input_sync(dev);
-}
-
-
  /* led management */
 static void wistron_mail_led_set(struct led_classdev *led_cdev,
 				enum led_brightness value)
@@ -1128,43 +1103,13 @@ static inline void wistron_led_resume(void)
 		led_classdev_resume(&wistron_wifi_led);
 }
 
-static struct key_entry *wistron_get_entry_by_scancode(int code)
-{
-	struct key_entry *key;
-
-	for (key = keymap; key->type != KE_END; key++)
-		if (code == key->code)
-			return key;
-
-	return NULL;
-}
-
-static struct key_entry *wistron_get_entry_by_keycode(int keycode)
-{
-	struct key_entry *key;
-
-	for (key = keymap; key->type != KE_END; key++)
-		if (key->type == KE_KEY && keycode == key->keycode)
-			return key;
-
-	return NULL;
-}
-
 static void handle_key(u8 code)
 {
-	const struct key_entry *key = wistron_get_entry_by_scancode(code);
+	const struct key_entry *key =
+		sparse_keymap_entry_from_scancode(wistron_idev->input, code);
 
 	if (key) {
 		switch (key->type) {
-		case KE_KEY:
-			report_key(wistron_idev->input, key->keycode);
-			break;
-
-		case KE_SW:
-			report_switch(wistron_idev->input,
-				      key->sw.code, key->sw.value);
-			break;
-
 		case KE_WIFI:
 			if (have_wifi) {
 				wifi_enabled = !wifi_enabled;
@@ -1180,7 +1125,9 @@ static void handle_key(u8 code)
 			break;
 
 		default:
-			BUG();
+			sparse_keymap_report_entry(wistron_idev->input,
+						   key, 1, true);
+			break;
 		}
 		jiffies_last_press = jiffies;
 	} else
@@ -1220,42 +1167,39 @@ static void wistron_poll(struct input_polled_dev *dev)
 		dev->poll_interval = POLL_INTERVAL_DEFAULT;
 }
 
-static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode)
+static int __devinit wistron_setup_keymap(struct input_dev *dev,
+					  struct key_entry *entry)
 {
-	const struct key_entry *key = wistron_get_entry_by_scancode(scancode);
+	switch (entry->type) {
 
-	if (key && key->type == KE_KEY) {
-		*keycode = key->keycode;
-		return 0;
-	}
-
-	return -EINVAL;
-}
+	/* if wifi or bluetooth are not available, create normal keys */
+	case KE_WIFI:
+		if (!have_wifi) {
+			entry->type = KE_KEY;
+			entry->keycode = KEY_WLAN;
+		}
+		break;
 
-static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode)
-{
-	struct key_entry *key;
-	int old_keycode;
-
-	if (keycode < 0 || keycode > KEY_MAX)
-		return -EINVAL;
-
-	key = wistron_get_entry_by_scancode(scancode);
-	if (key && key->type == KE_KEY) {
-		old_keycode = key->keycode;
-		key->keycode = keycode;
-		set_bit(keycode, dev->keybit);
-		if (!wistron_get_entry_by_keycode(old_keycode))
-			clear_bit(old_keycode, dev->keybit);
-		return 0;
+	case KE_BLUETOOTH:
+		if (!have_bluetooth) {
+			entry->type = KE_KEY;
+			entry->keycode = KEY_BLUETOOTH;
+		}
+		break;
+
+	case KE_END:
+		if (entry->code & FE_UNTESTED)
+			printk(KERN_WARNING "Untested laptop multimedia keys, "
+				"please report success or failure to "
+				"eric.piel@tremplin-utc.net\n");
+		break;
 	}
 
-	return -EINVAL;
+	return 0;
 }
 
 static int __devinit setup_input_dev(void)
 {
-	struct key_entry *key;
 	struct input_dev *input_dev;
 	int error;
 
@@ -1273,56 +1217,21 @@ static int __devinit setup_input_dev(void)
 	input_dev->id.bustype = BUS_HOST;
 	input_dev->dev.parent = &wistron_device->dev;
 
-	input_dev->getkeycode = wistron_getkeycode;
-	input_dev->setkeycode = wistron_setkeycode;
-
-	for (key = keymap; key->type != KE_END; key++) {
-		switch (key->type) {
-			case KE_KEY:
-				set_bit(EV_KEY, input_dev->evbit);
-				set_bit(key->keycode, input_dev->keybit);
-				break;
-
-			case KE_SW:
-				set_bit(EV_SW, input_dev->evbit);
-				set_bit(key->sw.code, input_dev->swbit);
-				break;
-
-			/* if wifi or bluetooth are not available, create normal keys */
-			case KE_WIFI:
-				if (!have_wifi) {
-					key->type = KE_KEY;
-					key->keycode = KEY_WLAN;
-					key--;
-				}
-				break;
-
-			case KE_BLUETOOTH:
-				if (!have_bluetooth) {
-					key->type = KE_KEY;
-					key->keycode = KEY_BLUETOOTH;
-					key--;
-				}
-				break;
-
-			default:
-				break;
-		}
-	}
-
-	/* reads information flags on KE_END */
-	if (key->code & FE_UNTESTED)
-		printk(KERN_WARNING "Untested laptop multimedia keys, "
-			"please report success or failure to eric.piel"
-			"@tremplin-utc.net\n");
+	error = sparse_keymap_setup(input_dev, keymap, wistron_setup_keymap);
+	if (error)
+		goto err_free_dev;
 
 	error = input_register_polled_device(wistron_idev);
-	if (error) {
-		input_free_polled_device(wistron_idev);
-		return error;
-	}
+	if (error)
+		goto err_free_keymap;
 
 	return 0;
+
+ err_free_keymap:
+	sparse_keymap_free(input_dev);
+ err_free_dev:
+	input_free_polled_device(wistron_idev);
+	return error;
 }
 
 /* Driver core */
@@ -1371,6 +1280,7 @@ static int __devexit wistron_remove(struct platform_device *dev)
 {
 	wistron_led_remove();
 	input_unregister_polled_device(wistron_idev);
+	sparse_keymap_free(wistron_idev->input);
 	input_free_polled_device(wistron_idev);
 	bios_detach();
 


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 3/9] Input: dm355evm_kbd - switch to using sparse keymap library
  2009-12-04  6:11 [PATCH v2 0/9] Implement sparse keymap library Dmitry Torokhov
  2009-12-04  6:11 ` [PATCH 1/9] Input: add generic support for sparse keymaps Dmitry Torokhov
  2009-12-04  6:12 ` [PATCH 2/9] Input: wistron_btns - switch to using sparse keymap library Dmitry Torokhov
@ 2009-12-04  6:12 ` Dmitry Torokhov
  2009-12-04  6:12 ` [PATCH 4/9] Input: dell-wmi " Dmitry Torokhov
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 22+ messages in thread
From: Dmitry Torokhov @ 2009-12-04  6:12 UTC (permalink / raw)
  To: linux-input, Len Brown
  Cc: linux-acpi, Herton Ronaldo Krzesinski, Harald Welte,
	Corentin Chary, Carlos Corbacho, Wu Zhangjin, Anisse Astier

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---

 drivers/input/misc/Kconfig         |    1 
 drivers/input/misc/dm355evm_keys.c |  150 +++++++++++++-----------------------
 2 files changed, 57 insertions(+), 94 deletions(-)

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index d25ecbb..16ec523 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -282,6 +282,7 @@ config INPUT_RB532_BUTTON
 config INPUT_DM355EVM
 	tristate "TI DaVinci DM355 EVM Keypad and IR Remote"
 	depends on MFD_DM355EVM_MSP
+	select INPUT_SPARSEKMAP
 	help
 	  Supports the pushbuttons and IR remote used with
 	  the DM355 EVM board.
diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c
index f2b67dc..09a2815 100644
--- a/drivers/input/misc/dm355evm_keys.c
+++ b/drivers/input/misc/dm355evm_keys.c
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 
@@ -33,12 +34,8 @@ struct dm355evm_keys {
 	int			irq;
 };
 
-/* These initial keycodes can be remapped by dm355evm_setkeycode(). */
-static struct {
-	u16	event;
-	u16	keycode;
-} dm355evm_keys[] = {
-
+/* These initial keycodes can be remapped */
+static const struct key_entry dm355evm_keys[] = {
 	/*
 	 * Pushbuttons on the EVM board ... note that the labels for these
 	 * are SW10/SW11/etc on the PC board.  The left/right orientation
@@ -47,11 +44,11 @@ static struct {
 	 * is to the right.  (That is, rotate the board counter-clockwise
 	 * by 90 degrees from the SW10/etc and "DM355 EVM" labels.)
 	 */
-	{ 0x00d8, KEY_OK, },		/* SW12 */
-	{ 0x00b8, KEY_UP, },		/* SW13 */
-	{ 0x00e8, KEY_DOWN, },		/* SW11 */
-	{ 0x0078, KEY_LEFT, },		/* SW14 */
-	{ 0x00f0, KEY_RIGHT, },		/* SW10 */
+	{ KE_KEY, 0x00d8, { KEY_OK } },		/* SW12 */
+	{ KE_KEY, 0x00b8, { KEY_UP } },		/* SW13 */
+	{ KE_KEY, 0x00e8, { KEY_DOWN } },	/* SW11 */
+	{ KE_KEY, 0x0078, { KEY_LEFT } },	/* SW14 */
+	{ KE_KEY, 0x00f0, { KEY_RIGHT } },	/* SW10 */
 
 	/*
 	 * IR buttons ... codes assigned to match the universal remote
@@ -65,35 +62,35 @@ static struct {
 	 * RC5 codes are 14 bits, with two start bits (0x3 prefix)
 	 * and a toggle bit (masked out below).
 	 */
-	{ 0x300c, KEY_POWER, },		/* NOTE: docs omit this */
-	{ 0x3000, KEY_NUMERIC_0, },
-	{ 0x3001, KEY_NUMERIC_1, },
-	{ 0x3002, KEY_NUMERIC_2, },
-	{ 0x3003, KEY_NUMERIC_3, },
-	{ 0x3004, KEY_NUMERIC_4, },
-	{ 0x3005, KEY_NUMERIC_5, },
-	{ 0x3006, KEY_NUMERIC_6, },
-	{ 0x3007, KEY_NUMERIC_7, },
-	{ 0x3008, KEY_NUMERIC_8, },
-	{ 0x3009, KEY_NUMERIC_9, },
-	{ 0x3022, KEY_ENTER, },
-	{ 0x30ec, KEY_MODE, },		/* "tv/vcr/..." */
-	{ 0x300f, KEY_SELECT, },	/* "info" */
-	{ 0x3020, KEY_CHANNELUP, },	/* "up" */
-	{ 0x302e, KEY_MENU, },		/* "in/out" */
-	{ 0x3011, KEY_VOLUMEDOWN, },	/* "left" */
-	{ 0x300d, KEY_MUTE, },		/* "ok" */
-	{ 0x3010, KEY_VOLUMEUP, },	/* "right" */
-	{ 0x301e, KEY_SUBTITLE, },	/* "cc" */
-	{ 0x3021, KEY_CHANNELDOWN, },	/* "down" */
-	{ 0x3022, KEY_PREVIOUS, },
-	{ 0x3026, KEY_SLEEP, },
-	{ 0x3172, KEY_REWIND, },	/* NOTE: docs wrongly say 0x30ca */
-	{ 0x3175, KEY_PLAY, },
-	{ 0x3174, KEY_FASTFORWARD, },
-	{ 0x3177, KEY_RECORD, },
-	{ 0x3176, KEY_STOP, },
-	{ 0x3169, KEY_PAUSE, },
+	{ KE_KEY, 0x300c, { KEY_POWER } },	/* NOTE: docs omit this */
+	{ KE_KEY, 0x3000, { KEY_NUMERIC_0 } },
+	{ KE_KEY, 0x3001, { KEY_NUMERIC_1 } },
+	{ KE_KEY, 0x3002, { KEY_NUMERIC_2 } },
+	{ KE_KEY, 0x3003, { KEY_NUMERIC_3 } },
+	{ KE_KEY, 0x3004, { KEY_NUMERIC_4 } },
+	{ KE_KEY, 0x3005, { KEY_NUMERIC_5 } },
+	{ KE_KEY, 0x3006, { KEY_NUMERIC_6 } },
+	{ KE_KEY, 0x3007, { KEY_NUMERIC_7 } },
+	{ KE_KEY, 0x3008, { KEY_NUMERIC_8 } },
+	{ KE_KEY, 0x3009, { KEY_NUMERIC_9 } },
+	{ KE_KEY, 0x3022, { KEY_ENTER } },
+	{ KE_KEY, 0x30ec, { KEY_MODE } },	/* "tv/vcr/..." */
+	{ KE_KEY, 0x300f, { KEY_SELECT } },	/* "info" */
+	{ KE_KEY, 0x3020, { KEY_CHANNELUP } },	/* "up" */
+	{ KE_KEY, 0x302e, { KEY_MENU } },	/* "in/out" */
+	{ KE_KEY, 0x3011, { KEY_VOLUMEDOWN } },	/* "left" */
+	{ KE_KEY, 0x300d, { KEY_MUTE } },	/* "ok" */
+	{ KE_KEY, 0x3010, { KEY_VOLUMEUP } },	/* "right" */
+	{ KE_KEY, 0x301e, { KEY_SUBTITLE } },	/* "cc" */
+	{ KE_KEY, 0x3021, { KEY_CHANNELDOWN } },/* "down" */
+	{ KE_KEY, 0x3022, { KEY_PREVIOUS } },
+	{ KE_KEY, 0x3026, { KEY_SLEEP } },
+	{ KE_KEY, 0x3172, { KEY_REWIND } },	/* NOTE: docs wrongly say 0x30ca */
+	{ KE_KEY, 0x3175, { KEY_PLAY } },
+	{ KE_KEY, 0x3174, { KEY_FASTFORWARD } },
+	{ KE_KEY, 0x3177, { KEY_RECORD } },
+	{ KE_KEY, 0x3176, { KEY_STOP } },
+	{ KE_KEY, 0x3169, { KEY_PAUSE } },
 };
 
 /*
@@ -105,19 +102,18 @@ static struct {
  */
 static irqreturn_t dm355evm_keys_irq(int irq, void *_keys)
 {
-	struct dm355evm_keys	*keys = _keys;
-	int			status;
+	static u16 last_event;
+	struct dm355evm_keys *keys = _keys;
+	struct key_entry *ke;
+	unsigned int keycode;
+	int status;
+	u16 event;
 
 	/* For simplicity we ignore INPUT_COUNT and just read
 	 * events until we get the "queue empty" indicator.
 	 * Reading INPUT_LOW decrements the count.
 	 */
 	for (;;) {
-		static u16	last_event;
-		u16		event;
-		int		keycode;
-		int		i;
-
 		status = dm355evm_msp_read(DM355EVM_MSP_INPUT_HIGH);
 		if (status < 0) {
 			dev_dbg(keys->dev, "input high err %d\n",
@@ -156,14 +152,9 @@ static irqreturn_t dm355evm_keys_irq(int irq, void *_keys)
 		/* ignore the RC5 toggle bit */
 		event &= ~0x0800;
 
-		/* find the key, or leave it as unknown */
-		keycode = KEY_UNKNOWN;
-		for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) {
-			if (dm355evm_keys[i].event != event)
-				continue;
-			keycode = dm355evm_keys[i].keycode;
-			break;
-		}
+		/* find the key, or report it as unknown */
+		ke = sparse_keymap_entry_from_scancode(keys->input, event);
+		keycode = ke ? ke->keycode : KEY_UNKNOWN;
 		dev_dbg(keys->dev,
 			"input event 0x%04x--> keycode %d\n",
 			event, keycode);
@@ -174,36 +165,8 @@ static irqreturn_t dm355evm_keys_irq(int irq, void *_keys)
 		input_report_key(keys->input, keycode, 0);
 		input_sync(keys->input);
 	}
-	return IRQ_HANDLED;
-}
 
-static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode)
-{
-	u16		old_keycode;
-	unsigned	i;
-
-	if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys))
-		return -EINVAL;
-
-	old_keycode = dm355evm_keys[index].keycode;
-	dm355evm_keys[index].keycode = keycode;
-	set_bit(keycode, dev->keybit);
-
-	for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) {
-		if (dm355evm_keys[index].keycode == old_keycode)
-			goto done;
-	}
-	clear_bit(old_keycode, dev->keybit);
-done:
-	return 0;
-}
-
-static int dm355evm_getkeycode(struct input_dev *dev, int index, int *keycode)
-{
-	if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys))
-		return -EINVAL;
-
-	return dm355evm_keys[index].keycode;
+	return IRQ_HANDLED;
 }
 
 /*----------------------------------------------------------------------*/
@@ -213,7 +176,6 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev)
 	struct dm355evm_keys	*keys;
 	struct input_dev	*input;
 	int			status;
-	int			i;
 
 	/* allocate instance struct and input dev */
 	keys = kzalloc(sizeof *keys, GFP_KERNEL);
@@ -242,31 +204,30 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev)
 	input->id.product = 0x0355;
 	input->id.version = dm355evm_msp_read(DM355EVM_MSP_FIRMREV);
 
-	input->evbit[0] = BIT(EV_KEY);
-	for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++)
-		__set_bit(dm355evm_keys[i].keycode, input->keybit);
-
-	input->setkeycode = dm355evm_setkeycode;
-	input->getkeycode = dm355evm_getkeycode;
+	status = sparse_keymap_setup(input, dm355evm_keys, NULL);
+	if (status)
+		goto fail1;
 
 	/* REVISIT:  flush the event queue? */
 
 	status = request_threaded_irq(keys->irq, NULL, dm355evm_keys_irq,
 			IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), keys);
 	if (status < 0)
-		goto fail1;
+		goto fail2;
 
 	/* register */
 	status = input_register_device(input);
 	if (status < 0)
-		goto fail2;
+		goto fail3;
 
 	platform_set_drvdata(pdev, keys);
 
 	return 0;
 
-fail2:
+fail3:
 	free_irq(keys->irq, keys);
+fail2:
+	sparse_keymap_free(input);
 fail1:
 	input_free_device(input);
 	kfree(keys);
@@ -280,6 +241,7 @@ static int __devexit dm355evm_keys_remove(struct platform_device *pdev)
 	struct dm355evm_keys	*keys = platform_get_drvdata(pdev);
 
 	free_irq(keys->irq, keys);
+	sparse_keymap_free(keys->input);
 	input_unregister_device(keys->input);
 	kfree(keys);
 


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 4/9] Input: dell-wmi - switch to using sparse keymap library
  2009-12-04  6:11 [PATCH v2 0/9] Implement sparse keymap library Dmitry Torokhov
                   ` (2 preceding siblings ...)
  2009-12-04  6:12 ` [PATCH 3/9] Input: dm355evm_kbd " Dmitry Torokhov
@ 2009-12-04  6:12 ` Dmitry Torokhov
  2009-12-04  6:12 ` [PATCH 5/9] Input: hp-wmi " Dmitry Torokhov
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 22+ messages in thread
From: Dmitry Torokhov @ 2009-12-04  6:12 UTC (permalink / raw)
  To: linux-input, Len Brown
  Cc: linux-acpi, Herton Ronaldo Krzesinski, Harald Welte,
	Corentin Chary, Carlos Corbacho, Wu Zhangjin, Anisse Astier

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---

 drivers/platform/x86/Kconfig    |    1 
 drivers/platform/x86/dell-wmi.c |  199 ++++++++++++---------------------------
 2 files changed, 64 insertions(+), 136 deletions(-)

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 55ca39d..1f10bf4 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -88,6 +88,7 @@ config DELL_WMI
 	tristate "Dell WMI extras"
 	depends on ACPI_WMI
 	depends on INPUT
+	select INPUT_SPARSEKMAP
 	---help---
 	  Say Y here if you want to support WMI-based hotkeys on Dell laptops.
 
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 0f900cc..a35ec82 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 #include <acpi/acpi_drivers.h>
 #include <linux/acpi.h>
 #include <linux/string.h>
@@ -40,123 +41,59 @@ MODULE_LICENSE("GPL");
 
 MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
 
-struct key_entry {
-	char type;		/* See KE_* below */
-	u16 code;
-	u16 keycode;
-};
-
-enum { KE_KEY, KE_SW, KE_IGNORE, KE_END };
-
 /*
  * Certain keys are flagged as KE_IGNORE. All of these are either
  * notifications (rather than requests for change) or are also sent
  * via the keyboard controller so should not be sent again.
  */
 
-static struct key_entry dell_wmi_keymap[] = {
-	{KE_KEY, 0xe045, KEY_PROG1},
-	{KE_KEY, 0xe009, KEY_EJECTCD},
+static const struct key_entry dell_wmi_keymap[] = {
+	{ KE_KEY, 0xe045, { KEY_PROG1 } },
+	{ KE_KEY, 0xe009, { KEY_EJECTCD } },
 
 	/* These also contain the brightness level at offset 6 */
-	{KE_KEY, 0xe006, KEY_BRIGHTNESSUP},
-	{KE_KEY, 0xe005, KEY_BRIGHTNESSDOWN},
+	{ KE_KEY, 0xe006, { KEY_BRIGHTNESSUP } },
+	{ KE_KEY, 0xe005, { KEY_BRIGHTNESSDOWN } },
 
 	/* Battery health status button */
-	{KE_KEY, 0xe007, KEY_BATTERY},
+	{ KE_KEY, 0xe007, { KEY_BATTERY } },
 
 	/* This is actually for all radios. Although physically a
 	 * switch, the notification does not provide an indication of
 	 * state and so it should be reported as a key */
-	{KE_KEY, 0xe008, KEY_WLAN},
+	{ KE_KEY, 0xe008, { KEY_WLAN } },
 
 	/* The next device is at offset 6, the active devices are at
 	   offset 8 and the attached devices at offset 10 */
-	{KE_KEY, 0xe00b, KEY_DISPLAYTOGGLE},
+	{ KE_KEY, 0xe00b, { KEY_DISPLAYTOGGLE } },
 
-	{KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE},
+	{ KE_IGNORE, 0xe00c, {KEY_KBDILLUMTOGGLE } },
 
 	/* BIOS error detected */
-	{KE_IGNORE, 0xe00d, KEY_RESERVED},
+	{ KE_IGNORE, 0xe00d, { KEY_RESERVED } },
 
 	/* Wifi Catcher */
-	{KE_KEY, 0xe011, KEY_PROG2},
+	{ KE_KEY, 0xe011, {KEY_PROG2 } },
 
 	/* Ambient light sensor toggle */
-	{KE_IGNORE, 0xe013, KEY_RESERVED},
-
-	{KE_IGNORE, 0xe020, KEY_MUTE},
-	{KE_IGNORE, 0xe02e, KEY_VOLUMEDOWN},
-	{KE_IGNORE, 0xe030, KEY_VOLUMEUP},
-	{KE_IGNORE, 0xe033, KEY_KBDILLUMUP},
-	{KE_IGNORE, 0xe034, KEY_KBDILLUMDOWN},
-	{KE_IGNORE, 0xe03a, KEY_CAPSLOCK},
-	{KE_IGNORE, 0xe045, KEY_NUMLOCK},
-	{KE_IGNORE, 0xe046, KEY_SCROLLLOCK},
-	{KE_END, 0}
+	{ KE_IGNORE, 0xe013, { KEY_RESERVED } },
+
+	{ KE_IGNORE, 0xe020, { KEY_MUTE } },
+	{ KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } },
+	{ KE_IGNORE, 0xe030, { KEY_VOLUMEUP } },
+	{ KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } },
+	{ KE_IGNORE, 0xe034, { KEY_KBDILLUMDOWN } },
+	{ KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } },
+	{ KE_IGNORE, 0xe045, { KEY_NUMLOCK } },
+	{ KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } },
+	{ KE_END, 0}
 };
 
 static struct input_dev *dell_wmi_input_dev;
 
-static struct key_entry *dell_wmi_get_entry_by_scancode(int code)
-{
-	struct key_entry *key;
-
-	for (key = dell_wmi_keymap; key->type != KE_END; key++)
-		if (code == key->code)
-			return key;
-
-	return NULL;
-}
-
-static struct key_entry *dell_wmi_get_entry_by_keycode(int keycode)
-{
-	struct key_entry *key;
-
-	for (key = dell_wmi_keymap; key->type != KE_END; key++)
-		if (key->type == KE_KEY && keycode == key->keycode)
-			return key;
-
-	return NULL;
-}
-
-static int dell_wmi_getkeycode(struct input_dev *dev, int scancode,
-			       int *keycode)
-{
-	struct key_entry *key = dell_wmi_get_entry_by_scancode(scancode);
-
-	if (key && key->type == KE_KEY) {
-		*keycode = key->keycode;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static int dell_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode)
-{
-	struct key_entry *key;
-	int old_keycode;
-
-	if (keycode < 0 || keycode > KEY_MAX)
-		return -EINVAL;
-
-	key = dell_wmi_get_entry_by_scancode(scancode);
-	if (key && key->type == KE_KEY) {
-		old_keycode = key->keycode;
-		key->keycode = keycode;
-		set_bit(keycode, dev->keybit);
-		if (!dell_wmi_get_entry_by_keycode(old_keycode))
-			clear_bit(old_keycode, dev->keybit);
-		return 0;
-	}
-	return -EINVAL;
-}
-
 static void dell_wmi_notify(u32 value, void *context)
 {
 	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
-	static struct key_entry *key;
 	union acpi_object *obj;
 
 	wmi_get_event_data(value, &response);
@@ -170,55 +107,48 @@ static void dell_wmi_notify(u32 value, void *context)
 		 *  additional information, so mask them off for the
 		 *  scancode lookup
 		 */
-		key = dell_wmi_get_entry_by_scancode(buffer[1] & 0xFFFF);
-		if (key) {
-			input_report_key(dell_wmi_input_dev, key->keycode, 1);
-			input_sync(dell_wmi_input_dev);
-			input_report_key(dell_wmi_input_dev, key->keycode, 0);
-			input_sync(dell_wmi_input_dev);
-		} else if (buffer[1] & 0xFFFF)
+		unsigned int code = buffer[1] & 0xFFFF;
+
+		if (!sparse_keymap_report_event(dell_wmi_input_dev,
+						code, 1, true))
 			printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n",
-			       buffer[1] & 0xFFFF);
+			       code);
 	}
 }
 
 static int __init dell_wmi_input_setup(void)
 {
-	struct key_entry *key;
 	int err;
 
 	dell_wmi_input_dev = input_allocate_device();
-
 	if (!dell_wmi_input_dev)
 		return -ENOMEM;
 
 	dell_wmi_input_dev->name = "Dell WMI hotkeys";
 	dell_wmi_input_dev->phys = "wmi/input0";
 	dell_wmi_input_dev->id.bustype = BUS_HOST;
-	dell_wmi_input_dev->getkeycode = dell_wmi_getkeycode;
-	dell_wmi_input_dev->setkeycode = dell_wmi_setkeycode;
-
-	for (key = dell_wmi_keymap; key->type != KE_END; key++) {
-		switch (key->type) {
-		case KE_KEY:
-			set_bit(EV_KEY, dell_wmi_input_dev->evbit);
-			set_bit(key->keycode, dell_wmi_input_dev->keybit);
-			break;
-		case KE_SW:
-			set_bit(EV_SW, dell_wmi_input_dev->evbit);
-			set_bit(key->keycode, dell_wmi_input_dev->swbit);
-			break;
-		}
-	}
 
-	err = input_register_device(dell_wmi_input_dev);
+	err = sparse_keymap_setup(dell_wmi_input_dev, dell_wmi_keymap, NULL);
+	if (err)
+		goto err_free_dev;
 
-	if (err) {
-		input_free_device(dell_wmi_input_dev);
-		return err;
-	}
+	err = input_register_device(dell_wmi_input_dev);
+	if (err)
+		goto err_free_keymap;
 
 	return 0;
+
+ err_free_keymap:
+	sparse_keymap_free(dell_wmi_input_dev);
+ err_free_dev:
+	input_free_device(dell_wmi_input_dev);
+	return err;
+}
+
+static void dell_wmi_input_destroy(void)
+{
+	sparse_keymap_free(dell_wmi_input_dev);
+	input_unregister_device(dell_wmi_input_dev);
 }
 
 static int __init dell_wmi_init(void)
@@ -226,33 +156,30 @@ static int __init dell_wmi_init(void)
 	int err;
 
 	if (wmi_has_guid(DELL_EVENT_GUID)) {
-		err = dell_wmi_input_setup();
-
-		if (err)
-			return err;
+		printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n");
+		return -ENODEV;
+	}
 
-		err = wmi_install_notify_handler(DELL_EVENT_GUID,
-						 dell_wmi_notify, NULL);
-		if (err) {
-			input_unregister_device(dell_wmi_input_dev);
-			printk(KERN_ERR "dell-wmi: Unable to register"
-			       " notify handler - %d\n", err);
-			return err;
-		}
+	err = dell_wmi_input_setup();
+	if (err)
+		return err;
 
-	} else
-		printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n");
+	err = wmi_install_notify_handler(DELL_EVENT_GUID,
+					 dell_wmi_notify, NULL);
+	if (err) {
+		dell_wmi_input_destroy();
+		printk(KERN_ERR "dell-wmi: Unable to register"
+		       " notify handler - %d\n", err);
+		return err;
+	}
 
 	return 0;
 }
+module_init(dell_wmi_init);
 
 static void __exit dell_wmi_exit(void)
 {
-	if (wmi_has_guid(DELL_EVENT_GUID)) {
-		wmi_remove_notify_handler(DELL_EVENT_GUID);
-		input_unregister_device(dell_wmi_input_dev);
-	}
+	wmi_remove_notify_handler(DELL_EVENT_GUID);
+	dell_wmi_input_destroy();
 }
-
-module_init(dell_wmi_init);
 module_exit(dell_wmi_exit);


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 5/9] Input: hp-wmi - switch to using sparse keymap library
  2009-12-04  6:11 [PATCH v2 0/9] Implement sparse keymap library Dmitry Torokhov
                   ` (3 preceding siblings ...)
  2009-12-04  6:12 ` [PATCH 4/9] Input: dell-wmi " Dmitry Torokhov
@ 2009-12-04  6:12 ` Dmitry Torokhov
  2009-12-04  6:12 ` [PATCH 6/9] Input: eeepc-laptop " Dmitry Torokhov
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 22+ messages in thread
From: Dmitry Torokhov @ 2009-12-04  6:12 UTC (permalink / raw)
  To: linux-input, Len Brown
  Cc: linux-acpi, Herton Ronaldo Krzesinski, Harald Welte,
	Corentin Chary, Carlos Corbacho, Wu Zhangjin, Anisse Astier

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---

 drivers/platform/x86/Kconfig  |    1 
 drivers/platform/x86/hp-wmi.c |  159 ++++++++++++-----------------------------
 2 files changed, 49 insertions(+), 111 deletions(-)

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 1f10bf4..18b66fd 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -137,6 +137,7 @@ config HP_WMI
 	depends on ACPI_WMI
 	depends on INPUT
 	depends on RFKILL || RFKILL = n
+	select INPUT_SPARSEKMAP
 	help
 	 Say Y here if you want to support WMI-based hotkeys on HP laptops and
 	 to read data from WMI such as docking or ambient light sensor state.
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index c284217..3e3fe69 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 #include <acpi/acpi_drivers.h>
 #include <linux/platform_device.h>
 #include <linux/acpi.h>
@@ -69,22 +70,14 @@ struct bios_return {
 	u32 value;
 };
 
-struct key_entry {
-	char type;		/* See KE_* below */
-	u16 code;
-	u16 keycode;
-};
-
-enum { KE_KEY, KE_END };
-
-static struct key_entry hp_wmi_keymap[] = {
-	{KE_KEY, 0x02, KEY_BRIGHTNESSUP},
-	{KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
-	{KE_KEY, 0x20e6, KEY_PROG1},
-	{KE_KEY, 0x2142, KEY_MEDIA},
-	{KE_KEY, 0x213b, KEY_INFO},
-	{KE_KEY, 0x231b, KEY_HELP},
-	{KE_END, 0}
+static const struct key_entry hp_wmi_keymap[] = {
+	{ KE_KEY, 0x02,   { KEY_BRIGHTNESSUP } },
+	{ KE_KEY, 0x03,   { KEY_BRIGHTNESSDOWN } },
+	{ KE_KEY, 0x20e6, { KEY_PROG1 } },
+	{ KE_KEY, 0x2142, { KEY_MEDIA } },
+	{ KE_KEY, 0x213b, { KEY_INFO } },
+	{ KE_KEY, 0x231b, { KEY_HELP } },
+	{ KE_END, 0}
 };
 
 static struct input_dev *hp_wmi_input_dev;
@@ -274,65 +267,10 @@ static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als);
 static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL);
 static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL);
 
-static struct key_entry *hp_wmi_get_entry_by_scancode(int code)
-{
-	struct key_entry *key;
-
-	for (key = hp_wmi_keymap; key->type != KE_END; key++)
-		if (code == key->code)
-			return key;
-
-	return NULL;
-}
-
-static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode)
-{
-	struct key_entry *key;
-
-	for (key = hp_wmi_keymap; key->type != KE_END; key++)
-		if (key->type == KE_KEY && keycode == key->keycode)
-			return key;
-
-	return NULL;
-}
-
-static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode)
-{
-	struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode);
-
-	if (key && key->type == KE_KEY) {
-		*keycode = key->keycode;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static int hp_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode)
-{
-	struct key_entry *key;
-	int old_keycode;
-
-	if (keycode < 0 || keycode > KEY_MAX)
-		return -EINVAL;
-
-	key = hp_wmi_get_entry_by_scancode(scancode);
-	if (key && key->type == KE_KEY) {
-		old_keycode = key->keycode;
-		key->keycode = keycode;
-		set_bit(keycode, dev->keybit);
-		if (!hp_wmi_get_entry_by_keycode(old_keycode))
-			clear_bit(old_keycode, dev->keybit);
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
 static void hp_wmi_notify(u32 value, void *context)
 {
 	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
-	static struct key_entry *key;
+	const struct key_entry *key;
 	union acpi_object *obj;
 
 	wmi_get_event_data(value, &response);
@@ -344,18 +282,11 @@ static void hp_wmi_notify(u32 value, void *context)
 		if (eventcode == 0x4)
 			eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
 							 0);
-		key = hp_wmi_get_entry_by_scancode(eventcode);
+		key = sparse_keymap_entry_from_scancode(hp_wmi_input_dev,
+							eventcode);
 		if (key) {
-			switch (key->type) {
-			case KE_KEY:
-				input_report_key(hp_wmi_input_dev,
-						 key->keycode, 1);
-				input_sync(hp_wmi_input_dev);
-				input_report_key(hp_wmi_input_dev,
-						 key->keycode, 0);
-				input_sync(hp_wmi_input_dev);
-				break;
-			}
+			sparse_keymap_report_entry(hp_wmi_input_dev,
+						   key, 1, true);
 		} else if (eventcode == 0x1) {
 			input_report_switch(hp_wmi_input_dev, SW_DOCK,
 					    hp_wmi_dock_state());
@@ -381,7 +312,6 @@ static void hp_wmi_notify(u32 value, void *context)
 
 static int __init hp_wmi_input_setup(void)
 {
-	struct key_entry *key;
 	int err;
 
 	hp_wmi_input_dev = input_allocate_device();
@@ -389,21 +319,14 @@ static int __init hp_wmi_input_setup(void)
 	hp_wmi_input_dev->name = "HP WMI hotkeys";
 	hp_wmi_input_dev->phys = "wmi/input0";
 	hp_wmi_input_dev->id.bustype = BUS_HOST;
-	hp_wmi_input_dev->getkeycode = hp_wmi_getkeycode;
-	hp_wmi_input_dev->setkeycode = hp_wmi_setkeycode;
-
-	for (key = hp_wmi_keymap; key->type != KE_END; key++) {
-		switch (key->type) {
-		case KE_KEY:
-			set_bit(EV_KEY, hp_wmi_input_dev->evbit);
-			set_bit(key->keycode, hp_wmi_input_dev->keybit);
-			break;
-		}
-	}
 
-	set_bit(EV_SW, hp_wmi_input_dev->evbit);
-	set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
-	set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
+	__set_bit(EV_SW, hp_wmi_input_dev->evbit);
+	__set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
+	__set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
+
+	err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
+	if (err)
+		goto err_free_dev;
 
 	/* Set initial hardware state */
 	input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state());
@@ -411,14 +334,30 @@ static int __init hp_wmi_input_setup(void)
 			    hp_wmi_tablet_state());
 	input_sync(hp_wmi_input_dev);
 
-	err = input_register_device(hp_wmi_input_dev);
+	err = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
+	if (err)
+		goto err_free_keymap;
 
-	if (err) {
-		input_free_device(hp_wmi_input_dev);
-		return err;
-	}
+	err = input_register_device(hp_wmi_input_dev);
+	if (err)
+		goto err_uninstall_notifier;
 
 	return 0;
+
+ err_uninstall_notifier:
+	wmi_remove_notify_handler(HPWMI_EVENT_GUID);
+ err_free_keymap:
+	sparse_keymap_free(hp_wmi_input_dev);
+ err_free_dev:
+	input_free_device(hp_wmi_input_dev);
+	return err;
+}
+
+static void __exit hp_wmi_input_destroy(void)
+{
+	wmi_remove_notify_handler(HPWMI_EVENT_GUID);
+	sparse_keymap_free(hp_wmi_input_dev);
+	input_unregister_device(hp_wmi_input_dev);
 }
 
 static void cleanup_sysfs(struct platform_device *device)
@@ -541,10 +480,9 @@ static int __init hp_wmi_init(void)
 	int err;
 
 	if (wmi_has_guid(HPWMI_EVENT_GUID)) {
-		err = wmi_install_notify_handler(HPWMI_EVENT_GUID,
-						 hp_wmi_notify, NULL);
-		if (!err)
-			hp_wmi_input_setup();
+		err = hp_wmi_input_setup();
+		if (err)
+			return err;
 	}
 
 	if (wmi_has_guid(HPWMI_BIOS_GUID)) {
@@ -564,10 +502,9 @@ static int __init hp_wmi_init(void)
 
 static void __exit hp_wmi_exit(void)
 {
-	if (wmi_has_guid(HPWMI_EVENT_GUID)) {
-		wmi_remove_notify_handler(HPWMI_EVENT_GUID);
-		input_unregister_device(hp_wmi_input_dev);
-	}
+	if (wmi_has_guid(HPWMI_EVENT_GUID))
+		hp_wmi_input_destroy();
+
 	if (hp_wmi_platform_dev) {
 		platform_device_del(hp_wmi_platform_dev);
 		platform_driver_unregister(&hp_wmi_driver);


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 6/9] Input: eeepc-laptop - switch to using sparse keymap library
  2009-12-04  6:11 [PATCH v2 0/9] Implement sparse keymap library Dmitry Torokhov
                   ` (4 preceding siblings ...)
  2009-12-04  6:12 ` [PATCH 5/9] Input: hp-wmi " Dmitry Torokhov
@ 2009-12-04  6:12 ` Dmitry Torokhov
  2009-12-04  6:12 ` [PATCH 7/9] Input: asus-laptop " Dmitry Torokhov
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 22+ messages in thread
From: Dmitry Torokhov @ 2009-12-04  6:12 UTC (permalink / raw)
  To: linux-input, Len Brown
  Cc: linux-acpi, Herton Ronaldo Krzesinski, Harald Welte,
	Corentin Chary, Carlos Corbacho, Wu Zhangjin, Anisse Astier

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---

 drivers/platform/x86/Kconfig        |    1 
 drivers/platform/x86/eeepc-laptop.c |  170 +++++++++++------------------------
 2 files changed, 52 insertions(+), 119 deletions(-)

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 18b66fd..ae9c976 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -336,6 +336,7 @@ config EEEPC_LAPTOP
 	depends on HOTPLUG_PCI
 	select BACKLIGHT_CLASS_DEVICE
 	select HWMON
+	select INPUT_SPARSEKMAP
 	---help---
 	  This driver supports the Fn-Fx keys on Eee PC laptops.
 
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 4226e53..c97305e 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -31,6 +31,7 @@
 #include <acpi/acpi_bus.h>
 #include <linux/uaccess.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 #include <linux/rfkill.h>
 #include <linux/pci.h>
 #include <linux/pci_hotplug.h>
@@ -169,32 +170,25 @@ static struct platform_driver platform_driver = {
 
 static struct platform_device *platform_device;
 
-struct key_entry {
-	char type;
-	u8 code;
-	u16 keycode;
-};
-
-enum { KE_KEY, KE_END };
-
-static struct key_entry eeepc_keymap[] = {
+static const struct key_entry eeepc_keymap[] = {
 	/* Sleep already handled via generic ACPI code */
-	{KE_KEY, 0x10, KEY_WLAN },
-	{KE_KEY, 0x11, KEY_WLAN },
-	{KE_KEY, 0x12, KEY_PROG1 },
-	{KE_KEY, 0x13, KEY_MUTE },
-	{KE_KEY, 0x14, KEY_VOLUMEDOWN },
-	{KE_KEY, 0x15, KEY_VOLUMEUP },
-	{KE_KEY, 0x1a, KEY_COFFEE },
-	{KE_KEY, 0x1b, KEY_ZOOM },
-	{KE_KEY, 0x1c, KEY_PROG2 },
-	{KE_KEY, 0x1d, KEY_PROG3 },
-	{KE_KEY, NOTIFY_BRN_MIN,     KEY_BRIGHTNESSDOWN },
-	{KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP },
-	{KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
-	{KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
-	{KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
-	{KE_END, 0},
+	{ KE_KEY, 0x10, { KEY_WLAN } },
+	{ KE_KEY, 0x11, { KEY_WLAN } },
+	{ KE_KEY, 0x12, { KEY_PROG1 } },
+	{ KE_KEY, 0x13, { KEY_MUTE } },
+	{ KE_KEY, 0x14, { KEY_VOLUMEDOWN } },
+	{ KE_KEY, 0x15, { KEY_VOLUMEUP } },
+	{ KE_KEY, 0x1a, { KEY_COFFEE } },
+	{ KE_KEY, 0x1b, { KEY_ZOOM } },
+	{ KE_KEY, 0x1c, { KEY_PROG2 } },
+	{ KE_KEY, 0x1d, { KEY_PROG3 } },
+	{ KE_KEY, NOTIFY_BRN_MIN,     { KEY_BRIGHTNESSDOWN } },
+	{ KE_IGNORE, NOTIFY_BRN_MIN + 1, },
+	{ KE_KEY, NOTIFY_BRN_MIN + 2, { KEY_BRIGHTNESSUP } },
+	{ KE_KEY, 0x30, { KEY_SWITCHVIDEOMODE } },
+	{ KE_KEY, 0x31, { KEY_SWITCHVIDEOMODE } },
+	{ KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } },
+	{ KE_END, 0},
 };
 
 /*
@@ -509,61 +503,6 @@ static struct attribute_group platform_attribute_group = {
 /*
  * Hotkey functions
  */
-static struct key_entry *eepc_get_entry_by_scancode(int code)
-{
-	struct key_entry *key;
-
-	for (key = eeepc_keymap; key->type != KE_END; key++)
-		if (code == key->code)
-			return key;
-
-	return NULL;
-}
-
-static struct key_entry *eepc_get_entry_by_keycode(int code)
-{
-	struct key_entry *key;
-
-	for (key = eeepc_keymap; key->type != KE_END; key++)
-		if (code == key->keycode && key->type == KE_KEY)
-			return key;
-
-	return NULL;
-}
-
-static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
-{
-	struct key_entry *key = eepc_get_entry_by_scancode(scancode);
-
-	if (key && key->type == KE_KEY) {
-		*keycode = key->keycode;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
-{
-	struct key_entry *key;
-	int old_keycode;
-
-	if (keycode < 0 || keycode > KEY_MAX)
-		return -EINVAL;
-
-	key = eepc_get_entry_by_scancode(scancode);
-	if (key && key->type == KE_KEY) {
-		old_keycode = key->keycode;
-		key->keycode = keycode;
-		set_bit(keycode, dev->keybit);
-		if (!eepc_get_entry_by_keycode(old_keycode))
-			clear_bit(old_keycode, dev->keybit);
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
 static void cmsg_quirk(int cm, const char *name)
 {
 	int dummy;
@@ -698,9 +637,8 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
 
 static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
 {
-	static struct key_entry *key;
-	u16 count;
 	int brn = -ENODEV;
+	u16 count;
 
 	if (!ehotk)
 		return;
@@ -729,19 +667,8 @@ static void eeepc_hotk_notify(struct acpi_device *device, u32 event)
 			else
 				event = NOTIFY_BRN_MIN + 1; /* ... unchanged */
 		}
-		key = eepc_get_entry_by_scancode(event);
-		if (key) {
-			switch (key->type) {
-			case KE_KEY:
-				input_report_key(ehotk->inputdev, key->keycode,
-						 1);
-				input_sync(ehotk->inputdev);
-				input_report_key(ehotk->inputdev, key->keycode,
-						 0);
-				input_sync(ehotk->inputdev);
-				break;
-			}
-		}
+
+		sparse_keymap_report_event(ehotk->inputdev, event, 1, true);
 	}
 }
 
@@ -1017,8 +944,10 @@ static void eeepc_rfkill_exit(void)
 
 static void eeepc_input_exit(void)
 {
-	if (ehotk->inputdev)
+	if (ehotk->inputdev) {
+		sparse_keymap_free(ehotk->inputdev);
 		input_unregister_device(ehotk->inputdev);
+	}
 }
 
 static void eeepc_hwmon_exit(void)
@@ -1158,36 +1087,39 @@ static int eeepc_hwmon_init(struct device *dev)
 
 static int eeepc_input_init(struct device *dev)
 {
-	const struct key_entry *key;
-	int result;
+	struct input_dev *input;
+	int error;
 
-	ehotk->inputdev = input_allocate_device();
-	if (!ehotk->inputdev) {
+	input = input_allocate_device();
+	if (!input) {
 		pr_info("Unable to allocate input device\n");
 		return -ENOMEM;
 	}
-	ehotk->inputdev->name = "Asus EeePC extra buttons";
-	ehotk->inputdev->dev.parent = dev;
-	ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0";
-	ehotk->inputdev->id.bustype = BUS_HOST;
-	ehotk->inputdev->getkeycode = eeepc_getkeycode;
-	ehotk->inputdev->setkeycode = eeepc_setkeycode;
-
-	for (key = eeepc_keymap; key->type != KE_END; key++) {
-		switch (key->type) {
-		case KE_KEY:
-			set_bit(EV_KEY, ehotk->inputdev->evbit);
-			set_bit(key->keycode, ehotk->inputdev->keybit);
-			break;
-		}
+	input->name = "Asus EeePC extra buttons";
+	input->dev.parent = dev;
+	input->phys = EEEPC_HOTK_FILE "/input0";
+	input->id.bustype = BUS_HOST;
+
+	error = sparse_keymap_setup(input, eeepc_keymap, NULL);
+	if (error) {
+		pr_err("Unable to setup input device keymap\n");
+		goto err_free_dev;
 	}
-	result = input_register_device(ehotk->inputdev);
-	if (result) {
-		pr_info("Unable to register input device\n");
-		input_free_device(ehotk->inputdev);
-		return result;
+
+	error = input_register_device(input);
+	if (error) {
+		pr_err("Unable to register input device\n");
+		goto err_free_keymap;
 	}
+
+	ehotk->inputdev = input;
 	return 0;
+
+ err_free_keymap:
+	sparse_keymap_free(input);
+ err_free_dev:
+	input_free_device(input);
+	return error;
 }
 
 static int __devinit eeepc_hotk_add(struct acpi_device *device)


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 7/9] Input: asus-laptop - switch to using sparse keymap library
  2009-12-04  6:11 [PATCH v2 0/9] Implement sparse keymap library Dmitry Torokhov
                   ` (5 preceding siblings ...)
  2009-12-04  6:12 ` [PATCH 6/9] Input: eeepc-laptop " Dmitry Torokhov
@ 2009-12-04  6:12 ` Dmitry Torokhov
  2009-12-04  6:12 ` [PATCH 8/9] Input: topstar-laptop " Dmitry Torokhov
  2009-12-04  6:12 ` [PATCH 9/9] Input: panasonic-laptop " Dmitry Torokhov
  8 siblings, 0 replies; 22+ messages in thread
From: Dmitry Torokhov @ 2009-12-04  6:12 UTC (permalink / raw)
  To: linux-input, Len Brown
  Cc: linux-acpi, Herton Ronaldo Krzesinski, Harald Welte,
	Corentin Chary, Carlos Corbacho, Wu Zhangjin, Anisse Astier

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---

 drivers/platform/x86/Kconfig       |    1 
 drivers/platform/x86/asus-laptop.c |  198 ++++++++++++------------------------
 2 files changed, 66 insertions(+), 133 deletions(-)

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index ae9c976..e555d39 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -59,6 +59,7 @@ config ASUS_LAPTOP
 	select NEW_LEDS
 	select BACKLIGHT_CLASS_DEVICE
 	depends on INPUT
+	select INPUT_SPARSEKMAP
 	---help---
 	  This is the new Linux driver for Asus laptops. It may also support some
 	  MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index b39d2bb..7da59d8 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -49,6 +49,7 @@
 #include <acpi/acpi_bus.h>
 #include <asm/uaccess.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 
 #define ASUS_LAPTOP_VERSION "0.42"
 
@@ -284,42 +285,34 @@ ASUS_LED(pled, "phone", 1);
 ASUS_LED(gled, "gaming", 1);
 ASUS_LED(kled, "kbd_backlight", 3);
 
-struct key_entry {
-	char type;
-	u8 code;
-	u16 keycode;
-};
-
-enum { KE_KEY, KE_END };
-
-static struct key_entry asus_keymap[] = {
-	{KE_KEY, 0x30, KEY_VOLUMEUP},
-	{KE_KEY, 0x31, KEY_VOLUMEDOWN},
-	{KE_KEY, 0x32, KEY_MUTE},
-	{KE_KEY, 0x33, KEY_SWITCHVIDEOMODE},
-	{KE_KEY, 0x34, KEY_SWITCHVIDEOMODE},
-	{KE_KEY, 0x40, KEY_PREVIOUSSONG},
-	{KE_KEY, 0x41, KEY_NEXTSONG},
-	{KE_KEY, 0x43, KEY_STOPCD},
-	{KE_KEY, 0x45, KEY_PLAYPAUSE},
-	{KE_KEY, 0x4c, KEY_MEDIA},
-	{KE_KEY, 0x50, KEY_EMAIL},
-	{KE_KEY, 0x51, KEY_WWW},
-	{KE_KEY, 0x55, KEY_CALC},
-	{KE_KEY, 0x5C, KEY_SCREENLOCK},  /* Screenlock */
-	{KE_KEY, 0x5D, KEY_WLAN},
-	{KE_KEY, 0x5E, KEY_WLAN},
-	{KE_KEY, 0x5F, KEY_WLAN},
-	{KE_KEY, 0x60, KEY_SWITCHVIDEOMODE},
-	{KE_KEY, 0x61, KEY_SWITCHVIDEOMODE},
-	{KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */
-	{KE_KEY, 0x82, KEY_CAMERA},
-	{KE_KEY, 0x8A, KEY_PROG1},
-	{KE_KEY, 0x95, KEY_MEDIA},
-	{KE_KEY, 0x99, KEY_PHONE},
-	{KE_KEY, 0xc4, KEY_KBDILLUMUP},
-	{KE_KEY, 0xc5, KEY_KBDILLUMDOWN},
-	{KE_END, 0},
+static const struct key_entry asus_keymap[] = {
+	{ KE_KEY, 0x30, { KEY_VOLUMEUP } },
+	{ KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
+	{ KE_KEY, 0x32, { KEY_MUTE } },
+	{ KE_KEY, 0x33, { KEY_SWITCHVIDEOMODE } },
+	{ KE_KEY, 0x34, { KEY_SWITCHVIDEOMODE } },
+	{ KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
+	{ KE_KEY, 0x41, { KEY_NEXTSONG } },
+	{ KE_KEY, 0x43, { KEY_STOPCD } },
+	{ KE_KEY, 0x45, { KEY_PLAYPAUSE } },
+	{ KE_KEY, 0x4c, { KEY_MEDIA } },
+	{ KE_KEY, 0x50, { KEY_EMAIL } },
+	{ KE_KEY, 0x51, { KEY_WWW } },
+	{ KE_KEY, 0x55, { KEY_CALC } },
+	{ KE_KEY, 0x5C, { KEY_SCREENLOCK } },  /* Screenlock */
+	{ KE_KEY, 0x5D, { KEY_WLAN } },
+	{ KE_KEY, 0x5E, { KEY_WLAN } },
+	{ KE_KEY, 0x5F, { KEY_WLAN } },
+	{ KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } },
+	{ KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } },
+	{ KE_KEY, 0x6B, { BTN_TOUCH } }, /* Lock Mouse */
+	{ KE_KEY, 0x82, { KEY_CAMERA } },
+	{ KE_KEY, 0x8A, { KEY_PROG1 } },
+	{ KE_KEY, 0x95, { KEY_MEDIA } },
+	{ KE_KEY, 0x99, { KEY_PHONE } },
+	{ KE_KEY, 0xc4, { KEY_KBDILLUMUP } },
+	{ KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
+	{ KE_END, 0},
 };
 
 /*
@@ -866,64 +859,8 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
 /*
  * Hotkey functions
  */
-static struct key_entry *asus_get_entry_by_scancode(int code)
-{
-	struct key_entry *key;
-
-	for (key = asus_keymap; key->type != KE_END; key++)
-		if (code == key->code)
-			return key;
-
-	return NULL;
-}
-
-static struct key_entry *asus_get_entry_by_keycode(int code)
-{
-	struct key_entry *key;
-
-	for (key = asus_keymap; key->type != KE_END; key++)
-		if (code == key->keycode && key->type == KE_KEY)
-			return key;
-
-	return NULL;
-}
-
-static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode)
-{
-	struct key_entry *key = asus_get_entry_by_scancode(scancode);
-
-	if (key && key->type == KE_KEY) {
-		*keycode = key->keycode;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)
-{
-	struct key_entry *key;
-	int old_keycode;
-
-	if (keycode < 0 || keycode > KEY_MAX)
-		return -EINVAL;
-
-	key = asus_get_entry_by_scancode(scancode);
-	if (key && key->type == KE_KEY) {
-		old_keycode = key->keycode;
-		key->keycode = keycode;
-		set_bit(keycode, dev->keybit);
-		if (!asus_get_entry_by_keycode(old_keycode))
-			clear_bit(old_keycode, dev->keybit);
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
 static void asus_hotk_notify(struct acpi_device *device, u32 event)
 {
-	static struct key_entry *key;
 	u16 count;
 
 	/* TODO Find a better way to handle events count. */
@@ -948,20 +885,8 @@ static void asus_hotk_notify(struct acpi_device *device, u32 event)
 					dev_name(&hotk->device->dev), event,
 					count);
 
-	if (hotk->inputdev) {
-		key = asus_get_entry_by_scancode(event);
-		if (!key)
-			return ;
-
-		switch (key->type) {
-		case KE_KEY:
-			input_report_key(hotk->inputdev, key->keycode, 1);
-			input_sync(hotk->inputdev);
-			input_report_key(hotk->inputdev, key->keycode, 0);
-			input_sync(hotk->inputdev);
-			break;
-		}
-	}
+	if (hotk->inputdev)
+		sparse_keymap_report_event(hotk->inputdev, event, 1, true);
 }
 
 #define ASUS_CREATE_DEVICE_ATTR(_name)					\
@@ -1009,7 +934,7 @@ static struct platform_driver asuspf_driver = {
 	.driver = {
 		   .name = ASUS_HOTK_FILE,
 		   .owner = THIS_MODULE,
-		   }
+	},
 };
 
 static struct platform_device *asuspf_device;
@@ -1184,36 +1109,41 @@ static int asus_hotk_get_info(void)
 	return AE_OK;
 }
 
-static int asus_input_init(void)
+static int __init asus_input_init(void)
 {
-	const struct key_entry *key;
-	int result;
+	struct input_dev *inputdev;
+	int error;
 
-	hotk->inputdev = input_allocate_device();
-	if (!hotk->inputdev) {
-		pr_info("Unable to allocate input device\n");
-		return 0;
+	inputdev = input_allocate_device();
+	if (!inputdev) {
+		pr_err("Unable to allocate input device\n");
+		return -ENOMEM;
 	}
-	hotk->inputdev->name = "Asus Laptop extra buttons";
-	hotk->inputdev->phys = ASUS_HOTK_FILE "/input0";
-	hotk->inputdev->id.bustype = BUS_HOST;
-	hotk->inputdev->getkeycode = asus_getkeycode;
-	hotk->inputdev->setkeycode = asus_setkeycode;
-
-	for (key = asus_keymap; key->type != KE_END; key++) {
-		switch (key->type) {
-		case KE_KEY:
-			set_bit(EV_KEY, hotk->inputdev->evbit);
-			set_bit(key->keycode, hotk->inputdev->keybit);
-			break;
-		}
+
+	inputdev->name = "Asus Laptop extra buttons";
+	inputdev->phys = ASUS_HOTK_FILE "/input0";
+	inputdev->id.bustype = BUS_HOST;
+
+	error = sparse_keymap_setup(inputdev, asus_keymap, NULL);
+	if (error) {
+		pr_err("Unable to setup input device keymap\n");
+		goto err_free_dev;
 	}
-	result = input_register_device(hotk->inputdev);
-	if (result) {
-		pr_info("Unable to register input device\n");
-		input_free_device(hotk->inputdev);
+
+	error = input_register_device(inputdev);
+	if (error) {
+		pr_err("Unable to register input device\n");
+		goto err_free_keymap;
 	}
-	return result;
+
+	hotk->inputdev = inputdev;
+	return 0;
+
+ err_free_keymap:
+	sparse_keymap_free(inputdev);
+ err_free_dev:
+	input_free_device(inputdev);
+	return error;
 }
 
 static int asus_hotk_check(void)
@@ -1338,8 +1268,10 @@ static void asus_led_exit(void)
 
 static void asus_input_exit(void)
 {
-	if (hotk->inputdev)
+	if (hotk->inputdev) {
+		sparse_keymap_free(hotk->inputdev);
 		input_unregister_device(hotk->inputdev);
+	}
 }
 
 static void __exit asus_laptop_exit(void)


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 8/9] Input: topstar-laptop - switch to using sparse keymap library
  2009-12-04  6:11 [PATCH v2 0/9] Implement sparse keymap library Dmitry Torokhov
                   ` (6 preceding siblings ...)
  2009-12-04  6:12 ` [PATCH 7/9] Input: asus-laptop " Dmitry Torokhov
@ 2009-12-04  6:12 ` Dmitry Torokhov
  2010-03-29 22:19   ` Herton Ronaldo Krzesinski
  2009-12-04  6:12 ` [PATCH 9/9] Input: panasonic-laptop " Dmitry Torokhov
  8 siblings, 1 reply; 22+ messages in thread
From: Dmitry Torokhov @ 2009-12-04  6:12 UTC (permalink / raw)
  To: linux-input, Len Brown
  Cc: linux-acpi, Herton Ronaldo Krzesinski, Harald Welte,
	Corentin Chary, Carlos Corbacho, Wu Zhangjin, Anisse Astier

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---

 drivers/platform/x86/Kconfig          |    1 
 drivers/platform/x86/topstar-laptop.c |  162 +++++++++++----------------------
 2 files changed, 55 insertions(+), 108 deletions(-)

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index e555d39..00e94b0 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -405,6 +405,7 @@ config TOPSTAR_LAPTOP
 	tristate "Topstar Laptop Extras"
 	depends on ACPI
 	depends on INPUT
+	select INPUT_SPARSEKMAP
 	---help---
 	  This driver adds support for hotkeys found on Topstar laptops.
 
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index 02f3d4e..75a8b62 100644
--- a/drivers/platform/x86/topstar-laptop.c
+++ b/drivers/platform/x86/topstar-laptop.c
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 
 #define ACPI_TOPSTAR_CLASS "topstar"
 
@@ -25,52 +26,37 @@ struct topstar_hkey {
 	struct input_dev *inputdev;
 };
 
-struct tps_key_entry {
-	u8 code;
-	u16 keycode;
-};
-
-static struct tps_key_entry topstar_keymap[] = {
-	{ 0x80, KEY_BRIGHTNESSUP },
-	{ 0x81, KEY_BRIGHTNESSDOWN },
-	{ 0x83, KEY_VOLUMEUP },
-	{ 0x84, KEY_VOLUMEDOWN },
-	{ 0x85, KEY_MUTE },
-	{ 0x86, KEY_SWITCHVIDEOMODE },
-	{ 0x87, KEY_F13 }, /* touchpad enable/disable key */
-	{ 0x88, KEY_WLAN },
-	{ 0x8a, KEY_WWW },
-	{ 0x8b, KEY_MAIL },
-	{ 0x8c, KEY_MEDIA },
-	{ 0x96, KEY_F14 }, /* G key? */
-	{ }
-};
-
-static struct tps_key_entry *tps_get_key_by_scancode(int code)
-{
-	struct tps_key_entry *key;
-
-	for (key = topstar_keymap; key->code; key++)
-		if (code == key->code)
-			return key;
+static const struct key_entry topstar_keymap[] = {
+	{ KE_KEY, 0x80, { KEY_BRIGHTNESSUP } },
+	{ KE_KEY, 0x81, { KEY_BRIGHTNESSDOWN } },
+	{ KE_KEY, 0x83, { KEY_VOLUMEUP } },
+	{ KE_KEY, 0x84, { KEY_VOLUMEDOWN } },
+	{ KE_KEY, 0x85, { KEY_MUTE } },
+	{ KE_KEY, 0x86, { KEY_SWITCHVIDEOMODE } },
+	{ KE_KEY, 0x87, { KEY_F13 } }, /* touchpad enable/disable key */
+	{ KE_KEY, 0x88, { KEY_WLAN } },
+	{ KE_KEY, 0x8a, { KEY_WWW } },
+	{ KE_KEY, 0x8b, { KEY_MAIL } },
+	{ KE_KEY, 0x8c, { KEY_MEDIA } },
 
-	return NULL;
-}
-
-static struct tps_key_entry *tps_get_key_by_keycode(int code)
-{
-	struct tps_key_entry *key;
+	/* Known non hotkey events don't handled or that we don't care yet */
+	{ KE_IGNORE, 0x8e, },
+	{ KE_IGNORE, 0x8f, },
+	{ KE_IGNORE, 0x90, },
 
-	for (key = topstar_keymap; key->code; key++)
-		if (code == key->keycode)
-			return key;
+	/*
+	 * 'G key' generate two event codes, convert to only
+	 * one event/key code for now, consider replacing by
+	 * a switch (3G switch - SW_3G?)
+	 */
+	{ KE_KEY, 0x96, { KEY_F14 } },
+	{ KE_KEY, 0x97, { KEY_F14 } },
 
-	return NULL;
-}
+	{ KE_END, 0 }
+};
 
 static void acpi_topstar_notify(struct acpi_device *device, u32 event)
 {
-	struct tps_key_entry *key;
 	static bool dup_evnt[2];
 	bool *dup;
 	struct topstar_hkey *hkey = acpi_driver_data(device);
@@ -85,27 +71,8 @@ static void acpi_topstar_notify(struct acpi_device *device, u32 event)
 		*dup = true;
 	}
 
-	/*
-	 * 'G key' generate two event codes, convert to only
-	 * one event/key code for now (3G switch?)
-	 */
-	if (event == 0x97)
-		event = 0x96;
-
-	key = tps_get_key_by_scancode(event);
-	if (key) {
-		input_report_key(hkey->inputdev, key->keycode, 1);
-		input_sync(hkey->inputdev);
-		input_report_key(hkey->inputdev, key->keycode, 0);
-		input_sync(hkey->inputdev);
-		return;
-	}
-
-	/* Known non hotkey events don't handled or that we don't care yet */
-	if (event == 0x8e || event == 0x8f || event == 0x90)
-		return;
-
-	pr_info("unknown event = 0x%02x\n", event);
+	if (!sparse_keymap_report_event(hkey->inputdev, event, 1, true))
+		pr_info("unknown event = 0x%02x\n", event);
 }
 
 static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
@@ -126,63 +93,41 @@ static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
 	return 0;
 }
 
-static int topstar_getkeycode(struct input_dev *dev, int scancode, int *keycode)
-{
-	struct tps_key_entry *key = tps_get_key_by_scancode(scancode);
-
-	if (!key)
-		return -EINVAL;
-
-	*keycode = key->keycode;
-	return 0;
-}
-
-static int topstar_setkeycode(struct input_dev *dev, int scancode, int keycode)
-{
-	struct tps_key_entry *key;
-	int old_keycode;
-
-	if (keycode < 0 || keycode > KEY_MAX)
-		return -EINVAL;
-
-	key = tps_get_key_by_scancode(scancode);
-
-	if (!key)
-		return -EINVAL;
-
-	old_keycode = key->keycode;
-	key->keycode = keycode;
-	set_bit(keycode, dev->keybit);
-	if (!tps_get_key_by_keycode(old_keycode))
-		clear_bit(old_keycode, dev->keybit);
-	return 0;
-}
-
 static int acpi_topstar_init_hkey(struct topstar_hkey *hkey)
 {
-	struct tps_key_entry *key;
+	struct input_dev *input;
+	int error;
 
-	hkey->inputdev = input_allocate_device();
-	if (!hkey->inputdev) {
+	input = input_allocate_device();
+	if (!input) {
 		pr_err("Unable to allocate input device\n");
-		return -ENODEV;
+		return -ENOMEM;
 	}
-	hkey->inputdev->name = "Topstar Laptop extra buttons";
-	hkey->inputdev->phys = "topstar/input0";
-	hkey->inputdev->id.bustype = BUS_HOST;
-	hkey->inputdev->getkeycode = topstar_getkeycode;
-	hkey->inputdev->setkeycode = topstar_setkeycode;
-	for (key = topstar_keymap; key->code; key++) {
-		set_bit(EV_KEY, hkey->inputdev->evbit);
-		set_bit(key->keycode, hkey->inputdev->keybit);
+
+	input->name = "Topstar Laptop extra buttons";
+	input->phys = "topstar/input0";
+	input->id.bustype = BUS_HOST;
+
+	error = sparse_keymap_setup(input, topstar_keymap, NULL);
+	if (error) {
+		pr_err("Unable to setup input device keymap\n");
+		goto err_free_dev;
 	}
-	if (input_register_device(hkey->inputdev)) {
+
+	error = input_register_device(input);
+	if (error) {
 		pr_err("Unable to register input device\n");
-		input_free_device(hkey->inputdev);
-		return -ENODEV;
+		goto err_free_keymap;
 	}
 
+	hkey->inputdev = input;
 	return 0;
+
+ err_free_keymap:
+	sparse_keymap_free(input);
+ err_free_dev:
+	input_free_device(input);
+	return error;
 }
 
 static int acpi_topstar_add(struct acpi_device *device)
@@ -216,6 +161,7 @@ static int acpi_topstar_remove(struct acpi_device *device, int type)
 
 	acpi_topstar_fncx_switch(device, false);
 
+	sparse_keymap_free(tps_hkey->inputdev);
 	input_unregister_device(tps_hkey->inputdev);
 	kfree(tps_hkey);
 


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [PATCH 9/9] Input: panasonic-laptop - switch to using sparse keymap library
  2009-12-04  6:11 [PATCH v2 0/9] Implement sparse keymap library Dmitry Torokhov
                   ` (7 preceding siblings ...)
  2009-12-04  6:12 ` [PATCH 8/9] Input: topstar-laptop " Dmitry Torokhov
@ 2009-12-04  6:12 ` Dmitry Torokhov
  2009-12-04 19:14   ` Harald Welte
  8 siblings, 1 reply; 22+ messages in thread
From: Dmitry Torokhov @ 2009-12-04  6:12 UTC (permalink / raw)
  To: linux-input, Len Brown
  Cc: linux-acpi, Herton Ronaldo Krzesinski, Harald Welte,
	Corentin Chary, Carlos Corbacho, Wu Zhangjin, Anisse Astier

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---

 drivers/platform/x86/Kconfig            |    1 
 drivers/platform/x86/panasonic-laptop.c |  165 +++++++++++--------------------
 2 files changed, 58 insertions(+), 108 deletions(-)

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 00e94b0..1b27e4d 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -168,6 +168,7 @@ config PANASONIC_LAPTOP
 	tristate "Panasonic Laptop Extras"
 	depends on INPUT && ACPI
 	depends on BACKLIGHT_CLASS_DEVICE
+	select INPUT_SPARSEKMAP
 	---help---
 	  This driver adds support for access to backlight control and hotkeys
 	  on Panasonic Let's Note laptops.
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index fe7cf01..85f1189 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -127,6 +127,7 @@
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 
 
 #ifndef ACPI_HOTKEY_COMPONENT
@@ -199,30 +200,29 @@ static struct acpi_driver acpi_pcc_driver = {
 			},
 };
 
-#define KEYMAP_SIZE		11
-static const int initial_keymap[KEYMAP_SIZE] = {
-	/*  0 */ KEY_RESERVED,
-	/*  1 */ KEY_BRIGHTNESSDOWN,
-	/*  2 */ KEY_BRIGHTNESSUP,
-	/*  3 */ KEY_DISPLAYTOGGLE,
-	/*  4 */ KEY_MUTE,
-	/*  5 */ KEY_VOLUMEDOWN,
-	/*  6 */ KEY_VOLUMEUP,
-	/*  7 */ KEY_SLEEP,
-	/*  8 */ KEY_PROG1, /* Change CPU boost */
-	/*  9 */ KEY_BATTERY,
-	/* 10 */ KEY_SUSPEND,
+static const struct key_entry panasonic_keymap[] = {
+	{ KE_KEY, 0, { KEY_RESERVED } },
+	{ KE_KEY, 1, { KEY_BRIGHTNESSDOWN } },
+	{ KE_KEY, 2, { KEY_BRIGHTNESSUP } },
+	{ KE_KEY, 3, { KEY_DISPLAYTOGGLE } },
+	{ KE_KEY, 4, { KEY_MUTE } },
+	{ KE_KEY, 5, { KEY_VOLUMEDOWN } },
+	{ KE_KEY, 6, { KEY_VOLUMEUP } },
+	{ KE_KEY, 7, { KEY_SLEEP } },
+	{ KE_KEY, 8, { KEY_PROG1 } }, /* Change CPU boost */
+	{ KE_KEY, 9, { KEY_BATTERY } },
+	{ KE_KEY, 10, { KEY_SUSPEND } },
+	{ KE_END, 0 }
 };
 
 struct pcc_acpi {
 	acpi_handle		handle;
 	unsigned long		num_sifr;
 	int			sticky_mode;
-	u32 			*sinf;
+	u32			*sinf;
 	struct acpi_device	*device;
 	struct input_dev	*input_dev;
 	struct backlight_device	*backlight;
-	int			keymap[KEYMAP_SIZE];
 };
 
 struct pcc_keyinput {
@@ -445,57 +445,10 @@ static struct attribute_group pcc_attr_group = {
 
 /* hotkey input device driver */
 
-static int pcc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
-{
-	struct pcc_acpi *pcc = input_get_drvdata(dev);
-
-	if (scancode >= ARRAY_SIZE(pcc->keymap))
-		return -EINVAL;
-
-	*keycode = pcc->keymap[scancode];
-
-	return 0;
-}
-
-static int keymap_get_by_keycode(struct pcc_acpi *pcc, int keycode)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) {
-		if (pcc->keymap[i] == keycode)
-			return i+1;
-	}
-
-	return 0;
-}
-
-static int pcc_setkeycode(struct input_dev *dev, int scancode, int keycode)
-{
-	struct pcc_acpi *pcc = input_get_drvdata(dev);
-	int oldkeycode;
-
-	if (scancode >= ARRAY_SIZE(pcc->keymap))
-		return -EINVAL;
-
-	if (keycode < 0 || keycode > KEY_MAX)
-		return -EINVAL;
-
-	oldkeycode = pcc->keymap[scancode];
-	pcc->keymap[scancode] = keycode;
-
-	set_bit(keycode, dev->keybit);
-
-	if (!keymap_get_by_keycode(pcc, oldkeycode))
-		clear_bit(oldkeycode, dev->keybit);
-
-	return 0;
-}
-
 static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
 {
 	struct input_dev *hotk_input_dev = pcc->input_dev;
 	int rc;
-	int key_code, hkey_num;
 	unsigned long long result;
 
 	rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
@@ -508,25 +461,10 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
 
 	acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result);
 
-	hkey_num = result & 0xf;
-
-	if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) {
+	if (!sparse_keymap_report_event(hotk_input_dev,
+					result & 0xf, result & 0x80, false))
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-				  "hotkey number out of range: %d\n",
-				  hkey_num));
-		return;
-	}
-
-	key_code = pcc->keymap[hkey_num];
-
-	if (key_code != KEY_RESERVED) {
-		int pushed = (result & 0x80) ? TRUE : FALSE;
-
-		input_report_key(hotk_input_dev, key_code, pushed);
-		input_sync(hotk_input_dev);
-	}
-
-	return;
+				  "Unknown hotkey event: %d\n", result));
 }
 
 static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
@@ -545,40 +483,55 @@ static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
 
 static int acpi_pcc_init_input(struct pcc_acpi *pcc)
 {
-	int i, rc;
+	struct input_dev *input_dev;
+	int error;
 
-	pcc->input_dev = input_allocate_device();
-	if (!pcc->input_dev) {
+	input_dev = input_allocate_device();
+	if (!input_dev) {
 		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 				  "Couldn't allocate input device for hotkey"));
 		return -ENOMEM;
 	}
 
-	pcc->input_dev->evbit[0] = BIT(EV_KEY);
+	input_dev->name = ACPI_PCC_DRIVER_NAME;
+	input_dev->phys = ACPI_PCC_INPUT_PHYS;
+	input_dev->id.bustype = BUS_HOST;
+	input_dev->id.vendor = 0x0001;
+	input_dev->id.product = 0x0001;
+	input_dev->id.version = 0x0100;
 
-	pcc->input_dev->name = ACPI_PCC_DRIVER_NAME;
-	pcc->input_dev->phys = ACPI_PCC_INPUT_PHYS;
-	pcc->input_dev->id.bustype = BUS_HOST;
-	pcc->input_dev->id.vendor = 0x0001;
-	pcc->input_dev->id.product = 0x0001;
-	pcc->input_dev->id.version = 0x0100;
-	pcc->input_dev->getkeycode = pcc_getkeycode;
-	pcc->input_dev->setkeycode = pcc_setkeycode;
+	error = sparse_keymap_setup(input_dev, panasonic_keymap, NULL);
+	if (error) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+				  "Unable to setup input device keymap\n"));
+		goto err_free_dev;
+	}
 
-	/* load initial keymap */
-	memcpy(pcc->keymap, initial_keymap, sizeof(pcc->keymap));
+	input_set_drvdata(input_dev, pcc);
 
-	for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++)
-		__set_bit(pcc->keymap[i], pcc->input_dev->keybit);
-	__clear_bit(KEY_RESERVED, pcc->input_dev->keybit);
+	error = input_register_device(input_dev);
+	if (error) {
+		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+				  "Unable to register input device\n"));
+		goto err_free_keymap;
+	}
 
-	input_set_drvdata(pcc->input_dev, pcc);
+	pcc->input_dev = input_dev;
+	return 0;
 
-	rc = input_register_device(pcc->input_dev);
-	if (rc < 0)
-		input_free_device(pcc->input_dev);
+ err_free_keymap:
+	sparse_keymap_free(input_dev);
+ err_free_dev:
+	input_free_device(input_dev);
+	return error;
+}
 
-	return rc;
+static void acpi_pcc_destroy_input(struct pcc_acpi *pcc)
+{
+	sparse_keymap_free(pcc->input_dev);
+	input_unregister_device(pcc->input_dev);
+	/* no need to input_free_device() since core input API refcount and
+	 * free()s the device */
 }
 
 /* kernel module interface */
@@ -671,9 +624,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
 out_backlight:
 	backlight_device_unregister(pcc->backlight);
 out_input:
-	input_unregister_device(pcc->input_dev);
-	/* no need to input_free_device() since core input API refcount and
-	 * free()s the device */
+	acpi_pcc_destroy_input(pcc);
 out_sinf:
 	kfree(pcc->sinf);
 out_hotkey:
@@ -710,9 +661,7 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
 
 	backlight_device_unregister(pcc->backlight);
 
-	input_unregister_device(pcc->input_dev);
-	/* no need to input_free_device() since core input API refcount and
-	 * free()s the device */
+	acpi_pcc_destroy_input(pcc);
 
 	kfree(pcc->sinf);
 	kfree(pcc);


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/9] Input: add generic support for sparse keymaps
  2009-12-04  6:11 ` [PATCH 1/9] Input: add generic support for sparse keymaps Dmitry Torokhov
@ 2009-12-04  8:02   ` Wu Zhangjin
  2009-12-04  8:34     ` Anisse Astier
  2009-12-04  8:37     ` Dmitry Torokhov
  2009-12-04 14:06   ` Anisse Astier
  2009-12-06 22:57   ` Anisse Astier
  2 siblings, 2 replies; 22+ messages in thread
From: Wu Zhangjin @ 2009-12-04  8:02 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: linux-input, Len Brown, linux-acpi, Herton Ronaldo Krzesinski,
	Harald Welte, Corentin Chary, Carlos Corbacho, Anisse Astier

On Thu, 2009-12-03 at 22:11 -0800, Dmitry Torokhov wrote:
> More and more devices choose to reimplement support for sparse keymaps
> first introduced by wistron driver. Move it into a library module so it
> can be easily used by interested parties.

Hi, Dmitry

I have tried to apply this patch to the latest 2.6.32 and the linux-mips
tree, both rejected.

So, which git tree should I use?

Thanks!
	Wu Zhangjin

> 
> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
> ---
> 
>  Documentation/DocBook/device-drivers.tmpl |    4 
>  drivers/input/Kconfig                     |   28 ++-
>  drivers/input/Makefile                    |    1 
>  drivers/input/input-polldev.c             |   14 +-
>  drivers/input/sparse-keymap.c             |  251 +++++++++++++++++++++++++++++
>  include/linux/input/sparse-keymap.h       |   62 +++++++
>  6 files changed, 348 insertions(+), 12 deletions(-)
>  create mode 100644 drivers/input/sparse-keymap.c
>  create mode 100644 include/linux/input/sparse-keymap.h
> 
> diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
> index e994d1d..f9a6e2c 100644
> --- a/Documentation/DocBook/device-drivers.tmpl
> +++ b/Documentation/DocBook/device-drivers.tmpl
> @@ -306,6 +306,10 @@ X!Idrivers/video/console/fonts.c
>       <sect1><title>Matrix keyboars/keypads</title>
>  !Iinclude/linux/input/matrix_keypad.h
>       </sect1>
> +     <sect1><title>Sparse keymap support</title>
> +!Iinclude/linux/input/sparse-keymap.h
> +!Edrivers/input/sparse-keymap.c
> +     </sect1>
>    </chapter>
>  
>    <chapter id="spi">
> diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
> index cd50c00..50af91e 100644
> --- a/drivers/input/Kconfig
> +++ b/drivers/input/Kconfig
> @@ -8,7 +8,7 @@ menu "Input device support"
>  config INPUT
>  	tristate "Generic input layer (needed for keyboard, mouse, ...)" if EMBEDDED
>  	default y
> -	---help---
> +	help
>  	  Say Y here if you have any input device (mouse, keyboard, tablet,
>  	  joystick, steering wheel ...) connected to your system and want
>  	  it to be available to applications. This includes standard PS/2
> @@ -27,8 +27,7 @@ if INPUT
>  
>  config INPUT_FF_MEMLESS
>  	tristate "Support for memoryless force-feedback devices"
> -	default n
> -	---help---
> +	help
>  	  Say Y here if you have memoryless force-feedback input device
>  	  such as Logitech WingMan Force 3D, ThrustMaster FireStorm Dual
>  	  Power 2, or similar. You will also need to enable hardware-specific
> @@ -52,12 +51,25 @@ config INPUT_POLLDEV
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called input-polldev.
>  
> +config INPUT_SPARSEKMAP
> +	tristate "Sparse keymap support library"
> +	help
> +	  Say Y here if you are using a driver for an input
> +	  device that uses sparse keymap. This option is only
> +	  useful for out-of-tree drivers since in-tree drivers
> +	  select it automatically.
> +
> +	  If unsure, say N.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called sparse-keymap.
> +
>  comment "Userland interfaces"
>  
>  config INPUT_MOUSEDEV
>  	tristate "Mouse interface" if EMBEDDED
>  	default y
> -	---help---
> +	help
>  	  Say Y here if you want your mouse to be accessible as char devices
>  	  13:32+ - /dev/input/mouseX and 13:63 - /dev/input/mice as an
>  	  emulated IntelliMouse Explorer PS/2 mouse. That way, all user space
> @@ -73,7 +85,7 @@ config INPUT_MOUSEDEV_PSAUX
>  	bool "Provide legacy /dev/psaux device"
>  	default y
>  	depends on INPUT_MOUSEDEV
> -	---help---
> +	help
>  	  Say Y here if you want your mouse also be accessible as char device
>  	  10:1 - /dev/psaux. The data available through /dev/psaux is exactly
>  	  the same as the data from /dev/input/mice.
> @@ -103,7 +115,7 @@ config INPUT_MOUSEDEV_SCREEN_Y
>  
>  config INPUT_JOYDEV
>  	tristate "Joystick interface"
> -	---help---
> +	help
>  	  Say Y here if you want your joystick or gamepad to be
>  	  accessible as char device 13:0+ - /dev/input/jsX device.
>  
> @@ -125,7 +137,7 @@ config INPUT_EVDEV
>  
>  config INPUT_EVBUG
>  	tristate "Event debugging"
> -	---help---
> +	help
>  	  Say Y here if you have a problem with the input subsystem and
>  	  want all events (keypresses, mouse movements), to be output to
>  	  the system log. While this is useful for debugging, it's also
> @@ -140,7 +152,7 @@ config INPUT_EVBUG
>  config INPUT_APMPOWER
>  	tristate "Input Power Event -> APM Bridge" if EMBEDDED
>  	depends on INPUT && APM_EMULATION
> -	---help---
> +	help
>  	  Say Y here if you want suspend key events to trigger a user
>  	  requested suspend through APM. This is useful on embedded
>  	  systems where such behaviour is desired without userspace
> diff --git a/drivers/input/Makefile b/drivers/input/Makefile
> index 4c9c745..7ad212d 100644
> --- a/drivers/input/Makefile
> +++ b/drivers/input/Makefile
> @@ -9,6 +9,7 @@ input-core-objs := input.o input-compat.o ff-core.o
>  
>  obj-$(CONFIG_INPUT_FF_MEMLESS)	+= ff-memless.o
>  obj-$(CONFIG_INPUT_POLLDEV)	+= input-polldev.o
> +obj-$(CONFIG_INPUT_SPARSEKMAP)	+= sparse-keymap.o
>  
>  obj-$(CONFIG_INPUT_MOUSEDEV)	+= mousedev.o
>  obj-$(CONFIG_INPUT_JOYDEV)	+= joydev.o
> diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c
> index 6a2eb39..aa6713b 100644
> --- a/drivers/input/input-polldev.c
> +++ b/drivers/input/input-polldev.c
> @@ -212,7 +212,7 @@ EXPORT_SYMBOL(input_allocate_polled_device);
>   * @dev: device to free
>   *
>   * The function frees memory allocated for polling device and drops
> - * reference to the associated input device (if present).
> + * reference to the associated input device.
>   */
>  void input_free_polled_device(struct input_polled_dev *dev)
>  {
> @@ -258,6 +258,15 @@ int input_register_polled_device(struct input_polled_dev *dev)
>  		return error;
>  	}
>  
> +	/*
> +	 * Take extra reference to the underlying input device so
> +	 * that it survives call to input_unregister_polled_device()
> +	 * and is deleted only after input_free_polled_device()
> +	 * has been invoked. This is needed to ease task of freeing
> +	 * sparse keymaps.
> +	 */
> +	input_get_device(input);
> +
>  	return 0;
>  }
>  EXPORT_SYMBOL(input_register_polled_device);
> @@ -269,8 +278,6 @@ EXPORT_SYMBOL(input_register_polled_device);
>   * The function unregisters previously registered polled input
>   * device from input layer. Polling is stopped and device is
>   * ready to be freed with call to input_free_polled_device().
> - * Callers should not attempt to access dev->input pointer
> - * after calling this function.
>   */
>  void input_unregister_polled_device(struct input_polled_dev *dev)
>  {
> @@ -278,7 +285,6 @@ void input_unregister_polled_device(struct input_polled_dev *dev)
>  			   &input_polldev_attribute_group);
>  
>  	input_unregister_device(dev->input);
> -	dev->input = NULL;
>  }
>  EXPORT_SYMBOL(input_unregister_polled_device);
>  
> diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c
> new file mode 100644
> index 0000000..4655c56
> --- /dev/null
> +++ b/drivers/input/sparse-keymap.c
> @@ -0,0 +1,251 @@
> +/*
> + * Generic support for sparse keymaps
> + *
> + * Copyright (c) 2009 Dmitry Torokhov
> + *
> + * Derived from wistron button driver:
> + * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
> + * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
> + * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + */
> +
> +#include <linux/input.h>
> +#include <linux/input/sparse-keymap.h>
> +
> +MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
> +MODULE_DESCRIPTION("Generic support for sparse keymaps");
> +MODULE_LICENSE("GPL v2");
> +MODULE_VERSION("0.1");
> +
> +/**
> + * sparse_keymap_entry_from_scancode - perform sparse keymap lookup
> + * @dev: Input device using sparse keymap
> + * @code: Scan code
> + *
> + * This function is used to perform &struct key_entry lookup in an
> + * input device using sparse keymap.
> + */
> +struct key_entry *sparse_keymap_entry_from_scancode(struct input_dev *dev,
> +						    unsigned int code)
> +{
> +	struct key_entry *key;
> +
> +	for (key = dev->keycode; key->type != KE_END; key++)
> +		if (code == key->code)
> +			return key;
> +
> +	return NULL;
> +}
> +EXPORT_SYMBOL(sparse_keymap_entry_from_scancode);
> +
> +/**
> + * sparse_keymap_entry_from_keycode - perform sparse keymap lookup
> + * @dev: Input device using sparse keymap
> + * @keycode: Key code
> + *
> + * This function is used to perform &struct key_entry lookup in an
> + * input device using sparse keymap.
> + */
> +struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev,
> +						   unsigned int keycode)
> +{
> +	struct key_entry *key;
> +
> +	for (key = dev->keycode; key->type != KE_END; key++)
> +		if (key->type == KE_KEY && keycode == key->keycode)
> +			return key;
> +
> +	return NULL;
> +}
> +EXPORT_SYMBOL(sparse_keymap_entry_from_keycode);
> +
> +static int sparse_keymap_getkeycode(struct input_dev *dev,
> +				    int scancode, int *keycode)
> +{
> +	const struct key_entry *key =
> +			sparse_keymap_entry_from_scancode(dev, scancode);
> +
> +	if (key && key->type == KE_KEY) {
> +		*keycode = key->keycode;
> +		return 0;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int sparse_keymap_setkeycode(struct input_dev *dev,
> +				    int scancode, int keycode)
> +{
> +	struct key_entry *key;
> +	int old_keycode;
> +
> +	if (keycode < 0 || keycode > KEY_MAX)
> +		return -EINVAL;
> +
> +	key = sparse_keymap_entry_from_scancode(dev, scancode);
> +	if (key && key->type == KE_KEY) {
> +		old_keycode = key->keycode;
> +		key->keycode = keycode;
> +		set_bit(keycode, dev->keybit);
> +		if (!sparse_keymap_entry_from_keycode(dev, old_keycode))
> +			clear_bit(old_keycode, dev->keybit);
> +		return 0;
> +	}
> +
> +	return -EINVAL;
> +}
> +EXPORT_SYMBOL(sparse_keymap_setkeycode);
> +
> +/**
> + * sparse_keymap_setup - set up sparse keymap for an input device
> + * @dev: Input device
> + * @keymap: Keymap in form of array of &key_entry structures ending
> + *	with %KE_END type entry
> + * @setup: Function that can be used to adjust keymap entries
> + *	depending on device's deeds, may be %NULL
> + *
> + * The function calculates size and allocates copy of the original
> + * keymap after which sets up input device event bits appropriately.
> + * Before detsroying input device allocated keymap should be freed
> + * with a call to sparse_keymap_free().
> + */
> +int sparse_keymap_setup(struct input_dev *dev,
> +			const struct key_entry *keymap,
> +			int (*setup)(struct input_dev *, struct key_entry *))
> +{
> +	size_t map_size = 1; /* to account for the last KE_END entry */
> +	const struct key_entry *e;
> +	struct key_entry *map, *entry;
> +	int i;
> +	int error;
> +
> +	for (e = keymap; e->type != KE_END; e++)
> +		map_size++;
> +
> +	map = kcalloc(map_size, sizeof (struct key_entry), GFP_KERNEL);
> +	if (!map)
> +		return -ENOMEM;
> +
> +	memcpy(map, keymap, map_size * sizeof (struct key_entry));
> +
> +	for (i = 0; i < map_size; i++) {
> +		entry = &map[i];
> +
> +		if (setup) {
> +			error = setup(dev, entry);
> +			if (error)
> +				goto err_out;
> +		}
> +
> +		switch (entry->type) {
> +		case KE_KEY:
> +			__set_bit(EV_KEY, dev->evbit);
> +			__set_bit(entry->keycode, dev->keybit);
> +			break;
> +
> +		case KE_SW:
> +			__set_bit(EV_SW, dev->evbit);
> +			__set_bit(entry->sw.code, dev->swbit);
> +			break;
> +		}
> +	}
> +
> +	dev->keycode = map;
> +	dev->keycodemax = map_size;
> +	dev->getkeycode = sparse_keymap_getkeycode;
> +	dev->setkeycode = sparse_keymap_setkeycode;
> +
> +	return 0;
> +
> + err_out:
> +	kfree(keymap);
> +	return error;
> +
> +}
> +EXPORT_SYMBOL(sparse_keymap_setup);
> +
> +/**
> + * sparse_keymap_free - free memory allocated for sparse keymap
> + * @dev: Input device using sparse keymap
> + *
> + * This function is used to free memory allocated by sparse keymap
> + * in an input device that was set up by sparse_keymap_setup().
> + */
> +void sparse_keymap_free(struct input_dev *dev)
> +{
> +	kfree(dev->keycode);
> +	dev->keycode = NULL;
> +	dev->keycodemax = 0;
> +	dev->getkeycode = NULL;
> +	dev->setkeycode = NULL;
> +}
> +EXPORT_SYMBOL(sparse_keymap_free);
> +
> +/**
> + * sparse_keymap_report_event - report event corresponding to given key entry
> + * @dev: Input device for which event should be reported
> + * @ke: key entry describing event
> + * @value: Value that should be reported (ignored by %KE_SW entries)
> + * @autorelease: Signals whether release event should be emitted for %KE_KEY
> + *	entries right after reporting press event, ignored by all other
> + *	entries
> + *
> + * This function is used to report input event described by given
> + * &struct key_entry.
> + */
> +void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *ke,
> +				unsigned int value, bool autorelease)
> +{
> +	switch (ke->type) {
> +	case KE_KEY:
> +		input_report_key(dev, ke->keycode, value);
> +		input_sync(dev);
> +		if (value && autorelease) {
> +			input_report_key(dev, ke->keycode, 0);
> +			input_sync(dev);
> +		}
> +		break;
> +
> +	case KE_SW:
> +		value = ke->sw.value;
> +		/* fall through */
> +
> +	case KE_VSW:
> +		input_report_switch(dev, ke->sw.code, value);
> +		break;
> +	}
> +}
> +EXPORT_SYMBOL(sparse_keymap_report_entry);
> +
> +/**
> + * sparse_keymap_report_event - report event corresponding to given scancode
> + * @dev: Input device using sparse keymap
> + * @code: Scan code
> + * @value: Value that should be reported (ignored by %KE_SW entries)
> + * @autorelease: Signals whether release event should be emitted for %KE_KEY
> + *	entries right after reporting press event, ignored by all other
> + *	entries
> + *
> + * This function is used to perform lookup in an input device using sparse
> + * keymap and report corresponding event. Returns %true if lookup was
> + * successful and %false otherwise.
> + */
> +bool sparse_keymap_report_event(struct input_dev *dev, unsigned int code,
> +				unsigned int value, bool autorelease)
> +{
> +	const struct key_entry *ke =
> +		sparse_keymap_entry_from_scancode(dev, code);
> +
> +	if (ke) {
> +		sparse_keymap_report_entry(dev, ke, value, autorelease);
> +		return true;
> +	}
> +
> +	return false;
> +}
> +EXPORT_SYMBOL(sparse_keymap_report_event);
> +
> diff --git a/include/linux/input/sparse-keymap.h b/include/linux/input/sparse-keymap.h
> new file mode 100644
> index 0000000..52db620
> --- /dev/null
> +++ b/include/linux/input/sparse-keymap.h
> @@ -0,0 +1,62 @@
> +#ifndef _SPARSE_KEYMAP_H
> +#define _SPARSE_KEYMAP_H
> +
> +/*
> + * Copyright (c) 2009 Dmitry Torokhov
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + */
> +
> +#define KE_END		0	/* Indicates end of keymap */
> +#define KE_KEY		1	/* Ordinary key/button */
> +#define KE_SW		2	/* Switch (predetermined value) */
> +#define KE_VSW		3	/* Switch (value supplied at runtime) */
> +#define KE_IGNORE	4	/* Known entry that should be ignored */
> +#define KE_LAST		KE_IGNORE
> +
> +/**
> + * struct key_entry - keymap entry for use in sparse keymap
> + * @type: Type of the key entry (KE_KEY, KE_SW, KE_VSW, KE_END);
> + *	drivers are allowed to extend the list with their own
> + *	private definitions.
> + * @code: Device-specific data identifying the button/switch
> + * @keycode: KEY_* code assigned to a key/button
> + * @sw.code: SW_* code assigned to a switch
> + * @sw.value: Value that should be sent in an input even when KE_SW
> + *	switch is toggled. KE_VSW switches ignore this field and
> + *	expect driver to supply value for the event.
> + *
> + * This structure defines an entry in a sparse keymap used by some
> + * input devices for which traditional table-based approach is not
> + * suitable.
> + */
> +struct key_entry {
> +	int type;		/* See KE_* above */
> +	u32 code;
> +	union {
> +		u16 keycode;		/* For KE_KEY */
> +		struct {		/* For KE_SW, KE_VSW */
> +			u8 code;
> +			u8 value;	/* For KE_SW, ignored by KE_VSW */
> +		} sw;
> +	};
> +};
> +
> +struct key_entry *sparse_keymap_entry_from_scancode(struct input_dev *dev,
> +						    unsigned int code);
> +struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev,
> +						   unsigned int code);
> +int sparse_keymap_setup(struct input_dev *dev,
> +			const struct key_entry *keymap,
> +			int (*setup)(struct input_dev *, struct key_entry *));
> +void sparse_keymap_free(struct input_dev *dev);
> +
> +void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *ke,
> +				unsigned int value, bool autorelease);
> +
> +bool sparse_keymap_report_event(struct input_dev *dev, unsigned int code,
> +				unsigned int value, bool autorelease);
> +
> +#endif /* _SPARSE_KEYMAP_H */
> 



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/9] Input: add generic support for sparse keymaps
  2009-12-04  8:02   ` Wu Zhangjin
@ 2009-12-04  8:34     ` Anisse Astier
  2009-12-04  9:17       ` Wu Zhangjin
  2009-12-04  8:37     ` Dmitry Torokhov
  1 sibling, 1 reply; 22+ messages in thread
From: Anisse Astier @ 2009-12-04  8:34 UTC (permalink / raw)
  To: wuzhangjin
  Cc: Dmitry Torokhov, linux-input, Len Brown, linux-acpi,
	Herton Ronaldo Krzesinski, Harald Welte, Corentin Chary,
	Carlos Corbacho

Hi Wu,

On Fri, 04 Dec 2009 16:02:24 +0800, Wu Zhangjin <wuzhangjin@gmail.com>
wrote :

> 
> I have tried to apply this patch to the latest 2.6.32 and the linux-mips
> tree, both rejected.
> 
> So, which git tree should I use?

Last time I had to use Dmitry's input tree:
git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git
Just checked it, this one applies.

Regards,

Anisse

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/9] Input: add generic support for sparse keymaps
  2009-12-04  8:02   ` Wu Zhangjin
  2009-12-04  8:34     ` Anisse Astier
@ 2009-12-04  8:37     ` Dmitry Torokhov
  2009-12-04  9:18       ` Wu Zhangjin
  1 sibling, 1 reply; 22+ messages in thread
From: Dmitry Torokhov @ 2009-12-04  8:37 UTC (permalink / raw)
  To: Wu Zhangjin
  Cc: linux-input, Len Brown, linux-acpi, Herton Ronaldo Krzesinski,
	Harald Welte, Corentin Chary, Carlos Corbacho, Anisse Astier

On Fri, Dec 04, 2009 at 04:02:24PM +0800, Wu Zhangjin wrote:
> On Thu, 2009-12-03 at 22:11 -0800, Dmitry Torokhov wrote:
> > More and more devices choose to reimplement support for sparse keymaps
> > first introduced by wistron driver. Move it into a library module so it
> > can be easily used by interested parties.
> 
> Hi, Dmitry
> 
> I have tried to apply this patch to the latest 2.6.32 and the linux-mips
> tree, both rejected.
> 
> So, which git tree should I use?
> 

Mine ;)

	git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next

-- 
Dmitry

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/9] Input: add generic support for sparse keymaps
  2009-12-04  8:34     ` Anisse Astier
@ 2009-12-04  9:17       ` Wu Zhangjin
  0 siblings, 0 replies; 22+ messages in thread
From: Wu Zhangjin @ 2009-12-04  9:17 UTC (permalink / raw)
  To: Anisse Astier
  Cc: Dmitry Torokhov, linux-input, Len Brown, linux-acpi,
	Herton Ronaldo Krzesinski, Harald Welte, Corentin Chary,
	Carlos Corbacho

On Fri, 2009-12-04 at 09:34 +0100, Anisse Astier wrote:
> Hi Wu,
> 
> On Fri, 04 Dec 2009 16:02:24 +0800, Wu Zhangjin <wuzhangjin@gmail.com>
> wrote :
> 
> > 
> > I have tried to apply this patch to the latest 2.6.32 and the linux-mips
> > tree, both rejected.
> > 
> > So, which git tree should I use?
> 
> Last time I had to use Dmitry's input tree:
> git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git
> Just checked it, this one applies.
> 

Thanks! Just fetched it ;)

> Regards,
> 
> Anisse



^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/9] Input: add generic support for sparse keymaps
  2009-12-04  8:37     ` Dmitry Torokhov
@ 2009-12-04  9:18       ` Wu Zhangjin
  0 siblings, 0 replies; 22+ messages in thread
From: Wu Zhangjin @ 2009-12-04  9:18 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: linux-input, Len Brown, linux-acpi, Herton Ronaldo Krzesinski,
	Harald Welte, Corentin Chary, Carlos Corbacho, Anisse Astier

On Fri, 2009-12-04 at 00:37 -0800, Dmitry Torokhov wrote:
> On Fri, Dec 04, 2009 at 04:02:24PM +0800, Wu Zhangjin wrote:
> > On Thu, 2009-12-03 at 22:11 -0800, Dmitry Torokhov wrote:
> > > More and more devices choose to reimplement support for sparse keymaps
> > > first introduced by wistron driver. Move it into a library module so it
> > > can be easily used by interested parties.
> > 
> > Hi, Dmitry
> > 
> > I have tried to apply this patch to the latest 2.6.32 and the linux-mips
> > tree, both rejected.
> > 
> > So, which git tree should I use?
> > 
> 
> Mine ;)
> 
> 	git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
> 

Thanks, I am rebasing the input driver for YeeLoong on your git tree ;)

Regards,
	Wu Zhangjin


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/9] Input: add generic support for sparse keymaps
  2009-12-04  6:11 ` [PATCH 1/9] Input: add generic support for sparse keymaps Dmitry Torokhov
  2009-12-04  8:02   ` Wu Zhangjin
@ 2009-12-04 14:06   ` Anisse Astier
  2009-12-04 18:19     ` Dmitry Torokhov
  2009-12-06 22:57   ` Anisse Astier
  2 siblings, 1 reply; 22+ messages in thread
From: Anisse Astier @ 2009-12-04 14:06 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: linux-input, Len Brown, linux-acpi, Herton Ronaldo Krzesinski,
	Harald Welte, Corentin Chary, Carlos Corbacho, Wu Zhangjin

On Thu, 03 Dec 2009 22:11:58 -0800, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote :

> +
> +/**
> + * sparse_keymap_report_event - report event corresponding to given key entry
You meant _report_entry ?

> + * @dev: Input device for which event should be reported
> + * @ke: key entry describing event
> + * @value: Value that should be reported (ignored by %KE_SW entries)
> + * @autorelease: Signals whether release event should be emitted for %KE_KEY
> + *	entries right after reporting press event, ignored by all other
> + *	entries
> + *
> + * This function is used to report input event described by given
> + * &struct key_entry.
> + */
> +void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *ke,
> +				unsigned int value, bool autorelease)
> +{
> +	switch (ke->type) {
> +	case KE_KEY:
> +		input_report_key(dev, ke->keycode, value);
> +		input_sync(dev);
> +		if (value && autorelease) {
> +			input_report_key(dev, ke->keycode, 0);
> +			input_sync(dev);
> +		}
> +		break;
> +
> +	case KE_SW:
> +		value = ke->sw.value;
> +		/* fall through */
> +
> +	case KE_VSW:
> +		input_report_switch(dev, ke->sw.code, value);
> +		break;
> +	}
> +}
> +EXPORT_SYMBOL(sparse_keymap_report_entry);
> +
> +/**
> + * sparse_keymap_report_event - report event corresponding to given scancode
> + * @dev: Input device using sparse keymap
> + * @code: Scan code
> + * @value: Value that should be reported (ignored by %KE_SW entries)
> + * @autorelease: Signals whether release event should be emitted for %KE_KEY
> + *	entries right after reporting press event, ignored by all other
> + *	entries
> + *
> + * This function is used to perform lookup in an input device using sparse
> + * keymap and report corresponding event. Returns %true if lookup was
> + * successful and %false otherwise.
> + */
> +bool sparse_keymap_report_event(struct input_dev *dev, unsigned int code,
> +				unsigned int value, bool autorelease)
> +{
> +	const struct key_entry *ke =
> +		sparse_keymap_entry_from_scancode(dev, code);
> +
> +	if (ke) {
> +		sparse_keymap_report_entry(dev, ke, value, autorelease);
> +		return true;
> +	}
> +
> +	return false;
> +}
> +EXPORT_SYMBOL(sparse_keymap_report_event);
> +


^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/9] Input: add generic support for sparse keymaps
  2009-12-04 14:06   ` Anisse Astier
@ 2009-12-04 18:19     ` Dmitry Torokhov
  2009-12-04 21:15       ` Anisse Astier
  0 siblings, 1 reply; 22+ messages in thread
From: Dmitry Torokhov @ 2009-12-04 18:19 UTC (permalink / raw)
  To: Anisse Astier
  Cc: linux-input, Len Brown, linux-acpi, Herton Ronaldo Krzesinski,
	Harald Welte, Corentin Chary, Carlos Corbacho, Wu Zhangjin

On Fri, Dec 04, 2009 at 03:06:21PM +0100, Anisse Astier wrote:
> On Thu, 03 Dec 2009 22:11:58 -0800, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote :
> 
> > +
> > +/**
> > + * sparse_keymap_report_event - report event corresponding to given key entry
> You meant _report_entry ?
> 

Indeed. Can I add your "Reviewed-by:" please?

-- 
Dmitry

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 9/9] Input: panasonic-laptop - switch to using sparse keymap library
  2009-12-04  6:12 ` [PATCH 9/9] Input: panasonic-laptop " Dmitry Torokhov
@ 2009-12-04 19:14   ` Harald Welte
  2009-12-04 20:27     ` Dmitry Torokhov
  0 siblings, 1 reply; 22+ messages in thread
From: Harald Welte @ 2009-12-04 19:14 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input

Dear Dmitry.

Looks fine to me, but I'm currently travelling and don't have any hardware
where I can test it on.  I will put it on my todo list, but that will likely
take one week.

How shall we proceed?
-- 
- Harald Welte <laforge@gnumonks.org>           http://laforge.gnumonks.org/
============================================================================
"Privacy in residential applications is a desirable marketing option."
                                                  (ETSI EN 300 175-7 Ch. A6)

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 9/9] Input: panasonic-laptop - switch to using sparse keymap library
  2009-12-04 19:14   ` Harald Welte
@ 2009-12-04 20:27     ` Dmitry Torokhov
  0 siblings, 0 replies; 22+ messages in thread
From: Dmitry Torokhov @ 2009-12-04 20:27 UTC (permalink / raw)
  To: Harald Welte; +Cc: linux-input

Hi Harald,

On Sat, Dec 05, 2009 at 12:44:15AM +0530, Harald Welte wrote:
> Dear Dmitry.
> 
> Looks fine to me, but I'm currently travelling and don't have any hardware
> where I can test it on.  I will put it on my todo list, but that will likely
> take one week.
> 

That should be fine.

I will be merging the input parts (the library module) in the merge
window but drivers can folow later (in fact, since drivers/platform is
Len's domain he will decide when to push them out once the changes been
reviewed and tested). Ultimately I'd prefer to have these changes appear
in .33 release.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/9] Input: add generic support for sparse keymaps
  2009-12-04 18:19     ` Dmitry Torokhov
@ 2009-12-04 21:15       ` Anisse Astier
  0 siblings, 0 replies; 22+ messages in thread
From: Anisse Astier @ 2009-12-04 21:15 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: linux-input, Len Brown, linux-acpi, Herton Ronaldo Krzesinski,
	Harald Welte, Corentin Chary, Carlos Corbacho, Wu Zhangjin

On Fri, Dec 4, 2009 at 19:19, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
>
> On Fri, Dec 04, 2009 at 03:06:21PM +0100, Anisse Astier wrote:
> > On Thu, 03 Dec 2009 22:11:58 -0800, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote :
> >
> > > +
> > > +/**
> > > + * sparse_keymap_report_event - report event corresponding to given key entry
> > You meant _report_entry ?
> >
>
> Indeed. Can I add your "Reviewed-by:" please?

You can, but I didn't review the whole thing, just read the patch
quickly and checked if it applied.



--
Anisse

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 1/9] Input: add generic support for sparse keymaps
  2009-12-04  6:11 ` [PATCH 1/9] Input: add generic support for sparse keymaps Dmitry Torokhov
  2009-12-04  8:02   ` Wu Zhangjin
  2009-12-04 14:06   ` Anisse Astier
@ 2009-12-06 22:57   ` Anisse Astier
  2 siblings, 0 replies; 22+ messages in thread
From: Anisse Astier @ 2009-12-06 22:57 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: linux-input, Len Brown, linux-acpi, Herton Ronaldo Krzesinski,
	Harald Welte, Corentin Chary, Carlos Corbacho, Wu Zhangjin

Hi Dmitry,

On Fri, Dec 4, 2009 at 07:11, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
> More and more devices choose to reimplement support for sparse keymaps
> first introduced by wistron driver. Move it into a library module so it
> can be easily used by interested parties.
>
> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

Reviewed-by: Anisse Astier <anisse@astier.eu>

Regards,

-- 
Anisse

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [PATCH 8/9] Input: topstar-laptop - switch to using sparse keymap library
  2009-12-04  6:12 ` [PATCH 8/9] Input: topstar-laptop " Dmitry Torokhov
@ 2010-03-29 22:19   ` Herton Ronaldo Krzesinski
  0 siblings, 0 replies; 22+ messages in thread
From: Herton Ronaldo Krzesinski @ 2010-03-29 22:19 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: linux-input, Len Brown, linux-acpi, Harald Welte, Corentin Chary,
	Carlos Corbacho, Wu Zhangjin, Anisse Astier

Em Sex 04 Dez 2009, às 04:12:36, Dmitry Torokhov escreveu:
> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
> ---
> 
>  drivers/platform/x86/Kconfig          |    1 
>  drivers/platform/x86/topstar-laptop.c |  162 +++++++++++----------------------
>  2 files changed, 55 insertions(+), 108 deletions(-)

Hi, I saw this wasn't included in 2.6.34. From my side is ok, I was without any
topstar notebook for some time, now I got a sample and tested it too, the patch
is ok, It only needs a rediff now with latest 2.6.34-rc2-gitX

I thought it was going to be included without any ack etc., if needed you can add:
Acked-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
and tested-by or signed-off if desired.

The rediffed patch for latest 2.6.34 is below:

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index e631dbe..02d31db 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -455,6 +455,7 @@ config TOPSTAR_LAPTOP
 	tristate "Topstar Laptop Extras"
 	depends on ACPI
 	depends on INPUT
+	select INPUT_SPARSEKMAP
 	---help---
 	  This driver adds support for hotkeys found on Topstar laptops.
 
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index 4d6516f..75a8b62 100644
--- a/drivers/platform/x86/topstar-laptop.c
+++ b/drivers/platform/x86/topstar-laptop.c
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 
 #define ACPI_TOPSTAR_CLASS "topstar"
 
@@ -25,52 +26,37 @@ struct topstar_hkey {
 	struct input_dev *inputdev;
 };
 
-struct tps_key_entry {
-	u8 code;
-	u16 keycode;
-};
-
-static struct tps_key_entry topstar_keymap[] = {
-	{ 0x80, KEY_BRIGHTNESSUP },
-	{ 0x81, KEY_BRIGHTNESSDOWN },
-	{ 0x83, KEY_VOLUMEUP },
-	{ 0x84, KEY_VOLUMEDOWN },
-	{ 0x85, KEY_MUTE },
-	{ 0x86, KEY_SWITCHVIDEOMODE },
-	{ 0x87, KEY_F13 }, /* touchpad enable/disable key */
-	{ 0x88, KEY_WLAN },
-	{ 0x8a, KEY_WWW },
-	{ 0x8b, KEY_MAIL },
-	{ 0x8c, KEY_MEDIA },
-	{ 0x96, KEY_F14 }, /* G key? */
-	{ }
-};
-
-static struct tps_key_entry *tps_get_key_by_scancode(unsigned int code)
-{
-	struct tps_key_entry *key;
-
-	for (key = topstar_keymap; key->code; key++)
-		if (code == key->code)
-			return key;
+static const struct key_entry topstar_keymap[] = {
+	{ KE_KEY, 0x80, { KEY_BRIGHTNESSUP } },
+	{ KE_KEY, 0x81, { KEY_BRIGHTNESSDOWN } },
+	{ KE_KEY, 0x83, { KEY_VOLUMEUP } },
+	{ KE_KEY, 0x84, { KEY_VOLUMEDOWN } },
+	{ KE_KEY, 0x85, { KEY_MUTE } },
+	{ KE_KEY, 0x86, { KEY_SWITCHVIDEOMODE } },
+	{ KE_KEY, 0x87, { KEY_F13 } }, /* touchpad enable/disable key */
+	{ KE_KEY, 0x88, { KEY_WLAN } },
+	{ KE_KEY, 0x8a, { KEY_WWW } },
+	{ KE_KEY, 0x8b, { KEY_MAIL } },
+	{ KE_KEY, 0x8c, { KEY_MEDIA } },
 
-	return NULL;
-}
-
-static struct tps_key_entry *tps_get_key_by_keycode(unsigned int code)
-{
-	struct tps_key_entry *key;
+	/* Known non hotkey events don't handled or that we don't care yet */
+	{ KE_IGNORE, 0x8e, },
+	{ KE_IGNORE, 0x8f, },
+	{ KE_IGNORE, 0x90, },
 
-	for (key = topstar_keymap; key->code; key++)
-		if (code == key->keycode)
-			return key;
+	/*
+	 * 'G key' generate two event codes, convert to only
+	 * one event/key code for now, consider replacing by
+	 * a switch (3G switch - SW_3G?)
+	 */
+	{ KE_KEY, 0x96, { KEY_F14 } },
+	{ KE_KEY, 0x97, { KEY_F14 } },
 
-	return NULL;
-}
+	{ KE_END, 0 }
+};
 
 static void acpi_topstar_notify(struct acpi_device *device, u32 event)
 {
-	struct tps_key_entry *key;
 	static bool dup_evnt[2];
 	bool *dup;
 	struct topstar_hkey *hkey = acpi_driver_data(device);
@@ -85,27 +71,8 @@ static void acpi_topstar_notify(struct acpi_device *device, u32 event)
 		*dup = true;
 	}
 
-	/*
-	 * 'G key' generate two event codes, convert to only
-	 * one event/key code for now (3G switch?)
-	 */
-	if (event == 0x97)
-		event = 0x96;
-
-	key = tps_get_key_by_scancode(event);
-	if (key) {
-		input_report_key(hkey->inputdev, key->keycode, 1);
-		input_sync(hkey->inputdev);
-		input_report_key(hkey->inputdev, key->keycode, 0);
-		input_sync(hkey->inputdev);
-		return;
-	}
-
-	/* Known non hotkey events don't handled or that we don't care yet */
-	if (event == 0x8e || event == 0x8f || event == 0x90)
-		return;
-
-	pr_info("unknown event = 0x%02x\n", event);
+	if (!sparse_keymap_report_event(hkey->inputdev, event, 1, true))
+		pr_info("unknown event = 0x%02x\n", event);
 }
 
 static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
@@ -126,62 +93,41 @@ static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
 	return 0;
 }
 
-static int topstar_getkeycode(struct input_dev *dev,
-				unsigned int scancode, unsigned int *keycode)
-{
-	struct tps_key_entry *key = tps_get_key_by_scancode(scancode);
-
-	if (!key)
-		return -EINVAL;
-
-	*keycode = key->keycode;
-	return 0;
-}
-
-static int topstar_setkeycode(struct input_dev *dev,
-				unsigned int scancode, unsigned int keycode)
-{
-	struct tps_key_entry *key;
-	int old_keycode;
-
-	key = tps_get_key_by_scancode(scancode);
-
-	if (!key)
-		return -EINVAL;
-
-	old_keycode = key->keycode;
-	key->keycode = keycode;
-	set_bit(keycode, dev->keybit);
-	if (!tps_get_key_by_keycode(old_keycode))
-		clear_bit(old_keycode, dev->keybit);
-	return 0;
-}
-
 static int acpi_topstar_init_hkey(struct topstar_hkey *hkey)
 {
-	struct tps_key_entry *key;
+	struct input_dev *input;
+	int error;
 
-	hkey->inputdev = input_allocate_device();
-	if (!hkey->inputdev) {
+	input = input_allocate_device();
+	if (!input) {
 		pr_err("Unable to allocate input device\n");
-		return -ENODEV;
+		return -ENOMEM;
 	}
-	hkey->inputdev->name = "Topstar Laptop extra buttons";
-	hkey->inputdev->phys = "topstar/input0";
-	hkey->inputdev->id.bustype = BUS_HOST;
-	hkey->inputdev->getkeycode = topstar_getkeycode;
-	hkey->inputdev->setkeycode = topstar_setkeycode;
-	for (key = topstar_keymap; key->code; key++) {
-		set_bit(EV_KEY, hkey->inputdev->evbit);
-		set_bit(key->keycode, hkey->inputdev->keybit);
+
+	input->name = "Topstar Laptop extra buttons";
+	input->phys = "topstar/input0";
+	input->id.bustype = BUS_HOST;
+
+	error = sparse_keymap_setup(input, topstar_keymap, NULL);
+	if (error) {
+		pr_err("Unable to setup input device keymap\n");
+		goto err_free_dev;
 	}
-	if (input_register_device(hkey->inputdev)) {
+
+	error = input_register_device(input);
+	if (error) {
 		pr_err("Unable to register input device\n");
-		input_free_device(hkey->inputdev);
-		return -ENODEV;
+		goto err_free_keymap;
 	}
 
+	hkey->inputdev = input;
 	return 0;
+
+ err_free_keymap:
+	sparse_keymap_free(input);
+ err_free_dev:
+	input_free_device(input);
+	return error;
 }
 
 static int acpi_topstar_add(struct acpi_device *device)
@@ -215,6 +161,7 @@ static int acpi_topstar_remove(struct acpi_device *device, int type)
 
 	acpi_topstar_fncx_switch(device, false);
 
+	sparse_keymap_free(tps_hkey->inputdev);
 	input_unregister_device(tps_hkey->inputdev);
 	kfree(tps_hkey);
 



> 
> diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> index e555d39..00e94b0 100644
> --- a/drivers/platform/x86/Kconfig
> +++ b/drivers/platform/x86/Kconfig
> @@ -405,6 +405,7 @@ config TOPSTAR_LAPTOP
>  	tristate "Topstar Laptop Extras"
>  	depends on ACPI
>  	depends on INPUT
> +	select INPUT_SPARSEKMAP
>  	---help---
>  	  This driver adds support for hotkeys found on Topstar laptops.
>  
> diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
> index 02f3d4e..75a8b62 100644
> --- a/drivers/platform/x86/topstar-laptop.c
> +++ b/drivers/platform/x86/topstar-laptop.c
> @@ -18,6 +18,7 @@
>  #include <linux/init.h>
>  #include <linux/acpi.h>
>  #include <linux/input.h>
> +#include <linux/input/sparse-keymap.h>
>  
>  #define ACPI_TOPSTAR_CLASS "topstar"
>  
> @@ -25,52 +26,37 @@ struct topstar_hkey {
>  	struct input_dev *inputdev;
>  };
>  
> -struct tps_key_entry {
> -	u8 code;
> -	u16 keycode;
> -};
> -
> -static struct tps_key_entry topstar_keymap[] = {
> -	{ 0x80, KEY_BRIGHTNESSUP },
> -	{ 0x81, KEY_BRIGHTNESSDOWN },
> -	{ 0x83, KEY_VOLUMEUP },
> -	{ 0x84, KEY_VOLUMEDOWN },
> -	{ 0x85, KEY_MUTE },
> -	{ 0x86, KEY_SWITCHVIDEOMODE },
> -	{ 0x87, KEY_F13 }, /* touchpad enable/disable key */
> -	{ 0x88, KEY_WLAN },
> -	{ 0x8a, KEY_WWW },
> -	{ 0x8b, KEY_MAIL },
> -	{ 0x8c, KEY_MEDIA },
> -	{ 0x96, KEY_F14 }, /* G key? */
> -	{ }
> -};
> -
> -static struct tps_key_entry *tps_get_key_by_scancode(int code)
> -{
> -	struct tps_key_entry *key;
> -
> -	for (key = topstar_keymap; key->code; key++)
> -		if (code == key->code)
> -			return key;
> +static const struct key_entry topstar_keymap[] = {
> +	{ KE_KEY, 0x80, { KEY_BRIGHTNESSUP } },
> +	{ KE_KEY, 0x81, { KEY_BRIGHTNESSDOWN } },
> +	{ KE_KEY, 0x83, { KEY_VOLUMEUP } },
> +	{ KE_KEY, 0x84, { KEY_VOLUMEDOWN } },
> +	{ KE_KEY, 0x85, { KEY_MUTE } },
> +	{ KE_KEY, 0x86, { KEY_SWITCHVIDEOMODE } },
> +	{ KE_KEY, 0x87, { KEY_F13 } }, /* touchpad enable/disable key */
> +	{ KE_KEY, 0x88, { KEY_WLAN } },
> +	{ KE_KEY, 0x8a, { KEY_WWW } },
> +	{ KE_KEY, 0x8b, { KEY_MAIL } },
> +	{ KE_KEY, 0x8c, { KEY_MEDIA } },
>  
> -	return NULL;
> -}
> -
> -static struct tps_key_entry *tps_get_key_by_keycode(int code)
> -{
> -	struct tps_key_entry *key;
> +	/* Known non hotkey events don't handled or that we don't care yet */
> +	{ KE_IGNORE, 0x8e, },
> +	{ KE_IGNORE, 0x8f, },
> +	{ KE_IGNORE, 0x90, },
>  
> -	for (key = topstar_keymap; key->code; key++)
> -		if (code == key->keycode)
> -			return key;
> +	/*
> +	 * 'G key' generate two event codes, convert to only
> +	 * one event/key code for now, consider replacing by
> +	 * a switch (3G switch - SW_3G?)
> +	 */
> +	{ KE_KEY, 0x96, { KEY_F14 } },
> +	{ KE_KEY, 0x97, { KEY_F14 } },
>  
> -	return NULL;
> -}
> +	{ KE_END, 0 }
> +};
>  
>  static void acpi_topstar_notify(struct acpi_device *device, u32 event)
>  {
> -	struct tps_key_entry *key;
>  	static bool dup_evnt[2];
>  	bool *dup;
>  	struct topstar_hkey *hkey = acpi_driver_data(device);
> @@ -85,27 +71,8 @@ static void acpi_topstar_notify(struct acpi_device *device, u32 event)
>  		*dup = true;
>  	}
>  
> -	/*
> -	 * 'G key' generate two event codes, convert to only
> -	 * one event/key code for now (3G switch?)
> -	 */
> -	if (event == 0x97)
> -		event = 0x96;
> -
> -	key = tps_get_key_by_scancode(event);
> -	if (key) {
> -		input_report_key(hkey->inputdev, key->keycode, 1);
> -		input_sync(hkey->inputdev);
> -		input_report_key(hkey->inputdev, key->keycode, 0);
> -		input_sync(hkey->inputdev);
> -		return;
> -	}
> -
> -	/* Known non hotkey events don't handled or that we don't care yet */
> -	if (event == 0x8e || event == 0x8f || event == 0x90)
> -		return;
> -
> -	pr_info("unknown event = 0x%02x\n", event);
> +	if (!sparse_keymap_report_event(hkey->inputdev, event, 1, true))
> +		pr_info("unknown event = 0x%02x\n", event);
>  }
>  
>  static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
> @@ -126,63 +93,41 @@ static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
>  	return 0;
>  }
>  
> -static int topstar_getkeycode(struct input_dev *dev, int scancode, int *keycode)
> -{
> -	struct tps_key_entry *key = tps_get_key_by_scancode(scancode);
> -
> -	if (!key)
> -		return -EINVAL;
> -
> -	*keycode = key->keycode;
> -	return 0;
> -}
> -
> -static int topstar_setkeycode(struct input_dev *dev, int scancode, int keycode)
> -{
> -	struct tps_key_entry *key;
> -	int old_keycode;
> -
> -	if (keycode < 0 || keycode > KEY_MAX)
> -		return -EINVAL;
> -
> -	key = tps_get_key_by_scancode(scancode);
> -
> -	if (!key)
> -		return -EINVAL;
> -
> -	old_keycode = key->keycode;
> -	key->keycode = keycode;
> -	set_bit(keycode, dev->keybit);
> -	if (!tps_get_key_by_keycode(old_keycode))
> -		clear_bit(old_keycode, dev->keybit);
> -	return 0;
> -}
> -
>  static int acpi_topstar_init_hkey(struct topstar_hkey *hkey)
>  {
> -	struct tps_key_entry *key;
> +	struct input_dev *input;
> +	int error;
>  
> -	hkey->inputdev = input_allocate_device();
> -	if (!hkey->inputdev) {
> +	input = input_allocate_device();
> +	if (!input) {
>  		pr_err("Unable to allocate input device\n");
> -		return -ENODEV;
> +		return -ENOMEM;
>  	}
> -	hkey->inputdev->name = "Topstar Laptop extra buttons";
> -	hkey->inputdev->phys = "topstar/input0";
> -	hkey->inputdev->id.bustype = BUS_HOST;
> -	hkey->inputdev->getkeycode = topstar_getkeycode;
> -	hkey->inputdev->setkeycode = topstar_setkeycode;
> -	for (key = topstar_keymap; key->code; key++) {
> -		set_bit(EV_KEY, hkey->inputdev->evbit);
> -		set_bit(key->keycode, hkey->inputdev->keybit);
> +
> +	input->name = "Topstar Laptop extra buttons";
> +	input->phys = "topstar/input0";
> +	input->id.bustype = BUS_HOST;
> +
> +	error = sparse_keymap_setup(input, topstar_keymap, NULL);
> +	if (error) {
> +		pr_err("Unable to setup input device keymap\n");
> +		goto err_free_dev;
>  	}
> -	if (input_register_device(hkey->inputdev)) {
> +
> +	error = input_register_device(input);
> +	if (error) {
>  		pr_err("Unable to register input device\n");
> -		input_free_device(hkey->inputdev);
> -		return -ENODEV;
> +		goto err_free_keymap;
>  	}
>  
> +	hkey->inputdev = input;
>  	return 0;
> +
> + err_free_keymap:
> +	sparse_keymap_free(input);
> + err_free_dev:
> +	input_free_device(input);
> +	return error;
>  }
>  
>  static int acpi_topstar_add(struct acpi_device *device)
> @@ -216,6 +161,7 @@ static int acpi_topstar_remove(struct acpi_device *device, int type)
>  
>  	acpi_topstar_fncx_switch(device, false);
>  
> +	sparse_keymap_free(tps_hkey->inputdev);
>  	input_unregister_device(tps_hkey->inputdev);
>  	kfree(tps_hkey);
>  
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
[]'s
Herton
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2010-03-29 22:49 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-12-04  6:11 [PATCH v2 0/9] Implement sparse keymap library Dmitry Torokhov
2009-12-04  6:11 ` [PATCH 1/9] Input: add generic support for sparse keymaps Dmitry Torokhov
2009-12-04  8:02   ` Wu Zhangjin
2009-12-04  8:34     ` Anisse Astier
2009-12-04  9:17       ` Wu Zhangjin
2009-12-04  8:37     ` Dmitry Torokhov
2009-12-04  9:18       ` Wu Zhangjin
2009-12-04 14:06   ` Anisse Astier
2009-12-04 18:19     ` Dmitry Torokhov
2009-12-04 21:15       ` Anisse Astier
2009-12-06 22:57   ` Anisse Astier
2009-12-04  6:12 ` [PATCH 2/9] Input: wistron_btns - switch to using sparse keymap library Dmitry Torokhov
2009-12-04  6:12 ` [PATCH 3/9] Input: dm355evm_kbd " Dmitry Torokhov
2009-12-04  6:12 ` [PATCH 4/9] Input: dell-wmi " Dmitry Torokhov
2009-12-04  6:12 ` [PATCH 5/9] Input: hp-wmi " Dmitry Torokhov
2009-12-04  6:12 ` [PATCH 6/9] Input: eeepc-laptop " Dmitry Torokhov
2009-12-04  6:12 ` [PATCH 7/9] Input: asus-laptop " Dmitry Torokhov
2009-12-04  6:12 ` [PATCH 8/9] Input: topstar-laptop " Dmitry Torokhov
2010-03-29 22:19   ` Herton Ronaldo Krzesinski
2009-12-04  6:12 ` [PATCH 9/9] Input: panasonic-laptop " Dmitry Torokhov
2009-12-04 19:14   ` Harald Welte
2009-12-04 20:27     ` Dmitry Torokhov

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.