···1 ThinkPad ACPI Extras Driver23- Version 0.154- July 1st, 200756 Borislav Deianov <borislav@users.sf.net>7 Henrique de Moraes Holschuh <hmh@hmh.eng.br>···161firmware that such a driver is present, and modifies how the ThinkPad162firmware will behave in many situations.16300000164When the hotkey feature is enabled and the hot key mask is set (see165-below), the various hot keys either generate ACPI events in the166-following format:167168 ibm/hotkey HKEY 00000080 0000xxxx169170-or events over the input layer. The input layer support accepts the171-standard IOCTLs to remap the keycodes assigned to each hotkey.172173-When the input device is open, the driver will suppress any ACPI hot key174-events that get translated into a meaningful input layer event, in order175-to avoid sending duplicate events to userspace. Hot keys that are176-mapped to KEY_RESERVED in the keymap are not translated, and will always177-generate an ACPI ibm/hotkey HKEY event, and no input layer events.178179The hot key bit mask allows some control over which hot keys generate180events. If a key is "masked" (bit set to 0 in the mask), the firmware···257 attribute will read 0 if the switch is in the "radios258 disabled" postition, and 1 if the switch is in the259 "radios enabled" position.00000000000000260261input layer notes:262···409hot key press or release, but the firmware will do it for either one, not410both.411412-If a key is mapped to KEY_RESERVED, it generates no input events at all,413-and it may generate a legacy thinkpad-acpi ACPI hotkey event.414-415If a key is mapped to KEY_UNKNOWN, it generates an input event that416-includes an scan code, and it may also generate a legacy thinkpad-acpi417-ACPI hotkey event.418-419-If a key is mapped to anything else, it will only generate legacy420-thinkpad-acpi ACPI hotkey events if nobody has opened the input device.421422Non hot-key ACPI HKEY event map:4230x5001 Lid closed4240x5002 Lid opened4250x7000 Radio Switch may have changed state00000000000000000000000000000000000000000000000426427428Bluetooth
···1 ThinkPad ACPI Extras Driver23+ Version 0.164+ August 2nd, 200756 Borislav Deianov <borislav@users.sf.net>7 Henrique de Moraes Holschuh <hmh@hmh.eng.br>···161firmware that such a driver is present, and modifies how the ThinkPad162firmware will behave in many situations.163164+The driver enables the hot key feature automatically when loaded. The165+feature can later be disabled and enabled back at runtime. The driver166+will also restore the hot key feature to its previous state and mask167+when it is unloaded.168+169When the hotkey feature is enabled and the hot key mask is set (see170+below), the driver will report HKEY events in the following format:0171172 ibm/hotkey HKEY 00000080 0000xxxx173174+Some of these events refer to hot key presses, but not all.0175176+The driver will generate events over the input layer for hot keys and177+radio switches, and over the ACPI netlink layer for other events. The178+input layer support accepts the standard IOCTLs to remap the keycodes179+assigned to each hot key.0180181The hot key bit mask allows some control over which hot keys generate182events. If a key is "masked" (bit set to 0 in the mask), the firmware···255 attribute will read 0 if the switch is in the "radios256 disabled" postition, and 1 if the switch is in the257 "radios enabled" position.258+259+ hotkey_report_mode:260+ Returns the state of the procfs ACPI event report mode261+ filter for hot keys. If it is set to 1 (the default),262+ all hot key presses are reported both through the input263+ layer and also as ACPI events through procfs (but not264+ through netlink). If it is set to 2, hot key presses265+ are reported only through the input layer.266+267+ This attribute is read-only in kernels 2.6.23 or later,268+ and read-write on earlier kernels.269+270+ May return -EPERM (write access locked out by module271+ parameter) or -EACCES (read-only).272273input layer notes:274···393hot key press or release, but the firmware will do it for either one, not394both.395396+If a key is mapped to KEY_RESERVED, it generates no input events at all.00397If a key is mapped to KEY_UNKNOWN, it generates an input event that398+includes an scan code. If a key is mapped to anything else, it will399+generate input device EV_KEY events.000400401Non hot-key ACPI HKEY event map:4020x5001 Lid closed4030x5002 Lid opened4040x7000 Radio Switch may have changed state405+406+The above events are not propagated by the driver, except for legacy407+compatibility purposes when hotkey_report_mode is set to 1.408+409+Compatibility notes:410+411+ibm-acpi and thinkpad-acpi 0.15 (mainline kernels before 2.6.23) never412+supported the input layer, and sent events over the procfs ACPI event413+interface.414+415+To avoid sending duplicate events over the input layer and the ACPI416+event interface, thinkpad-acpi 0.16 implements a module parameter417+(hotkey_report_mode), and also a sysfs device attribute with the same418+name.419+420+Make no mistake here: userspace is expected to switch to using the input421+layer interface of thinkpad-acpi, together with the ACPI netlink event422+interface in kernels 2.6.23 and later, or with the ACPI procfs event423+interface in kernels 2.6.22 and earlier.424+425+If no hotkey_report_mode module parameter is specified (or it is set to426+zero), the driver defaults to mode 1 (see below), and on kernels 2.6.22427+and earlier, also allows one to change the hotkey_report_mode through428+sysfs. In kernels 2.6.23 and later, where the netlink ACPI event429+interface is available, hotkey_report_mode cannot be changed through430+sysfs (it is read-only).431+432+If the hotkey_report_mode module parameter is set to 1 or 2, it cannot433+be changed later through sysfs (any writes will return -EPERM to signal434+that hotkey_report_mode was locked. On 2.6.23 and later, where435+hotkey_report_mode cannot be changed at all, writes will return -EACES).436+437+hotkey_report_mode set to 1 makes the driver export through the procfs438+ACPI event interface all hot key presses (which are *also* sent to the439+input layer). This is a legacy compatibility behaviour, and it is also440+the default mode of operation for the driver.441+442+hotkey_report_mode set to 2 makes the driver filter out the hot key443+presses from the procfs ACPI event interface, so these events will only444+be sent through the input layer. Userspace that has been updated to use445+the thinkpad-acpi input layer interface should set hotkey_report_mode to446+2.447+448+Hot key press events are never sent to the ACPI netlink event interface.449+Really up-to-date userspace under kernel 2.6.23 and later is to use the450+netlink interface and the input layer interface, and don't bother at all451+with hotkey_report_mode.452453454Bluetooth
-20
drivers/misc/Kconfig
···202203 If you are not sure, say Y here.204205-config THINKPAD_ACPI_INPUT_ENABLED206- bool "Enable input layer support by default"207- depends on THINKPAD_ACPI208- default n209- ---help---210- This option enables thinkpad-acpi hot key handling over the input211- layer at driver load time. When it is unset, the driver does not212- enable hot key handling by default, and also starts up with a mostly213- empty keymap.214-215- This option should be enabled if you have a new enough HAL or other216- userspace support that properly handles the thinkpad-acpi event217- device. It auto-tunes the hot key support to those reported by the218- firmware and enables it automatically.219-220- If unsure, say N here to retain the old behaviour of ibm-acpi, and221- thinkpad-acpi up to kernel 2.6.21: userspace will have to enable and222- set up the thinkpad-acpi hot key handling using the sysfs interace223- after loading the driver.224-225226endif # MISC_DEVICES
···202203 If you are not sure, say Y here.20400000000000000000000205206endif # MISC_DEVICES
+88-58
drivers/misc/thinkpad_acpi.c
···21 * 02110-1301, USA.22 */2324-#define IBM_VERSION "0.15"25#define TPACPI_SYSFS_VERSION 0x0100002627/*···906static struct device_attribute dev_attr_hotkey_radio_sw =907 __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL);908000000000000909/* --------------------------------------------------------------------- */910911-static struct attribute *hotkey_mask_attributes[] = {00000912 &dev_attr_hotkey_mask.attr,913 &dev_attr_hotkey_bios_enabled.attr,914 &dev_attr_hotkey_bios_mask.attr,···1004 str_supported(tp_features.hotkey));10051006 if (tp_features.hotkey) {1007- hotkey_dev_attributes = create_attr_set(7, NULL);1008 if (!hotkey_dev_attributes)1009 return -ENOMEM;1010- res = add_to_attr_set(hotkey_dev_attributes,1011- &dev_attr_hotkey_enable.attr);01012 if (res)1013 return res;1014···1073 TPACPI_HOTKEY_MAP_SIZE);1074 }10751076-#ifndef CONFIG_THINKPAD_ACPI_INPUT_ENABLED1077- for (i = 0; i < 12; i++)1078- hotkey_keycode_map[i] = KEY_UNKNOWN;1079-#endif /* ! CONFIG_THINKPAD_ACPI_INPUT_ENABLED */1080-1081 set_bit(EV_KEY, tpacpi_inputdev->evbit);1082 set_bit(EV_MSC, tpacpi_inputdev->evbit);1083 set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);···1094 set_bit(SW_RADIO, tpacpi_inputdev->swbit);1095 }10961097-#ifdef CONFIG_THINKPAD_ACPI_INPUT_ENABLED1098 dbg_printk(TPACPI_DBG_INIT,1099 "enabling hot key handling\n");1100 res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask)1101 | hotkey_orig_mask);1102 if (res)1103 return res;1104-#endif /* CONFIG_THINKPAD_ACPI_INPUT_ENABLED */00001105 }11061107 return (tp_features.hotkey)? 0 : 1;···1158{1159 u32 hkey;1160 unsigned int keycode, scancode;1161- int sendacpi = 1;11621163 if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {1164- if (tpacpi_inputdev->users > 0) {1165- switch (hkey >> 12) {1166- case 1:1167- /* 0x1000-0x1FFF: key presses */1168- scancode = hkey & 0xfff;1169- if (scancode > 0 && scancode < 0x21) {1170- scancode--;1171- keycode = hotkey_keycode_map[scancode];1172- tpacpi_input_send_key(scancode, keycode);1173- sendacpi = (keycode == KEY_RESERVED1174- || keycode == KEY_UNKNOWN);1175- } else {1176- printk(IBM_ERR1177- "hotkey 0x%04x out of range for keyboard map\n",1178- hkey);1179- }1180- break;1181- case 5:1182- /* 0x5000-0x5FFF: LID */1183- /* we don't handle it through this path, just1184- * eat up known LID events */1185- if (hkey != 0x5001 && hkey != 0x5002) {1186- printk(IBM_ERR1187- "unknown LID-related hotkey event: 0x%04x\n",1188- hkey);1189- }1190- break;1191- case 7:1192- /* 0x7000-0x7FFF: misc */1193- if (tp_features.hotkey_wlsw && hkey == 0x7000) {1194- tpacpi_input_send_radiosw();1195- sendacpi = 0;1196- break;1197- }1198- /* fallthrough to default */1199- default:1200- /* case 2: dock-related */1201- /* 0x2305 - T43 waking up due to bay lever eject while aslept */1202- /* case 3: ultra-bay related. maybe bay in dock? */1203- /* 0x3003 - T43 after wake up by bay lever eject (0x2305) */1204- printk(IBM_NOTICE "unhandled hotkey event 0x%04x\n", hkey);1205 }000000000000000000000000001206 }1207-1208- if (sendacpi)1209- acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey);1210 } else {1211 printk(IBM_ERR "unknown hotkey notification event %d\n", event);1212- acpi_bus_generate_proc_event(ibm->acpi->device, event, 0);0000000000001213 }1214}1215···4646static int brightness_mode;4647module_param_named(brightness_mode, brightness_mode, int, 0);46480004649#define IBM_PARAM(feature) \4650 module_param_call(feature, set_ibm_param, NULL, NULL, 0)4651···4673static int __init thinkpad_acpi_module_init(void)4674{4675 int ret, i;000046764677 /* Driver-level probe */4678
···21 * 02110-1301, USA.22 */2324+#define IBM_VERSION "0.16"25#define TPACPI_SYSFS_VERSION 0x0100002627/*···906static struct device_attribute dev_attr_hotkey_radio_sw =907 __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL);908909+/* sysfs hotkey report_mode -------------------------------------------- */910+static ssize_t hotkey_report_mode_show(struct device *dev,911+ struct device_attribute *attr,912+ char *buf)913+{914+ return snprintf(buf, PAGE_SIZE, "%d\n",915+ (hotkey_report_mode != 0) ? hotkey_report_mode : 1);916+}917+918+static struct device_attribute dev_attr_hotkey_report_mode =919+ __ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL);920+921/* --------------------------------------------------------------------- */922923+static struct attribute *hotkey_attributes[] __initdata = {924+ &dev_attr_hotkey_enable.attr,925+ &dev_attr_hotkey_report_mode.attr,926+};927+928+static struct attribute *hotkey_mask_attributes[] __initdata = {929 &dev_attr_hotkey_mask.attr,930 &dev_attr_hotkey_bios_enabled.attr,931 &dev_attr_hotkey_bios_mask.attr,···987 str_supported(tp_features.hotkey));988989 if (tp_features.hotkey) {990+ hotkey_dev_attributes = create_attr_set(8, NULL);991 if (!hotkey_dev_attributes)992 return -ENOMEM;993+ res = add_many_to_attr_set(hotkey_dev_attributes,994+ hotkey_attributes,995+ ARRAY_SIZE(hotkey_attributes));996 if (res)997 return res;998···1055 TPACPI_HOTKEY_MAP_SIZE);1056 }1057000001058 set_bit(EV_KEY, tpacpi_inputdev->evbit);1059 set_bit(EV_MSC, tpacpi_inputdev->evbit);1060 set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);···1081 set_bit(SW_RADIO, tpacpi_inputdev->swbit);1082 }108301084 dbg_printk(TPACPI_DBG_INIT,1085 "enabling hot key handling\n");1086 res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask)1087 | hotkey_orig_mask);1088 if (res)1089 return res;1090+1091+ dbg_printk(TPACPI_DBG_INIT,1092+ "legacy hot key reporting over procfs %s\n",1093+ (hotkey_report_mode < 2) ?1094+ "enabled" : "disabled");1095 }10961097 return (tp_features.hotkey)? 0 : 1;···1142{1143 u32 hkey;1144 unsigned int keycode, scancode;1145+ int send_acpi_ev = 0;11461147 if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {1148+ switch (hkey >> 12) {1149+ case 1:1150+ /* 0x1000-0x1FFF: key presses */1151+ scancode = hkey & 0xfff;1152+ if (scancode > 0 && scancode < 0x21) {1153+ scancode--;1154+ keycode = hotkey_keycode_map[scancode];1155+ tpacpi_input_send_key(scancode, keycode);1156+ } else {1157+ printk(IBM_ERR1158+ "hotkey 0x%04x out of range for keyboard map\n",1159+ hkey);1160+ send_acpi_ev = 1;00000000000000000000000000001161 }1162+ break;1163+ case 5:1164+ /* 0x5000-0x5FFF: LID */1165+ /* we don't handle it through this path, just1166+ * eat up known LID events */1167+ if (hkey != 0x5001 && hkey != 0x5002) {1168+ printk(IBM_ERR1169+ "unknown LID-related hotkey event: 0x%04x\n",1170+ hkey);1171+ send_acpi_ev = 1;1172+ }1173+ break;1174+ case 7:1175+ /* 0x7000-0x7FFF: misc */1176+ if (tp_features.hotkey_wlsw && hkey == 0x7000) {1177+ tpacpi_input_send_radiosw();1178+ break;1179+ }1180+ /* fallthrough to default */1181+ default:1182+ /* case 2: dock-related */1183+ /* 0x2305 - T43 waking up due to bay lever eject while aslept */1184+ /* case 3: ultra-bay related. maybe bay in dock? */1185+ /* 0x3003 - T43 after wake up by bay lever eject (0x2305) */1186+ printk(IBM_NOTICE "unhandled HKEY event 0x%04x\n", hkey);1187+ send_acpi_ev = 1;1188 }0001189 } else {1190 printk(IBM_ERR "unknown hotkey notification event %d\n", event);1191+ hkey = 0;1192+ send_acpi_ev = 1;1193+ }1194+1195+ /* Legacy events */1196+ if (send_acpi_ev || hotkey_report_mode < 2)1197+ acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey);1198+1199+ /* netlink events */1200+ if (send_acpi_ev) {1201+ acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,1202+ ibm->acpi->device->dev.bus_id,1203+ event, hkey);1204 }1205}1206···4623static int brightness_mode;4624module_param_named(brightness_mode, brightness_mode, int, 0);46254626+static unsigned int hotkey_report_mode;4627+module_param(hotkey_report_mode, uint, 0);4628+4629#define IBM_PARAM(feature) \4630 module_param_call(feature, set_ibm_param, NULL, NULL, 0)4631···4647static int __init thinkpad_acpi_module_init(void)4648{4649 int ret, i;4650+4651+ /* Parameter checking */4652+ if (hotkey_report_mode > 2)4653+ return -EINVAL;46544655 /* Driver-level probe */4656
+1
drivers/misc/thinkpad_acpi.h
···181static int experimental;182static u32 dbg_level;183static int force_load;0184185static int thinkpad_acpi_module_init(void);186static void thinkpad_acpi_module_exit(void);
···181static int experimental;182static u32 dbg_level;183static int force_load;184+static unsigned int hotkey_report_mode;185186static int thinkpad_acpi_module_init(void);187static void thinkpad_acpi_module_exit(void);