diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-08-05 01:29:57 -0400 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2010-10-21 09:36:42 -0400 |
commit | 97490f1cf82cccf2e088aafffb0517802f0ee336 (patch) | |
tree | 80fb1b72c8a4dbc261328e2382987e0ec7cf657d /drivers/platform | |
parent | f6f94e2ab1b33f0082ac22d71f66385a60d8157f (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/Kconfig | 1 | ||||
-rw-r--r-- | drivers/platform/x86/topstar-laptop.c | 161 |
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 | ||
29 | struct tps_key_entry { | 30 | static 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 } }, | |
34 | static 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 | |||
50 | static 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, }, | |
61 | static 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 | ||
72 | static void acpi_topstar_notify(struct acpi_device *device, u32 event) | 59 | static 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 | ||
112 | static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state) | 79 | static 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 | ||
130 | static 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 | |||
142 | static 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 | |||
161 | static int acpi_topstar_init_hkey(struct topstar_hkey *hkey) | 97 | static 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 | ||
188 | static int acpi_topstar_add(struct acpi_device *device) | 134 | static 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 | ||