diff options
| -rw-r--r-- | drivers/input/misc/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/input/misc/wistron_btns.c | 178 |
2 files changed, 45 insertions, 134 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index a9bb2544b2de..d25ecbb87bfc 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
| @@ -80,6 +80,7 @@ config INPUT_WISTRON_BTNS | |||
| 80 | tristate "x86 Wistron laptop button interface" | 80 | tristate "x86 Wistron laptop button interface" |
| 81 | depends on X86 && !X86_64 | 81 | depends on X86 && !X86_64 |
| 82 | select INPUT_POLLDEV | 82 | select INPUT_POLLDEV |
| 83 | select INPUT_SPARSEKMAP | ||
| 83 | select NEW_LEDS | 84 | select NEW_LEDS |
| 84 | select LEDS_CLASS | 85 | select LEDS_CLASS |
| 85 | select CHECK_SIGNATURE | 86 | select CHECK_SIGNATURE |
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index f9d2bc87b355..38da6ab04384 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/dmi.h> | 21 | #include <linux/dmi.h> |
| 22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 23 | #include <linux/input-polldev.h> | 23 | #include <linux/input-polldev.h> |
| 24 | #include <linux/input/sparse-keymap.h> | ||
| 24 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 25 | #include <linux/jiffies.h> | 26 | #include <linux/jiffies.h> |
| 26 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| @@ -224,19 +225,8 @@ static void bios_set_state(u8 subsys, int enable) | |||
| 224 | 225 | ||
| 225 | /* Hardware database */ | 226 | /* Hardware database */ |
| 226 | 227 | ||
| 227 | struct key_entry { | 228 | #define KE_WIFI (KE_LAST + 1) |
| 228 | char type; /* See KE_* below */ | 229 | #define KE_BLUETOOTH (KE_LAST + 2) |
| 229 | u8 code; | ||
| 230 | union { | ||
| 231 | u16 keycode; /* For KE_KEY */ | ||
| 232 | struct { /* For KE_SW */ | ||
| 233 | u8 code; | ||
| 234 | u8 value; | ||
| 235 | } sw; | ||
| 236 | }; | ||
| 237 | }; | ||
| 238 | |||
| 239 | enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH }; | ||
| 240 | 230 | ||
| 241 | #define FE_MAIL_LED 0x01 | 231 | #define FE_MAIL_LED 0x01 |
| 242 | #define FE_WIFI_LED 0x02 | 232 | #define FE_WIFI_LED 0x02 |
| @@ -1037,21 +1027,6 @@ static unsigned long jiffies_last_press; | |||
| 1037 | static bool wifi_enabled; | 1027 | static bool wifi_enabled; |
| 1038 | static bool bluetooth_enabled; | 1028 | static bool bluetooth_enabled; |
| 1039 | 1029 | ||
| 1040 | static void report_key(struct input_dev *dev, unsigned int keycode) | ||
| 1041 | { | ||
| 1042 | input_report_key(dev, keycode, 1); | ||
| 1043 | input_sync(dev); | ||
| 1044 | input_report_key(dev, keycode, 0); | ||
| 1045 | input_sync(dev); | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | static void report_switch(struct input_dev *dev, unsigned int code, int value) | ||
| 1049 | { | ||
| 1050 | input_report_switch(dev, code, value); | ||
| 1051 | input_sync(dev); | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | |||
| 1055 | /* led management */ | 1030 | /* led management */ |
| 1056 | static void wistron_mail_led_set(struct led_classdev *led_cdev, | 1031 | static void wistron_mail_led_set(struct led_classdev *led_cdev, |
| 1057 | enum led_brightness value) | 1032 | enum led_brightness value) |
| @@ -1128,43 +1103,13 @@ static inline void wistron_led_resume(void) | |||
| 1128 | led_classdev_resume(&wistron_wifi_led); | 1103 | led_classdev_resume(&wistron_wifi_led); |
| 1129 | } | 1104 | } |
| 1130 | 1105 | ||
| 1131 | static struct key_entry *wistron_get_entry_by_scancode(int code) | ||
| 1132 | { | ||
| 1133 | struct key_entry *key; | ||
| 1134 | |||
| 1135 | for (key = keymap; key->type != KE_END; key++) | ||
| 1136 | if (code == key->code) | ||
| 1137 | return key; | ||
| 1138 | |||
| 1139 | return NULL; | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | static struct key_entry *wistron_get_entry_by_keycode(int keycode) | ||
| 1143 | { | ||
| 1144 | struct key_entry *key; | ||
| 1145 | |||
| 1146 | for (key = keymap; key->type != KE_END; key++) | ||
| 1147 | if (key->type == KE_KEY && keycode == key->keycode) | ||
| 1148 | return key; | ||
| 1149 | |||
| 1150 | return NULL; | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | static void handle_key(u8 code) | 1106 | static void handle_key(u8 code) |
| 1154 | { | 1107 | { |
| 1155 | const struct key_entry *key = wistron_get_entry_by_scancode(code); | 1108 | const struct key_entry *key = |
| 1109 | sparse_keymap_entry_from_scancode(wistron_idev->input, code); | ||
| 1156 | 1110 | ||
| 1157 | if (key) { | 1111 | if (key) { |
| 1158 | switch (key->type) { | 1112 | switch (key->type) { |
| 1159 | case KE_KEY: | ||
| 1160 | report_key(wistron_idev->input, key->keycode); | ||
| 1161 | break; | ||
| 1162 | |||
| 1163 | case KE_SW: | ||
| 1164 | report_switch(wistron_idev->input, | ||
| 1165 | key->sw.code, key->sw.value); | ||
| 1166 | break; | ||
| 1167 | |||
| 1168 | case KE_WIFI: | 1113 | case KE_WIFI: |
| 1169 | if (have_wifi) { | 1114 | if (have_wifi) { |
| 1170 | wifi_enabled = !wifi_enabled; | 1115 | wifi_enabled = !wifi_enabled; |
| @@ -1180,7 +1125,9 @@ static void handle_key(u8 code) | |||
| 1180 | break; | 1125 | break; |
| 1181 | 1126 | ||
| 1182 | default: | 1127 | default: |
| 1183 | BUG(); | 1128 | sparse_keymap_report_entry(wistron_idev->input, |
| 1129 | key, 1, true); | ||
| 1130 | break; | ||
| 1184 | } | 1131 | } |
| 1185 | jiffies_last_press = jiffies; | 1132 | jiffies_last_press = jiffies; |
| 1186 | } else | 1133 | } else |
| @@ -1220,42 +1167,39 @@ static void wistron_poll(struct input_polled_dev *dev) | |||
| 1220 | dev->poll_interval = POLL_INTERVAL_DEFAULT; | 1167 | dev->poll_interval = POLL_INTERVAL_DEFAULT; |
| 1221 | } | 1168 | } |
| 1222 | 1169 | ||
| 1223 | static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode) | 1170 | static int __devinit wistron_setup_keymap(struct input_dev *dev, |
| 1171 | struct key_entry *entry) | ||
| 1224 | { | 1172 | { |
| 1225 | const struct key_entry *key = wistron_get_entry_by_scancode(scancode); | 1173 | switch (entry->type) { |
| 1226 | 1174 | ||
| 1227 | if (key && key->type == KE_KEY) { | 1175 | /* if wifi or bluetooth are not available, create normal keys */ |
| 1228 | *keycode = key->keycode; | 1176 | case KE_WIFI: |
| 1229 | return 0; | 1177 | if (!have_wifi) { |
| 1230 | } | 1178 | entry->type = KE_KEY; |
| 1231 | 1179 | entry->keycode = KEY_WLAN; | |
| 1232 | return -EINVAL; | 1180 | } |
| 1233 | } | 1181 | break; |
| 1234 | 1182 | ||
| 1235 | static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode) | 1183 | case KE_BLUETOOTH: |
| 1236 | { | 1184 | if (!have_bluetooth) { |
| 1237 | struct key_entry *key; | 1185 | entry->type = KE_KEY; |
| 1238 | int old_keycode; | 1186 | entry->keycode = KEY_BLUETOOTH; |
| 1239 | 1187 | } | |
| 1240 | if (keycode < 0 || keycode > KEY_MAX) | 1188 | break; |
| 1241 | return -EINVAL; | 1189 | |
| 1242 | 1190 | case KE_END: | |
| 1243 | key = wistron_get_entry_by_scancode(scancode); | 1191 | if (entry->code & FE_UNTESTED) |
| 1244 | if (key && key->type == KE_KEY) { | 1192 | printk(KERN_WARNING "Untested laptop multimedia keys, " |
| 1245 | old_keycode = key->keycode; | 1193 | "please report success or failure to " |
| 1246 | key->keycode = keycode; | 1194 | "eric.piel@tremplin-utc.net\n"); |
| 1247 | set_bit(keycode, dev->keybit); | 1195 | break; |
| 1248 | if (!wistron_get_entry_by_keycode(old_keycode)) | ||
| 1249 | clear_bit(old_keycode, dev->keybit); | ||
| 1250 | return 0; | ||
| 1251 | } | 1196 | } |
| 1252 | 1197 | ||
| 1253 | return -EINVAL; | 1198 | return 0; |
| 1254 | } | 1199 | } |
| 1255 | 1200 | ||
| 1256 | static int __devinit setup_input_dev(void) | 1201 | static int __devinit setup_input_dev(void) |
| 1257 | { | 1202 | { |
| 1258 | struct key_entry *key; | ||
| 1259 | struct input_dev *input_dev; | 1203 | struct input_dev *input_dev; |
| 1260 | int error; | 1204 | int error; |
| 1261 | 1205 | ||
| @@ -1273,56 +1217,21 @@ static int __devinit setup_input_dev(void) | |||
| 1273 | input_dev->id.bustype = BUS_HOST; | 1217 | input_dev->id.bustype = BUS_HOST; |
| 1274 | input_dev->dev.parent = &wistron_device->dev; | 1218 | input_dev->dev.parent = &wistron_device->dev; |
| 1275 | 1219 | ||
| 1276 | input_dev->getkeycode = wistron_getkeycode; | 1220 | error = sparse_keymap_setup(input_dev, keymap, wistron_setup_keymap); |
| 1277 | input_dev->setkeycode = wistron_setkeycode; | 1221 | if (error) |
| 1278 | 1222 | goto err_free_dev; | |
| 1279 | for (key = keymap; key->type != KE_END; key++) { | ||
| 1280 | switch (key->type) { | ||
| 1281 | case KE_KEY: | ||
| 1282 | set_bit(EV_KEY, input_dev->evbit); | ||
| 1283 | set_bit(key->keycode, input_dev->keybit); | ||
| 1284 | break; | ||
| 1285 | |||
| 1286 | case KE_SW: | ||
| 1287 | set_bit(EV_SW, input_dev->evbit); | ||
| 1288 | set_bit(key->sw.code, input_dev->swbit); | ||
| 1289 | break; | ||
| 1290 | |||
| 1291 | /* if wifi or bluetooth are not available, create normal keys */ | ||
| 1292 | case KE_WIFI: | ||
| 1293 | if (!have_wifi) { | ||
| 1294 | key->type = KE_KEY; | ||
| 1295 | key->keycode = KEY_WLAN; | ||
| 1296 | key--; | ||
| 1297 | } | ||
| 1298 | break; | ||
| 1299 | |||
| 1300 | case KE_BLUETOOTH: | ||
| 1301 | if (!have_bluetooth) { | ||
| 1302 | key->type = KE_KEY; | ||
| 1303 | key->keycode = KEY_BLUETOOTH; | ||
| 1304 | key--; | ||
| 1305 | } | ||
| 1306 | break; | ||
| 1307 | |||
| 1308 | default: | ||
| 1309 | break; | ||
| 1310 | } | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | /* reads information flags on KE_END */ | ||
| 1314 | if (key->code & FE_UNTESTED) | ||
| 1315 | printk(KERN_WARNING "Untested laptop multimedia keys, " | ||
| 1316 | "please report success or failure to eric.piel" | ||
| 1317 | "@tremplin-utc.net\n"); | ||
| 1318 | 1223 | ||
| 1319 | error = input_register_polled_device(wistron_idev); | 1224 | error = input_register_polled_device(wistron_idev); |
| 1320 | if (error) { | 1225 | if (error) |
| 1321 | input_free_polled_device(wistron_idev); | 1226 | goto err_free_keymap; |
| 1322 | return error; | ||
| 1323 | } | ||
| 1324 | 1227 | ||
| 1325 | return 0; | 1228 | return 0; |
| 1229 | |||
| 1230 | err_free_keymap: | ||
| 1231 | sparse_keymap_free(input_dev); | ||
| 1232 | err_free_dev: | ||
| 1233 | input_free_polled_device(wistron_idev); | ||
| 1234 | return error; | ||
| 1326 | } | 1235 | } |
| 1327 | 1236 | ||
| 1328 | /* Driver core */ | 1237 | /* Driver core */ |
| @@ -1371,6 +1280,7 @@ static int __devexit wistron_remove(struct platform_device *dev) | |||
| 1371 | { | 1280 | { |
| 1372 | wistron_led_remove(); | 1281 | wistron_led_remove(); |
| 1373 | input_unregister_polled_device(wistron_idev); | 1282 | input_unregister_polled_device(wistron_idev); |
| 1283 | sparse_keymap_free(wistron_idev->input); | ||
| 1374 | input_free_polled_device(wistron_idev); | 1284 | input_free_polled_device(wistron_idev); |
| 1375 | bios_detach(); | 1285 | bios_detach(); |
| 1376 | 1286 | ||
