From ffb6e0c9a0572f8e5f8e9337a1b40ac2ec1493a1 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 26 May 2015 14:45:29 -0700 Subject: tty: remove platform_sysrq_reset_seq The platform_sysrq_reset_seq code was intended as a way for an embedded platform to provide its own sysrq sequence at compile time. After over two years, nobody has started using it in an upstream kernel, and the platforms that were interested in it have moved on to devicetree, which can be used to configure the sequence without requiring kernel changes. The method is also incompatible with the way that most architectures build support for multiple platforms into a single kernel. Now the code is producing warnings when built with gcc-5.1: drivers/tty/sysrq.c: In function 'sysrq_init': drivers/tty/sysrq.c:959:33: warning: array subscript is above array bounds [-Warray-bounds] key = platform_sysrq_reset_seq[i]; We could fix this, but it seems unlikely that it will ever be used, so let's just remove the code instead. We still have the option to pass the sequence either in DT, using the kernel command line, or using the /sys/module/sysrq/parameters/reset_seq file. Fixes: 154b7a489a ("Input: sysrq - allow specifying alternate reset sequence") Signed-off-by: Arnd Bergmann Signed-off-by: Dmitry Torokhov --- drivers/tty/sysrq.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 259a4d5a4e8f..b21881e39d28 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -55,9 +55,6 @@ static int __read_mostly sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE; static bool __read_mostly sysrq_always_enabled; -unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED }; -int sysrq_reset_downtime_ms __weak; - static bool sysrq_on(void) { return sysrq_enabled || sysrq_always_enabled; @@ -568,6 +565,7 @@ void handle_sysrq(int key) EXPORT_SYMBOL(handle_sysrq); #ifdef CONFIG_INPUT +static int sysrq_reset_downtime_ms; /* Simple translation table for the SysRq keys */ static const unsigned char sysrq_xlate[KEY_CNT] = @@ -948,23 +946,8 @@ static bool sysrq_handler_registered; static inline void sysrq_register_handler(void) { - unsigned short key; int error; - int i; - - /* First check if a __weak interface was instantiated. */ - for (i = 0; i < ARRAY_SIZE(sysrq_reset_seq); i++) { - key = platform_sysrq_reset_seq[i]; - if (key == KEY_RESERVED || key > KEY_MAX) - break; - - sysrq_reset_seq[sysrq_reset_seq_len++] = key; - } - /* - * DT configuration takes precedence over anything that would - * have been defined via the __weak interface. - */ sysrq_of_get_keyreset_config(); error = input_register_handler(&sysrq_handler); -- cgit v1.2.3 From 5235552273e6b68abbed3b3047af6344e2e60c2c Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Mon, 16 Mar 2015 21:19:44 -0700 Subject: tty/vt/keyboard: define LED triggers for VT LED states Now that input core allows controlling keyboards LEDs via standard LED subsystem triggers let's switch VT keyboard code to make use of this feature. We will define the following standard triggers: "kbd-scrollock", "kbd-numlock", "kbd-capslock", and "kbd-kanalock" which are default triggers for respective LEDs on keyboards. Signed-off-by: Samuel Thibault Tested-by: Pavel Machek Acked-by: Pavel Machek Signed-off-by: Dmitry Torokhov --- drivers/tty/vt/keyboard.c | 141 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 117 insertions(+), 24 deletions(-) (limited to 'drivers/tty') diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 8a89f6e7715d..fc080bf1c4d2 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -961,6 +962,110 @@ static void k_brl(struct vc_data *vc, unsigned char value, char up_flag) } } +#if IS_ENABLED(CONFIG_INPUT_LEDS) && IS_ENABLED(CONFIG_LEDS_TRIGGERS) + +struct kbd_led_trigger { + struct led_trigger trigger; + unsigned int mask; +}; + +static void kbd_led_trigger_activate(struct led_classdev *cdev) +{ + struct kbd_led_trigger *trigger = + container_of(cdev->trigger, struct kbd_led_trigger, trigger); + + tasklet_disable(&keyboard_tasklet); + if (ledstate != 0xff) + led_trigger_event(&trigger->trigger, + ledstate & trigger->mask ? + LED_FULL : LED_OFF); + tasklet_enable(&keyboard_tasklet); +} + +#define KBD_LED_TRIGGER(_led_bit, _name) { \ + .trigger = { \ + .name = _name, \ + .activate = kbd_led_trigger_activate, \ + }, \ + .mask = BIT(_led_bit), \ + } + +static struct kbd_led_trigger kbd_led_triggers[] = { + KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrollock"), + KBD_LED_TRIGGER(VC_NUMLOCK, "kbd-numlock"), + KBD_LED_TRIGGER(VC_CAPSLOCK, "kbd-capslock"), + KBD_LED_TRIGGER(VC_KANALOCK, "kbd-kanalock"), +}; + +static void kbd_propagate_led_state(unsigned int old_state, + unsigned int new_state) +{ + struct kbd_led_trigger *trigger; + unsigned int changed = old_state ^ new_state; + int i; + + for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); i++) { + trigger = &kbd_led_triggers[i]; + + if (changed & trigger->mask) + led_trigger_event(&trigger->trigger, + new_state & trigger->mask ? + LED_FULL : LED_OFF); + } +} + +static int kbd_update_leds_helper(struct input_handle *handle, void *data) +{ + unsigned int led_state = *(unsigned int *)data; + + if (test_bit(EV_LED, handle->dev->evbit)) + kbd_propagate_led_state(~led_state, led_state); + + return 0; +} + +static void kbd_init_leds(void) +{ + int error; + int i; + + for (i = 0; i < ARRAY_SIZE(kbd_led_triggers); i++) { + error = led_trigger_register(&kbd_led_triggers[i].trigger); + if (error) + pr_err("error %d while registering trigger %s\n", + error, kbd_led_triggers[i].trigger.name); + } +} + +#else + +static int kbd_update_leds_helper(struct input_handle *handle, void *data) +{ + unsigned int leds = *(unsigned int *)data; + + if (test_bit(EV_LED, handle->dev->evbit)) { + input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01)); + input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02)); + input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04)); + input_inject_event(handle, EV_SYN, SYN_REPORT, 0); + } + + return 0; +} + +static void kbd_propagate_led_state(unsigned int old_state, + unsigned int new_state) +{ + input_handler_for_each_handle(&kbd_handler, &new_state, + kbd_update_leds_helper); +} + +static void kbd_init_leds(void) +{ +} + +#endif + /* * The leds display either (i) the status of NumLock, CapsLock, ScrollLock, * or (ii) whatever pattern of lights people want to show using KDSETLED, @@ -995,20 +1100,6 @@ static inline unsigned char getleds(void) return kb->ledflagstate; } -static int kbd_update_leds_helper(struct input_handle *handle, void *data) -{ - unsigned char leds = *(unsigned char *)data; - - if (test_bit(EV_LED, handle->dev->evbit)) { - input_inject_event(handle, EV_LED, LED_SCROLLL, !!(leds & 0x01)); - input_inject_event(handle, EV_LED, LED_NUML, !!(leds & 0x02)); - input_inject_event(handle, EV_LED, LED_CAPSL, !!(leds & 0x04)); - input_inject_event(handle, EV_SYN, SYN_REPORT, 0); - } - - return 0; -} - /** * vt_get_leds - helper for braille console * @console: console to read @@ -1085,24 +1176,22 @@ void vt_kbd_con_stop(int console) } /* - * This is the tasklet that updates LED state on all keyboards - * attached to the box. The reason we use tasklet is that we - * need to handle the scenario when keyboard handler is not - * registered yet but we already getting updates from the VT to - * update led state. + * This is the tasklet that updates LED state of LEDs using standard + * keyboard triggers. The reason we use tasklet is that we need to + * handle the scenario when keyboard handler is not registered yet + * but we already getting updates from the VT to update led state. */ static void kbd_bh(unsigned long dummy) { unsigned char leds; unsigned long flags; - + spin_lock_irqsave(&led_lock, flags); leds = getleds(); spin_unlock_irqrestore(&led_lock, flags); if (leds != ledstate) { - input_handler_for_each_handle(&kbd_handler, &leds, - kbd_update_leds_helper); + kbd_propagate_led_state(ledstate, leds); ledstate = leds; } } @@ -1450,8 +1539,10 @@ static void kbd_start(struct input_handle *handle) { tasklet_disable(&keyboard_tasklet); - if (ledstate != 0xff) - kbd_update_leds_helper(handle, &ledstate); + if (ledstate != 0xff) { + unsigned int state = ledstate; + kbd_update_leds_helper(handle, &state); + } tasklet_enable(&keyboard_tasklet); } @@ -1497,6 +1588,8 @@ int __init kbd_init(void) kbd_table[i].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE; } + kbd_init_leds(); + error = input_register_handler(&kbd_handler); if (error) return error; -- cgit v1.2.3 From eeb64c14275e52740d6410632e62e0ad9b88ca70 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 6 Jun 2015 11:44:39 -0700 Subject: 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 Tested-by: Pavel Machek Acked-by: Pavel Machek Signed-off-by: Dmitry Torokhov --- drivers/tty/vt/keyboard.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'drivers/tty') 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 */ static int shift_state = 0; -static unsigned char ledstate = 0xff; /* undefined */ +static unsigned int ledstate = -1U; /* undefined */ static unsigned char ledioctl; /* @@ -975,7 +975,7 @@ static void kbd_led_trigger_activate(struct led_classdev *cdev) container_of(cdev->trigger, struct kbd_led_trigger, trigger); tasklet_disable(&keyboard_tasklet); - if (ledstate != 0xff) + if (ledstate != -1U) led_trigger_event(&trigger->trigger, ledstate & trigger->mask ? LED_FULL : LED_OFF); @@ -990,11 +990,23 @@ static void kbd_led_trigger_activate(struct led_classdev *cdev) .mask = BIT(_led_bit), \ } +#define KBD_LOCKSTATE_TRIGGER(_led_bit, _name) \ + KBD_LED_TRIGGER((_led_bit) + 8, _name) + static struct kbd_led_trigger kbd_led_triggers[] = { KBD_LED_TRIGGER(VC_SCROLLOCK, "kbd-scrollock"), KBD_LED_TRIGGER(VC_NUMLOCK, "kbd-numlock"), KBD_LED_TRIGGER(VC_CAPSLOCK, "kbd-capslock"), KBD_LED_TRIGGER(VC_KANALOCK, "kbd-kanalock"), + + KBD_LOCKSTATE_TRIGGER(VC_SHIFTLOCK, "kbd-shiftlock"), + KBD_LOCKSTATE_TRIGGER(VC_ALTGRLOCK, "kbd-altgrlock"), + KBD_LOCKSTATE_TRIGGER(VC_CTRLLOCK, "kbd-ctrllock"), + KBD_LOCKSTATE_TRIGGER(VC_ALTLOCK, "kbd-altlock"), + KBD_LOCKSTATE_TRIGGER(VC_SHIFTLLOCK, "kbd-shiftllock"), + KBD_LOCKSTATE_TRIGGER(VC_SHIFTRLOCK, "kbd-shiftrlock"), + KBD_LOCKSTATE_TRIGGER(VC_CTRLLLOCK, "kbd-ctrlllock"), + KBD_LOCKSTATE_TRIGGER(VC_CTRLRLOCK, "kbd-ctrlrlock"), }; static void kbd_propagate_led_state(unsigned int old_state, @@ -1073,7 +1085,7 @@ static void kbd_init_leds(void) */ static unsigned char getledstate(void) { - return ledstate; + return ledstate & 0xff; } void setledstate(struct kbd_struct *kb, unsigned int led) @@ -1183,11 +1195,12 @@ void vt_kbd_con_stop(int console) */ static void kbd_bh(unsigned long dummy) { - unsigned char leds; + unsigned int leds; unsigned long flags; spin_lock_irqsave(&led_lock, flags); leds = getleds(); + leds |= (unsigned int)kbd->lockstate << 8; spin_unlock_irqrestore(&led_lock, flags); if (leds != ledstate) { @@ -1539,10 +1552,8 @@ static void kbd_start(struct input_handle *handle) { tasklet_disable(&keyboard_tasklet); - if (ledstate != 0xff) { - unsigned int state = ledstate; - kbd_update_leds_helper(handle, &state); - } + if (ledstate != -1U) + kbd_update_leds_helper(handle, &ledstate); tasklet_enable(&keyboard_tasklet); } -- cgit v1.2.3