Input: adbhid - fix capslock key state after suspend
[safe/jmp/linux-2.6] / drivers / macintosh / adbhid.c
index ef4c117..6e9afe2 100644 (file)
@@ -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      0x00000020
 
 static 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,21 @@ static int adbhid_kbd_event(struct input_dev *dev, unsigned int type, unsigned i
        return -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)
 {
@@ -697,8 +720,17 @@ adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
                }
 
                /* Stop pending led requests */
-               while(leds_req_pending)
+               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: