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 | ||