Input: adbhid - fix capslock key state after suspend
PATCH 1/1 Input: adbhid - fix capslock key state after suspend
If the adbhid module parameter restore_capslock_events is used, sometimes capslock will get stuck down after resuming.
My fix is to remember the capslock state before suspend and then ignore the first 'caps lock key down' message after resume if the capslock LED was on before suspending.
--- drivers/macintosh/adbhid.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 files changed, 37 insertions(+), 6 deletions(-)
drivers/macintosh/adbhid.c +37 -6
@@ -219,11 +219,12 @@ struct adbhid {int flags; }; -#define FLAG_FN_KEY_PRESSED 0x00000001 -#define FLAG_POWER_FROM_FN 0x00000002 -#define FLAG_EMU_FWDEL_DOWN 0x00000004 -#define FLAG_CAPSLOCK_TRANSLATE 0x00000008 -#define FLAG_CAPSLOCK_DOWN 0x00000010 +#define FLAG_FN_KEY_PRESSED 0x00000001 +#define FLAG_POWER_FROM_FN 0x00000002 +#define FLAG_EMU_FWDEL_DOWN 0x00000004 +#define FLAG_CAPSLOCK_TRANSLATE 0x00000008 +#define FLAG_CAPSLOCK_DOWN 0x00000010 +#define FLAG_CAPSLOCK_IGNORE_NEXT 0x00000020static struct adbhid *adbhid[16 ];
@@ -291,8 +292,15 @@ adbhid_input_keycode(int id, int scancode, int repeat)if (keycode ==ADB_KEY_CAPSLOCK && !up_flag) {/* Key pressed, turning on the CapsLock LED. * The next 0xff will be interpreted as a release. */ - ahid->flags |=FLAG_CAPSLOCK_TRANSLATE +if (ahid->flags &FLAG_CAPSLOCK_IGNORE_NEXT ) { +/* Throw away this key event if it happens +* just after resume. */ + ahid->flags &= ~FLAG_CAPSLOCK_IGNORE_NEXT ; +return ; + }else { + ahid->flags |=FLAG_CAPSLOCK_TRANSLATE |FLAG_CAPSLOCK_DOWN ; + } }else if (scancode ==0xff ) {/* Scancode 0xff usually signifies that the capslock * key was either pressed or released. */
@@ -681,6 +689,20 @@ static int adbhid_kbd_event(struct input_dev *dev, unsigned int type, unsigned ireturn -1 ; } +static void +adbhid_kbd_capslock_remember (void ) +{ +struct adbhid *ahid; +int i; +for (i =1 ; i <16 ; i++) { + ahid = adbhid[i]; + +if (ahid && ahid->id ==ADB_KEYBOARD ) +if (ahid->flags &FLAG_CAPSLOCK_TRANSLATE ) + ahid->flags |=FLAG_CAPSLOCK_IGNORE_NEXT ; + } +} +static int adb_message_handler (struct notifier_block *this,unsigned long code,void *x) {
@@ -699,6 +721,15 @@ adb_message_handler(struct notifier_block *this, unsigned long code, void *x)/* Stop pending led requests */ while (leds_req_pending)adb_poll (); + +/* After resume, and if the capslock LED is on, the PMU will +* send a "capslock down" key event. This confuses the +* restore_capslock_events logic. Remember if the capslock +* LED was on before suspend so the unwanted key event can +* be ignored after resume. */ +if (restore_capslock_events) +adbhid_kbd_capslock_remember (); +break ;case ADB_MSG_POST_RESET :
Signature · 1 line
1.5.4.4
Quoted 2 lines · Rodney Lorrimar
If the adbhid module parameter
restore_capslock_eventsis used, sometimes capslock will get stuck down after resuming.
Hmmm, why does that need to be a parameter? I mean... can we just do the right thing?
Pavel
Signature · 3 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html pomozte zachranit klanovicky les: http://www.ujezdskystrom.info/
Quoted 6 lines · Pavel Machek
Quoted 2 lines · Rodney Lorrimar
If the adbhid module parameter
restore_capslock_eventsis used, sometimes capslock will get stuck down after resuming.Hmmm, why does that need to be a parameter? I mean... can we just do the right thing?
I agree. There really don't seem to be any drawbacks to keeping track of capslock state. The worst thing that can happen is that it somehow occasionally fails to do the right thing.
Signature · 3 lines
Andrew McNabb http://www.mcnabbs.org/andrew/ PGP Fingerprint: 8A17 B57C 6879 1863 DE55 8012 AB4D 6098 8826 6868
Quoted 6 lines · Pavel Machek
Quoted 2 lines · Rodney Lorrimar
If the adbhid module parameter
restore_capslock_eventsis used, sometimes capslock will get stuck down after resuming.Hmmm, why does that need to be a parameter? I mean... can we just do the right thing?
Hi Pavel,
Sorry for taking so long to answer your questions. We can mostly do the right thing. I suppose it was a parameter so the quirk fixing didn't ruin the fun for the majority of users who don't remap their capslock. I know of two issues with the code:
1. Under heavy capslock usage the capslock key will sometimes get stuck down.
2. If the capslock LED is on and the power button is pressed, a "power button release" key event won't happen until capslock is pressed again. So in some situations (e.g. with pbbuttonsd) the next time capslock is hit the machine will suspend.
I will send a patch for 2, and continue to investigate 1.
Regarding the original patch, I think it's worth applying. If 1 is fixable then I will prepare two more patches to fix problem 1 and remove the parameter.
Rodney
PATCH 1/1 Input: adbhid - capslock and power button fix
If the adbhid module parameter restore_capslock_events is used, pressing the power button may confuse the capslock state. This is because the power button release scancode (0xff) is sometimes the same as the capslock press/release scancode.
This fix adds yet another flag to track the state of the power button so that it works independently of capslock.
---
This patch applies on top of the previous patch in the thread.
--- drivers/macintosh/adbhid.c | 15 ++++++++++++--- 1 files changed, 12 insertions(+), 3 deletions(-)
drivers/macintosh/adbhid.c +12 -3
@@ -225,6 +225,7 @@ struct adbhid {#define FLAG_CAPSLOCK_TRANSLATE 0x00000008#define FLAG_CAPSLOCK_DOWN 0x00000010#define FLAG_CAPSLOCK_IGNORE_NEXT 0x00000020 +#define FLAG_POWER_KEY_PRESSED 0x00000040static struct adbhid *adbhid[16 ];
@@ -301,9 +302,11 @@ adbhid_input_keycode(int id, int scancode, int repeat) ahid->flags |=FLAG_CAPSLOCK_TRANSLATE |FLAG_CAPSLOCK_DOWN ; } - }else if (scancode ==0xff ) { + }else if (scancode ==0xff && + !(ahid->flags &FLAG_POWER_KEY_PRESSED )) {/* Scancode 0xff usually signifies that the capslock -* key was either pressed or released. */ +* key was either pressed or released, or that the +* power button was released. */ if (ahid->flags &FLAG_CAPSLOCK_TRANSLATE ) { keycode =ADB_KEY_CAPSLOCK ;if (ahid->flags &FLAG_CAPSLOCK_DOWN ) {
@@ -317,7 +320,7 @@ adbhid_input_keycode(int id, int scancode, int repeat) } }else {printk (KERN_INFO "Spurious caps lock event " -"(scancode 0xff)." ); +"(scancode 0xff).\n" ); } } }
@@ -344,6 +347,12 @@ adbhid_input_keycode(int id, int scancode, int repeat) }break ;case ADB_KEY_POWER : +/* Keep track of the power key state */ +if (up_flag) + ahid->flags &= ~FLAG_POWER_KEY_PRESSED ; +else + ahid->flags |=FLAG_POWER_KEY_PRESSED ; +/* Fn + Command will produce a bogus "power" keycode */ if (ahid->flags &FLAG_FN_KEY_PRESSED ) { keycode =ADB_KEY_CMD ;
Signature · 1 line
1.5.4.5