Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tty/vt/keyboard: define LED triggers for VT keyboard lock states

In addition to defining triggers for VT LED states, let's define triggers
for VT keyboard lock states, such as "kbd-shiftlock", "kbd-altgrlock", etc.

This permits to fix #7063 from userland by using a modifier to implement
proper CapsLock behavior and have the keyboard caps lock led show that
modifier state.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Tested-by: Pavel Machek <pavel@ucw.cz>
Acked-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Samuel Thibault and committed by
Dmitry Torokhov
eeb64c14 52355522

+19 -8
+19 -8
drivers/tty/vt/keyboard.c
··· 130 130 131 131 static int shift_state = 0; 132 132 133 - static unsigned char ledstate = 0xff; /* undefined */ 133 + static unsigned int ledstate = -1U; /* undefined */ 134 134 static unsigned char ledioctl; 135 135 136 136 /* ··· 975 975 container_of(cdev->trigger, struct kbd_led_trigger, trigger); 976 976 977 977 tasklet_disable(&keyboard_tasklet); 978 - if (ledstate != 0xff) 978 + if (ledstate != -1U) 979 979 led_trigger_event(&trigger->trigger, 980 980 ledstate & trigger->mask ? 981 981 LED_FULL : LED_OFF); ··· 990 990 .mask = BIT(_led_bit), \ 991 991 } 992 992 993 + #define KBD_LOCKSTATE_TRIGGER(_led_bit, _name) \ 994 + KBD_LED_TRIGGER((_led_bit) + 8, _name) 995 + 993 996 static struct kbd_led_trigger kbd_led_triggers[] = { 994 997 KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrollock"), 995 998 KBD_LED_TRIGGER(VC_NUMLOCK, "kbd-numlock"), 996 999 KBD_LED_TRIGGER(VC_CAPSLOCK, "kbd-capslock"), 997 1000 KBD_LED_TRIGGER(VC_KANALOCK, "kbd-kanalock"), 1001 + 1002 + KBD_LOCKSTATE_TRIGGER(VC_SHIFTLOCK, "kbd-shiftlock"), 1003 + KBD_LOCKSTATE_TRIGGER(VC_ALTGRLOCK, "kbd-altgrlock"), 1004 + KBD_LOCKSTATE_TRIGGER(VC_CTRLLOCK, "kbd-ctrllock"), 1005 + KBD_LOCKSTATE_TRIGGER(VC_ALTLOCK, "kbd-altlock"), 1006 + KBD_LOCKSTATE_TRIGGER(VC_SHIFTLLOCK, "kbd-shiftllock"), 1007 + KBD_LOCKSTATE_TRIGGER(VC_SHIFTRLOCK, "kbd-shiftrlock"), 1008 + KBD_LOCKSTATE_TRIGGER(VC_CTRLLLOCK, "kbd-ctrlllock"), 1009 + KBD_LOCKSTATE_TRIGGER(VC_CTRLRLOCK, "kbd-ctrlrlock"), 998 1010 }; 999 1011 1000 1012 static void kbd_propagate_led_state(unsigned int old_state, ··· 1085 1073 */ 1086 1074 static unsigned char getledstate(void) 1087 1075 { 1088 - return ledstate; 1076 + return ledstate & 0xff; 1089 1077 } 1090 1078 1091 1079 void setledstate(struct kbd_struct *kb, unsigned int led) ··· 1195 1183 */ 1196 1184 static void kbd_bh(unsigned long dummy) 1197 1185 { 1198 - unsigned char leds; 1186 + unsigned int leds; 1199 1187 unsigned long flags; 1200 1188 1201 1189 spin_lock_irqsave(&led_lock, flags); 1202 1190 leds = getleds(); 1191 + leds |= (unsigned int)kbd->lockstate << 8; 1203 1192 spin_unlock_irqrestore(&led_lock, flags); 1204 1193 1205 1194 if (leds != ledstate) { ··· 1552 1539 { 1553 1540 tasklet_disable(&keyboard_tasklet); 1554 1541 1555 - if (ledstate != 0xff) { 1556 - unsigned int state = ledstate; 1557 - kbd_update_leds_helper(handle, &state); 1558 - } 1542 + if (ledstate != -1U) 1543 + kbd_update_leds_helper(handle, &ledstate); 1559 1544 1560 1545 tasklet_enable(&keyboard_tasklet); 1561 1546 }