Commit d1e14dca6a18aa40394316c872993ae3bc7e311a
Committed by
Matthew Garrett
1 parent
34a656d22f
Exists in
master
and in
7 other branches
thinkpad-acpi: add support for model-specific keymaps
Use the quirks engine to select model-specific keymaps, which makes it much easier to extend should we need it. Keycodes are based on the tables at http://www.thinkwiki.org/wiki/Default_meanings_of_special_keys. Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Signed-off-by: Matthew Garrett <mjg@redhat.com>
Showing 1 changed file with 42 additions and 18 deletions Side-by-side Diff
drivers/platform/x86/thinkpad_acpi.c
... | ... | @@ -3093,6 +3093,8 @@ |
3093 | 3093 | TPACPI_Q_IBM('1', 'D', TPACPI_HK_Q_INIMASK), /* X22, X23, X24 */ |
3094 | 3094 | }; |
3095 | 3095 | |
3096 | +typedef u16 tpacpi_keymap_t[TPACPI_HOTKEY_MAP_LEN]; | |
3097 | + | |
3096 | 3098 | static int __init hotkey_init(struct ibm_init_struct *iibm) |
3097 | 3099 | { |
3098 | 3100 | /* Requirements for changing the default keymaps: |
3099 | 3101 | |
... | ... | @@ -3124,9 +3126,17 @@ |
3124 | 3126 | * If the above is too much to ask, don't change the keymap. |
3125 | 3127 | * Ask the thinkpad-acpi maintainer to do it, instead. |
3126 | 3128 | */ |
3127 | - static u16 ibm_keycode_map[TPACPI_HOTKEY_MAP_LEN] __initdata = { | |
3129 | + | |
3130 | + enum keymap_index { | |
3131 | + TPACPI_KEYMAP_IBM_GENERIC = 0, | |
3132 | + TPACPI_KEYMAP_LENOVO_GENERIC, | |
3133 | + }; | |
3134 | + | |
3135 | + static const tpacpi_keymap_t tpacpi_keymaps[] __initconst = { | |
3136 | + /* Generic keymap for IBM ThinkPads */ | |
3137 | + [TPACPI_KEYMAP_IBM_GENERIC] = { | |
3128 | 3138 | /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ |
3129 | - KEY_FN_F1, KEY_FN_F2, KEY_COFFEE, KEY_SLEEP, | |
3139 | + KEY_FN_F1, KEY_BATTERY, KEY_COFFEE, KEY_SLEEP, | |
3130 | 3140 | KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, |
3131 | 3141 | KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, |
3132 | 3142 | |
... | ... | @@ -3157,8 +3167,10 @@ |
3157 | 3167 | /* (assignments unknown, please report if found) */ |
3158 | 3168 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, |
3159 | 3169 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, |
3160 | - }; | |
3161 | - static u16 lenovo_keycode_map[TPACPI_HOTKEY_MAP_LEN] __initdata = { | |
3170 | + }, | |
3171 | + | |
3172 | + /* Generic keymap for Lenovo ThinkPads */ | |
3173 | + [TPACPI_KEYMAP_LENOVO_GENERIC] = { | |
3162 | 3174 | /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ |
3163 | 3175 | KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP, |
3164 | 3176 | KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, |
3165 | 3177 | |
3166 | 3178 | |
... | ... | @@ -3200,11 +3212,26 @@ |
3200 | 3212 | /* (assignments unknown, please report if found) */ |
3201 | 3213 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, |
3202 | 3214 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, |
3215 | + }, | |
3203 | 3216 | }; |
3204 | 3217 | |
3205 | -#define TPACPI_HOTKEY_MAP_SIZE sizeof(ibm_keycode_map) | |
3206 | -#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(ibm_keycode_map[0]) | |
3218 | + static const struct tpacpi_quirk tpacpi_keymap_qtable[] __initconst = { | |
3219 | + /* Generic maps (fallback) */ | |
3220 | + { | |
3221 | + .vendor = PCI_VENDOR_ID_IBM, | |
3222 | + .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY, | |
3223 | + .quirks = TPACPI_KEYMAP_IBM_GENERIC, | |
3224 | + }, | |
3225 | + { | |
3226 | + .vendor = PCI_VENDOR_ID_LENOVO, | |
3227 | + .bios = TPACPI_MATCH_ANY, .ec = TPACPI_MATCH_ANY, | |
3228 | + .quirks = TPACPI_KEYMAP_LENOVO_GENERIC, | |
3229 | + }, | |
3230 | + }; | |
3207 | 3231 | |
3232 | +#define TPACPI_HOTKEY_MAP_SIZE sizeof(tpacpi_keymap_t) | |
3233 | +#define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(tpacpi_keymap_t[0]) | |
3234 | + | |
3208 | 3235 | int res, i; |
3209 | 3236 | int status; |
3210 | 3237 | int hkeyv; |
... | ... | @@ -3212,6 +3239,7 @@ |
3212 | 3239 | bool tabletsw_state = false; |
3213 | 3240 | |
3214 | 3241 | unsigned long quirks; |
3242 | + unsigned long keymap_id; | |
3215 | 3243 | |
3216 | 3244 | vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, |
3217 | 3245 | "initializing hotkey subdriver\n"); |
... | ... | @@ -3352,7 +3380,6 @@ |
3352 | 3380 | goto err_exit; |
3353 | 3381 | |
3354 | 3382 | /* Set up key map */ |
3355 | - | |
3356 | 3383 | hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, |
3357 | 3384 | GFP_KERNEL); |
3358 | 3385 | if (!hotkey_keycode_map) { |
... | ... | @@ -3362,17 +3389,14 @@ |
3362 | 3389 | goto err_exit; |
3363 | 3390 | } |
3364 | 3391 | |
3365 | - if (tpacpi_is_lenovo()) { | |
3366 | - dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, | |
3367 | - "using Lenovo default hot key map\n"); | |
3368 | - memcpy(hotkey_keycode_map, &lenovo_keycode_map, | |
3369 | - TPACPI_HOTKEY_MAP_SIZE); | |
3370 | - } else { | |
3371 | - dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, | |
3372 | - "using IBM default hot key map\n"); | |
3373 | - memcpy(hotkey_keycode_map, &ibm_keycode_map, | |
3374 | - TPACPI_HOTKEY_MAP_SIZE); | |
3375 | - } | |
3392 | + keymap_id = tpacpi_check_quirks(tpacpi_keymap_qtable, | |
3393 | + ARRAY_SIZE(tpacpi_keymap_qtable)); | |
3394 | + BUG_ON(keymap_id >= ARRAY_SIZE(tpacpi_keymaps)); | |
3395 | + dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, | |
3396 | + "using keymap number %lu\n", keymap_id); | |
3397 | + | |
3398 | + memcpy(hotkey_keycode_map, &tpacpi_keymaps[keymap_id], | |
3399 | + TPACPI_HOTKEY_MAP_SIZE); | |
3376 | 3400 | |
3377 | 3401 | input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN); |
3378 | 3402 | tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; |