diff options
Diffstat (limited to 'drivers/misc/thinkpad_acpi.c')
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 166 |
1 files changed, 102 insertions, 64 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index f6cd34a3dbac..0222bbaf7b76 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
@@ -21,7 +21,7 @@ | |||
21 | * 02110-1301, USA. | 21 | * 02110-1301, USA. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #define IBM_VERSION "0.15" | 24 | #define IBM_VERSION "0.16" |
25 | #define TPACPI_SYSFS_VERSION 0x010000 | 25 | #define TPACPI_SYSFS_VERSION 0x010000 |
26 | 26 | ||
27 | /* | 27 | /* |
@@ -906,9 +906,26 @@ static ssize_t hotkey_radio_sw_show(struct device *dev, | |||
906 | static struct device_attribute dev_attr_hotkey_radio_sw = | 906 | static struct device_attribute dev_attr_hotkey_radio_sw = |
907 | __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL); | 907 | __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL); |
908 | 908 | ||
909 | /* 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 | |||
909 | /* --------------------------------------------------------------------- */ | 921 | /* --------------------------------------------------------------------- */ |
910 | 922 | ||
911 | static struct attribute *hotkey_mask_attributes[] = { | 923 | 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 = { | ||
912 | &dev_attr_hotkey_mask.attr, | 929 | &dev_attr_hotkey_mask.attr, |
913 | &dev_attr_hotkey_bios_enabled.attr, | 930 | &dev_attr_hotkey_bios_enabled.attr, |
914 | &dev_attr_hotkey_bios_mask.attr, | 931 | &dev_attr_hotkey_bios_mask.attr, |
@@ -987,11 +1004,12 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
987 | str_supported(tp_features.hotkey)); | 1004 | str_supported(tp_features.hotkey)); |
988 | 1005 | ||
989 | if (tp_features.hotkey) { | 1006 | if (tp_features.hotkey) { |
990 | hotkey_dev_attributes = create_attr_set(7, NULL); | 1007 | hotkey_dev_attributes = create_attr_set(8, NULL); |
991 | if (!hotkey_dev_attributes) | 1008 | if (!hotkey_dev_attributes) |
992 | return -ENOMEM; | 1009 | return -ENOMEM; |
993 | res = add_to_attr_set(hotkey_dev_attributes, | 1010 | res = add_many_to_attr_set(hotkey_dev_attributes, |
994 | &dev_attr_hotkey_enable.attr); | 1011 | hotkey_attributes, |
1012 | ARRAY_SIZE(hotkey_attributes)); | ||
995 | if (res) | 1013 | if (res) |
996 | return res; | 1014 | return res; |
997 | 1015 | ||
@@ -1055,11 +1073,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
1055 | TPACPI_HOTKEY_MAP_SIZE); | 1073 | TPACPI_HOTKEY_MAP_SIZE); |
1056 | } | 1074 | } |
1057 | 1075 | ||
1058 | #ifndef CONFIG_THINKPAD_ACPI_INPUT_ENABLED | ||
1059 | for (i = 0; i < 12; i++) | ||
1060 | hotkey_keycode_map[i] = KEY_UNKNOWN; | ||
1061 | #endif /* ! CONFIG_THINKPAD_ACPI_INPUT_ENABLED */ | ||
1062 | |||
1063 | set_bit(EV_KEY, tpacpi_inputdev->evbit); | 1076 | set_bit(EV_KEY, tpacpi_inputdev->evbit); |
1064 | set_bit(EV_MSC, tpacpi_inputdev->evbit); | 1077 | set_bit(EV_MSC, tpacpi_inputdev->evbit); |
1065 | set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); | 1078 | set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); |
@@ -1081,14 +1094,17 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
1081 | set_bit(SW_RADIO, tpacpi_inputdev->swbit); | 1094 | set_bit(SW_RADIO, tpacpi_inputdev->swbit); |
1082 | } | 1095 | } |
1083 | 1096 | ||
1084 | #ifdef CONFIG_THINKPAD_ACPI_INPUT_ENABLED | ||
1085 | dbg_printk(TPACPI_DBG_INIT, | 1097 | dbg_printk(TPACPI_DBG_INIT, |
1086 | "enabling hot key handling\n"); | 1098 | "enabling hot key handling\n"); |
1087 | res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask) | 1099 | res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask) |
1088 | | hotkey_orig_mask); | 1100 | | hotkey_orig_mask); |
1089 | if (res) | 1101 | if (res) |
1090 | return res; | 1102 | return res; |
1091 | #endif /* CONFIG_THINKPAD_ACPI_INPUT_ENABLED */ | 1103 | |
1104 | dbg_printk(TPACPI_DBG_INIT, | ||
1105 | "legacy hot key reporting over procfs %s\n", | ||
1106 | (hotkey_report_mode < 2) ? | ||
1107 | "enabled" : "disabled"); | ||
1092 | } | 1108 | } |
1093 | 1109 | ||
1094 | return (tp_features.hotkey)? 0 : 1; | 1110 | return (tp_features.hotkey)? 0 : 1; |
@@ -1142,58 +1158,65 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) | |||
1142 | { | 1158 | { |
1143 | u32 hkey; | 1159 | u32 hkey; |
1144 | unsigned int keycode, scancode; | 1160 | unsigned int keycode, scancode; |
1145 | int sendacpi = 1; | 1161 | int send_acpi_ev = 0; |
1146 | 1162 | ||
1147 | if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) { | 1163 | if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) { |
1148 | if (tpacpi_inputdev->users > 0) { | 1164 | switch (hkey >> 12) { |
1149 | switch (hkey >> 12) { | 1165 | case 1: |
1150 | case 1: | 1166 | /* 0x1000-0x1FFF: key presses */ |
1151 | /* 0x1000-0x1FFF: key presses */ | 1167 | scancode = hkey & 0xfff; |
1152 | scancode = hkey & 0xfff; | 1168 | if (scancode > 0 && scancode < 0x21) { |
1153 | if (scancode > 0 && scancode < 0x21) { | 1169 | scancode--; |
1154 | scancode--; | 1170 | keycode = hotkey_keycode_map[scancode]; |
1155 | keycode = hotkey_keycode_map[scancode]; | 1171 | tpacpi_input_send_key(scancode, keycode); |
1156 | tpacpi_input_send_key(scancode, keycode); | 1172 | } else { |
1157 | sendacpi = (keycode == KEY_RESERVED | 1173 | printk(IBM_ERR |
1158 | || keycode == KEY_UNKNOWN); | 1174 | "hotkey 0x%04x out of range for keyboard map\n", |
1159 | } else { | 1175 | hkey); |
1160 | printk(IBM_ERR | 1176 | send_acpi_ev = 1; |
1161 | "hotkey 0x%04x out of range for keyboard map\n", | 1177 | } |
1162 | hkey); | 1178 | break; |
1163 | } | 1179 | case 5: |
1164 | break; | 1180 | /* 0x5000-0x5FFF: LID */ |
1165 | case 5: | 1181 | /* we don't handle it through this path, just |
1166 | /* 0x5000-0x5FFF: LID */ | 1182 | * eat up known LID events */ |
1167 | /* we don't handle it through this path, just | 1183 | if (hkey != 0x5001 && hkey != 0x5002) { |
1168 | * eat up known LID events */ | 1184 | printk(IBM_ERR |
1169 | if (hkey != 0x5001 && hkey != 0x5002) { | 1185 | "unknown LID-related hotkey event: 0x%04x\n", |
1170 | printk(IBM_ERR | 1186 | hkey); |
1171 | "unknown LID-related hotkey event: 0x%04x\n", | 1187 | send_acpi_ev = 1; |
1172 | hkey); | 1188 | } |
1173 | } | 1189 | break; |
1190 | case 7: | ||
1191 | /* 0x7000-0x7FFF: misc */ | ||
1192 | if (tp_features.hotkey_wlsw && hkey == 0x7000) { | ||
1193 | tpacpi_input_send_radiosw(); | ||
1174 | break; | 1194 | break; |
1175 | case 7: | ||
1176 | /* 0x7000-0x7FFF: misc */ | ||
1177 | if (tp_features.hotkey_wlsw && hkey == 0x7000) { | ||
1178 | tpacpi_input_send_radiosw(); | ||
1179 | sendacpi = 0; | ||
1180 | break; | ||
1181 | } | ||
1182 | /* fallthrough to default */ | ||
1183 | default: | ||
1184 | /* case 2: dock-related */ | ||
1185 | /* 0x2305 - T43 waking up due to bay lever eject while aslept */ | ||
1186 | /* case 3: ultra-bay related. maybe bay in dock? */ | ||
1187 | /* 0x3003 - T43 after wake up by bay lever eject (0x2305) */ | ||
1188 | printk(IBM_NOTICE "unhandled hotkey event 0x%04x\n", hkey); | ||
1189 | } | 1195 | } |
1196 | /* fallthrough to default */ | ||
1197 | default: | ||
1198 | /* case 2: dock-related */ | ||
1199 | /* 0x2305 - T43 waking up due to bay lever eject while aslept */ | ||
1200 | /* case 3: ultra-bay related. maybe bay in dock? */ | ||
1201 | /* 0x3003 - T43 after wake up by bay lever eject (0x2305) */ | ||
1202 | printk(IBM_NOTICE "unhandled HKEY event 0x%04x\n", hkey); | ||
1203 | send_acpi_ev = 1; | ||
1190 | } | 1204 | } |
1191 | |||
1192 | if (sendacpi) | ||
1193 | acpi_bus_generate_event(ibm->acpi->device, event, hkey); | ||
1194 | } else { | 1205 | } else { |
1195 | printk(IBM_ERR "unknown hotkey notification event %d\n", event); | 1206 | printk(IBM_ERR "unknown hotkey notification event %d\n", event); |
1196 | acpi_bus_generate_event(ibm->acpi->device, event, 0); | 1207 | hkey = 0; |
1208 | send_acpi_ev = 1; | ||
1209 | } | ||
1210 | |||
1211 | /* Legacy events */ | ||
1212 | if (send_acpi_ev || hotkey_report_mode < 2) | ||
1213 | acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey); | ||
1214 | |||
1215 | /* netlink events */ | ||
1216 | if (send_acpi_ev) { | ||
1217 | acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, | ||
1218 | ibm->acpi->device->dev.bus_id, | ||
1219 | event, hkey); | ||
1197 | } | 1220 | } |
1198 | } | 1221 | } |
1199 | 1222 | ||
@@ -2162,22 +2185,27 @@ static void dock_notify(struct ibm_struct *ibm, u32 event) | |||
2162 | int docked = dock_docked(); | 2185 | int docked = dock_docked(); |
2163 | int pci = ibm->acpi->hid && ibm->acpi->device && | 2186 | int pci = ibm->acpi->hid && ibm->acpi->device && |
2164 | acpi_match_device_ids(ibm->acpi->device, ibm_pci_device_ids); | 2187 | acpi_match_device_ids(ibm->acpi->device, ibm_pci_device_ids); |
2188 | int data; | ||
2165 | 2189 | ||
2166 | if (event == 1 && !pci) /* 570 */ | 2190 | if (event == 1 && !pci) /* 570 */ |
2167 | acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */ | 2191 | data = 1; /* button */ |
2168 | else if (event == 1 && pci) /* 570 */ | 2192 | else if (event == 1 && pci) /* 570 */ |
2169 | acpi_bus_generate_event(ibm->acpi->device, event, 3); /* dock */ | 2193 | data = 3; /* dock */ |
2170 | else if (event == 3 && docked) | 2194 | else if (event == 3 && docked) |
2171 | acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */ | 2195 | data = 1; /* button */ |
2172 | else if (event == 3 && !docked) | 2196 | else if (event == 3 && !docked) |
2173 | acpi_bus_generate_event(ibm->acpi->device, event, 2); /* undock */ | 2197 | data = 2; /* undock */ |
2174 | else if (event == 0 && docked) | 2198 | else if (event == 0 && docked) |
2175 | acpi_bus_generate_event(ibm->acpi->device, event, 3); /* dock */ | 2199 | data = 3; /* dock */ |
2176 | else { | 2200 | else { |
2177 | printk(IBM_ERR "unknown dock event %d, status %d\n", | 2201 | printk(IBM_ERR "unknown dock event %d, status %d\n", |
2178 | event, _sta(dock_handle)); | 2202 | event, _sta(dock_handle)); |
2179 | acpi_bus_generate_event(ibm->acpi->device, event, 0); /* unknown */ | 2203 | data = 0; /* unknown */ |
2180 | } | 2204 | } |
2205 | acpi_bus_generate_proc_event(ibm->acpi->device, event, data); | ||
2206 | acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, | ||
2207 | ibm->acpi->device->dev.bus_id, | ||
2208 | event, data); | ||
2181 | } | 2209 | } |
2182 | 2210 | ||
2183 | static int dock_read(char *p) | 2211 | static int dock_read(char *p) |
@@ -2275,7 +2303,10 @@ static int __init bay_init(struct ibm_init_struct *iibm) | |||
2275 | 2303 | ||
2276 | static void bay_notify(struct ibm_struct *ibm, u32 event) | 2304 | static void bay_notify(struct ibm_struct *ibm, u32 event) |
2277 | { | 2305 | { |
2278 | acpi_bus_generate_event(ibm->acpi->device, event, 0); | 2306 | acpi_bus_generate_proc_event(ibm->acpi->device, event, 0); |
2307 | acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, | ||
2308 | ibm->acpi->device->dev.bus_id, | ||
2309 | event, 0); | ||
2279 | } | 2310 | } |
2280 | 2311 | ||
2281 | #define bay_occupied(b) (_sta(b##_handle) & 1) | 2312 | #define bay_occupied(b) (_sta(b##_handle) & 1) |
@@ -4615,6 +4646,9 @@ module_param_named(fan_control, fan_control_allowed, bool, 0); | |||
4615 | static int brightness_mode; | 4646 | static int brightness_mode; |
4616 | module_param_named(brightness_mode, brightness_mode, int, 0); | 4647 | module_param_named(brightness_mode, brightness_mode, int, 0); |
4617 | 4648 | ||
4649 | static unsigned int hotkey_report_mode; | ||
4650 | module_param(hotkey_report_mode, uint, 0); | ||
4651 | |||
4618 | #define IBM_PARAM(feature) \ | 4652 | #define IBM_PARAM(feature) \ |
4619 | module_param_call(feature, set_ibm_param, NULL, NULL, 0) | 4653 | module_param_call(feature, set_ibm_param, NULL, NULL, 0) |
4620 | 4654 | ||
@@ -4640,6 +4674,10 @@ static int __init thinkpad_acpi_module_init(void) | |||
4640 | { | 4674 | { |
4641 | int ret, i; | 4675 | int ret, i; |
4642 | 4676 | ||
4677 | /* Parameter checking */ | ||
4678 | if (hotkey_report_mode > 2) | ||
4679 | return -EINVAL; | ||
4680 | |||
4643 | /* Driver-level probe */ | 4681 | /* Driver-level probe */ |
4644 | 4682 | ||
4645 | get_thinkpad_model_data(&thinkpad_id); | 4683 | get_thinkpad_model_data(&thinkpad_id); |