diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2015-06-06 14:44:39 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-06-16 17:59:46 -0400 |
commit | eeb64c14275e52740d6410632e62e0ad9b88ca70 (patch) | |
tree | 22b808cc11a63db51f10464613b6d1ed93b6536c | |
parent | 5235552273e6b68abbed3b3047af6344e2e60c2c (diff) |
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>
-rw-r--r-- | drivers/tty/vt/keyboard.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index fc080bf1c4d2..6f0336fff501 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c | |||
@@ -130,7 +130,7 @@ static char rep; /* flag telling character repeat */ | |||
130 | 130 | ||
131 | static int shift_state = 0; | 131 | static int shift_state = 0; |
132 | 132 | ||
133 | static unsigned char ledstate = 0xff; /* undefined */ | 133 | static unsigned int ledstate = -1U; /* undefined */ |
134 | static unsigned char ledioctl; | 134 | static unsigned char ledioctl; |
135 | 135 | ||
136 | /* | 136 | /* |
@@ -975,7 +975,7 @@ static void kbd_led_trigger_activate(struct led_classdev *cdev) | |||
975 | container_of(cdev->trigger, struct kbd_led_trigger, trigger); | 975 | container_of(cdev->trigger, struct kbd_led_trigger, trigger); |
976 | 976 | ||
977 | tasklet_disable(&keyboard_tasklet); | 977 | tasklet_disable(&keyboard_tasklet); |
978 | if (ledstate != 0xff) | 978 | if (ledstate != -1U) |
979 | led_trigger_event(&trigger->trigger, | 979 | led_trigger_event(&trigger->trigger, |
980 | ledstate & trigger->mask ? | 980 | ledstate & trigger->mask ? |
981 | LED_FULL : LED_OFF); | 981 | LED_FULL : LED_OFF); |
@@ -990,11 +990,23 @@ static void kbd_led_trigger_activate(struct led_classdev *cdev) | |||
990 | .mask = BIT(_led_bit), \ | 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 | static struct kbd_led_trigger kbd_led_triggers[] = { | 996 | static struct kbd_led_trigger kbd_led_triggers[] = { |
994 | KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrollock"), | 997 | KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrollock"), |
995 | KBD_LED_TRIGGER(VC_NUMLOCK, "kbd-numlock"), | 998 | KBD_LED_TRIGGER(VC_NUMLOCK, "kbd-numlock"), |
996 | KBD_LED_TRIGGER(VC_CAPSLOCK, "kbd-capslock"), | 999 | KBD_LED_TRIGGER(VC_CAPSLOCK, "kbd-capslock"), |
997 | KBD_LED_TRIGGER(VC_KANALOCK, "kbd-kanalock"), | 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 | static void kbd_propagate_led_state(unsigned int old_state, | 1012 | static void kbd_propagate_led_state(unsigned int old_state, |
@@ -1073,7 +1085,7 @@ static void kbd_init_leds(void) | |||
1073 | */ | 1085 | */ |
1074 | static unsigned char getledstate(void) | 1086 | static unsigned char getledstate(void) |
1075 | { | 1087 | { |
1076 | return ledstate; | 1088 | return ledstate & 0xff; |
1077 | } | 1089 | } |
1078 | 1090 | ||
1079 | void setledstate(struct kbd_struct *kb, unsigned int led) | 1091 | void setledstate(struct kbd_struct *kb, unsigned int led) |
@@ -1183,11 +1195,12 @@ void vt_kbd_con_stop(int console) | |||
1183 | */ | 1195 | */ |
1184 | static void kbd_bh(unsigned long dummy) | 1196 | static void kbd_bh(unsigned long dummy) |
1185 | { | 1197 | { |
1186 | unsigned char leds; | 1198 | unsigned int leds; |
1187 | unsigned long flags; | 1199 | unsigned long flags; |
1188 | 1200 | ||
1189 | spin_lock_irqsave(&led_lock, flags); | 1201 | spin_lock_irqsave(&led_lock, flags); |
1190 | leds = getleds(); | 1202 | leds = getleds(); |
1203 | leds |= (unsigned int)kbd->lockstate << 8; | ||
1191 | spin_unlock_irqrestore(&led_lock, flags); | 1204 | spin_unlock_irqrestore(&led_lock, flags); |
1192 | 1205 | ||
1193 | if (leds != ledstate) { | 1206 | if (leds != ledstate) { |
@@ -1539,10 +1552,8 @@ static void kbd_start(struct input_handle *handle) | |||
1539 | { | 1552 | { |
1540 | tasklet_disable(&keyboard_tasklet); | 1553 | tasklet_disable(&keyboard_tasklet); |
1541 | 1554 | ||
1542 | if (ledstate != 0xff) { | 1555 | if (ledstate != -1U) |
1543 | unsigned int state = ledstate; | 1556 | kbd_update_leds_helper(handle, &ledstate); |
1544 | kbd_update_leds_helper(handle, &state); | ||
1545 | } | ||
1546 | 1557 | ||
1547 | tasklet_enable(&keyboard_tasklet); | 1558 | tasklet_enable(&keyboard_tasklet); |
1548 | } | 1559 | } |