X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fmacintosh%2Fadbhid.c;h=5396c67ba0a45c9b7cc1196590d1cffe18b49f60;hb=908cf4b925e419bc74f3297b2f0e51d6f8a81da2;hp=2766e4fc4ea82e36cfa7ce205076ad7f1c3cae44;hpb=5c8e191e8437616a498a8e1cc0af3dd0d32bbff2;p=linux-2.6 diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index 2766e4fc4e..5396c67ba0 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -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]; @@ -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);