aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2010-08-05 01:29:57 -0400
committerMatthew Garrett <mjg@redhat.com>2010-10-21 09:36:42 -0400
commit97490f1cf82cccf2e088aafffb0517802f0ee336 (patch)
tree80fb1b72c8a4dbc261328e2382987e0ec7cf657d /drivers/platform
parentf6f94e2ab1b33f0082ac22d71f66385a60d8157f (diff)
topstar-laptop - switch to using sparse keymap library
Instead of implementing its own version of keymap hanlding switch over to using sparse keymap library. Acked-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br> Signed-off-by: Dmitry Torokhov <dtor@mail.ru> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/Kconfig1
-rw-r--r--drivers/platform/x86/topstar-laptop.c161
2 files changed, 55 insertions, 107 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index cff7cc2c1f02..0b11b41a85f9 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -478,6 +478,7 @@ config TOPSTAR_LAPTOP
478 tristate "Topstar Laptop Extras" 478 tristate "Topstar Laptop Extras"
479 depends on ACPI 479 depends on ACPI
480 depends on INPUT 480 depends on INPUT
481 select INPUT_SPARSEKMAP
481 ---help--- 482 ---help---
482 This driver adds support for hotkeys found on Topstar laptops. 483 This driver adds support for hotkeys found on Topstar laptops.
483 484
diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c
index ff4b476f1950..1d07d6d09f27 100644
--- a/drivers/platform/x86/topstar-laptop.c
+++ b/drivers/platform/x86/topstar-laptop.c
@@ -19,6 +19,7 @@
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/acpi.h> 20#include <linux/acpi.h>
21#include <linux/input.h> 21#include <linux/input.h>
22#include <linux/input/sparse-keymap.h>
22 23
23#define ACPI_TOPSTAR_CLASS "topstar" 24#define ACPI_TOPSTAR_CLASS "topstar"
24 25
@@ -26,52 +27,37 @@ struct topstar_hkey {
26 struct input_dev *inputdev; 27 struct input_dev *inputdev;
27}; 28};
28 29
29struct tps_key_entry { 30static const struct key_entry topstar_keymap[] = {
30 u8 code; 31 { KE_KEY, 0x80, { KEY_BRIGHTNESSUP } },
31 u16 keycode; 32 { KE_KEY, 0x81, { KEY_BRIGHTNESSDOWN } },
32}; 33 { KE_KEY, 0x83, { KEY_VOLUMEUP } },
33 34 { KE_KEY, 0x84, { KEY_VOLUMEDOWN } },
34static struct tps_key_entry topstar_keymap[] = { 35 { KE_KEY, 0x85, { KEY_MUTE } },
35 { 0x80, KEY_BRIGHTNESSUP }, 36 { KE_KEY, 0x86, { KEY_SWITCHVIDEOMODE } },
36 { 0x81, KEY_BRIGHTNESSDOWN }, 37 { KE_KEY, 0x87, { KEY_F13 } }, /* touchpad enable/disable key */
37 { 0x83, KEY_VOLUMEUP }, 38 { KE_KEY, 0x88, { KEY_WLAN } },
38 { 0x84, KEY_VOLUMEDOWN }, 39 { KE_KEY, 0x8a, { KEY_WWW } },
39 { 0x85, KEY_MUTE }, 40 { KE_KEY, 0x8b, { KEY_MAIL } },
40 { 0x86, KEY_SWITCHVIDEOMODE }, 41 { KE_KEY, 0x8c, { KEY_MEDIA } },
41 { 0x87, KEY_F13 }, /* touchpad enable/disable key */
42 { 0x88, KEY_WLAN },
43 { 0x8a, KEY_WWW },
44 { 0x8b, KEY_MAIL },
45 { 0x8c, KEY_MEDIA },
46 { 0x96, KEY_F14 }, /* G key? */
47 { }
48};
49
50static struct tps_key_entry *tps_get_key_by_scancode(unsigned int code)
51{
52 struct tps_key_entry *key;
53
54 for (key = topstar_keymap; key->code; key++)
55 if (code == key->code)
56 return key;
57 42
58 return NULL; 43 /* Known non hotkey events don't handled or that we don't care yet */
59} 44 { KE_IGNORE, 0x8e, },
60 45 { KE_IGNORE, 0x8f, },
61static struct tps_key_entry *tps_get_key_by_keycode(unsigned int code) 46 { KE_IGNORE, 0x90, },
62{
63 struct tps_key_entry *key;
64 47
65 for (key = topstar_keymap; key->code; key++) 48 /*
66 if (code == key->keycode) 49 * 'G key' generate two event codes, convert to only
67 return key; 50 * one event/key code for now, consider replacing by
51 * a switch (3G switch - SW_3G?)
52 */
53 { KE_KEY, 0x96, { KEY_F14 } },
54 { KE_KEY, 0x97, { KEY_F14 } },
68 55
69 return NULL; 56 { KE_END, 0 }
70} 57};
71 58
72static void acpi_topstar_notify(struct acpi_device *device, u32 event) 59static void acpi_topstar_notify(struct acpi_device *device, u32 event)
73{ 60{
74 struct tps_key_entry *key;
75 static bool dup_evnt[2]; 61 static bool dup_evnt[2];
76 bool *dup; 62 bool *dup;
77 struct topstar_hkey *hkey = acpi_driver_data(device); 63 struct topstar_hkey *hkey = acpi_driver_data(device);
@@ -86,27 +72,8 @@ static void acpi_topstar_notify(struct acpi_device *device, u32 event)
86 *dup = true; 72 *dup = true;
87 } 73 }
88 74
89 /* 75 if (!sparse_keymap_report_event(hkey->inputdev, event, 1, true))
90 * 'G key' generate two event codes, convert to only 76 pr_info("unknown event = 0x%02x\n", event);
91 * one event/key code for now (3G switch?)
92 */
93 if (event == 0x97)
94 event = 0x96;
95
96 key = tps_get_key_by_scancode(event);
97 if (key) {
98 input_report_key(hkey->inputdev, key->keycode, 1);
99 input_sync(hkey->inputdev);
100 input_report_key(hkey->inputdev, key->keycode, 0);
101 input_sync(hkey->inputdev);
102 return;
103 }
104
105 /* Known non hotkey events don't handled or that we don't care yet */
106 if (event == 0x8e || event == 0x8f || event == 0x90)
107 return;
108
109 pr_info("unknown event = 0x%02x\n", event);
110} 77}
111 78
112static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state) 79static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
@@ -127,62 +94,41 @@ static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
127 return 0; 94 return 0;
128} 95}
129 96
130static int topstar_getkeycode(struct input_dev *dev,
131 unsigned int scancode, unsigned int *keycode)
132{
133 struct tps_key_entry *key = tps_get_key_by_scancode(scancode);
134
135 if (!key)
136 return -EINVAL;
137
138 *keycode = key->keycode;
139 return 0;
140}
141
142static int topstar_setkeycode(struct input_dev *dev,
143 unsigned int scancode, unsigned int keycode)
144{
145 struct tps_key_entry *key;
146 int old_keycode;
147
148 key = tps_get_key_by_scancode(scancode);
149
150 if (!key)
151 return -EINVAL;
152
153 old_keycode = key->keycode;
154 key->keycode = keycode;
155 set_bit(keycode, dev->keybit);
156 if (!tps_get_key_by_keycode(old_keycode))
157 clear_bit(old_keycode, dev->keybit);
158 return 0;
159}
160
161static int acpi_topstar_init_hkey(struct topstar_hkey *hkey) 97static int acpi_topstar_init_hkey(struct topstar_hkey *hkey)
162{ 98{
163 struct tps_key_entry *key; 99 struct input_dev *input;
100 int error;
164 101
165 hkey->inputdev = input_allocate_device(); 102 input = input_allocate_device();
166 if (!hkey->inputdev) { 103 if (!input) {
167 pr_err("Unable to allocate input device\n"); 104 pr_err("Unable to allocate input device\n");
168 return -ENODEV; 105 return -ENOMEM;
169 } 106 }
170 hkey->inputdev->name = "Topstar Laptop extra buttons"; 107
171 hkey->inputdev->phys = "topstar/input0"; 108 input->name = "Topstar Laptop extra buttons";
172 hkey->inputdev->id.bustype = BUS_HOST; 109 input->phys = "topstar/input0";
173 hkey->inputdev->getkeycode = topstar_getkeycode; 110 input->id.bustype = BUS_HOST;
174 hkey->inputdev->setkeycode = topstar_setkeycode; 111
175 for (key = topstar_keymap; key->code; key++) { 112 error = sparse_keymap_setup(input, topstar_keymap, NULL);
176 set_bit(EV_KEY, hkey->inputdev->evbit); 113 if (error) {
177 set_bit(key->keycode, hkey->inputdev->keybit); 114 pr_err("Unable to setup input device keymap\n");
115 goto err_free_dev;
178 } 116 }
179 if (input_register_device(hkey->inputdev)) { 117
118 error = input_register_device(input);
119 if (error) {
180 pr_err("Unable to register input device\n"); 120 pr_err("Unable to register input device\n");
181 input_free_device(hkey->inputdev); 121 goto err_free_keymap;
182 return -ENODEV;
183 } 122 }
184 123
124 hkey->inputdev = input;
185 return 0; 125 return 0;
126
127 err_free_keymap:
128 sparse_keymap_free(input);
129 err_free_dev:
130 input_free_device(input);
131 return error;
186} 132}
187 133
188static int acpi_topstar_add(struct acpi_device *device) 134static int acpi_topstar_add(struct acpi_device *device)
@@ -216,6 +162,7 @@ static int acpi_topstar_remove(struct acpi_device *device, int type)
216 162
217 acpi_topstar_fncx_switch(device, false); 163 acpi_topstar_fncx_switch(device, false);
218 164
165 sparse_keymap_free(tps_hkey->inputdev);
219 input_unregister_device(tps_hkey->inputdev); 166 input_unregister_device(tps_hkey->inputdev);
220 kfree(tps_hkey); 167 kfree(tps_hkey);
221 168