aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRodney Lorrimar <rodney@rodney.id.au>2008-05-05 11:59:00 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2008-05-16 14:50:04 -0400
commit2e75f044c717b85f65d74c8c90624428ba31078c (patch)
tree1f366b123ff5e7472a19538fd044e426f8308134
parentd2fc60d6925574eeeadd037aa0f1378e07189a1a (diff)
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. Signed-off-by: Rodney Lorrimar <rodney@rodney.id.au> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
-rw-r--r--drivers/macintosh/adbhid.c46
1 files changed, 39 insertions, 7 deletions
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index ef4c117ea35f..6e9afe26db89 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -219,11 +219,12 @@ struct adbhid {
219 int flags; 219 int flags;
220}; 220};
221 221
222#define FLAG_FN_KEY_PRESSED 0x00000001 222#define FLAG_FN_KEY_PRESSED 0x00000001
223#define FLAG_POWER_FROM_FN 0x00000002 223#define FLAG_POWER_FROM_FN 0x00000002
224#define FLAG_EMU_FWDEL_DOWN 0x00000004 224#define FLAG_EMU_FWDEL_DOWN 0x00000004
225#define FLAG_CAPSLOCK_TRANSLATE 0x00000008 225#define FLAG_CAPSLOCK_TRANSLATE 0x00000008
226#define FLAG_CAPSLOCK_DOWN 0x00000010 226#define FLAG_CAPSLOCK_DOWN 0x00000010
227#define FLAG_CAPSLOCK_IGNORE_NEXT 0x00000020
227 228
228static struct adbhid *adbhid[16]; 229static struct adbhid *adbhid[16];
229 230
@@ -291,8 +292,15 @@ adbhid_input_keycode(int id, int scancode, int repeat)
291 if (keycode == ADB_KEY_CAPSLOCK && !up_flag) { 292 if (keycode == ADB_KEY_CAPSLOCK && !up_flag) {
292 /* Key pressed, turning on the CapsLock LED. 293 /* Key pressed, turning on the CapsLock LED.
293 * The next 0xff will be interpreted as a release. */ 294 * The next 0xff will be interpreted as a release. */
294 ahid->flags |= FLAG_CAPSLOCK_TRANSLATE 295 if (ahid->flags & FLAG_CAPSLOCK_IGNORE_NEXT) {
296 /* Throw away this key event if it happens
297 * just after resume. */
298 ahid->flags &= ~FLAG_CAPSLOCK_IGNORE_NEXT;
299 return;
300 } else {
301 ahid->flags |= FLAG_CAPSLOCK_TRANSLATE
295 | FLAG_CAPSLOCK_DOWN; 302 | FLAG_CAPSLOCK_DOWN;
303 }
296 } else if (scancode == 0xff) { 304 } else if (scancode == 0xff) {
297 /* Scancode 0xff usually signifies that the capslock 305 /* Scancode 0xff usually signifies that the capslock
298 * key was either pressed or released. */ 306 * key was either pressed or released. */
@@ -681,6 +689,21 @@ static int adbhid_kbd_event(struct input_dev *dev, unsigned int type, unsigned i
681 return -1; 689 return -1;
682} 690}
683 691
692static void
693adbhid_kbd_capslock_remember(void)
694{
695 struct adbhid *ahid;
696 int i;
697
698 for (i = 1; i < 16; i++) {
699 ahid = adbhid[i];
700
701 if (ahid && ahid->id == ADB_KEYBOARD)
702 if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE)
703 ahid->flags |= FLAG_CAPSLOCK_IGNORE_NEXT;
704 }
705}
706
684static int 707static int
685adb_message_handler(struct notifier_block *this, unsigned long code, void *x) 708adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
686{ 709{
@@ -697,8 +720,17 @@ adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
697 } 720 }
698 721
699 /* Stop pending led requests */ 722 /* Stop pending led requests */
700 while(leds_req_pending) 723 while (leds_req_pending)
701 adb_poll(); 724 adb_poll();
725
726 /* After resume, and if the capslock LED is on, the PMU will
727 * send a "capslock down" key event. This confuses the
728 * restore_capslock_events logic. Remember if the capslock
729 * LED was on before suspend so the unwanted key event can
730 * be ignored after resume. */
731 if (restore_capslock_events)
732 adbhid_kbd_capslock_remember();
733
702 break; 734 break;
703 735
704 case ADB_MSG_POST_RESET: 736 case ADB_MSG_POST_RESET: