Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6 into next
[pandora-kernel.git] / drivers / macintosh / adbhid.c
index 8cce016..5396c67 100644 (file)
@@ -75,7 +75,7 @@ static struct notifier_block adbhid_adb_notifier = {
 #define ADB_KEY_POWER_OLD      0x7e
 #define ADB_KEY_POWER          0x7f
 
-u16 adb_to_linux_keycodes[128] = {
+static const u16 adb_to_linux_keycodes[128] = {
        /* 0x00 */ KEY_A,               /*  30 */
        /* 0x01 */ KEY_S,               /*  31 */
        /* 0x02 */ KEY_D,               /*  32 */
@@ -219,11 +219,13 @@ 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
+#define FLAG_POWER_KEY_PRESSED         0x00000040
 
 static struct adbhid *adbhid[16];
 
@@ -282,7 +284,7 @@ static void
 adbhid_input_keycode(int id, int scancode, int repeat)
 {
        struct adbhid *ahid = adbhid[id];
-       int keycode, up_flag;
+       int keycode, up_flag, key;
 
        keycode = scancode & 0x7f;
        up_flag = scancode & 0x80;
@@ -291,11 +293,20 @@ 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) {
+                       }
+               } 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) {
@@ -309,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");
                        }
                }
        }
@@ -322,8 +333,9 @@ adbhid_input_keycode(int id, int scancode, int repeat)
                        input_sync(ahid->input);
                        input_report_key(ahid->input, KEY_CAPSLOCK, 0);
                        input_sync(ahid->input);
+                       return;
                }
-               return;
+               break;
 #ifdef CONFIG_PPC_PMAC
        case ADB_KEY_POWER_OLD: /* Power key on PBook 3400 needs remapping */
                switch(pmac_call_feature(PMAC_FTR_GET_MB_INFO,
@@ -335,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;
@@ -680,6 +698,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)
 {
@@ -696,8 +729,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:
@@ -791,8 +833,10 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
                        if (hid->keycode[i])
                                set_bit(hid->keycode[i], input_dev->keybit);
 
-               input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
-               input_dev->ledbit[0] = BIT(LED_SCROLLL) | BIT(LED_CAPSL) | BIT(LED_NUML);
+               input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_LED) |
+                       BIT_MASK(EV_REP);
+               input_dev->ledbit[0] = BIT_MASK(LED_SCROLLL) |
+                       BIT_MASK(LED_CAPSL) | BIT_MASK(LED_NUML);
                input_dev->event = adbhid_kbd_event;
                input_dev->keycodemax = KEY_FN;
                input_dev->keycodesize = sizeof(hid->keycode[0]);
@@ -801,16 +845,18 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
        case ADB_MOUSE:
                sprintf(hid->name, "ADB mouse");
 
-               input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
-               input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
-               input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);
+               input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+               input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+                       BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
+               input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
                break;
 
        case ADB_MISC:
                switch (original_handler_id) {
                case 0x02: /* Adjustable keyboard button device */
                        sprintf(hid->name, "ADB adjustable keyboard buttons");
-                       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+                       input_dev->evbit[0] = BIT_MASK(EV_KEY) |
+                               BIT_MASK(EV_REP);
                        set_bit(KEY_SOUND, input_dev->keybit);
                        set_bit(KEY_MUTE, input_dev->keybit);
                        set_bit(KEY_VOLUMEUP, input_dev->keybit);
@@ -818,7 +864,8 @@ adbhid_input_register(int id, int default_id, int original_handler_id,
                        break;
                case 0x1f: /* Powerbook button device */
                        sprintf(hid->name, "ADB Powerbook buttons");
-                       input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+                       input_dev->evbit[0] = BIT_MASK(EV_KEY) |
+                               BIT_MASK(EV_REP);
                        set_bit(KEY_MUTE, input_dev->keybit);
                        set_bit(KEY_VOLUMEUP, input_dev->keybit);
                        set_bit(KEY_VOLUMEDOWN, input_dev->keybit);