Commit 66a71dd1f7c4eee636867d381995b7e6ae489dc3

Authored by Corentin Chary
1 parent d0930a2d42

asus-laptop: switch to sparse keymap library

This patch is based on Dmitry Torokhov's patch with
some modifications and cleanups.

Signed-off-by: Corentin Chary <corentincj@iksaif.net>

Showing 2 changed files with 68 additions and 141 deletions Side-by-side Diff

drivers/platform/x86/Kconfig
... ... @@ -59,6 +59,7 @@
59 59 select NEW_LEDS
60 60 select BACKLIGHT_CLASS_DEVICE
61 61 depends on INPUT
  62 + select INPUT_SPARSEKMAP
62 63 ---help---
63 64 This is the new Linux driver for Asus laptops. It may also support some
64 65 MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate
drivers/platform/x86/asus-laptop.c
... ... @@ -49,6 +49,7 @@
49 49 #include <acpi/acpi_bus.h>
50 50 #include <asm/uaccess.h>
51 51 #include <linux/input.h>
  52 +#include <linux/input/sparse-keymap.h>
52 53  
53 54 #define ASUS_LAPTOP_VERSION "0.42"
54 55  
55 56  
56 57  
... ... @@ -243,52 +244,45 @@
243 244 u16 *keycode_map;
244 245 };
245 246  
246   -struct key_entry {
247   - char type;
248   - u8 code;
249   - u16 keycode;
250   -};
251   -
252   -enum { KE_KEY, KE_END };
253   -
254 247 static const struct key_entry asus_keymap[] = {
255   - {KE_KEY, 0x02, KEY_SCREENLOCK},
256   - {KE_KEY, 0x05, KEY_WLAN},
257   - {KE_KEY, 0x08, KEY_F13},
258   - {KE_KEY, 0x17, KEY_ZOOM},
259   - {KE_KEY, 0x1f, KEY_BATTERY},
260   - {KE_KEY, 0x30, KEY_VOLUMEUP},
261   - {KE_KEY, 0x31, KEY_VOLUMEDOWN},
262   - {KE_KEY, 0x32, KEY_MUTE},
263   - {KE_KEY, 0x33, KEY_SWITCHVIDEOMODE},
264   - {KE_KEY, 0x34, KEY_SWITCHVIDEOMODE},
265   - {KE_KEY, 0x40, KEY_PREVIOUSSONG},
266   - {KE_KEY, 0x41, KEY_NEXTSONG},
267   - {KE_KEY, 0x43, KEY_STOPCD},
268   - {KE_KEY, 0x45, KEY_PLAYPAUSE},
269   - {KE_KEY, 0x4c, KEY_MEDIA},
270   - {KE_KEY, 0x50, KEY_EMAIL},
271   - {KE_KEY, 0x51, KEY_WWW},
272   - {KE_KEY, 0x55, KEY_CALC},
273   - {KE_KEY, 0x5C, KEY_SCREENLOCK}, /* Screenlock */
274   - {KE_KEY, 0x5D, KEY_WLAN},
275   - {KE_KEY, 0x5E, KEY_WLAN},
276   - {KE_KEY, 0x5F, KEY_WLAN},
277   - {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE},
278   - {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE},
279   - {KE_KEY, 0x62, KEY_SWITCHVIDEOMODE},
280   - {KE_KEY, 0x63, KEY_SWITCHVIDEOMODE},
281   - {KE_KEY, 0x6B, KEY_F13}, /* Lock Touchpad */
282   - {KE_KEY, 0x82, KEY_CAMERA},
283   - {KE_KEY, 0x88, KEY_WLAN },
284   - {KE_KEY, 0x8A, KEY_PROG1},
285   - {KE_KEY, 0x95, KEY_MEDIA},
286   - {KE_KEY, 0x99, KEY_PHONE},
287   - {KE_KEY, 0xc4, KEY_KBDILLUMUP},
288   - {KE_KEY, 0xc5, KEY_KBDILLUMDOWN},
  248 + {KE_KEY, 0x02, { KEY_SCREENLOCK } },
  249 + {KE_KEY, 0x05, { KEY_WLAN } },
  250 + {KE_KEY, 0x08, { KEY_F13 } },
  251 + {KE_KEY, 0x17, { KEY_ZOOM } },
  252 + {KE_KEY, 0x1f, { KEY_BATTERY } },
  253 + {KE_KEY, 0x30, { KEY_VOLUMEUP } },
  254 + {KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
  255 + {KE_KEY, 0x32, { KEY_MUTE } },
  256 + {KE_KEY, 0x33, { KEY_SWITCHVIDEOMODE } },
  257 + {KE_KEY, 0x34, { KEY_SWITCHVIDEOMODE } },
  258 + {KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
  259 + {KE_KEY, 0x41, { KEY_NEXTSONG } },
  260 + {KE_KEY, 0x43, { KEY_STOPCD } },
  261 + {KE_KEY, 0x45, { KEY_PLAYPAUSE } },
  262 + {KE_KEY, 0x4c, { KEY_MEDIA } },
  263 + {KE_KEY, 0x50, { KEY_EMAIL } },
  264 + {KE_KEY, 0x51, { KEY_WWW } },
  265 + {KE_KEY, 0x55, { KEY_CALC } },
  266 + {KE_KEY, 0x5C, { KEY_SCREENLOCK } }, /* Screenlock */
  267 + {KE_KEY, 0x5D, { KEY_WLAN } },
  268 + {KE_KEY, 0x5E, { KEY_WLAN } },
  269 + {KE_KEY, 0x5F, { KEY_WLAN } },
  270 + {KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } },
  271 + {KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } },
  272 + {KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
  273 + {KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
  274 + {KE_KEY, 0x6B, { KEY_F13 } }, /* Lock Touchpad */
  275 + {KE_KEY, 0x82, { KEY_CAMERA } },
  276 + {KE_KEY, 0x88, { KEY_WLAN } },
  277 + {KE_KEY, 0x8A, { KEY_PROG1 } },
  278 + {KE_KEY, 0x95, { KEY_MEDIA } },
  279 + {KE_KEY, 0x99, { KEY_PHONE } },
  280 + {KE_KEY, 0xc4, { KEY_KBDILLUMUP } },
  281 + {KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
289 282 {KE_END, 0},
290 283 };
291 284  
  285 +
292 286 /*
293 287 * This function evaluates an ACPI method, given an int as parameter, the
294 288 * method is searched within the scope of the handle, can be NULL. The output
295 289  
296 290  
297 291  
298 292  
299 293  
300 294  
301 295  
302 296  
303 297  
304 298  
... ... @@ -1050,123 +1044,55 @@
1050 1044 /*
1051 1045 * Input device (i.e. hotkeys)
1052 1046 */
1053   -static struct key_entry *asus_get_entry_by_scancode(struct asus_laptop *asus,
1054   - int code)
1055   -{
1056   - struct key_entry *key;
1057   -
1058   - for (key = asus->keymap; key->type != KE_END; key++)
1059   - if (code == key->code)
1060   - return key;
1061   -
1062   - return NULL;
1063   -}
1064   -
1065   -static struct key_entry *asus_get_entry_by_keycode(struct asus_laptop *asus,
1066   - int code)
1067   -{
1068   - struct key_entry *key;
1069   -
1070   - for (key = asus->keymap; key->type != KE_END; key++)
1071   - if (code == key->keycode && key->type == KE_KEY)
1072   - return key;
1073   -
1074   - return NULL;
1075   -}
1076   -
1077   -static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode)
1078   -{
1079   - struct asus_laptop *asus = input_get_drvdata(dev);
1080   - struct key_entry *key = asus_get_entry_by_scancode(asus, scancode);
1081   -
1082   - if (key && key->type == KE_KEY) {
1083   - *keycode = key->keycode;
1084   - return 0;
1085   - }
1086   -
1087   - return -EINVAL;
1088   -}
1089   -
1090   -static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode)
1091   -{
1092   - struct asus_laptop *asus = input_get_drvdata(dev);
1093   - struct key_entry *key;
1094   - int old_keycode;
1095   -
1096   - if (keycode < 0 || keycode > KEY_MAX)
1097   - return -EINVAL;
1098   -
1099   - key = asus_get_entry_by_scancode(asus, scancode);
1100   - if (key && key->type == KE_KEY) {
1101   - old_keycode = key->keycode;
1102   - key->keycode = keycode;
1103   - set_bit(keycode, dev->keybit);
1104   - if (!asus_get_entry_by_keycode(asus, old_keycode))
1105   - clear_bit(old_keycode, dev->keybit);
1106   - return 0;
1107   - }
1108   -
1109   - return -EINVAL;
1110   -}
1111   -
1112 1047 static void asus_input_notify(struct asus_laptop *asus, int event)
1113 1048 {
1114   - struct key_entry *key;
1115   -
1116   - key = asus_get_entry_by_scancode(asus, event);
1117   - if (!key)
1118   - return ;
1119   -
1120   - switch (key->type) {
1121   - case KE_KEY:
1122   - input_report_key(asus->inputdev, key->keycode, 1);
1123   - input_sync(asus->inputdev);
1124   - input_report_key(asus->inputdev, key->keycode, 0);
1125   - input_sync(asus->inputdev);
1126   - break;
1127   - }
  1049 + if (asus->inputdev)
  1050 + sparse_keymap_report_event(asus->inputdev, event, 1, true);
1128 1051 }
1129 1052  
1130 1053 static int asus_input_init(struct asus_laptop *asus)
1131 1054 {
1132   - const struct key_entry *key;
1133   - int result;
  1055 + struct input_dev *input;
  1056 + int error;
1134 1057  
1135   - asus->inputdev = input_allocate_device();
1136   - if (!asus->inputdev) {
  1058 + input = input_allocate_device();
  1059 + if (!input) {
1137 1060 pr_info("Unable to allocate input device\n");
1138 1061 return 0;
1139 1062 }
1140   - asus->inputdev->name = "Asus Laptop extra buttons";
1141   - asus->inputdev->dev.parent = &asus->platform_device->dev;
1142   - asus->inputdev->phys = ASUS_LAPTOP_FILE "/input0";
1143   - asus->inputdev->id.bustype = BUS_HOST;
1144   - asus->inputdev->getkeycode = asus_getkeycode;
1145   - asus->inputdev->setkeycode = asus_setkeycode;
1146   - input_set_drvdata(asus->inputdev, asus);
  1063 + input->name = "Asus Laptop extra buttons";
  1064 + input->phys = ASUS_LAPTOP_FILE "/input0";
  1065 + input->id.bustype = BUS_HOST;
  1066 + input->dev.parent = &asus->platform_device->dev;
  1067 + input_set_drvdata(input, asus);
1147 1068  
1148   - asus->keymap = kmemdup(asus_keymap, sizeof(asus_keymap),
1149   - GFP_KERNEL);
1150   - for (key = asus->keymap; key->type != KE_END; key++) {
1151   - switch (key->type) {
1152   - case KE_KEY:
1153   - set_bit(EV_KEY, asus->inputdev->evbit);
1154   - set_bit(key->keycode, asus->inputdev->keybit);
1155   - break;
1156   - }
  1069 + error = sparse_keymap_setup(input, asus_keymap, NULL);
  1070 + if (error) {
  1071 + pr_err("Unable to setup input device keymap\n");
  1072 + goto err_keymap;
1157 1073 }
1158   - result = input_register_device(asus->inputdev);
1159   - if (result) {
  1074 + error = input_register_device(input);
  1075 + if (error) {
1160 1076 pr_info("Unable to register input device\n");
1161   - input_free_device(asus->inputdev);
  1077 + goto err_device;
1162 1078 }
1163   - return result;
  1079 +
  1080 + asus->inputdev = input;
  1081 + return 0;
  1082 +
  1083 +err_keymap:
  1084 + sparse_keymap_free(input);
  1085 +err_device:
  1086 + input_free_device(input);
  1087 + return error;
1164 1088 }
1165 1089  
1166 1090 static void asus_input_exit(struct asus_laptop *asus)
1167 1091 {
1168   - if (asus->inputdev)
  1092 + if (asus->inputdev) {
  1093 + sparse_keymap_free(asus->inputdev);
1169 1094 input_unregister_device(asus->inputdev);
  1095 + }
1170 1096 }
1171 1097  
1172 1098 /*