diff options
Diffstat (limited to 'drivers/macintosh/adbhid.c')
-rw-r--r-- | drivers/macintosh/adbhid.c | 58 |
1 files changed, 48 insertions, 10 deletions
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index 48d17bf6c92..8cce016b3d0 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -52,6 +52,11 @@ MODULE_AUTHOR("Franz Sirl <Franz.Sirl-kernel@lauterbach.com>"); +static int restore_capslock_events; +module_param(restore_capslock_events, int, 0644); +MODULE_PARM_DESC(restore_capslock_events, + "Produce keypress events for capslock on both keyup and keydown."); + #define KEYB_KEYREG 0 /* register # for key up/down data */ #define KEYB_LEDREG 2 /* register # for leds on ADB keyboard */ #define MOUSE_DATAREG 0 /* reg# for movement/button codes from mouse */ @@ -217,6 +222,8 @@ struct adbhid { #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 static struct adbhid *adbhid[16]; @@ -272,19 +279,50 @@ adbhid_keyboard_input(unsigned char *data, int nb, int apoll) } static void -adbhid_input_keycode(int id, int keycode, int repeat) +adbhid_input_keycode(int id, int scancode, int repeat) { struct adbhid *ahid = adbhid[id]; - int up_flag, key; - - up_flag = (keycode & 0x80); - keycode &= 0x7f; + int keycode, up_flag; + + keycode = scancode & 0x7f; + up_flag = scancode & 0x80; + + if (restore_capslock_events) { + 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 + | FLAG_CAPSLOCK_DOWN; + } else if (scancode == 0xff) { + /* Scancode 0xff usually signifies that the capslock + * key was either pressed or released. */ + if (ahid->flags & FLAG_CAPSLOCK_TRANSLATE) { + keycode = ADB_KEY_CAPSLOCK; + if (ahid->flags & FLAG_CAPSLOCK_DOWN) { + /* Key released */ + up_flag = 1; + ahid->flags &= ~FLAG_CAPSLOCK_DOWN; + } else { + /* Key pressed */ + up_flag = 0; + ahid->flags &= ~FLAG_CAPSLOCK_TRANSLATE; + } + } else { + printk(KERN_INFO "Spurious caps lock event " + "(scancode 0xff)."); + } + } + } switch (keycode) { - case ADB_KEY_CAPSLOCK: /* Generate down/up events for CapsLock everytime. */ - input_report_key(ahid->input, KEY_CAPSLOCK, 1); - input_report_key(ahid->input, KEY_CAPSLOCK, 0); - input_sync(ahid->input); + case ADB_KEY_CAPSLOCK: + if (!restore_capslock_events) { + /* Generate down/up events for CapsLock everytime. */ + input_report_key(ahid->input, KEY_CAPSLOCK, 1); + input_sync(ahid->input); + input_report_key(ahid->input, KEY_CAPSLOCK, 0); + input_sync(ahid->input); + } return; #ifdef CONFIG_PPC_PMAC case ADB_KEY_POWER_OLD: /* Power key on PBook 3400 needs remapping */ @@ -296,7 +334,7 @@ adbhid_input_keycode(int id, int keycode, int repeat) keycode = ADB_KEY_POWER; } break; - case ADB_KEY_POWER: + case ADB_KEY_POWER: /* Fn + Command will produce a bogus "power" keycode */ if (ahid->flags & FLAG_FN_KEY_PRESSED) { keycode = ADB_KEY_CMD; |