diff options
-rw-r--r-- | Documentation/thinkpad-acpi.txt | 151 | ||||
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 108 |
2 files changed, 255 insertions, 4 deletions
diff --git a/Documentation/thinkpad-acpi.txt b/Documentation/thinkpad-acpi.txt index bd00d14538c6..91d08921a4ca 100644 --- a/Documentation/thinkpad-acpi.txt +++ b/Documentation/thinkpad-acpi.txt | |||
@@ -167,6 +167,17 @@ All labeled Fn-Fx key combinations generate distinct events. In | |||
167 | addition, the lid microswitch and some docking station buttons may | 167 | addition, the lid microswitch and some docking station buttons may |
168 | also generate such events. | 168 | also generate such events. |
169 | 169 | ||
170 | Hot keys also generate regular keyboard key press/release events through | ||
171 | the input layer in addition to the ibm/hotkey ACPI events. The input | ||
172 | layer support accepts the standard IOCTLs to remap the keycodes assigned | ||
173 | to each hotkey. | ||
174 | |||
175 | When the input device is open, the driver will suppress any ACPI hot key | ||
176 | events that get translated into a meaningful input layer event, in order | ||
177 | to avoid sending duplicate events to userspace. Hot keys that are | ||
178 | mapped to KEY_RESERVED are not translated, and will always generate only | ||
179 | ACPI hot key event, and no input layer events. | ||
180 | |||
170 | The bit mask allows some control over which hot keys generate ACPI | 181 | The bit mask allows some control over which hot keys generate ACPI |
171 | events. Not all bits in the mask can be modified. Not all bits that can | 182 | events. Not all bits in the mask can be modified. Not all bits that can |
172 | be modified do anything. Not all hot keys can be individually controlled | 183 | be modified do anything. Not all hot keys can be individually controlled |
@@ -248,6 +259,146 @@ sysfs notes: | |||
248 | disabled" postition, and 1 if the switch is in the | 259 | disabled" postition, and 1 if the switch is in the |
249 | "radios enabled" position. | 260 | "radios enabled" position. |
250 | 261 | ||
262 | input layer notes: | ||
263 | |||
264 | A Hot key is mapped to a single input layer EV_KEY event, possibly | ||
265 | followed by an EV_MSC MSC_SCAN event that shall contain that key's scan | ||
266 | code. An EV_SYN event will always be generated to mark the end of the | ||
267 | event block. | ||
268 | |||
269 | Do not use the EV_MSC MSC_SCAN events to process keys. They are to be | ||
270 | used as a helper to remap keys, only. They are particularly useful when | ||
271 | remapping KEY_UNKNOWN keys. | ||
272 | |||
273 | The events are available in an input device, with the following id: | ||
274 | |||
275 | Bus: BUS_HOST | ||
276 | vendor: 0x1014 (PCI_VENDOR_ID_IBM) | ||
277 | product: 0x5054 ("TP") | ||
278 | version: 0x4101 | ||
279 | |||
280 | The version will have its LSB incremented if the keymap changes in a | ||
281 | backwards-compatible way. The MSB shall always be 0x41 for this input | ||
282 | device. If the MSB is not 0x41, do not use the device as described in | ||
283 | this section, as it is either something else (e.g. another input device | ||
284 | exported by a thinkpad driver, such as HDAPS) or its functionality has | ||
285 | been changed in a non-backwards compatible way. | ||
286 | |||
287 | Adding other event types for other functionalities shall be considered a | ||
288 | backwards-compatible change for this input device. | ||
289 | |||
290 | Thinkpad-acpi Hot Key event map (version 0x4101): | ||
291 | |||
292 | ACPI Scan | ||
293 | event code Key Notes | ||
294 | |||
295 | 0x1001 0x00 FN+F1 - | ||
296 | 0x1002 0x01 FN+F2 - | ||
297 | |||
298 | 0x1003 0x02 FN+F3 Many models always report this | ||
299 | hot key, even with hot keys | ||
300 | disabled or with Fn+F3 masked | ||
301 | off | ||
302 | |||
303 | 0x1004 0x03 FN+F4 Sleep button (ACPI sleep button | ||
304 | semanthics, i.e. sleep-to-RAM). | ||
305 | It is always generate some kind | ||
306 | of event, either the hot key | ||
307 | event or a ACPI sleep button | ||
308 | event. The firmware may | ||
309 | refuse to generate further FN+F4 | ||
310 | key presses until a S3 or S4 ACPI | ||
311 | sleep cycle is performed or some | ||
312 | time passes. | ||
313 | |||
314 | 0x1005 0x04 FN+F5 Radio. Enables/disables | ||
315 | the internal BlueTooth hardware | ||
316 | and W-WAN card if left in control | ||
317 | of the firmware. Does not affect | ||
318 | the WLAN card. | ||
319 | |||
320 | 0x1006 0x05 FN+F6 - | ||
321 | |||
322 | 0x1007 0x06 FN+F7 Video output cycle. | ||
323 | Do you feel lucky today? | ||
324 | |||
325 | 0x1008 0x07 FN+F8 - | ||
326 | .. .. .. | ||
327 | 0x100B 0x0A FN+F11 - | ||
328 | |||
329 | 0x100C 0x0B FN+F12 Sleep to disk. You are always | ||
330 | supposed to handle it yourself, | ||
331 | either through the ACPI event, | ||
332 | or through a hotkey event. | ||
333 | The firmware may refuse to | ||
334 | generate further FN+F4 key | ||
335 | press events until a S3 or S4 | ||
336 | ACPI sleep cycle is performed, | ||
337 | or some time passes. | ||
338 | |||
339 | 0x100D 0x0C FN+BACKSPACE - | ||
340 | 0x100E 0x0D FN+INSERT - | ||
341 | 0x100F 0x0E FN+DELETE - | ||
342 | |||
343 | 0x1010 0x0F FN+HOME Brightness up. This key is | ||
344 | always handled by the firmware, | ||
345 | even when unmasked. Just leave | ||
346 | it alone. | ||
347 | 0x1011 0x10 FN+END Brightness down. This key is | ||
348 | always handled by the firmware, | ||
349 | even when unmasked. Just leave | ||
350 | it alone. | ||
351 | 0x1012 0x11 FN+PGUP Thinklight toggle. This key is | ||
352 | always handled by the firmware, | ||
353 | even when unmasked. | ||
354 | |||
355 | 0x1013 0x12 FN+PGDOWN - | ||
356 | |||
357 | 0x1014 0x13 FN+SPACE Zoom key | ||
358 | |||
359 | 0x1015 0x14 VOLUME UP Internal mixer volume up. This | ||
360 | key is always handled by the | ||
361 | firmware, even when unmasked. | ||
362 | 0x1016 0x15 VOLUME DOWN Internal mixer volume up. This | ||
363 | key is always handled by the | ||
364 | firmware, even when unmasked. | ||
365 | 0x1017 0x16 MUTE Mute internal mixer. This | ||
366 | key is always handled by the | ||
367 | firmware, even when unmasked. | ||
368 | |||
369 | 0x1018 0x17 THINKPAD Thinkpad/Access IBM/Lenovo key | ||
370 | |||
371 | 0x1019 0x18 unknown | ||
372 | .. .. .. | ||
373 | 0x1020 0x1F unknown | ||
374 | |||
375 | The ThinkPad firmware does not allow one to differentiate when most hot | ||
376 | keys are pressed or released (either that, or we don't know how to, yet). | ||
377 | For these keys, the driver generates a set of events for a key press and | ||
378 | immediately issues the same set of events for a key release. It is | ||
379 | unknown by the driver if the ThinkPad firmware triggered these events on | ||
380 | hot key press or release, but the firmware will do it for either one, not | ||
381 | both. | ||
382 | |||
383 | If a key is mapped to KEY_RESERVED, it generates no input events at all, | ||
384 | and it may generate a legacy thinkpad-acpi ACPI hotkey event. | ||
385 | |||
386 | If a key is mapped to KEY_UNKNOWN, it generates an input event that | ||
387 | includes an scan code, and it may also generate a legacy thinkpad-acpi | ||
388 | ACPI hotkey event. | ||
389 | |||
390 | If a key is mapped to anything else, it will only generate legacy | ||
391 | thinkpad-acpi ACPI hotkey events if nobody has opened the input device. | ||
392 | |||
393 | For userspace backwards-compatibility purposes, the keycode map is | ||
394 | initially filled with KEY_RESERVED and KEY_UNKNOWN mappings for scan codes | ||
395 | 0x00 to 0x10 (and maybe others). | ||
396 | |||
397 | Non hot-key ACPI HKEY event map: | ||
398 | 0x5001 Lid closed | ||
399 | 0x5002 Lid opened | ||
400 | 0x7000 Radio Switch may have changed state | ||
401 | |||
251 | 402 | ||
252 | Bluetooth | 403 | Bluetooth |
253 | --------- | 404 | --------- |
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 4427c994bc7d..5c1bea1a6c37 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
@@ -730,7 +730,31 @@ static struct ibm_struct thinkpad_acpi_driver_data = { | |||
730 | static int hotkey_orig_status; | 730 | static int hotkey_orig_status; |
731 | static u32 hotkey_orig_mask; | 731 | static u32 hotkey_orig_mask; |
732 | static u32 hotkey_all_mask; | 732 | static u32 hotkey_all_mask; |
733 | static u32 hotkey_reserved_mask = 0x00778000; | 733 | static u32 hotkey_reserved_mask; |
734 | |||
735 | static u16 hotkey_keycode_map[] = { | ||
736 | /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ | ||
737 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
738 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
739 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
740 | /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */ | ||
741 | KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ | ||
742 | KEY_UNKNOWN, /* 0x0D: FN+INSERT */ | ||
743 | KEY_UNKNOWN, /* 0x0E: FN+DELETE */ | ||
744 | KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ | ||
745 | /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ | ||
746 | KEY_RESERVED, /* 0x10: FN+END (brightness down) */ | ||
747 | KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ | ||
748 | KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ | ||
749 | KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ | ||
750 | KEY_RESERVED, /* 0x14: VOLUME UP */ | ||
751 | KEY_RESERVED, /* 0x15: VOLUME DOWN */ | ||
752 | KEY_RESERVED, /* 0x16: MUTE */ | ||
753 | KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ | ||
754 | /* (assignments unknown, please report if found) */ | ||
755 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
756 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
757 | }; | ||
734 | 758 | ||
735 | static struct attribute_set *hotkey_dev_attributes; | 759 | static struct attribute_set *hotkey_dev_attributes; |
736 | 760 | ||
@@ -889,11 +913,13 @@ static struct attribute *hotkey_mask_attributes[] = { | |||
889 | 913 | ||
890 | static int __init hotkey_init(struct ibm_init_struct *iibm) | 914 | static int __init hotkey_init(struct ibm_init_struct *iibm) |
891 | { | 915 | { |
892 | int res; | 916 | int res, i; |
893 | int status; | 917 | int status; |
894 | 918 | ||
895 | vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); | 919 | vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); |
896 | 920 | ||
921 | BUG_ON(!tpacpi_inputdev); | ||
922 | |||
897 | IBM_ACPIHANDLE_INIT(hkey); | 923 | IBM_ACPIHANDLE_INIT(hkey); |
898 | mutex_init(&hotkey_mutex); | 924 | mutex_init(&hotkey_mutex); |
899 | 925 | ||
@@ -950,6 +976,23 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
950 | &tpacpi_pdev->dev.kobj); | 976 | &tpacpi_pdev->dev.kobj); |
951 | if (res) | 977 | if (res) |
952 | return res; | 978 | return res; |
979 | |||
980 | set_bit(EV_KEY, tpacpi_inputdev->evbit); | ||
981 | set_bit(EV_MSC, tpacpi_inputdev->evbit); | ||
982 | set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); | ||
983 | tpacpi_inputdev->keycodesize = sizeof(hotkey_keycode_map[0]); | ||
984 | tpacpi_inputdev->keycodemax = ARRAY_SIZE(hotkey_keycode_map); | ||
985 | tpacpi_inputdev->keycode = &hotkey_keycode_map; | ||
986 | for (i = 0; i < ARRAY_SIZE(hotkey_keycode_map); i++) { | ||
987 | if (hotkey_keycode_map[i] != KEY_RESERVED) { | ||
988 | set_bit(hotkey_keycode_map[i], | ||
989 | tpacpi_inputdev->keybit); | ||
990 | } else { | ||
991 | if (i < sizeof(hotkey_reserved_mask)*8) | ||
992 | hotkey_reserved_mask |= 1 << i; | ||
993 | } | ||
994 | } | ||
995 | |||
953 | } | 996 | } |
954 | 997 | ||
955 | return (tp_features.hotkey)? 0 : 1; | 998 | return (tp_features.hotkey)? 0 : 1; |
@@ -972,12 +1015,69 @@ static void hotkey_exit(void) | |||
972 | } | 1015 | } |
973 | } | 1016 | } |
974 | 1017 | ||
1018 | static void tpacpi_input_send_key(unsigned int scancode, | ||
1019 | unsigned int keycode) | ||
1020 | { | ||
1021 | if (keycode != KEY_RESERVED) { | ||
1022 | input_report_key(tpacpi_inputdev, keycode, 1); | ||
1023 | if (keycode == KEY_UNKNOWN) | ||
1024 | input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, | ||
1025 | scancode); | ||
1026 | input_sync(tpacpi_inputdev); | ||
1027 | |||
1028 | input_report_key(tpacpi_inputdev, keycode, 0); | ||
1029 | if (keycode == KEY_UNKNOWN) | ||
1030 | input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, | ||
1031 | scancode); | ||
1032 | input_sync(tpacpi_inputdev); | ||
1033 | } | ||
1034 | } | ||
1035 | |||
975 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) | 1036 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) |
976 | { | 1037 | { |
977 | int hkey; | 1038 | u32 hkey; |
1039 | unsigned int keycode, scancode; | ||
1040 | int sendacpi = 1; | ||
978 | 1041 | ||
979 | if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) { | 1042 | if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) { |
980 | acpi_bus_generate_event(ibm->acpi->device, event, hkey); | 1043 | if (tpacpi_inputdev->users > 0) { |
1044 | switch (hkey >> 12) { | ||
1045 | case 1: | ||
1046 | /* 0x1000-0x1FFF: key presses */ | ||
1047 | scancode = hkey & 0xfff; | ||
1048 | if (scancode > 0 && scancode < 0x21) { | ||
1049 | scancode--; | ||
1050 | keycode = hotkey_keycode_map[scancode]; | ||
1051 | tpacpi_input_send_key(scancode, keycode); | ||
1052 | sendacpi = (keycode == KEY_RESERVED | ||
1053 | || keycode == KEY_UNKNOWN); | ||
1054 | } else { | ||
1055 | printk(IBM_ERR | ||
1056 | "hotkey 0x%04x out of range for keyboard map\n", | ||
1057 | hkey); | ||
1058 | } | ||
1059 | break; | ||
1060 | case 5: | ||
1061 | /* 0x5000-0x5FFF: LID */ | ||
1062 | /* we don't handle it through this path, just | ||
1063 | * eat up known LID events */ | ||
1064 | if (hkey != 0x5001 && hkey != 0x5002) { | ||
1065 | printk(IBM_ERR | ||
1066 | "unknown LID-related hotkey event: 0x%04x\n", | ||
1067 | hkey); | ||
1068 | } | ||
1069 | break; | ||
1070 | default: | ||
1071 | /* case 2: dock-related */ | ||
1072 | /* 0x2305 - T43 waking up due to bay lever eject while aslept */ | ||
1073 | /* case 3: ultra-bay related. maybe bay in dock? */ | ||
1074 | /* 0x3003 - T43 after wake up by bay lever eject (0x2305) */ | ||
1075 | printk(IBM_NOTICE "unhandled hotkey event 0x%04x\n", hkey); | ||
1076 | } | ||
1077 | } | ||
1078 | |||
1079 | if (sendacpi) | ||
1080 | acpi_bus_generate_event(ibm->acpi->device, event, hkey); | ||
981 | } else { | 1081 | } else { |
982 | printk(IBM_ERR "unknown hotkey notification event %d\n", event); | 1082 | printk(IBM_ERR "unknown hotkey notification event %d\n", event); |
983 | acpi_bus_generate_event(ibm->acpi->device, event, 0); | 1083 | acpi_bus_generate_event(ibm->acpi->device, event, 0); |