diff options
Diffstat (limited to 'drivers/macintosh')
-rw-r--r-- | drivers/macintosh/adbhid.c | 61 |
1 files changed, 51 insertions, 10 deletions
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index 59ea520a5d7a..5396c67ba0a4 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c | |||
@@ -219,11 +219,13 @@ 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 | ||
228 | #define FLAG_POWER_KEY_PRESSED 0x00000040 | ||
227 | 229 | ||
228 | static struct adbhid *adbhid[16]; | 230 | static struct adbhid *adbhid[16]; |
229 | 231 | ||
@@ -291,11 +293,20 @@ adbhid_input_keycode(int id, int scancode, int repeat) | |||
291 | if (keycode == ADB_KEY_CAPSLOCK && !up_flag) { | 293 | if (keycode == ADB_KEY_CAPSLOCK && !up_flag) { |
292 | /* Key pressed, turning on the CapsLock LED. | 294 | /* Key pressed, turning on the CapsLock LED. |
293 | * The next 0xff will be interpreted as a release. */ | 295 | * The next 0xff will be interpreted as a release. */ |
294 | ahid->flags |= FLAG_CAPSLOCK_TRANSLATE | 296 | if (ahid->flags & FLAG_CAPSLOCK_IGNORE_NEXT) { |
297 | /* Throw away this key event if it happens | ||
298 | * just after resume. */ | ||
299 | ahid->flags &= ~FLAG_CAPSLOCK_IGNORE_NEXT; | ||
300 | return; | ||
301 | } else { | ||
302 | ahid->flags |= FLAG_CAPSLOCK_TRANSLATE | ||
295 | | FLAG_CAPSLOCK_DOWN; | 303 | | FLAG_CAPSLOCK_DOWN; |
296 | } else if (scancode == 0xff) { | 304 | } |
305 | } else if (scancode == 0xff && | ||
306 | !(ahid->flags & FLAG_POWER_KEY_PRESSED)) { | ||
297 | /* Scancode 0xff usually signifies that the capslock | 307 | /* Scancode 0xff usually signifies that the capslock |
298 | * key was either pressed or released. */ | 308 | * key was either pressed or released, or that the |
309 | * power button was released. */ | ||
299 | if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE) { | 310 | if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE) { |
300 | keycode = ADB_KEY_CAPSLOCK; | 311 | keycode = ADB_KEY_CAPSLOCK; |
301 | if (ahid->flags & FLAG_CAPSLOCK_DOWN) { | 312 | if (ahid->flags & FLAG_CAPSLOCK_DOWN) { |
@@ -309,7 +320,7 @@ adbhid_input_keycode(int id, int scancode, int repeat) | |||
309 | } | 320 | } |
310 | } else { | 321 | } else { |
311 | printk(KERN_INFO "Spurious caps lock event " | 322 | printk(KERN_INFO "Spurious caps lock event " |
312 | "(scancode 0xff)."); | 323 | "(scancode 0xff).\n"); |
313 | } | 324 | } |
314 | } | 325 | } |
315 | } | 326 | } |
@@ -336,6 +347,12 @@ adbhid_input_keycode(int id, int scancode, int repeat) | |||
336 | } | 347 | } |
337 | break; | 348 | break; |
338 | case ADB_KEY_POWER: | 349 | case ADB_KEY_POWER: |
350 | /* Keep track of the power key state */ | ||
351 | if (up_flag) | ||
352 | ahid->flags &= ~FLAG_POWER_KEY_PRESSED; | ||
353 | else | ||
354 | ahid->flags |= FLAG_POWER_KEY_PRESSED; | ||
355 | |||
339 | /* Fn + Command will produce a bogus "power" keycode */ | 356 | /* Fn + Command will produce a bogus "power" keycode */ |
340 | if (ahid->flags & FLAG_FN_KEY_PRESSED) { | 357 | if (ahid->flags & FLAG_FN_KEY_PRESSED) { |
341 | keycode = ADB_KEY_CMD; | 358 | keycode = ADB_KEY_CMD; |
@@ -681,6 +698,21 @@ static int adbhid_kbd_event(struct input_dev *dev, unsigned int type, unsigned i | |||
681 | return -1; | 698 | return -1; |
682 | } | 699 | } |
683 | 700 | ||
701 | static void | ||
702 | adbhid_kbd_capslock_remember(void) | ||
703 | { | ||
704 | struct adbhid *ahid; | ||
705 | int i; | ||
706 | |||
707 | for (i = 1; i < 16; i++) { | ||
708 | ahid = adbhid[i]; | ||
709 | |||
710 | if (ahid && ahid->id == ADB_KEYBOARD) | ||
711 | if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE) | ||
712 | ahid->flags |= FLAG_CAPSLOCK_IGNORE_NEXT; | ||
713 | } | ||
714 | } | ||
715 | |||
684 | static int | 716 | static int |
685 | adb_message_handler(struct notifier_block *this, unsigned long code, void *x) | 717 | adb_message_handler(struct notifier_block *this, unsigned long code, void *x) |
686 | { | 718 | { |
@@ -697,8 +729,17 @@ adb_message_handler(struct notifier_block *this, unsigned long code, void *x) | |||
697 | } | 729 | } |
698 | 730 | ||
699 | /* Stop pending led requests */ | 731 | /* Stop pending led requests */ |
700 | while(leds_req_pending) | 732 | while (leds_req_pending) |
701 | adb_poll(); | 733 | adb_poll(); |
734 | |||
735 | /* After resume, and if the capslock LED is on, the PMU will | ||
736 | * send a "capslock down" key event. This confuses the | ||
737 | * restore_capslock_events logic. Remember if the capslock | ||
738 | * LED was on before suspend so the unwanted key event can | ||
739 | * be ignored after resume. */ | ||
740 | if (restore_capslock_events) | ||
741 | adbhid_kbd_capslock_remember(); | ||
742 | |||
702 | break; | 743 | break; |
703 | 744 | ||
704 | case ADB_MSG_POST_RESET: | 745 | case ADB_MSG_POST_RESET: |