Subject: toshiba_acpi: add support for altering keymap Implement getkeycode and setkeycode methods of input device so that users can adjust driver's keymap if they wish to do so. Signed-off-by: Dmitry Torokhov --- drivers/acpi/toshiba_acpi.c | 114 +++++++++++++++++++++++++++++--------------- 1 file changed, 77 insertions(+), 37 deletions(-) Index: linux/drivers/acpi/toshiba_acpi.c =================================================================== --- linux.orig/drivers/acpi/toshiba_acpi.c +++ linux/drivers/acpi/toshiba_acpi.c @@ -603,51 +603,88 @@ static struct backlight_ops toshiba_back .update_status = set_lcd_status, }; +static struct toshiba_key { + int code; + int keycode; +} toshiba_keymap[] = { + { HCI_HKEY_FN, KEY_RESERVED }, /* ignore lone FN */ + { HCI_HKEY_MUTE, KEY_MUTE }, + { HCI_HKEY_BREAK, KEY_COFFEE }, /* AKA KEY_SCREENLOCK */ + { HCI_HKEY_SEARCH, KEY_SEARCH }, + { HCI_HKEY_SUSPEND, KEY_SLEEP }, + { HCI_HKEY_HIBERNATE, KEY_SUSPEND }, + { HCI_HKEY_BRIGHTNESSDOWN, KEY_BRIGHTNESSDOWN }, + { HCI_HKEY_BRIGHTNESSUP, KEY_BRIGHTNESSUP }, + { HCI_HKEY_WLAN, KEY_WLAN }, +}; + +static struct toshiba_key *toshiba_get_key_by_scancode(int code) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(toshiba_keymap); i++) + if (code == toshiba_keymap[i].code) + return &toshiba_keymap[i]; + + return NULL; +} + +static struct toshiba_key *toshiba_get_key_by_keycode(int keycode) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(toshiba_keymap); i++) + if (keycode == toshiba_keymap[i].keycode) + return &toshiba_keymap[i]; + + return NULL; +} + +static int toshiba_getkeycode(struct input_dev *dev, int scancode, int *keycode) +{ + const struct toshiba_key *key = toshiba_get_key_by_scancode(scancode); + + if (key) { + *keycode = key->keycode; + return 0; + } + + return -EINVAL; +} + +static int toshiba_setkeycode(struct input_dev *dev, int scancode, int keycode) +{ + struct toshiba_key *key; + int old_keycode; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + key = toshiba_get_key_by_scancode(scancode); + if (key) { + old_keycode = key->keycode; + key->keycode = keycode; + set_bit(keycode, dev->keybit); + if (!toshiba_get_key_by_keycode(old_keycode)) + clear_bit(old_keycode, dev->keybit); + return 0; + } + + return -EINVAL; +} + static void toshiba_deliver_button_event(struct input_dev *input, u32 value) { - int keycode; + struct toshiba_key *key; int key_down; /* translate MSB to key up */ key_down = !(value & 0x80); value &= ~0x80; - /* translate keys to keycodes */ - switch (value) { - case HCI_HKEY_FN: - keycode = KEY_RESERVED; /* ignore FN on its own */ - return; - case HCI_HKEY_MUTE: - keycode = KEY_MUTE; - break; - case HCI_HKEY_BREAK: - keycode = KEY_COFFEE; /* AKA KEY_SCREENLOCK */ - break; - case HCI_HKEY_SEARCH: - keycode = KEY_SEARCH; - break; - case HCI_HKEY_SUSPEND: - keycode = KEY_SLEEP; - break; - case HCI_HKEY_HIBERNATE: - keycode = KEY_SUSPEND; - break; - case HCI_HKEY_BRIGHTNESSDOWN: - keycode = KEY_BRIGHTNESSDOWN; - break; - case HCI_HKEY_BRIGHTNESSUP: - keycode = KEY_BRIGHTNESSUP; - break; - case HCI_HKEY_WLAN: - keycode = KEY_WLAN; - break; - default: - keycode = KEY_UNKNOWN; - break; - } - - if (keycode != KEY_RESERVED) { - input_report_key(input, keycode, key_down); + key = toshiba_get_key_by_scancode(value); + if (key && key->keycode != KEY_RESERVED) { + input_report_key(input, key->keycode, key_down); input_event(input, EV_MSC, MSC_SCAN, value); input_sync(input); } @@ -720,6 +757,9 @@ static int __init toshiba_input_polldev_ set_bit(KEY_BRIGHTNESSUP, input->keybit); set_bit(KEY_WLAN, input->keybit); + input->getkeycode = toshiba_getkeycode; + input->setkeycode = toshiba_setkeycode; + error = input_register_polled_device(toshiba_poll_dev); if (error) { printk(MY_ERR "could not register input device\n");