aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor@mail.ru>2010-01-06 16:07:39 -0500
committerLen Brown <len.brown@intel.com>2010-01-16 01:49:41 -0500
commit642e0447cb910ceabae0b4ea6c0cd3449d5c5abb (patch)
tree9f0b33620830c3c90e0a94d02a79a1d9ee5c7b2b /drivers/platform
parent10ae4b5663ff3092553bfbd867e7bd474ce6c553 (diff)
eeepc-laptop: switch to using sparse keymap library
Signed-off-by: Dmitry Torokhov <dtor@mail.ru> Tested-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk> Acked-by: Corentin Chary <corentincj@iksaif.net> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/platform')
-rw-r--r--drivers/platform/x86/Kconfig1
-rw-r--r--drivers/platform/x86/eeepc-laptop.c186
2 files changed, 52 insertions, 135 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index db32c25e360..f526e735c5a 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -364,6 +364,7 @@ config EEEPC_LAPTOP
364 select HWMON 364 select HWMON
365 select LEDS_CLASS 365 select LEDS_CLASS
366 select NEW_LEDS 366 select NEW_LEDS
367 select INPUT_SPARSEKMAP
367 ---help--- 368 ---help---
368 This driver supports the Fn-Fx keys on Eee PC laptops. 369 This driver supports the Fn-Fx keys on Eee PC laptops.
369 370
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 7fc944ac207..07d7978c558 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -31,6 +31,7 @@
31#include <acpi/acpi_bus.h> 31#include <acpi/acpi_bus.h>
32#include <linux/uaccess.h> 32#include <linux/uaccess.h>
33#include <linux/input.h> 33#include <linux/input.h>
34#include <linux/input/sparse-keymap.h>
34#include <linux/rfkill.h> 35#include <linux/rfkill.h>
35#include <linux/pci.h> 36#include <linux/pci.h>
36#include <linux/pci_hotplug.h> 37#include <linux/pci_hotplug.h>
@@ -121,38 +122,28 @@ static const char *cm_setv[] = {
121 NULL, NULL, "PBPS", "TPDS" 122 NULL, NULL, "PBPS", "TPDS"
122}; 123};
123 124
124struct key_entry {
125 char type;
126 u8 code;
127 u16 keycode;
128};
129
130enum { KE_KEY, KE_END };
131
132static const struct key_entry eeepc_keymap[] = { 125static const struct key_entry eeepc_keymap[] = {
133 /* Sleep already handled via generic ACPI code */ 126 { KE_KEY, 0x10, { KEY_WLAN } },
134 {KE_KEY, 0x10, KEY_WLAN }, 127 { KE_KEY, 0x11, { KEY_WLAN } },
135 {KE_KEY, 0x11, KEY_WLAN }, 128 { KE_KEY, 0x12, { KEY_PROG1 } },
136 {KE_KEY, 0x12, KEY_PROG1 }, 129 { KE_KEY, 0x13, { KEY_MUTE } },
137 {KE_KEY, 0x13, KEY_MUTE }, 130 { KE_KEY, 0x14, { KEY_VOLUMEDOWN } },
138 {KE_KEY, 0x14, KEY_VOLUMEDOWN }, 131 { KE_KEY, 0x15, { KEY_VOLUMEUP } },
139 {KE_KEY, 0x15, KEY_VOLUMEUP }, 132 { KE_KEY, 0x16, { KEY_DISPLAY_OFF } },
140 {KE_KEY, 0x16, KEY_DISPLAY_OFF }, 133 { KE_KEY, 0x1a, { KEY_COFFEE } },
141 {KE_KEY, 0x1a, KEY_COFFEE }, 134 { KE_KEY, 0x1b, { KEY_ZOOM } },
142 {KE_KEY, 0x1b, KEY_ZOOM }, 135 { KE_KEY, 0x1c, { KEY_PROG2 } },
143 {KE_KEY, 0x1c, KEY_PROG2 }, 136 { KE_KEY, 0x1d, { KEY_PROG3 } },
144 {KE_KEY, 0x1d, KEY_PROG3 }, 137 { KE_KEY, NOTIFY_BRN_MIN, { KEY_BRIGHTNESSDOWN } },
145 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN }, 138 { KE_KEY, NOTIFY_BRN_MAX, { KEY_BRIGHTNESSUP } },
146 {KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP }, 139 { KE_KEY, 0x30, { KEY_SWITCHVIDEOMODE } },
147 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, 140 { KE_KEY, 0x31, { KEY_SWITCHVIDEOMODE } },
148 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, 141 { KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } },
149 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, 142 { KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */
150 {KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */ 143 { KE_KEY, 0x38, { KEY_F14 } },
151 {KE_KEY, 0x38, KEY_F14 }, 144 { KE_END, 0 },
152 {KE_END, 0},
153}; 145};
154 146
155
156/* 147/*
157 * This is the main structure, we can use it to store useful information 148 * This is the main structure, we can use it to store useful information
158 */ 149 */
@@ -1143,120 +1134,42 @@ static void eeepc_backlight_exit(struct eeepc_laptop *eeepc)
1143/* 1134/*
1144 * Input device (i.e. hotkeys) 1135 * Input device (i.e. hotkeys)
1145 */ 1136 */
1146static struct key_entry *eeepc_get_entry_by_scancode( 1137static int eeepc_input_init(struct eeepc_laptop *eeepc)
1147 struct eeepc_laptop *eeepc,
1148 int code)
1149{ 1138{
1150 struct key_entry *key; 1139 struct input_dev *input;
1151 1140 int error;
1152 for (key = eeepc->keymap; key->type != KE_END; key++)
1153 if (code == key->code)
1154 return key;
1155 1141
1156 return NULL; 1142 input = input_allocate_device();
1157} 1143 if (!input) {
1158 1144 pr_info("Unable to allocate input device\n");
1159static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event) 1145 return -ENOMEM;
1160{
1161 static struct key_entry *key;
1162
1163 key = eeepc_get_entry_by_scancode(eeepc, event);
1164 if (key) {
1165 switch (key->type) {
1166 case KE_KEY:
1167 input_report_key(eeepc->inputdev, key->keycode,
1168 1);
1169 input_sync(eeepc->inputdev);
1170 input_report_key(eeepc->inputdev, key->keycode,
1171 0);
1172 input_sync(eeepc->inputdev);
1173 break;
1174 }
1175 } 1146 }
1176}
1177
1178static struct key_entry *eeepc_get_entry_by_keycode(
1179 struct eeepc_laptop *eeepc, int code)
1180{
1181 struct key_entry *key;
1182
1183 for (key = eeepc->keymap; key->type != KE_END; key++)
1184 if (code == key->keycode && key->type == KE_KEY)
1185 return key;
1186 1147
1187 return NULL; 1148 input->name = "Asus EeePC extra buttons";
1188} 1149 input->phys = EEEPC_LAPTOP_FILE "/input0";
1150 input->id.bustype = BUS_HOST;
1151 input->dev.parent = &eeepc->platform_device->dev;
1189 1152
1190static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) 1153 error = sparse_keymap_setup(input, eeepc_keymap, NULL);
1191{ 1154 if (error) {
1192 struct eeepc_laptop *eeepc = input_get_drvdata(dev); 1155 pr_err("Unable to setup input device keymap\n");
1193 struct key_entry *key = eeepc_get_entry_by_scancode(eeepc, scancode); 1156 goto err_free_dev;
1194
1195 if (key && key->type == KE_KEY) {
1196 *keycode = key->keycode;
1197 return 0;
1198 } 1157 }
1199 1158
1200 return -EINVAL; 1159 error = input_register_device(input);
1201} 1160 if (error) {
1202 1161 pr_err("Unable to register input device\n");
1203static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) 1162 goto err_free_keymap;
1204{
1205 struct eeepc_laptop *eeepc = input_get_drvdata(dev);
1206 struct key_entry *key;
1207 int old_keycode;
1208
1209 if (keycode < 0 || keycode > KEY_MAX)
1210 return -EINVAL;
1211
1212 key = eeepc_get_entry_by_scancode(eeepc, scancode);
1213 if (key && key->type == KE_KEY) {
1214 old_keycode = key->keycode;
1215 key->keycode = keycode;
1216 set_bit(keycode, dev->keybit);
1217 if (!eeepc_get_entry_by_keycode(eeepc, old_keycode))
1218 clear_bit(old_keycode, dev->keybit);
1219 return 0;
1220 } 1163 }
1221 1164
1222 return -EINVAL; 1165 eeepc->inputdev = input;
1223}
1224
1225static int eeepc_input_init(struct eeepc_laptop *eeepc)
1226{
1227 const struct key_entry *key;
1228 int result;
1229
1230 eeepc->inputdev = input_allocate_device();
1231 if (!eeepc->inputdev) {
1232 pr_info("Unable to allocate input device\n");
1233 return -ENOMEM;
1234 }
1235 eeepc->inputdev->name = "Asus EeePC extra buttons";
1236 eeepc->inputdev->dev.parent = &eeepc->platform_device->dev;
1237 eeepc->inputdev->phys = EEEPC_LAPTOP_FILE "/input0";
1238 eeepc->inputdev->id.bustype = BUS_HOST;
1239 eeepc->inputdev->getkeycode = eeepc_getkeycode;
1240 eeepc->inputdev->setkeycode = eeepc_setkeycode;
1241 input_set_drvdata(eeepc->inputdev, eeepc);
1242
1243 eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap),
1244 GFP_KERNEL);
1245 for (key = eeepc_keymap; key->type != KE_END; key++) {
1246 switch (key->type) {
1247 case KE_KEY:
1248 set_bit(EV_KEY, eeepc->inputdev->evbit);
1249 set_bit(key->keycode, eeepc->inputdev->keybit);
1250 break;
1251 }
1252 }
1253 result = input_register_device(eeepc->inputdev);
1254 if (result) {
1255 pr_info("Unable to register input device\n");
1256 input_free_device(eeepc->inputdev);
1257 return result;
1258 }
1259 return 0; 1166 return 0;
1167
1168 err_free_keymap:
1169 sparse_keymap_free(input);
1170 err_free_dev:
1171 input_free_device(input);
1172 return error;
1260} 1173}
1261 1174
1262static void eeepc_input_exit(struct eeepc_laptop *eeepc) 1175static void eeepc_input_exit(struct eeepc_laptop *eeepc)
@@ -1306,11 +1219,12 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
1306 * event will be desired value (or else ignored) 1219 * event will be desired value (or else ignored)
1307 */ 1220 */
1308 } 1221 }
1309 eeepc_input_notify(eeepc, event); 1222 sparse_keymap_report_event(eeepc->inputdev, event,
1223 1, true);
1310 } 1224 }
1311 } else { 1225 } else {
1312 /* Everything else is a bona-fide keypress event */ 1226 /* Everything else is a bona-fide keypress event */
1313 eeepc_input_notify(eeepc, event); 1227 sparse_keymap_report_event(eeepc->inputdev, event, 1, true);
1314 } 1228 }
1315} 1229}
1316 1230
@@ -1554,10 +1468,12 @@ static int __init eeepc_laptop_init(void)
1554 result = acpi_bus_register_driver(&eeepc_acpi_driver); 1468 result = acpi_bus_register_driver(&eeepc_acpi_driver);
1555 if (result < 0) 1469 if (result < 0)
1556 goto fail_acpi_driver; 1470 goto fail_acpi_driver;
1471
1557 if (!eeepc_device_present) { 1472 if (!eeepc_device_present) {
1558 result = -ENODEV; 1473 result = -ENODEV;
1559 goto fail_no_device; 1474 goto fail_no_device;
1560 } 1475 }
1476
1561 return 0; 1477 return 0;
1562 1478
1563fail_no_device: 1479fail_no_device: