linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] input&tty: Fix the keyboard led light display problem
@ 2021-10-15  1:20 lianzhi chang
  0 siblings, 0 replies; 19+ messages in thread
From: lianzhi chang @ 2021-10-15  1:20 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-input, lianzhi chang

Switching from the desktop environment to the tty environment,
the state of the keyboard led lights and the state of the keyboard
lock are inconsistent. This is because the attribute kb->kbdmode
of the tty bound in the desktop environment (xorg) is set to
VC_OFF, which causes the ledstate and kb->ledflagstate
values of the bound tty to always be 0, which causes the switch
from the desktop When to the tty environment, the LED light
status is inconsistent with the keyboard lock status.

Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
---
 drivers/input/input.c     |  7 ++++++-
 drivers/tty/vt/keyboard.c | 30 +++++++++++++++++++++++++++++-
 include/linux/kbd_kern.h  |  2 ++
 3 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index ccaeb2426385..43c09700bf68 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -25,6 +25,7 @@
 #include <linux/rcupdate.h>
 #include "input-compat.h"
 #include "input-poller.h"
+#include <linux/kbd_kern.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("Input core");
@@ -472,8 +473,12 @@ void input_inject_event(struct input_handle *handle,
 
 		rcu_read_lock();
 		grab = rcu_dereference(dev->grab);
-		if (!grab || grab == handle)
+		if (!grab || grab == handle) {
 			input_handle_event(dev, type, code, value);
+
+			if (type == EV_LED && code < LED_SCROLLL)
+				update_value_ledstate(code, value);
+		}
 		rcu_read_unlock();
 
 		spin_unlock_irqrestore(&dev->event_lock, flags);
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index c7fbbcdcc346..0240915cdfef 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -1140,6 +1140,31 @@ static unsigned char getledstate(void)
 	return ledstate & 0xff;
 }
 
+void update_value_ledstate(unsigned int flag, unsigned int value)
+{
+	unsigned int bit;
+
+	switch (flag) {
+	case LED_NUML:
+		bit = VC_NUMLOCK;
+		break;
+	case LED_CAPSL:
+		bit = VC_CAPSLOCK;
+		break;
+	case LED_SCROLLL:
+		bit = VC_SCROLLOCK;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	if (value)
+		ledstate |= BIT(bit);
+	else
+		ledstate &= ~BIT(bit);
+}
+
 void setledstate(struct kbd_struct *kb, unsigned int led)
 {
         unsigned long flags;
@@ -1249,6 +1274,10 @@ static void kbd_bh(struct tasklet_struct *unused)
 {
 	unsigned int leds;
 	unsigned long flags;
+	struct kbd_struct *kb = kbd_table + fg_console;
+
+	if (kb->kbdmode == VC_OFF)
+		return;
 
 	spin_lock_irqsave(&led_lock, flags);
 	leds = getleds();
@@ -1257,7 +1286,6 @@ static void kbd_bh(struct tasklet_struct *unused)
 
 	if (leds != ledstate) {
 		kbd_propagate_led_state(ledstate, leds);
-		ledstate = leds;
 	}
 }
 
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index c40811d79769..36a3402658e6 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -62,6 +62,8 @@ extern int kbd_init(void);
 
 extern void setledstate(struct kbd_struct *kbd, unsigned int led);
 
+extern void update_value_ledstate(int flag, int value);
+
 extern int do_poke_blanked_console;
 
 extern void (*kbd_ledfunc)(unsigned int led);
-- 
2.20.1

Dear friends, because the email I send to linux-kernel@vger.kernel.org 
will always fail many times, in order not to harass you, the latest 
information may not be synchronized with you. For the previous problem, 
I will resend it again. And respond to the previous questions:

@Jiri Slaby <jirislaby@kernel.org>
(1)
> +            if (type == EV_LED && code < 3)
>
> 3 is a magic constant. In fact, you mean "code <= LED_SCROLLL", right?

> > Yes, that's it.I have corrected it.
(2)
>   +void update_value_ledstate(int flag, int value)
>
> Why is the int signed?

> >I will correct it, it's my mistake

(3)
> +{
> +    if (ledstate == -1U)
> +        ledstate = 0;
> +
> +    if (flag == LED_NUML) {
> +        ledstate &= ~(1 << 1);

> ledstate &= ~BIT(VC_NUMLOCK);
>
> +        ledstate |= value << 1;
>
>What ensures that value is 0 or 1 here?

> >The original code here is like this, there is no guarantee that the
> >value passed down is 0 or 1, I need to think about how to do it!

(4)
> What about something like this (maybe ifs would be shorter, dunno, try
> it):
> unsigned int bit;
>
> switch (flag) {
> case LED_NUML:
>   bit = VC_NUMLOCK;
>   break;
> case LED_CAPSL:
>   bit = VC_CAPSLOCK;
>   break;
> case LED_SCROLLL:
>   bit = VC_SCROLLOCK;
>   break;
> default:
>   WARN_ON_ONCE(1);
>   return;
> }
>
> if (value)
>   ledstate |= BIT(bit);
> else
>   ledstate &= ~BIT(BIT);

>>This way the intention is clearer, I also considered how to optimize
>>here, your code is better than mine!

(5)
> Can you explain why (not to me, to the commit log)?
>
>       spin_lock_irqsave(&led_lock, flags);
>       leds = getleds();
> @@ -1257,7 +1278,6 @@ static void kbd_bh(struct tasklet_struct *unused)
>         if (leds != ledstate) {
>           kbd_propagate_led_state(ledstate, leds);
> -        ledstate = leds;
>
> The same here. Why this doesn't break the current behaviour.

>>Assuming that the desktop environment (xorg) occupies tty1,
>> kb->kbdmode of tty1 will be set to VC_OFF. According to the code logic
>> before modification, problems will occur:
>>1) The ledstate and kb->ledflagstate in the tty1 environment are
>always 0 and will not be modified.
>>2) At this time, if ledstate is not 0 in the tty2 environment,
>>switch from tty2 to tty1 (desktop environment). According to the code
>> logic of kbd_event (tasklet_schedule(&keyboard_tasklet), the code
>> execution enters the kbd_bh() function, at this time tty1 Will go to
>> set the keyboard state to 0. At this time, the keyboard setting state
>> of xorg may not be like this.


@Andy Shevchenko<andriy.shevchenko@linux.intel.com>
(1)
> + if (value)
> + ledstate |= BIT(bit);
> + else
> + ledstate &= ~BIT(BIT);

>NIH assign_bit().

>On top of that, what is BIT as parameter does in the else branch? Have you
>compiled this?

>>This is an error and has been corrected.
(2)
>  extern void setledstate(struct kbd_struct *kbd, unsigned int led);

>

>Not sure if wee need this blank line, since both functions are from the same
>(functional) group.

> +extern void update_value_ledstate(int flag, int value);

>>I don't understand what you mean here. Isn't there a blank line between all function declarations?

(3)
> + unsigned int bit;
unsigned long bit;
(see below why)
>>Why is unsigned long bit??

@Dmitry Torokhov <dmitry.torokhov@gmail.com> 
>No, we should not be putting hooks for tty/vt directly into input core.
>The code in drivers/tty/vt/keyboard.c is getting all relevant input
>events and should be able to keep the led state synchronized. Please
>keep all the changes localized there.

>>Although driver/tty/vt/keyboard.c is acquiring all related input events, 
>>the related operations of the input_inject_event function should be passed to 
>>the keyboard driver, right? After input_inject_event is completed, can 
>>kbd_event still get the corresponding change event?

>>I think it is possible to put the ledstate variable and the update_value_ledstate function into the input module, and add a new function for keyboard.c to call (for example: get_kbd_ledstate), so that keyboard.c can get the value of ledstate. Is this okay?

---
Thank you very much for your hard work!!
lianzhi chang



^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH] input&tty: Fix the keyboard led light display problem
       [not found] <35696980-2a55-c5c1-3fa9-eadf251dcdde@uniontech.com>
@ 2021-10-15 13:06 ` Andy Shevchenko
  0 siblings, 0 replies; 19+ messages in thread
From: Andy Shevchenko @ 2021-10-15 13:06 UTC (permalink / raw)
  To: changlianzhi
  Cc: linux-kernel, dmitry.torokhov, gregkh, jirislaby, linux-input, 282827961

On Fri, Oct 15, 2021 at 04:16:35PM +0800, changlianzhi wrote:
> Switching from the desktop environment to the tty environment,
> the state of the keyboard led lights and the state of the keyboard
> lock are inconsistent. This is because the attribute kb->kbdmode
> of the tty bound in the desktop environment (xorg) is set to
> VC_OFF, which causes the ledstate and kb->ledflagstate
> values of the bound tty to always be 0, which causes the switch
> from the desktop When to the tty environment, the LED light
> status is inconsistent with the keyboard lock status.

Have you even read what others tell you?!

If you continue this way, I think it will be guaranteed that your email
ends up in a ban list.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] input&tty: Fix the keyboard led light display problem
       [not found]   ` <616942b2.1c69fb81.dfbff.25afSMTPIN_ADDED_BROKEN@mx.google.com>
@ 2021-10-15 10:16     ` Greg KH
  0 siblings, 0 replies; 19+ messages in thread
From: Greg KH @ 2021-10-15 10:16 UTC (permalink / raw)
  To: changlianzhi
  Cc: linux-kernel, dmitry.torokhov, jirislaby, andriy.shevchenko,
	linux-input, 282827961

On Fri, Oct 15, 2021 at 04:57:17PM +0800, changlianzhi wrote:
> 
> On 2021/10/15 下午4:41, Greg KH wrote:
> > On Fri, Oct 15, 2021 at 04:36:13PM +0800, lianzhi chang wrote:
> > > Switching from the desktop environment to the tty environment,
> > > the state of the keyboard led lights and the state of the keyboard
> > > lock are inconsistent. This is because the attribute kb->kbdmode
> > > of the tty bound in the desktop environment (xorg) is set to
> > > VC_OFF, which causes the ledstate and kb->ledflagstate
> > > values of the bound tty to always be 0, which causes the switch
> > > from the desktop When to the tty environment, the LED light
> > > status is inconsistent with the keyboard lock status.
> > > 
> > > Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
> > > ---
> > > The latest changes:
> > > (1) Move the definition of ledstate to the input module (/drivers/input/input.c),
> > > and set or get its value through the input_update_ledstate and input_get_ledstate
> > > functions.
> > > (2) To update the ledstate reference in keyboard.c, you must first get the value
> > > through input_get_ledstate.
> > > (3) Other necessary changes
> > You have not changed the subject line at all.
> > 
> > Look at how others submit patches that are new versions on the mailing
> > list, and most importantly, read the documentation we have about this.
> > 
> > thanks,
> > 
> > greg k-h
> 
> 
> Sorry, because the emails I send using the mail client are always bounced
> back, I can only use git send-email to send emails. Haven't found a way to
> modify the theme. very sorry.

git send-email works just for for v2 and so on, it will send whatever
you make the patch text file to look like.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] input&tty: Fix the keyboard led light display problem
       [not found] <20211015083613.7429-1-changlianzhi@uniontech.com>
@ 2021-10-15  8:41 ` Greg KH
       [not found]   ` <616942b2.1c69fb81.dfbff.25afSMTPIN_ADDED_BROKEN@mx.google.com>
  0 siblings, 1 reply; 19+ messages in thread
From: Greg KH @ 2021-10-15  8:41 UTC (permalink / raw)
  To: lianzhi chang
  Cc: linux-kernel, dmitry.torokhov, jirislaby, andriy.shevchenko,
	linux-input, 282827961

On Fri, Oct 15, 2021 at 04:36:13PM +0800, lianzhi chang wrote:
> Switching from the desktop environment to the tty environment,
> the state of the keyboard led lights and the state of the keyboard
> lock are inconsistent. This is because the attribute kb->kbdmode
> of the tty bound in the desktop environment (xorg) is set to
> VC_OFF, which causes the ledstate and kb->ledflagstate
> values of the bound tty to always be 0, which causes the switch
> from the desktop When to the tty environment, the LED light
> status is inconsistent with the keyboard lock status.
> 
> Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
> ---
> The latest changes:
> (1) Move the definition of ledstate to the input module (/drivers/input/input.c), 
> and set or get its value through the input_update_ledstate and input_get_ledstate 
> functions.
> (2) To update the ledstate reference in keyboard.c, you must first get the value 
> through input_get_ledstate.
> (3) Other necessary changes

You have not changed the subject line at all.

Look at how others submit patches that are new versions on the mailing
list, and most importantly, read the documentation we have about this.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH] input&tty: Fix the keyboard led light display problem
@ 2021-10-15  8:37 lianzhi chang
  0 siblings, 0 replies; 19+ messages in thread
From: lianzhi chang @ 2021-10-15  8:37 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-input, lianzhi chang

Switching from the desktop environment to the tty environment,
the state of the keyboard led lights and the state of the keyboard
lock are inconsistent. This is because the attribute kb->kbdmode
of the tty bound in the desktop environment (xorg) is set to
VC_OFF, which causes the ledstate and kb->ledflagstate
values of the bound tty to always be 0, which causes the switch
from the desktop When to the tty environment, the LED light
status is inconsistent with the keyboard lock status.

Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
---
The latest changes:
(1) Move the definition of ledstate to the input module (/drivers/input/input.c), 
and set or get its value through the input_update_ledstate and input_get_ledstate 
functions.
(2) To update the ledstate reference in keyboard.c, you must first get the value 
through input_get_ledstate.
(3) Other necessary changes

 drivers/input/input.c     | 46 ++++++++++++++++++++++++++++++++++++++-
 drivers/tty/vt/keyboard.c | 19 ++++++++++++++--
 include/linux/input.h     |  3 +++
 3 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index ccaeb2426385..8c0ef947ac34 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -37,6 +37,11 @@ static DEFINE_IDA(input_ida);
 static LIST_HEAD(input_dev_list);
 static LIST_HEAD(input_handler_list);
 
+#define VC_SCROLLOCK	0	/* scroll-lock mode */
+#define VC_NUMLOCK	1	/* numeric lock mode */
+#define VC_CAPSLOCK	2	/* capslock mode */
+static unsigned int ledstate = -1U;			/* undefined */
+
 /*
  * input_mutex protects access to both input_dev_list and input_handler_list.
  * This also causes input_[un]register_device and input_[un]register_handler
@@ -472,8 +477,12 @@ void input_inject_event(struct input_handle *handle,
 
 		rcu_read_lock();
 		grab = rcu_dereference(dev->grab);
-		if (!grab || grab == handle)
+		if (!grab || grab == handle) {
 			input_handle_event(dev, type, code, value);
+
+			if (type == EV_LED && code <= LED_SCROLLL)
+				input_update_ledstate(code, value);
+		}
 		rcu_read_unlock();
 
 		spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -481,6 +490,41 @@ void input_inject_event(struct input_handle *handle,
 }
 EXPORT_SYMBOL(input_inject_event);
 
+void input_update_ledstate(unsigned int flag, unsigned int value)
+{
+	unsigned int bit;
+
+	switch (flag) {
+	case LED_NUML:
+		bit = VC_NUMLOCK;
+		break;
+	case LED_CAPSL:
+		bit = VC_CAPSLOCK;
+		break;
+	case LED_SCROLLL:
+		bit = VC_SCROLLOCK;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	if (ledstate == -1U)
+		ledstate = 0;
+
+	if (value)
+		ledstate |= BIT(bit);
+	else
+		ledstate &= ~BIT(bit);
+}
+EXPORT_SYMBOL(input_update_ledstate);
+
+unsigned int input_get_ledstate(void)
+{
+	return ledstate;
+}
+EXPORT_SYMBOL(input_get_ledstate);
+
 /**
  * input_alloc_absinfo - allocates array of input_absinfo structs
  * @dev: the input device emitting absolute events
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index c7fbbcdcc346..0cfccb1d7992 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -151,7 +151,6 @@ static bool rep;			/* flag telling character repeat */
 
 static int shift_state = 0;
 
-static unsigned int ledstate = -1U;			/* undefined */
 static unsigned char ledioctl;
 
 /*
@@ -1021,10 +1020,14 @@ struct kbd_led_trigger {
 
 static int kbd_led_trigger_activate(struct led_classdev *cdev)
 {
+	unsigned int ledstate;
+
 	struct kbd_led_trigger *trigger =
 		container_of(cdev->trigger, struct kbd_led_trigger, trigger);
 
 	tasklet_disable(&keyboard_tasklet);
+
+	ledstate = input_get_ledstate();
 	if (ledstate != -1U)
 		led_trigger_event(&trigger->trigger,
 				  ledstate & trigger->mask ?
@@ -1137,6 +1140,10 @@ static void kbd_init_leds(void)
  */
 static unsigned char getledstate(void)
 {
+	unsigned int ledstate;
+
+	ledstate = input_get_ledstate();
+
 	return ledstate & 0xff;
 }
 
@@ -1248,16 +1255,21 @@ void vt_kbd_con_stop(unsigned int console)
 static void kbd_bh(struct tasklet_struct *unused)
 {
 	unsigned int leds;
+	unsigned int ledstate;
 	unsigned long flags;
+	struct kbd_struct *kb = kbd_table + fg_console;
+
+	if (kb->kbdmode == VC_OFF)
+		return;
 
 	spin_lock_irqsave(&led_lock, flags);
 	leds = getleds();
+	ledstate = input_get_ledstate();
 	leds |= (unsigned int)kbd->lockstate << 8;
 	spin_unlock_irqrestore(&led_lock, flags);
 
 	if (leds != ledstate) {
 		kbd_propagate_led_state(ledstate, leds);
-		ledstate = leds;
 	}
 }
 
@@ -1604,8 +1616,11 @@ static void kbd_disconnect(struct input_handle *handle)
  */
 static void kbd_start(struct input_handle *handle)
 {
+	unsigned int ledstate;
+
 	tasklet_disable(&keyboard_tasklet);
 
+	ledstate = input_get_ledstate();
 	if (ledstate != -1U)
 		kbd_update_leds_helper(handle, &ledstate);
 
diff --git a/include/linux/input.h b/include/linux/input.h
index 0354b298d874..0e0ba53a9cc7 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -420,6 +420,9 @@ ktime_t *input_get_timestamp(struct input_dev *dev);
 void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
 void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value);
 
+void input_update_ledstate(unsigned int flag, unsigned int value);
+unsigned int input_get_ledstate(void);
+
 static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
 {
 	input_event(dev, EV_KEY, code, !!value);
-- 
2.20.1




^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH] input&tty: Fix the keyboard led light display problem
       [not found] <61693925.1c69fb81.a058.27f2SMTPIN_ADDED_BROKEN@mx.google.com>
@ 2021-10-15  8:25 ` Greg KH
  0 siblings, 0 replies; 19+ messages in thread
From: Greg KH @ 2021-10-15  8:25 UTC (permalink / raw)
  To: changlianzhi
  Cc: linux-kernel, dmitry.torokhov, jirislaby, andriy.shevchenko,
	linux-input, 282827961

On Fri, Oct 15, 2021 at 04:16:35PM +0800, changlianzhi wrote:
> Switching from the desktop environment to the tty environment,
> the state of the keyboard led lights and the state of the keyboard
> lock are inconsistent. This is because the attribute kb->kbdmode
> of the tty bound in the desktop environment (xorg) is set to
> VC_OFF, which causes the ledstate and kb->ledflagstate
> values of the bound tty to always be 0, which causes the switch
> from the desktop When to the tty environment, the LED light
> status is inconsistent with the keyboard lock status.
> 
> Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
> ---
> drivers/input/input.c | 46 ++++++++++++++++++++++++++++++++++++++-
> drivers/tty/vt/keyboard.c | 19 ++++++++++++++--
> include/linux/input.h | 3 +++
> 3 files changed, 65 insertions(+), 3 deletions(-)

Hi,

This is the friendly patch-bot of Greg Kroah-Hartman.  You have sent him
a patch that has triggered this response.  He used to manually respond
to these common problems, but in order to save his sanity (he kept
writing the same thing over and over, yet to different people), I was
created.  Hopefully you will not take offence and will fix the problem
in your patch and resubmit it so that it can be accepted into the Linux
kernel tree.

You are receiving this message because of the following common error(s)
as indicated below:

- Your patch is malformed (tabs converted to spaces, linewrapped, etc.)
  and can not be applied.  Please read the file,
  Documentation/email-clients.txt in order to fix this.

- This looks like a new version of a previously submitted patch, but you
  did not list below the --- line any changes from the previous version.
  Please read the section entitled "The canonical patch format" in the
  kernel file, Documentation/SubmittingPatches for what needs to be done
  here to properly describe this.

If you wish to discuss this problem further, or you have questions about
how to resolve this issue, please feel free to respond to this email and
Greg will reply once he has dug out from the pending patches received
from other developers.

thanks,

greg k-h's patch email bot

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] input&tty: Fix the keyboard led light display problem
       [not found]   ` <616934f3.1c69fb81.59ff6.49d9SMTPIN_ADDED_BROKEN@mx.google.com>
@ 2021-10-15  8:04     ` Greg KH
  0 siblings, 0 replies; 19+ messages in thread
From: Greg KH @ 2021-10-15  8:04 UTC (permalink / raw)
  To: changlianzhi
  Cc: linux-kernel, dmitry.torokhov, jirislaby, andriy.shevchenko,
	linux-input, 282827961

On Fri, Oct 15, 2021 at 03:59:38PM +0800, changlianzhi wrote:
> 
> On 2021/10/15 下午2:52, Greg KH wrote:
> > On Fri, Oct 15, 2021 at 02:45:34PM +0800, lianzhi chang wrote:
> > > Switching from the desktop environment to the tty environment,
> > > the state of the keyboard led lights and the state of the keyboard
> > > lock are inconsistent. This is because the attribute kb->kbdmode
> > > of the tty bound in the desktop environment (xorg) is set to
> > > VC_OFF, which causes the ledstate and kb->ledflagstate
> > > values of the bound tty to always be 0, which causes the switch
> > > from the desktop When to the tty environment, the LED light
> > > status is inconsistent with the keyboard lock status.
> > > 
> > > Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
> > > ---
> > >   drivers/input/input.c     | 46 ++++++++++++++++++++++++++++++++++++++-
> > >   drivers/tty/vt/keyboard.c | 19 ++++++++++++++--
> > >   include/linux/input.h     |  3 +++
> > >   3 files changed, 65 insertions(+), 3 deletions(-)
> > Hi,
> > 
> > This is the friendly patch-bot of Greg Kroah-Hartman.  You have sent him
> > a patch that has triggered this response.  He used to manually respond
> > to these common problems, but in order to save his sanity (he kept
> > writing the same thing over and over, yet to different people), I was
> > created.  Hopefully you will not take offence and will fix the problem
> > in your patch and resubmit it so that it can be accepted into the Linux
> > kernel tree.
> > 
> > You are receiving this message because of the following common error(s)
> > as indicated below:
> > 
> > - This looks like a new version of a previously submitted patch, but you
> >    did not list below the --- line any changes from the previous version.
> >    Please read the section entitled "The canonical patch format" in the
> >    kernel file, Documentation/SubmittingPatches for what needs to be done
> >    here to properly describe this.
> > 
> > If you wish to discuss this problem further, or you have questions about
> > how to resolve this issue, please feel free to respond to this email and
> > Greg will reply once he has dug out from the pending patches received
> > from other developers.
> > 
> > thanks,
> > 
> > greg k-h's patch email bot
> > 
> 
> >>The latest changes:
> >>(1) Move the definition of ledstate to the input module
> (/drivers/input/input.c), and set or get its value through the
> input_update_ledstate and input_get_ledstate functions.
> >>(2) To update the ledstate reference in keyboard.c, you must first get the
> value through input_get_ledstate.
> >>(3) Other necessary changes

I do not want to see this here, it needs to go into the patch you submit
as the documentation says to.  Read the link that the bot pointed you at
above please...

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] input&tty: Fix the keyboard led light display problem
  2021-10-15  6:45 lianzhi chang
@ 2021-10-15  6:52 ` Greg KH
       [not found]   ` <616934f3.1c69fb81.59ff6.49d9SMTPIN_ADDED_BROKEN@mx.google.com>
  0 siblings, 1 reply; 19+ messages in thread
From: Greg KH @ 2021-10-15  6:52 UTC (permalink / raw)
  To: lianzhi chang
  Cc: linux-kernel, dmitry.torokhov, jirislaby, andriy.shevchenko,
	linux-input, 282827961

On Fri, Oct 15, 2021 at 02:45:34PM +0800, lianzhi chang wrote:
> Switching from the desktop environment to the tty environment,
> the state of the keyboard led lights and the state of the keyboard
> lock are inconsistent. This is because the attribute kb->kbdmode
> of the tty bound in the desktop environment (xorg) is set to
> VC_OFF, which causes the ledstate and kb->ledflagstate
> values of the bound tty to always be 0, which causes the switch
> from the desktop When to the tty environment, the LED light
> status is inconsistent with the keyboard lock status.
> 
> Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
> ---
>  drivers/input/input.c     | 46 ++++++++++++++++++++++++++++++++++++++-
>  drivers/tty/vt/keyboard.c | 19 ++++++++++++++--
>  include/linux/input.h     |  3 +++
>  3 files changed, 65 insertions(+), 3 deletions(-)

Hi,

This is the friendly patch-bot of Greg Kroah-Hartman.  You have sent him
a patch that has triggered this response.  He used to manually respond
to these common problems, but in order to save his sanity (he kept
writing the same thing over and over, yet to different people), I was
created.  Hopefully you will not take offence and will fix the problem
in your patch and resubmit it so that it can be accepted into the Linux
kernel tree.

You are receiving this message because of the following common error(s)
as indicated below:

- This looks like a new version of a previously submitted patch, but you
  did not list below the --- line any changes from the previous version.
  Please read the section entitled "The canonical patch format" in the
  kernel file, Documentation/SubmittingPatches for what needs to be done
  here to properly describe this.

If you wish to discuss this problem further, or you have questions about
how to resolve this issue, please feel free to respond to this email and
Greg will reply once he has dug out from the pending patches received
from other developers.

thanks,

greg k-h's patch email bot

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH] input&tty: Fix the keyboard led light display problem
@ 2021-10-15  6:45 lianzhi chang
  2021-10-15  6:52 ` Greg KH
  0 siblings, 1 reply; 19+ messages in thread
From: lianzhi chang @ 2021-10-15  6:45 UTC (permalink / raw)
  To: linux-kernel
  Cc: dmitry.torokhov, gregkh, jirislaby, andriy.shevchenko,
	linux-input, 282827961, lianzhi chang

Switching from the desktop environment to the tty environment,
the state of the keyboard led lights and the state of the keyboard
lock are inconsistent. This is because the attribute kb->kbdmode
of the tty bound in the desktop environment (xorg) is set to
VC_OFF, which causes the ledstate and kb->ledflagstate
values of the bound tty to always be 0, which causes the switch
from the desktop When to the tty environment, the LED light
status is inconsistent with the keyboard lock status.

Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
---
 drivers/input/input.c     | 46 ++++++++++++++++++++++++++++++++++++++-
 drivers/tty/vt/keyboard.c | 19 ++++++++++++++--
 include/linux/input.h     |  3 +++
 3 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index ccaeb2426385..8c0ef947ac34 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -37,6 +37,11 @@ static DEFINE_IDA(input_ida);
 static LIST_HEAD(input_dev_list);
 static LIST_HEAD(input_handler_list);
 
+#define VC_SCROLLOCK	0	/* scroll-lock mode */
+#define VC_NUMLOCK	1	/* numeric lock mode */
+#define VC_CAPSLOCK	2	/* capslock mode */
+static unsigned int ledstate = -1U;			/* undefined */
+
 /*
  * input_mutex protects access to both input_dev_list and input_handler_list.
  * This also causes input_[un]register_device and input_[un]register_handler
@@ -472,8 +477,12 @@ void input_inject_event(struct input_handle *handle,
 
 		rcu_read_lock();
 		grab = rcu_dereference(dev->grab);
-		if (!grab || grab == handle)
+		if (!grab || grab == handle) {
 			input_handle_event(dev, type, code, value);
+
+			if (type == EV_LED && code <= LED_SCROLLL)
+				input_update_ledstate(code, value);
+		}
 		rcu_read_unlock();
 
 		spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -481,6 +490,41 @@ void input_inject_event(struct input_handle *handle,
 }
 EXPORT_SYMBOL(input_inject_event);
 
+void input_update_ledstate(unsigned int flag, unsigned int value)
+{
+	unsigned int bit;
+
+	switch (flag) {
+	case LED_NUML:
+		bit = VC_NUMLOCK;
+		break;
+	case LED_CAPSL:
+		bit = VC_CAPSLOCK;
+		break;
+	case LED_SCROLLL:
+		bit = VC_SCROLLOCK;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	if (ledstate == -1U)
+		ledstate = 0;
+
+	if (value)
+		ledstate |= BIT(bit);
+	else
+		ledstate &= ~BIT(bit);
+}
+EXPORT_SYMBOL(input_update_ledstate);
+
+unsigned int input_get_ledstate(void)
+{
+	return ledstate;
+}
+EXPORT_SYMBOL(input_get_ledstate);
+
 /**
  * input_alloc_absinfo - allocates array of input_absinfo structs
  * @dev: the input device emitting absolute events
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index c7fbbcdcc346..0cfccb1d7992 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -151,7 +151,6 @@ static bool rep;			/* flag telling character repeat */
 
 static int shift_state = 0;
 
-static unsigned int ledstate = -1U;			/* undefined */
 static unsigned char ledioctl;
 
 /*
@@ -1021,10 +1020,14 @@ struct kbd_led_trigger {
 
 static int kbd_led_trigger_activate(struct led_classdev *cdev)
 {
+	unsigned int ledstate;
+
 	struct kbd_led_trigger *trigger =
 		container_of(cdev->trigger, struct kbd_led_trigger, trigger);
 
 	tasklet_disable(&keyboard_tasklet);
+
+	ledstate = input_get_ledstate();
 	if (ledstate != -1U)
 		led_trigger_event(&trigger->trigger,
 				  ledstate & trigger->mask ?
@@ -1137,6 +1140,10 @@ static void kbd_init_leds(void)
  */
 static unsigned char getledstate(void)
 {
+	unsigned int ledstate;
+
+	ledstate = input_get_ledstate();
+
 	return ledstate & 0xff;
 }
 
@@ -1248,16 +1255,21 @@ void vt_kbd_con_stop(unsigned int console)
 static void kbd_bh(struct tasklet_struct *unused)
 {
 	unsigned int leds;
+	unsigned int ledstate;
 	unsigned long flags;
+	struct kbd_struct *kb = kbd_table + fg_console;
+
+	if (kb->kbdmode == VC_OFF)
+		return;
 
 	spin_lock_irqsave(&led_lock, flags);
 	leds = getleds();
+	ledstate = input_get_ledstate();
 	leds |= (unsigned int)kbd->lockstate << 8;
 	spin_unlock_irqrestore(&led_lock, flags);
 
 	if (leds != ledstate) {
 		kbd_propagate_led_state(ledstate, leds);
-		ledstate = leds;
 	}
 }
 
@@ -1604,8 +1616,11 @@ static void kbd_disconnect(struct input_handle *handle)
  */
 static void kbd_start(struct input_handle *handle)
 {
+	unsigned int ledstate;
+
 	tasklet_disable(&keyboard_tasklet);
 
+	ledstate = input_get_ledstate();
 	if (ledstate != -1U)
 		kbd_update_leds_helper(handle, &ledstate);
 
diff --git a/include/linux/input.h b/include/linux/input.h
index 0354b298d874..0e0ba53a9cc7 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -420,6 +420,9 @@ ktime_t *input_get_timestamp(struct input_dev *dev);
 void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value);
 void input_inject_event(struct input_handle *handle, unsigned int type, unsigned int code, int value);
 
+void input_update_ledstate(unsigned int flag, unsigned int value);
+unsigned int input_get_ledstate(void);
+
 static inline void input_report_key(struct input_dev *dev, unsigned int code, int value)
 {
 	input_event(dev, EV_KEY, code, !!value);
-- 
2.20.1




^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH] input&tty: Fix the keyboard led light display problem
       [not found] <20211014071627.23256-1-changlianzhi@uniontech.com>
  2021-10-14  7:34 ` Greg KH
  2021-10-14 15:13 ` Andy Shevchenko
@ 2021-10-14 18:20 ` Dmitry Torokhov
  2 siblings, 0 replies; 19+ messages in thread
From: Dmitry Torokhov @ 2021-10-14 18:20 UTC (permalink / raw)
  To: lianzhi chang
  Cc: linux-kernel, gregkh, jirislaby, andriy.shevchenko, linux-input,
	282827961

Hi lianzhi,

On Thu, Oct 14, 2021 at 03:16:27PM +0800, lianzhi chang wrote:
> Switching from the desktop environment to the tty environment,
> the state of the keyboard led lights and the state of the keyboard
> lock are inconsistent. This is because the attribute kb->kbdmode
> of the tty bound in the desktop environment (xorg) is set to
> VC_OFF, which causes the ledstate and kb->ledflagstate
> values of the bound tty to always be 0, which causes the switch
> from the desktop When to the tty environment, the LED light
> status is inconsistent with the keyboard lock status.
> 
> Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
> ---
>  drivers/input/input.c     |  7 ++++++-
>  drivers/tty/vt/keyboard.c | 30 +++++++++++++++++++++++++++++-
>  include/linux/kbd_kern.h  |  2 ++
>  3 files changed, 37 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/input/input.c b/drivers/input/input.c
> index ccaeb2426385..43c09700bf68 100644
> --- a/drivers/input/input.c
> +++ b/drivers/input/input.c
> @@ -25,6 +25,7 @@
>  #include <linux/rcupdate.h>
>  #include "input-compat.h"
>  #include "input-poller.h"
> +#include <linux/kbd_kern.h>
>  
>  MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
>  MODULE_DESCRIPTION("Input core");
> @@ -472,8 +473,12 @@ void input_inject_event(struct input_handle *handle,
>  
>  		rcu_read_lock();
>  		grab = rcu_dereference(dev->grab);
> -		if (!grab || grab == handle)
> +		if (!grab || grab == handle) {
>  			input_handle_event(dev, type, code, value);
> +
> +			if (type == EV_LED && code < LED_SCROLLL)
> +				update_value_ledstate(code, value);

No, we should not be putting hooks for tty/vt directly into input core.
The code in drivers/tty/vt/keyboard.c is getting all relevant input
events and should be able to keep the led state synchronized. Please
keep all the changes localized there.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] input&tty: Fix the keyboard led light display problem
       [not found] <20211014071627.23256-1-changlianzhi@uniontech.com>
  2021-10-14  7:34 ` Greg KH
@ 2021-10-14 15:13 ` Andy Shevchenko
  2021-10-14 14:55   ` Jiri Slaby
  2021-10-14 18:20 ` Dmitry Torokhov
  2 siblings, 1 reply; 19+ messages in thread
From: Andy Shevchenko @ 2021-10-14 15:13 UTC (permalink / raw)
  To: lianzhi chang
  Cc: linux-kernel, dmitry.torokhov, gregkh, jirislaby, linux-input, 282827961

On Thu, Oct 14, 2021 at 03:16:27PM +0800, lianzhi chang wrote:
> Switching from the desktop environment to the tty environment,
> the state of the keyboard led lights and the state of the keyboard
> lock are inconsistent. This is because the attribute kb->kbdmode
> of the tty bound in the desktop environment (xorg) is set to
> VC_OFF, which causes the ledstate and kb->ledflagstate
> values of the bound tty to always be 0, which causes the switch
> from the desktop When to the tty environment, the LED light
> status is inconsistent with the keyboard lock status.

...

> +void update_value_ledstate(unsigned int flag, unsigned int value)
> +{
> +	unsigned int bit;

unsigned long bit;

(see below why)

> +	switch (flag) {
> +	case LED_NUML:
> +		bit = VC_NUMLOCK;
> +		break;
> +	case LED_CAPSL:
> +		bit = VC_CAPSLOCK;
> +		break;
> +	case LED_SCROLLL:
> +		bit = VC_SCROLLOCK;
> +		break;
> +	default:
> +		WARN_ON_ONCE(1);
> +		return;
> +	}

> +	if (value)
> +		ledstate |= BIT(bit);
> +	else
> +		ledstate &= ~BIT(BIT);

NIH assign_bit().

On top of that, what is BIT as parameter does in the else branch? Have you
compiled this?

> +}

...

>  	unsigned int leds;
>  	unsigned long flags;

> +	struct kbd_struct *kb = kbd_table + fg_console;

Reversed xmas tree order?

...

>  extern void setledstate(struct kbd_struct *kbd, unsigned int led);

>  

Not sure if wee need this blank line, since both functions are from the same
(functional) group.

> +extern void update_value_ledstate(int flag, int value);

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] input&tty: Fix the keyboard led light display problem
  2021-10-14 15:13 ` Andy Shevchenko
@ 2021-10-14 14:55   ` Jiri Slaby
  0 siblings, 0 replies; 19+ messages in thread
From: Jiri Slaby @ 2021-10-14 14:55 UTC (permalink / raw)
  To: Andy Shevchenko, lianzhi chang
  Cc: linux-kernel, dmitry.torokhov, gregkh, linux-input, 282827961

On 14. 10. 21, 17:13, Andy Shevchenko wrote:
> On Thu, Oct 14, 2021 at 03:16:27PM +0800, lianzhi chang wrote:
>> Switching from the desktop environment to the tty environment,
>> the state of the keyboard led lights and the state of the keyboard
>> lock are inconsistent. This is because the attribute kb->kbdmode
>> of the tty bound in the desktop environment (xorg) is set to
>> VC_OFF, which causes the ledstate and kb->ledflagstate
>> values of the bound tty to always be 0, which causes the switch
>> from the desktop When to the tty environment, the LED light
>> status is inconsistent with the keyboard lock status.
> 
> ...
> 
>> +void update_value_ledstate(unsigned int flag, unsigned int value)
>> +{
>> +	unsigned int bit;
> 
> unsigned long bit;
> 
> (see below why)

You'd need ledstate to be ulong, not bit. Or am I missing something?

-- 
js

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] input&tty: Fix the keyboard led light display problem
       [not found] ` <616827d8.1c69fb81.75aa0.eea0SMTPIN_ADDED_BROKEN@mx.google.com>
@ 2021-10-14 13:21   ` gregkh
  0 siblings, 0 replies; 19+ messages in thread
From: gregkh @ 2021-10-14 13:21 UTC (permalink / raw)
  To: changlianzhi
  Cc: linux-kernel, dmitry.torokhov, jirislaby, andriy.shevchenko,
	linux-input, 282827961

On Thu, Oct 14, 2021 at 12:50:31PM +0800, changlianzhi@uniontech.com wrote:
> Subject: [PATCH] input&tty: Fix the keyboard led light display problem
> 
> 
> Switching from the desktop environment to the tty environment,
> 
> 
> 
> the state of the keyboard led lights and the state of the keyboard
> 
> 
> 
> lock are inconsistent. This is because the attribute kb->kbdmode
> 
> 
> 
> of the tty bound in the desktop environment (xorg) is set to
> 
> 
> 
> VC_OFF, which causes the ledstate and kb->ledflagstate
> 
> 
> 
> values of the bound tty to always be 0, which causes the switch
> 
> 
> 
> from the desktop When to the tty environment, the LED light
> 
> 
> 
> status is inconsistent with the keyboard lock status.
> 
> 
> 
>  
> 
> 
> 
> Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
> 
> 
> 
> ---
> 
> 
> 
> drivers/input/input.c     |  7 ++++++-
> 
> 
> 
> drivers/tty/vt/keyboard.c | 30 +++++++++++++++++++++++++++++-
> 
> 
> 
> include/linux/kbd_kern.h  |  2 ++
> 
> 
> 
> 3 files changed, 37 insertions(+), 2 deletions(-)
> 
> 
> 
>  
> 
> 
> 
> diff --git a/drivers/input/input.c b/drivers/input/input.c
> 
> 
> 
> index ccaeb2426385..43c09700bf68 100644
> 
> 
> 
> --- a/drivers/input/input.c
> 
> 
> 
> +++ b/drivers/input/input.c
> 
> 
> 
> @@ -25,6 +25,7 @@
> 
> 
> 
> #include <linux/rcupdate.h>
> 
> 
> 
> #include "input-compat.h"
> 
> 
> 
> #include "input-poller.h"
> 
> 
> 
> +#include <linux/kbd_kern.h>
> 
> 
> 
> MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
> 
> 
> 
> MODULE_DESCRIPTION("Input core");
> 
> 
> 
> @@ -472,8 +473,12 @@ void input_inject_event(struct input_handle *handle,
> 
> 
> 
> rcu_read_lock();
> 
> 
> 
> grab = rcu_dereference(dev->grab);
> 
> 
> 
> - if (!grab || grab == handle)
> 
> 
> 
> + if (!grab || grab == handle) {
> 
> 
> 
> input_handle_event(dev, type, code, value);
> 
> 
> 
> +
> 
> 
> 
> + if (type == EV_LED && code < LED_SCROLLL)
> 
> 
> 
> + update_value_ledstate(code, value);
> 
> 
> 
> + }
> 
> 
> 
> rcu_read_unlock();
> 
> 
> 
> spin_unlock_irqrestore(&dev->event_lock, flags);
> 
> 
> 
> diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
> 
> 
> 
> index c7fbbcdcc346..0240915cdfef 100644
> 
> 
> 
> --- a/drivers/tty/vt/keyboard.c
> 
> 
> 
> +++ b/drivers/tty/vt/keyboard.c
> 
> 
> 
> @@ -1140,6 +1140,31 @@ static unsigned char getledstate(void)
> 
> 
> 
> return ledstate & 0xff;
> 
> 
> 
> }
> 
> 
> 
> +void update_value_ledstate(unsigned int flag, unsigned int value)
> 
> 
> 
> +{
> 
> 
> 
> + unsigned int bit;
> 
> 
> 
> +
> 
> 
> 
> + switch (flag) {
> 
> 
> 
> + case LED_NUML:
> 
> 
> 
> + bit = VC_NUMLOCK;
> 
> 
> 
> + break;
> 
> 
> 
> + case LED_CAPSL:
> 
> 
> 

<snip>

Something went very wrong with this patch submission :(

Please fix up your email client and try again, or just use 'git
send-email' directly, as that should be all that you need here.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH] input&tty: Fix the keyboard led light display problem
@ 2021-10-14  8:53 lianzhi chang
       [not found] ` <616827d8.1c69fb81.75aa0.eea0SMTPIN_ADDED_BROKEN@mx.google.com>
  0 siblings, 1 reply; 19+ messages in thread
From: lianzhi chang @ 2021-10-14  8:53 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-input, lianzhi chang

Switching from the desktop environment to the tty environment,
the state of the keyboard led lights and the state of the keyboard
lock are inconsistent. This is because the attribute kb->kbdmode
of the tty bound in the desktop environment (xorg) is set to
VC_OFF, which causes the ledstate and kb->ledflagstate
values of the bound tty to always be 0, which causes the switch
from the desktop When to the tty environment, the LED light
status is inconsistent with the keyboard lock status.

Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
---
 drivers/input/input.c     |  7 ++++++-
 drivers/tty/vt/keyboard.c | 30 +++++++++++++++++++++++++++++-
 include/linux/kbd_kern.h  |  2 ++
 3 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index ccaeb2426385..43c09700bf68 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -25,6 +25,7 @@
 #include <linux/rcupdate.h>
 #include "input-compat.h"
 #include "input-poller.h"
+#include <linux/kbd_kern.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("Input core");
@@ -472,8 +473,12 @@ void input_inject_event(struct input_handle *handle,
 
 		rcu_read_lock();
 		grab = rcu_dereference(dev->grab);
-		if (!grab || grab == handle)
+		if (!grab || grab == handle) {
 			input_handle_event(dev, type, code, value);
+
+			if (type == EV_LED && code < LED_SCROLLL)
+				update_value_ledstate(code, value);
+		}
 		rcu_read_unlock();
 
 		spin_unlock_irqrestore(&dev->event_lock, flags);
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index c7fbbcdcc346..0240915cdfef 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -1140,6 +1140,31 @@ static unsigned char getledstate(void)
 	return ledstate & 0xff;
 }
 
+void update_value_ledstate(unsigned int flag, unsigned int value)
+{
+	unsigned int bit;
+
+	switch (flag) {
+	case LED_NUML:
+		bit = VC_NUMLOCK;
+		break;
+	case LED_CAPSL:
+		bit = VC_CAPSLOCK;
+		break;
+	case LED_SCROLLL:
+		bit = VC_SCROLLOCK;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	if (value)
+		ledstate |= BIT(bit);
+	else
+		ledstate &= ~BIT(bit);
+}
+
 void setledstate(struct kbd_struct *kb, unsigned int led)
 {
         unsigned long flags;
@@ -1249,6 +1274,10 @@ static void kbd_bh(struct tasklet_struct *unused)
 {
 	unsigned int leds;
 	unsigned long flags;
+	struct kbd_struct *kb = kbd_table + fg_console;
+
+	if (kb->kbdmode == VC_OFF)
+		return;
 
 	spin_lock_irqsave(&led_lock, flags);
 	leds = getleds();
@@ -1257,7 +1286,6 @@ static void kbd_bh(struct tasklet_struct *unused)
 
 	if (leds != ledstate) {
 		kbd_propagate_led_state(ledstate, leds);
-		ledstate = leds;
 	}
 }
 
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index c40811d79769..36a3402658e6 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -62,6 +62,8 @@ extern int kbd_init(void);
 
 extern void setledstate(struct kbd_struct *kbd, unsigned int led);
 
+extern void update_value_ledstate(int flag, int value);
+
 extern int do_poke_blanked_console;
 
 extern void (*kbd_ledfunc)(unsigned int led);
-- 
2.20.1




^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH] input&tty: Fix the keyboard led light display problem
       [not found] <20211014071627.23256-1-changlianzhi@uniontech.com>
@ 2021-10-14  7:34 ` Greg KH
  2021-10-14 15:13 ` Andy Shevchenko
  2021-10-14 18:20 ` Dmitry Torokhov
  2 siblings, 0 replies; 19+ messages in thread
From: Greg KH @ 2021-10-14  7:34 UTC (permalink / raw)
  To: lianzhi chang
  Cc: linux-kernel, dmitry.torokhov, jirislaby, andriy.shevchenko,
	linux-input, 282827961

On Thu, Oct 14, 2021 at 03:16:27PM +0800, lianzhi chang wrote:
> Switching from the desktop environment to the tty environment,
> the state of the keyboard led lights and the state of the keyboard
> lock are inconsistent. This is because the attribute kb->kbdmode
> of the tty bound in the desktop environment (xorg) is set to
> VC_OFF, which causes the ledstate and kb->ledflagstate
> values of the bound tty to always be 0, which causes the switch
> from the desktop When to the tty environment, the LED light
> status is inconsistent with the keyboard lock status.
> 
> Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
> ---
>  drivers/input/input.c     |  7 ++++++-
>  drivers/tty/vt/keyboard.c | 30 +++++++++++++++++++++++++++++-
>  include/linux/kbd_kern.h  |  2 ++
>  3 files changed, 37 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/input/input.c b/drivers/input/input.c
> index ccaeb2426385..43c09700bf68 100644
> --- a/drivers/input/input.c
> +++ b/drivers/input/input.c
> @@ -25,6 +25,7 @@
>  #include <linux/rcupdate.h>
>  #include "input-compat.h"
>  #include "input-poller.h"
> +#include <linux/kbd_kern.h>
>  
>  MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
>  MODULE_DESCRIPTION("Input core");
> @@ -472,8 +473,12 @@ void input_inject_event(struct input_handle *handle,
>  
>  		rcu_read_lock();
>  		grab = rcu_dereference(dev->grab);
> -		if (!grab || grab == handle)
> +		if (!grab || grab == handle) {
>  			input_handle_event(dev, type, code, value);
> +
> +			if (type == EV_LED && code < LED_SCROLLL)
> +				update_value_ledstate(code, value);
> +		}
>  		rcu_read_unlock();
>  
>  		spin_unlock_irqrestore(&dev->event_lock, flags);
> diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
> index c7fbbcdcc346..f612ed5c647f 100644
> --- a/drivers/tty/vt/keyboard.c
> +++ b/drivers/tty/vt/keyboard.c
> @@ -1140,6 +1140,31 @@ static unsigned char getledstate(void)
>  	return ledstate & 0xff;
>  }
>  
> +void update_value_ledstate(unsigned int flag, unsigned int value)
> +{
> +	unsigned int bit;
> +
> +	switch (flag) {
> +	case LED_NUML:
> +		bit = VC_NUMLOCK;
> +		break;
> +	case LED_CAPSL:
> +		bit = VC_CAPSLOCK;
> +		break;
> +	case LED_SCROLLL:
> +		bit = VC_SCROLLOCK;
> +		break;
> +	default:
> +		WARN_ON_ONCE(1);
> +		return;
> +	}
> +
> +	if (value)
> +		ledstate |= BIT(bit);
> +	else
> +		ledstate &= ~BIT(BIT);
> +}
> +
>  void setledstate(struct kbd_struct *kb, unsigned int led)
>  {
>          unsigned long flags;
> @@ -1249,6 +1274,10 @@ static void kbd_bh(struct tasklet_struct *unused)
>  {
>  	unsigned int leds;
>  	unsigned long flags;
> +	struct kbd_struct *kb = kbd_table + fg_console;
> +
> +	if (kb->kbdmode == VC_OFF)
> +		return;
>  
>  	spin_lock_irqsave(&led_lock, flags);
>  	leds = getleds();
> @@ -1257,7 +1286,6 @@ static void kbd_bh(struct tasklet_struct *unused)
>  
>  	if (leds != ledstate) {
>  		kbd_propagate_led_state(ledstate, leds);
> -		ledstate = leds;
>  	}
>  }
>  
> diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
> index c40811d79769..36a3402658e6 100644
> --- a/include/linux/kbd_kern.h
> +++ b/include/linux/kbd_kern.h
> @@ -62,6 +62,8 @@ extern int kbd_init(void);
>  
>  extern void setledstate(struct kbd_struct *kbd, unsigned int led);
>  
> +extern void update_value_ledstate(int flag, int value);
> +
>  extern int do_poke_blanked_console;
>  
>  extern void (*kbd_ledfunc)(unsigned int led);
> -- 
> 2.20.1
> 

Hi,

This is the friendly patch-bot of Greg Kroah-Hartman.  You have sent him
a patch that has triggered this response.  He used to manually respond
to these common problems, but in order to save his sanity (he kept
writing the same thing over and over, yet to different people), I was
created.  Hopefully you will not take offence and will fix the problem
in your patch and resubmit it so that it can be accepted into the Linux
kernel tree.

You are receiving this message because of the following common error(s)
as indicated below:

- This looks like a new version of a previously submitted patch, but you
  did not list below the --- line any changes from the previous version.
  Please read the section entitled "The canonical patch format" in the
  kernel file, Documentation/SubmittingPatches for what needs to be done
  here to properly describe this.

If you wish to discuss this problem further, or you have questions about
how to resolve this issue, please feel free to respond to this email and
Greg will reply once he has dug out from the pending patches received
from other developers.

thanks,

greg k-h's patch email bot

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH] input&tty: Fix the keyboard led light display problem
@ 2021-10-14  7:20 lianzhi chang
  0 siblings, 0 replies; 19+ messages in thread
From: lianzhi chang @ 2021-10-14  7:20 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-input, lianzhi chang

Switching from the desktop environment to the tty environment,
the state of the keyboard led lights and the state of the keyboard
lock are inconsistent. This is because the attribute kb->kbdmode
of the tty bound in the desktop environment (xorg) is set to
VC_OFF, which causes the ledstate and kb->ledflagstate
values of the bound tty to always be 0, which causes the switch
from the desktop When to the tty environment, the LED light
status is inconsistent with the keyboard lock status.

Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
---
 drivers/input/input.c     |  7 ++++++-
 drivers/tty/vt/keyboard.c | 30 +++++++++++++++++++++++++++++-
 include/linux/kbd_kern.h  |  2 ++
 3 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index ccaeb2426385..43c09700bf68 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -25,6 +25,7 @@
 #include <linux/rcupdate.h>
 #include "input-compat.h"
 #include "input-poller.h"
+#include <linux/kbd_kern.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("Input core");
@@ -472,8 +473,12 @@ void input_inject_event(struct input_handle *handle,
 
 		rcu_read_lock();
 		grab = rcu_dereference(dev->grab);
-		if (!grab || grab == handle)
+		if (!grab || grab == handle) {
 			input_handle_event(dev, type, code, value);
+
+			if (type == EV_LED && code < LED_SCROLLL)
+				update_value_ledstate(code, value);
+		}
 		rcu_read_unlock();
 
 		spin_unlock_irqrestore(&dev->event_lock, flags);
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index c7fbbcdcc346..f612ed5c647f 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -1140,6 +1140,31 @@ static unsigned char getledstate(void)
 	return ledstate & 0xff;
 }
 
+void update_value_ledstate(unsigned int flag, unsigned int value)
+{
+	unsigned int bit;
+
+	switch (flag) {
+	case LED_NUML:
+		bit = VC_NUMLOCK;
+		break;
+	case LED_CAPSL:
+		bit = VC_CAPSLOCK;
+		break;
+	case LED_SCROLLL:
+		bit = VC_SCROLLOCK;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		return;
+	}
+
+	if (value)
+		ledstate |= BIT(bit);
+	else
+		ledstate &= ~BIT(BIT);
+}
+
 void setledstate(struct kbd_struct *kb, unsigned int led)
 {
         unsigned long flags;
@@ -1249,6 +1274,10 @@ static void kbd_bh(struct tasklet_struct *unused)
 {
 	unsigned int leds;
 	unsigned long flags;
+	struct kbd_struct *kb = kbd_table + fg_console;
+
+	if (kb->kbdmode == VC_OFF)
+		return;
 
 	spin_lock_irqsave(&led_lock, flags);
 	leds = getleds();
@@ -1257,7 +1286,6 @@ static void kbd_bh(struct tasklet_struct *unused)
 
 	if (leds != ledstate) {
 		kbd_propagate_led_state(ledstate, leds);
-		ledstate = leds;
 	}
 }
 
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index c40811d79769..36a3402658e6 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -62,6 +62,8 @@ extern int kbd_init(void);
 
 extern void setledstate(struct kbd_struct *kbd, unsigned int led);
 
+extern void update_value_ledstate(int flag, int value);
+
 extern int do_poke_blanked_console;
 
 extern void (*kbd_ledfunc)(unsigned int led);
-- 
2.20.1




^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH] input&tty: Fix the keyboard led light display problem
       [not found] <20211014040508.8367-1-changlianzhi@uniontech.com>
@ 2021-10-14  4:12 ` Jiri Slaby
  0 siblings, 0 replies; 19+ messages in thread
From: Jiri Slaby @ 2021-10-14  4:12 UTC (permalink / raw)
  To: lianzhi chang, linux-kernel
  Cc: dmitry.torokhov, gregkh, andriy.shevchenko, linux-input, 282827961

No need to send it 5 times...

On 14. 10. 21, 6:05, lianzhi chang wrote:
> Switching from the desktop environment to the tty environment,
> the state of the keyboard led lights and the state of the keyboard
> lock are inconsistent. This is because the attribute kb->kbdmode
> of the tty bound in the desktop environment (xorg) is set to
> VC_OFF, which causes the ledstate and kb->ledflagstate
> values of the bound tty to always be 0, which causes the switch
> from the desktop When to the tty environment, the LED light
> status is inconsistent with the keyboard lock status.
> 
> Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
> ---
>   drivers/input/input.c     |  7 ++++++-
>   drivers/tty/vt/keyboard.c | 22 +++++++++++++++++++++-
>   include/linux/kbd_kern.h  |  2 ++
>   3 files changed, 29 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/input/input.c b/drivers/input/input.c
> index ccaeb2426385..41f6186a9cc4 100644
> --- a/drivers/input/input.c
> +++ b/drivers/input/input.c
> @@ -25,6 +25,7 @@
>   #include <linux/rcupdate.h>
>   #include "input-compat.h"
>   #include "input-poller.h"
> +#include <linux/kbd_kern.h>
>   
>   MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
>   MODULE_DESCRIPTION("Input core");
> @@ -472,8 +473,12 @@ void input_inject_event(struct input_handle *handle,
>   
>   		rcu_read_lock();
>   		grab = rcu_dereference(dev->grab);
> -		if (!grab || grab == handle)
> +		if (!grab || grab == handle) {
>   			input_handle_event(dev, type, code, value);
> +
> +			if (type == EV_LED && code < 3)
> +				update_value_ledstate(code, value);
> +		}
>   		rcu_read_unlock();
>   
>   		spin_unlock_irqrestore(&dev->event_lock, flags);
> diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
> index c7fbbcdcc346..005fa5cf2a67 100644
> --- a/drivers/tty/vt/keyboard.c
> +++ b/drivers/tty/vt/keyboard.c
> @@ -1140,6 +1140,23 @@ static unsigned char getledstate(void)
>   	return ledstate & 0xff;
>   }
>   
> +void update_value_ledstate(int flag, int value)
> +{
> +	if (ledstate == -1U)
> +		ledstate = 0;
> +
> +	if (flag == LED_NUML) {
> +		ledstate &= ~(1 << 1);
> +		ledstate |= value << 1;
> +	} else if (flag == LED_CAPSL) {
> +		ledstate &= ~(1 << 2);
> +		ledstate |= value << 2;
> +	} else if (flag == LED_SCROLLL) {
> +		ledstate &= ~(1 << 0);
> +		ledstate |= value << 0;
> +	}
> +}
> +
>   void setledstate(struct kbd_struct *kb, unsigned int led)
>   {
>           unsigned long flags;
> @@ -1249,6 +1266,10 @@ static void kbd_bh(struct tasklet_struct *unused)
>   {
>   	unsigned int leds;
>   	unsigned long flags;
> +	struct kbd_struct *kb = kbd_table + fg_console;
> +
> +	if (kb->kbdmode == VC_OFF)
> +		return;
>   
>   	spin_lock_irqsave(&led_lock, flags);
>   	leds = getleds();
> @@ -1257,7 +1278,6 @@ static void kbd_bh(struct tasklet_struct *unused)
>   
>   	if (leds != ledstate) {
>   		kbd_propagate_led_state(ledstate, leds);
> -		ledstate = leds;
>   	}
>   }
>   
> diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
> index c40811d79769..36a3402658e6 100644
> --- a/include/linux/kbd_kern.h
> +++ b/include/linux/kbd_kern.h
> @@ -62,6 +62,8 @@ extern int kbd_init(void);
>   
>   extern void setledstate(struct kbd_struct *kbd, unsigned int led);
>   
> +extern void update_value_ledstate(int flag, int value);
> +
>   extern int do_poke_blanked_console;
>   
>   extern void (*kbd_ledfunc)(unsigned int led);
> 


-- 
js

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH] input&tty: Fix the keyboard led light display problem
       [not found] <20211014030836.30612-1-changlianzhi@uniontech.com>
@ 2021-10-14  4:12 ` Jiri Slaby
  0 siblings, 0 replies; 19+ messages in thread
From: Jiri Slaby @ 2021-10-14  4:12 UTC (permalink / raw)
  To: lianzhi chang, linux-kernel
  Cc: dmitry.torokhov, gregkh, andriy.shevchenko, linux-input, 282827961

On 14. 10. 21, 5:08, lianzhi chang wrote:
> Switching from the desktop environment to the tty environment,
> the state of the keyboard led lights and the state of the keyboard
> lock are inconsistent. This is because the attribute kb->kbdmode
> of the tty bound in the desktop environment (xorg) is set to
> VC_OFF, which causes the ledstate and kb->ledflagstate
> values of the bound tty to always be 0, which causes the switch
> from the desktop When to the tty environment, the LED light
> status is inconsistent with the keyboard lock status.
> 
> Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
> ---
>   drivers/input/input.c     |  7 ++++++-
>   drivers/tty/vt/keyboard.c | 22 +++++++++++++++++++++-
>   include/linux/kbd_kern.h  |  2 ++
>   3 files changed, 29 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/input/input.c b/drivers/input/input.c
> index ccaeb2426385..41f6186a9cc4 100644
> --- a/drivers/input/input.c
> +++ b/drivers/input/input.c
> @@ -25,6 +25,7 @@
>   #include <linux/rcupdate.h>
>   #include "input-compat.h"
>   #include "input-poller.h"
> +#include <linux/kbd_kern.h>
>   
>   MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
>   MODULE_DESCRIPTION("Input core");
> @@ -472,8 +473,12 @@ void input_inject_event(struct input_handle *handle,
>   
>   		rcu_read_lock();
>   		grab = rcu_dereference(dev->grab);
> -		if (!grab || grab == handle)
> +		if (!grab || grab == handle) {
>   			input_handle_event(dev, type, code, value);
> +
> +			if (type == EV_LED && code < 3)

3 is a magic constant. In fact, you mean "code <= LED_SCROLLL", right?

> +				update_value_ledstate(code, value);
> +		}
>   		rcu_read_unlock();
>   
>   		spin_unlock_irqrestore(&dev->event_lock, flags);
> diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
> index c7fbbcdcc346..005fa5cf2a67 100644
> --- a/drivers/tty/vt/keyboard.c
> +++ b/drivers/tty/vt/keyboard.c
> @@ -1140,6 +1140,23 @@ static unsigned char getledstate(void)
>   	return ledstate & 0xff;
>   }
>   
> +void update_value_ledstate(int flag, int value)

Why is the int signed?

> +{
> +	if (ledstate == -1U)
> +		ledstate = 0;
> +
> +	if (flag == LED_NUML) {
> +		ledstate &= ~(1 << 1);

ledstate &= ~BIT(VC_NUMLOCK);

> +		ledstate |= value << 1;

What ensures that value is 0 or 1 here?

> +	} else if (flag == LED_CAPSL) {
> +		ledstate &= ~(1 << 2);
> +		ledstate |= value << 2;
> +	} else if (flag == LED_SCROLLL) {
> +		ledstate &= ~(1 << 0);
> +		ledstate |= value << 0;
> +	}

What about something like this (maybe ifs would be shorter, dunno, try it):
unsigned int bit;

switch (flag) {
case LED_NUML:
   bit = VC_NUMLOCK;
   break;
case LED_CAPSL:
   bit = VC_CAPSLOCK;
   break;
case LED_SCROLLL:
   bit = VC_SCROLLOCK;
   break;
default:
   WARN_ON_ONCE(1);
   return;
}

if (value)
   ledstate |= BIT(bit);
else
   ledstate &= ~BIT(BIT);

> +}
> +
>   void setledstate(struct kbd_struct *kb, unsigned int led)
>   {
>           unsigned long flags;
> @@ -1249,6 +1266,10 @@ static void kbd_bh(struct tasklet_struct *unused)
>   {
>   	unsigned int leds;
>   	unsigned long flags;
> +	struct kbd_struct *kb = kbd_table + fg_console;
> +
> +	if (kb->kbdmode == VC_OFF)
> +		return;

Can you explain why (not to me, to the commit log)?

>   	spin_lock_irqsave(&led_lock, flags);
>   	leds = getleds();
> @@ -1257,7 +1278,6 @@ static void kbd_bh(struct tasklet_struct *unused)
>   
>   	if (leds != ledstate) {
>   		kbd_propagate_led_state(ledstate, leds);
> -		ledstate = leds;

The same here. Why this doesn't break the current behaviour.

>   	}
>   }
>   
> diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
> index c40811d79769..36a3402658e6 100644
> --- a/include/linux/kbd_kern.h
> +++ b/include/linux/kbd_kern.h
> @@ -62,6 +62,8 @@ extern int kbd_init(void);
>   
>   extern void setledstate(struct kbd_struct *kbd, unsigned int led);
>   
> +extern void update_value_ledstate(int flag, int value);
> +
>   extern int do_poke_blanked_console;
>   
>   extern void (*kbd_ledfunc)(unsigned int led);
> 

thanks,
-- 
js
suse labs

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH] input&tty: Fix the keyboard led light display problem
@ 2021-10-14  4:06 lianzhi chang
  0 siblings, 0 replies; 19+ messages in thread
From: lianzhi chang @ 2021-10-14  4:06 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-input, 282827961, lianzhi chang

Switching from the desktop environment to the tty environment,
the state of the keyboard led lights and the state of the keyboard
lock are inconsistent. This is because the attribute kb->kbdmode
of the tty bound in the desktop environment (xorg) is set to
VC_OFF, which causes the ledstate and kb->ledflagstate
values of the bound tty to always be 0, which causes the switch
from the desktop When to the tty environment, the LED light
status is inconsistent with the keyboard lock status.

Signed-off-by: lianzhi chang <changlianzhi@uniontech.com>
---
 drivers/input/input.c     |  7 ++++++-
 drivers/tty/vt/keyboard.c | 22 +++++++++++++++++++++-
 include/linux/kbd_kern.h  |  2 ++
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index ccaeb2426385..41f6186a9cc4 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -25,6 +25,7 @@
 #include <linux/rcupdate.h>
 #include "input-compat.h"
 #include "input-poller.h"
+#include <linux/kbd_kern.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_DESCRIPTION("Input core");
@@ -472,8 +473,12 @@ void input_inject_event(struct input_handle *handle,
 
 		rcu_read_lock();
 		grab = rcu_dereference(dev->grab);
-		if (!grab || grab == handle)
+		if (!grab || grab == handle) {
 			input_handle_event(dev, type, code, value);
+
+			if (type == EV_LED && code < 3)
+				update_value_ledstate(code, value);
+		}
 		rcu_read_unlock();
 
 		spin_unlock_irqrestore(&dev->event_lock, flags);
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index c7fbbcdcc346..005fa5cf2a67 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -1140,6 +1140,23 @@ static unsigned char getledstate(void)
 	return ledstate & 0xff;
 }
 
+void update_value_ledstate(int flag, int value)
+{
+	if (ledstate == -1U)
+		ledstate = 0;
+
+	if (flag == LED_NUML) {
+		ledstate &= ~(1 << 1);
+		ledstate |= value << 1;
+	} else if (flag == LED_CAPSL) {
+		ledstate &= ~(1 << 2);
+		ledstate |= value << 2;
+	} else if (flag == LED_SCROLLL) {
+		ledstate &= ~(1 << 0);
+		ledstate |= value << 0;
+	}
+}
+
 void setledstate(struct kbd_struct *kb, unsigned int led)
 {
         unsigned long flags;
@@ -1249,6 +1266,10 @@ static void kbd_bh(struct tasklet_struct *unused)
 {
 	unsigned int leds;
 	unsigned long flags;
+	struct kbd_struct *kb = kbd_table + fg_console;
+
+	if (kb->kbdmode == VC_OFF)
+		return;
 
 	spin_lock_irqsave(&led_lock, flags);
 	leds = getleds();
@@ -1257,7 +1278,6 @@ static void kbd_bh(struct tasklet_struct *unused)
 
 	if (leds != ledstate) {
 		kbd_propagate_led_state(ledstate, leds);
-		ledstate = leds;
 	}
 }
 
diff --git a/include/linux/kbd_kern.h b/include/linux/kbd_kern.h
index c40811d79769..36a3402658e6 100644
--- a/include/linux/kbd_kern.h
+++ b/include/linux/kbd_kern.h
@@ -62,6 +62,8 @@ extern int kbd_init(void);
 
 extern void setledstate(struct kbd_struct *kbd, unsigned int led);
 
+extern void update_value_ledstate(int flag, int value);
+
 extern int do_poke_blanked_console;
 
 extern void (*kbd_ledfunc)(unsigned int led);
-- 
2.20.1




^ permalink raw reply related	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2021-10-15 10:16 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-15  1:20 [PATCH] input&tty: Fix the keyboard led light display problem lianzhi chang
     [not found] <35696980-2a55-c5c1-3fa9-eadf251dcdde@uniontech.com>
2021-10-15 13:06 ` Andy Shevchenko
     [not found] <20211015083613.7429-1-changlianzhi@uniontech.com>
2021-10-15  8:41 ` Greg KH
     [not found]   ` <616942b2.1c69fb81.dfbff.25afSMTPIN_ADDED_BROKEN@mx.google.com>
2021-10-15 10:16     ` Greg KH
  -- strict thread matches above, loose matches on Subject: below --
2021-10-15  8:37 lianzhi chang
     [not found] <61693925.1c69fb81.a058.27f2SMTPIN_ADDED_BROKEN@mx.google.com>
2021-10-15  8:25 ` Greg KH
2021-10-15  6:45 lianzhi chang
2021-10-15  6:52 ` Greg KH
     [not found]   ` <616934f3.1c69fb81.59ff6.49d9SMTPIN_ADDED_BROKEN@mx.google.com>
2021-10-15  8:04     ` Greg KH
2021-10-14  8:53 lianzhi chang
     [not found] ` <616827d8.1c69fb81.75aa0.eea0SMTPIN_ADDED_BROKEN@mx.google.com>
2021-10-14 13:21   ` gregkh
     [not found] <20211014071627.23256-1-changlianzhi@uniontech.com>
2021-10-14  7:34 ` Greg KH
2021-10-14 15:13 ` Andy Shevchenko
2021-10-14 14:55   ` Jiri Slaby
2021-10-14 18:20 ` Dmitry Torokhov
2021-10-14  7:20 lianzhi chang
     [not found] <20211014040508.8367-1-changlianzhi@uniontech.com>
2021-10-14  4:12 ` Jiri Slaby
     [not found] <20211014030836.30612-1-changlianzhi@uniontech.com>
2021-10-14  4:12 ` Jiri Slaby
2021-10-14  4:06 lianzhi chang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).