diff options
Diffstat (limited to 'drivers/char/keyboard.c')
| -rw-r--r-- | drivers/char/keyboard.c | 139 |
1 files changed, 78 insertions, 61 deletions
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 056ebe84b81d..3e90aac37510 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
| @@ -107,7 +107,6 @@ const int NR_TYPES = ARRAY_SIZE(max_vals); | |||
| 107 | 107 | ||
| 108 | struct kbd_struct kbd_table[MAX_NR_CONSOLES]; | 108 | struct kbd_struct kbd_table[MAX_NR_CONSOLES]; |
| 109 | static struct kbd_struct *kbd = kbd_table; | 109 | static struct kbd_struct *kbd = kbd_table; |
| 110 | static struct kbd_struct kbd0; | ||
| 111 | 110 | ||
| 112 | int spawnpid, spawnsig; | 111 | int spawnpid, spawnsig; |
| 113 | 112 | ||
| @@ -223,13 +222,13 @@ static void kd_nosound(unsigned long ignored) | |||
| 223 | { | 222 | { |
| 224 | struct list_head *node; | 223 | struct list_head *node; |
| 225 | 224 | ||
| 226 | list_for_each(node,&kbd_handler.h_list) { | 225 | list_for_each(node, &kbd_handler.h_list) { |
| 227 | struct input_handle *handle = to_handle_h(node); | 226 | struct input_handle *handle = to_handle_h(node); |
| 228 | if (test_bit(EV_SND, handle->dev->evbit)) { | 227 | if (test_bit(EV_SND, handle->dev->evbit)) { |
| 229 | if (test_bit(SND_TONE, handle->dev->sndbit)) | 228 | if (test_bit(SND_TONE, handle->dev->sndbit)) |
| 230 | input_event(handle->dev, EV_SND, SND_TONE, 0); | 229 | input_inject_event(handle, EV_SND, SND_TONE, 0); |
| 231 | if (test_bit(SND_BELL, handle->dev->sndbit)) | 230 | if (test_bit(SND_BELL, handle->dev->sndbit)) |
| 232 | input_event(handle->dev, EV_SND, SND_BELL, 0); | 231 | input_inject_event(handle, EV_SND, SND_BELL, 0); |
| 233 | } | 232 | } |
| 234 | } | 233 | } |
| 235 | } | 234 | } |
| @@ -247,11 +246,11 @@ void kd_mksound(unsigned int hz, unsigned int ticks) | |||
| 247 | struct input_handle *handle = to_handle_h(node); | 246 | struct input_handle *handle = to_handle_h(node); |
| 248 | if (test_bit(EV_SND, handle->dev->evbit)) { | 247 | if (test_bit(EV_SND, handle->dev->evbit)) { |
| 249 | if (test_bit(SND_TONE, handle->dev->sndbit)) { | 248 | if (test_bit(SND_TONE, handle->dev->sndbit)) { |
| 250 | input_event(handle->dev, EV_SND, SND_TONE, hz); | 249 | input_inject_event(handle, EV_SND, SND_TONE, hz); |
| 251 | break; | 250 | break; |
| 252 | } | 251 | } |
| 253 | if (test_bit(SND_BELL, handle->dev->sndbit)) { | 252 | if (test_bit(SND_BELL, handle->dev->sndbit)) { |
| 254 | input_event(handle->dev, EV_SND, SND_BELL, 1); | 253 | input_inject_event(handle, EV_SND, SND_BELL, 1); |
| 255 | break; | 254 | break; |
| 256 | } | 255 | } |
| 257 | } | 256 | } |
| @@ -272,15 +271,15 @@ int kbd_rate(struct kbd_repeat *rep) | |||
| 272 | unsigned int d = 0; | 271 | unsigned int d = 0; |
| 273 | unsigned int p = 0; | 272 | unsigned int p = 0; |
| 274 | 273 | ||
| 275 | list_for_each(node,&kbd_handler.h_list) { | 274 | list_for_each(node, &kbd_handler.h_list) { |
| 276 | struct input_handle *handle = to_handle_h(node); | 275 | struct input_handle *handle = to_handle_h(node); |
| 277 | struct input_dev *dev = handle->dev; | 276 | struct input_dev *dev = handle->dev; |
| 278 | 277 | ||
| 279 | if (test_bit(EV_REP, dev->evbit)) { | 278 | if (test_bit(EV_REP, dev->evbit)) { |
| 280 | if (rep->delay > 0) | 279 | if (rep->delay > 0) |
| 281 | input_event(dev, EV_REP, REP_DELAY, rep->delay); | 280 | input_inject_event(handle, EV_REP, REP_DELAY, rep->delay); |
| 282 | if (rep->period > 0) | 281 | if (rep->period > 0) |
| 283 | input_event(dev, EV_REP, REP_PERIOD, rep->period); | 282 | input_inject_event(handle, EV_REP, REP_PERIOD, rep->period); |
| 284 | d = dev->rep[REP_DELAY]; | 283 | d = dev->rep[REP_DELAY]; |
| 285 | p = dev->rep[REP_PERIOD]; | 284 | p = dev->rep[REP_PERIOD]; |
| 286 | } | 285 | } |
| @@ -988,7 +987,7 @@ static inline unsigned char getleds(void) | |||
| 988 | * interrupt routines for this thing allows us to easily mask | 987 | * interrupt routines for this thing allows us to easily mask |
| 989 | * this when we don't want any of the above to happen. | 988 | * this when we don't want any of the above to happen. |
| 990 | * This allows for easy and efficient race-condition prevention | 989 | * This allows for easy and efficient race-condition prevention |
| 991 | * for kbd_refresh_leds => input_event(dev, EV_LED, ...) => ... | 990 | * for kbd_start => input_inject_event(dev, EV_LED, ...) => ... |
| 992 | */ | 991 | */ |
| 993 | 992 | ||
| 994 | static void kbd_bh(unsigned long dummy) | 993 | static void kbd_bh(unsigned long dummy) |
| @@ -998,11 +997,11 @@ static void kbd_bh(unsigned long dummy) | |||
| 998 | 997 | ||
| 999 | if (leds != ledstate) { | 998 | if (leds != ledstate) { |
| 1000 | list_for_each(node, &kbd_handler.h_list) { | 999 | list_for_each(node, &kbd_handler.h_list) { |
| 1001 | struct input_handle * handle = to_handle_h(node); | 1000 | struct input_handle *handle = to_handle_h(node); |
| 1002 | input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01)); | 1001 | input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01)); |
| 1003 | input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02)); | 1002 | input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02)); |
| 1004 | input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04)); | 1003 | input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04)); |
| 1005 | input_sync(handle->dev); | 1004 | input_inject_event(handle, EV_SYN, SYN_REPORT, 0); |
| 1006 | } | 1005 | } |
| 1007 | } | 1006 | } |
| 1008 | 1007 | ||
| @@ -1011,23 +1010,6 @@ static void kbd_bh(unsigned long dummy) | |||
| 1011 | 1010 | ||
| 1012 | DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); | 1011 | DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh, 0); |
| 1013 | 1012 | ||
| 1014 | /* | ||
| 1015 | * This allows a newly plugged keyboard to pick the LED state. | ||
| 1016 | */ | ||
| 1017 | static void kbd_refresh_leds(struct input_handle *handle) | ||
| 1018 | { | ||
| 1019 | unsigned char leds = ledstate; | ||
| 1020 | |||
| 1021 | tasklet_disable(&keyboard_tasklet); | ||
| 1022 | if (leds != 0xff) { | ||
| 1023 | input_event(handle->dev, EV_LED, LED_SCROLLL, !!(leds & 0x01)); | ||
| 1024 | input_event(handle->dev, EV_LED, LED_NUML, !!(leds & 0x02)); | ||
| 1025 | input_event(handle->dev, EV_LED, LED_CAPSL, !!(leds & 0x04)); | ||
| 1026 | input_sync(handle->dev); | ||
| 1027 | } | ||
| 1028 | tasklet_enable(&keyboard_tasklet); | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\ | 1013 | #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\ |
| 1032 | defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\ | 1014 | defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\ |
| 1033 | defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\ | 1015 | defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\ |
| @@ -1043,7 +1025,7 @@ static const unsigned short x86_keycodes[256] = | |||
| 1043 | 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, | 1025 | 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, |
| 1044 | 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, | 1026 | 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, |
| 1045 | 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92, | 1027 | 80, 81, 82, 83, 84,118, 86, 87, 88,115,120,119,121,112,123, 92, |
| 1046 | 284,285,309,298,312, 91,327,328,329,331,333,335,336,337,338,339, | 1028 | 284,285,309, 0,312, 91,327,328,329,331,333,335,336,337,338,339, |
| 1047 | 367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349, | 1029 | 367,288,302,304,350, 89,334,326,267,126,268,269,125,347,348,349, |
| 1048 | 360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355, | 1030 | 360,261,262,263,268,376,100,101,321,316,373,286,289,102,351,355, |
| 1049 | 103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361, | 1031 | 103,104,105,275,287,279,306,106,274,107,294,364,358,363,362,361, |
| @@ -1065,38 +1047,55 @@ extern void sun_do_break(void); | |||
| 1065 | static int emulate_raw(struct vc_data *vc, unsigned int keycode, | 1047 | static int emulate_raw(struct vc_data *vc, unsigned int keycode, |
| 1066 | unsigned char up_flag) | 1048 | unsigned char up_flag) |
| 1067 | { | 1049 | { |
| 1068 | if (keycode > 255 || !x86_keycodes[keycode]) | 1050 | int code; |
| 1069 | return -1; | ||
| 1070 | 1051 | ||
| 1071 | switch (keycode) { | 1052 | switch (keycode) { |
| 1072 | case KEY_PAUSE: | 1053 | case KEY_PAUSE: |
| 1073 | put_queue(vc, 0xe1); | 1054 | put_queue(vc, 0xe1); |
| 1074 | put_queue(vc, 0x1d | up_flag); | 1055 | put_queue(vc, 0x1d | up_flag); |
| 1075 | put_queue(vc, 0x45 | up_flag); | 1056 | put_queue(vc, 0x45 | up_flag); |
| 1076 | return 0; | 1057 | break; |
| 1058 | |||
| 1077 | case KEY_HANGEUL: | 1059 | case KEY_HANGEUL: |
| 1078 | if (!up_flag) | 1060 | if (!up_flag) |
| 1079 | put_queue(vc, 0xf2); | 1061 | put_queue(vc, 0xf2); |
| 1080 | return 0; | 1062 | break; |
| 1063 | |||
| 1081 | case KEY_HANJA: | 1064 | case KEY_HANJA: |
| 1082 | if (!up_flag) | 1065 | if (!up_flag) |
| 1083 | put_queue(vc, 0xf1); | 1066 | put_queue(vc, 0xf1); |
| 1084 | return 0; | 1067 | break; |
| 1085 | } | ||
| 1086 | 1068 | ||
| 1087 | if (keycode == KEY_SYSRQ && sysrq_alt) { | 1069 | case KEY_SYSRQ: |
| 1088 | put_queue(vc, 0x54 | up_flag); | 1070 | /* |
| 1089 | return 0; | 1071 | * Real AT keyboards (that's what we're trying |
| 1090 | } | 1072 | * to emulate here emit 0xe0 0x2a 0xe0 0x37 when |
| 1073 | * pressing PrtSc/SysRq alone, but simply 0x54 | ||
| 1074 | * when pressing Alt+PrtSc/SysRq. | ||
| 1075 | */ | ||
| 1076 | if (sysrq_alt) { | ||
| 1077 | put_queue(vc, 0x54 | up_flag); | ||
| 1078 | } else { | ||
| 1079 | put_queue(vc, 0xe0); | ||
| 1080 | put_queue(vc, 0x2a | up_flag); | ||
| 1081 | put_queue(vc, 0xe0); | ||
| 1082 | put_queue(vc, 0x37 | up_flag); | ||
| 1083 | } | ||
| 1084 | break; | ||
| 1085 | |||
| 1086 | default: | ||
| 1087 | if (keycode > 255) | ||
| 1088 | return -1; | ||
| 1091 | 1089 | ||
| 1092 | if (x86_keycodes[keycode] & 0x100) | 1090 | code = x86_keycodes[keycode]; |
| 1093 | put_queue(vc, 0xe0); | 1091 | if (!code) |
| 1092 | return -1; | ||
| 1094 | 1093 | ||
| 1095 | put_queue(vc, (x86_keycodes[keycode] & 0x7f) | up_flag); | 1094 | if (code & 0x100) |
| 1095 | put_queue(vc, 0xe0); | ||
| 1096 | put_queue(vc, (code & 0x7f) | up_flag); | ||
| 1096 | 1097 | ||
| 1097 | if (keycode == KEY_SYSRQ) { | 1098 | break; |
| 1098 | put_queue(vc, 0xe0); | ||
| 1099 | put_queue(vc, 0x37 | up_flag); | ||
| 1100 | } | 1099 | } |
| 1101 | 1100 | ||
| 1102 | return 0; | 1101 | return 0; |
| @@ -1298,16 +1297,15 @@ static struct input_handle *kbd_connect(struct input_handler *handler, | |||
| 1298 | if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit)) | 1297 | if (i == BTN_MISC && !test_bit(EV_SND, dev->evbit)) |
| 1299 | return NULL; | 1298 | return NULL; |
| 1300 | 1299 | ||
| 1301 | if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL))) | 1300 | handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); |
| 1301 | if (!handle) | ||
| 1302 | return NULL; | 1302 | return NULL; |
| 1303 | memset(handle, 0, sizeof(struct input_handle)); | ||
| 1304 | 1303 | ||
| 1305 | handle->dev = dev; | 1304 | handle->dev = dev; |
| 1306 | handle->handler = handler; | 1305 | handle->handler = handler; |
| 1307 | handle->name = "kbd"; | 1306 | handle->name = "kbd"; |
| 1308 | 1307 | ||
| 1309 | input_open_device(handle); | 1308 | input_open_device(handle); |
| 1310 | kbd_refresh_leds(handle); | ||
| 1311 | 1309 | ||
| 1312 | return handle; | 1310 | return handle; |
| 1313 | } | 1311 | } |
| @@ -1318,6 +1316,24 @@ static void kbd_disconnect(struct input_handle *handle) | |||
| 1318 | kfree(handle); | 1316 | kfree(handle); |
| 1319 | } | 1317 | } |
| 1320 | 1318 | ||
| 1319 | /* | ||
| 1320 | * Start keyboard handler on the new keyboard by refreshing LED state to | ||
| 1321 | * match the rest of the system. | ||
| 1322 | */ | ||
| 1323 | static void kbd_start(struct input_handle *handle) | ||
| 1324 | { | ||
| 1325 | unsigned char leds = ledstate; | ||
| 1326 | |||
| 1327 | tasklet_disable(&keyboard_tasklet); | ||
| 1328 | if (leds != 0xff) { | ||
| 1329 | input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01)); | ||
| 1330 | input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02)); | ||
| 1331 | input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04)); | ||
| 1332 | input_inject_event(handle, EV_SYN, SYN_REPORT, 0); | ||
| 1333 | } | ||
| 1334 | tasklet_enable(&keyboard_tasklet); | ||
| 1335 | } | ||
| 1336 | |||
| 1321 | static struct input_device_id kbd_ids[] = { | 1337 | static struct input_device_id kbd_ids[] = { |
| 1322 | { | 1338 | { |
| 1323 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT, | 1339 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT, |
| @@ -1338,6 +1354,7 @@ static struct input_handler kbd_handler = { | |||
| 1338 | .event = kbd_event, | 1354 | .event = kbd_event, |
| 1339 | .connect = kbd_connect, | 1355 | .connect = kbd_connect, |
| 1340 | .disconnect = kbd_disconnect, | 1356 | .disconnect = kbd_disconnect, |
| 1357 | .start = kbd_start, | ||
| 1341 | .name = "kbd", | 1358 | .name = "kbd", |
| 1342 | .id_table = kbd_ids, | 1359 | .id_table = kbd_ids, |
| 1343 | }; | 1360 | }; |
| @@ -1346,15 +1363,15 @@ int __init kbd_init(void) | |||
| 1346 | { | 1363 | { |
| 1347 | int i; | 1364 | int i; |
| 1348 | 1365 | ||
| 1349 | kbd0.ledflagstate = kbd0.default_ledflagstate = KBD_DEFLEDS; | 1366 | for (i = 0; i < MAX_NR_CONSOLES; i++) { |
| 1350 | kbd0.ledmode = LED_SHOW_FLAGS; | 1367 | kbd_table[i].ledflagstate = KBD_DEFLEDS; |
| 1351 | kbd0.lockstate = KBD_DEFLOCK; | 1368 | kbd_table[i].default_ledflagstate = KBD_DEFLEDS; |
| 1352 | kbd0.slockstate = 0; | 1369 | kbd_table[i].ledmode = LED_SHOW_FLAGS; |
| 1353 | kbd0.modeflags = KBD_DEFMODE; | 1370 | kbd_table[i].lockstate = KBD_DEFLOCK; |
| 1354 | kbd0.kbdmode = VC_XLATE; | 1371 | kbd_table[i].slockstate = 0; |
| 1355 | 1372 | kbd_table[i].modeflags = KBD_DEFMODE; | |
| 1356 | for (i = 0 ; i < MAX_NR_CONSOLES ; i++) | 1373 | kbd_table[i].kbdmode = VC_XLATE; |
| 1357 | kbd_table[i] = kbd0; | 1374 | } |
| 1358 | 1375 | ||
| 1359 | input_register_handler(&kbd_handler); | 1376 | input_register_handler(&kbd_handler); |
| 1360 | 1377 | ||
