diff options
| author | Dmitry Torokhov <dtor@mail.ru> | 2010-01-06 16:07:39 -0500 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2010-01-16 01:49:41 -0500 |
| commit | 642e0447cb910ceabae0b4ea6c0cd3449d5c5abb (patch) | |
| tree | 9f0b33620830c3c90e0a94d02a79a1d9ee5c7b2b | |
| parent | 10ae4b5663ff3092553bfbd867e7bd474ce6c553 (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>
| -rw-r--r-- | drivers/platform/x86/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/platform/x86/eeepc-laptop.c | 186 |
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 | ||
| 124 | struct key_entry { | ||
| 125 | char type; | ||
| 126 | u8 code; | ||
| 127 | u16 keycode; | ||
| 128 | }; | ||
| 129 | |||
| 130 | enum { KE_KEY, KE_END }; | ||
| 131 | |||
| 132 | static const struct key_entry eeepc_keymap[] = { | 125 | static 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 | */ |
| 1146 | static struct key_entry *eeepc_get_entry_by_scancode( | 1137 | static 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"); | |
| 1159 | static 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 | |||
| 1178 | static 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 | ||
| 1190 | static 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"); | |
| 1203 | static 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 | |||
| 1225 | static 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 | ||
| 1262 | static void eeepc_input_exit(struct eeepc_laptop *eeepc) | 1175 | static 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 | ||
| 1563 | fail_no_device: | 1479 | fail_no_device: |
