diff options
| -rw-r--r-- | Documentation/thinkpad-acpi.txt | 41 | ||||
| -rw-r--r-- | drivers/misc/thinkpad_acpi.c | 38 | ||||
| -rw-r--r-- | drivers/misc/thinkpad_acpi.h | 6 |
3 files changed, 42 insertions, 43 deletions
diff --git a/Documentation/thinkpad-acpi.txt b/Documentation/thinkpad-acpi.txt index b90d9a7e81b8..2f30db0e0db5 100644 --- a/Documentation/thinkpad-acpi.txt +++ b/Documentation/thinkpad-acpi.txt | |||
| @@ -153,29 +153,22 @@ addition, the lid microswitch and some docking station buttons may | |||
| 153 | also generate such events. | 153 | also generate such events. |
| 154 | 154 | ||
| 155 | The bit mask allows some control over which hot keys generate ACPI | 155 | The bit mask allows some control over which hot keys generate ACPI |
| 156 | events. Not all bits in the mask can be modified. Not all bits that | 156 | events. Not all bits in the mask can be modified. Not all bits that can |
| 157 | can be modified do anything. Not all hot keys can be individually | 157 | be modified do anything. Not all hot keys can be individually controlled |
| 158 | controlled by the mask. Most recent ThinkPad models honor the | 158 | by the mask. Some models do not support the mask at all. On those |
| 159 | following bits (assuming the hot keys feature has been enabled): | 159 | models, hot keys cannot be controlled individually. |
| 160 | |||
| 161 | key bit behavior when set behavior when unset | ||
| 162 | |||
| 163 | Fn-F3 always generates ACPI event | ||
| 164 | Fn-F4 always generates ACPI event | ||
| 165 | Fn-F5 0010 generate ACPI event enable/disable Bluetooth | ||
| 166 | Fn-F7 0040 generate ACPI event switch LCD and external display | ||
| 167 | Fn-F8 0080 generate ACPI event expand screen or none | ||
| 168 | Fn-F9 0100 generate ACPI event none | ||
| 169 | Fn-F12 always generates ACPI event | ||
| 170 | |||
| 171 | Some models do not support all of the above. For example, the T30 does | ||
| 172 | not support Fn-F5 and Fn-F9. Other models do not support the mask at | ||
| 173 | all. On those models, hot keys cannot be controlled individually. | ||
| 174 | 160 | ||
| 175 | Note that enabling ACPI events for some keys prevents their default | 161 | Note that enabling ACPI events for some keys prevents their default |
| 176 | behavior. For example, if events for Fn-F5 are enabled, that key will | 162 | behavior. For example, if events for Fn-F5 are enabled, that key will no |
| 177 | no longer enable/disable Bluetooth by itself. This can still be done | 163 | longer enable/disable Bluetooth by itself. This can still be done from |
| 178 | from an acpid handler for the ibm/hotkey event. | 164 | an acpid handler for the ibm/hotkey event. |
| 165 | |||
| 166 | On some models, even enabling/disabling the entire hot key feature may | ||
| 167 | change the way some keys behave (e.g. in a T43, Fn+F4 will generate an | ||
| 168 | button/sleep ACPI event if hot keys are disabled, and it will ignore its | ||
| 169 | mask when hot keys are enabled, so the key always does something. On a | ||
| 170 | X40, Fn+F4 respects its mask status, but generates the button/sleep ACPI | ||
| 171 | event if masked off). | ||
| 179 | 172 | ||
| 180 | Note also that not all Fn key combinations are supported through | 173 | Note also that not all Fn key combinations are supported through |
| 181 | ACPI. For example, on the X40, the brightness, volume and "Access IBM" | 174 | ACPI. For example, on the X40, the brightness, volume and "Access IBM" |
| @@ -189,9 +182,9 @@ The following commands can be written to the /proc/acpi/ibm/hotkey file: | |||
| 189 | 182 | ||
| 190 | echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature | 183 | echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature |
| 191 | echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature | 184 | echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature |
| 192 | echo 0xffff > /proc/acpi/ibm/hotkey -- enable all possible hot keys | 185 | echo 0xffffffff > /proc/acpi/ibm/hotkey -- enable all hot keys |
| 193 | echo 0x0000 > /proc/acpi/ibm/hotkey -- disable all possible hot keys | 186 | echo 0 > /proc/acpi/ibm/hotkey -- disable all possible hot keys |
| 194 | ... any other 4-hex-digit mask ... | 187 | ... any other 8-hex-digit mask ... |
| 195 | echo reset > /proc/acpi/ibm/hotkey -- restore the original mask | 188 | echo reset > /proc/acpi/ibm/hotkey -- restore the original mask |
| 196 | 189 | ||
| 197 | sysfs notes: | 190 | sysfs notes: |
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 9f10b4694eda..450b1e5cd681 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
| @@ -727,7 +727,7 @@ static struct ibm_struct thinkpad_acpi_driver_data = { | |||
| 727 | */ | 727 | */ |
| 728 | 728 | ||
| 729 | static int hotkey_orig_status; | 729 | static int hotkey_orig_status; |
| 730 | static int hotkey_orig_mask; | 730 | static u32 hotkey_orig_mask; |
| 731 | 731 | ||
| 732 | static struct attribute_set *hotkey_dev_attributes; | 732 | static struct attribute_set *hotkey_dev_attributes; |
| 733 | 733 | ||
| @@ -736,7 +736,8 @@ static ssize_t hotkey_enable_show(struct device *dev, | |||
| 736 | struct device_attribute *attr, | 736 | struct device_attribute *attr, |
| 737 | char *buf) | 737 | char *buf) |
| 738 | { | 738 | { |
| 739 | int res, status, mask; | 739 | int res, status; |
| 740 | u32 mask; | ||
| 740 | 741 | ||
| 741 | res = hotkey_get(&status, &mask); | 742 | res = hotkey_get(&status, &mask); |
| 742 | if (res) | 743 | if (res) |
| @@ -750,7 +751,8 @@ static ssize_t hotkey_enable_store(struct device *dev, | |||
| 750 | const char *buf, size_t count) | 751 | const char *buf, size_t count) |
| 751 | { | 752 | { |
| 752 | unsigned long t; | 753 | unsigned long t; |
| 753 | int res, status, mask; | 754 | int res, status; |
| 755 | u32 mask; | ||
| 754 | 756 | ||
| 755 | if (parse_strtoul(buf, 1, &t)) | 757 | if (parse_strtoul(buf, 1, &t)) |
| 756 | return -EINVAL; | 758 | return -EINVAL; |
| @@ -771,13 +773,14 @@ static ssize_t hotkey_mask_show(struct device *dev, | |||
| 771 | struct device_attribute *attr, | 773 | struct device_attribute *attr, |
| 772 | char *buf) | 774 | char *buf) |
| 773 | { | 775 | { |
| 774 | int res, status, mask; | 776 | int res, status; |
| 777 | u32 mask; | ||
| 775 | 778 | ||
| 776 | res = hotkey_get(&status, &mask); | 779 | res = hotkey_get(&status, &mask); |
| 777 | if (res) | 780 | if (res) |
| 778 | return res; | 781 | return res; |
| 779 | 782 | ||
| 780 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", mask); | 783 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", mask); |
| 781 | } | 784 | } |
| 782 | 785 | ||
| 783 | static ssize_t hotkey_mask_store(struct device *dev, | 786 | static ssize_t hotkey_mask_store(struct device *dev, |
| @@ -785,9 +788,10 @@ static ssize_t hotkey_mask_store(struct device *dev, | |||
| 785 | const char *buf, size_t count) | 788 | const char *buf, size_t count) |
| 786 | { | 789 | { |
| 787 | unsigned long t; | 790 | unsigned long t; |
| 788 | int res, status, mask; | 791 | int res, status; |
| 792 | u32 mask; | ||
| 789 | 793 | ||
| 790 | if (parse_strtoul(buf, 0xffff, &t)) | 794 | if (parse_strtoul(buf, 0xffffffffUL, &t)) |
| 791 | return -EINVAL; | 795 | return -EINVAL; |
| 792 | 796 | ||
| 793 | res = hotkey_get(&status, &mask); | 797 | res = hotkey_get(&status, &mask); |
| @@ -817,7 +821,7 @@ static ssize_t hotkey_bios_mask_show(struct device *dev, | |||
| 817 | struct device_attribute *attr, | 821 | struct device_attribute *attr, |
| 818 | char *buf) | 822 | char *buf) |
| 819 | { | 823 | { |
| 820 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", hotkey_orig_mask); | 824 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask); |
| 821 | } | 825 | } |
| 822 | 826 | ||
| 823 | static struct device_attribute dev_attr_hotkey_bios_mask = | 827 | static struct device_attribute dev_attr_hotkey_bios_mask = |
| @@ -902,10 +906,10 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) | |||
| 902 | { | 906 | { |
| 903 | int hkey; | 907 | int hkey; |
| 904 | 908 | ||
| 905 | if (acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) | 909 | if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) { |
| 906 | acpi_bus_generate_event(ibm->acpi->device, event, hkey); | 910 | acpi_bus_generate_event(ibm->acpi->device, event, hkey); |
| 907 | else { | 911 | } else { |
| 908 | printk(IBM_ERR "unknown hotkey event %d\n", event); | 912 | printk(IBM_ERR "unknown hotkey notification event %d\n", event); |
| 909 | acpi_bus_generate_event(ibm->acpi->device, event, 0); | 913 | acpi_bus_generate_event(ibm->acpi->device, event, 0); |
| 910 | } | 914 | } |
| 911 | } | 915 | } |
| @@ -913,7 +917,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) | |||
| 913 | /* | 917 | /* |
| 914 | * Call with hotkey_mutex held | 918 | * Call with hotkey_mutex held |
| 915 | */ | 919 | */ |
| 916 | static int hotkey_get(int *status, int *mask) | 920 | static int hotkey_get(int *status, u32 *mask) |
| 917 | { | 921 | { |
| 918 | if (!acpi_evalf(hkey_handle, status, "DHKC", "d")) | 922 | if (!acpi_evalf(hkey_handle, status, "DHKC", "d")) |
| 919 | return -EIO; | 923 | return -EIO; |
| @@ -928,7 +932,7 @@ static int hotkey_get(int *status, int *mask) | |||
| 928 | /* | 932 | /* |
| 929 | * Call with hotkey_mutex held | 933 | * Call with hotkey_mutex held |
| 930 | */ | 934 | */ |
| 931 | static int hotkey_set(int status, int mask) | 935 | static int hotkey_set(int status, u32 mask) |
| 932 | { | 936 | { |
| 933 | int i; | 937 | int i; |
| 934 | 938 | ||
| @@ -949,7 +953,8 @@ static int hotkey_set(int status, int mask) | |||
| 949 | /* procfs -------------------------------------------------------------- */ | 953 | /* procfs -------------------------------------------------------------- */ |
| 950 | static int hotkey_read(char *p) | 954 | static int hotkey_read(char *p) |
| 951 | { | 955 | { |
| 952 | int res, status, mask; | 956 | int res, status; |
| 957 | u32 mask; | ||
| 953 | int len = 0; | 958 | int len = 0; |
| 954 | 959 | ||
| 955 | if (!tp_features.hotkey) { | 960 | if (!tp_features.hotkey) { |
| @@ -967,7 +972,7 @@ static int hotkey_read(char *p) | |||
| 967 | 972 | ||
| 968 | len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); | 973 | len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); |
| 969 | if (tp_features.hotkey_mask) { | 974 | if (tp_features.hotkey_mask) { |
| 970 | len += sprintf(p + len, "mask:\t\t0x%04x\n", mask); | 975 | len += sprintf(p + len, "mask:\t\t0x%08x\n", mask); |
| 971 | len += sprintf(p + len, | 976 | len += sprintf(p + len, |
| 972 | "commands:\tenable, disable, reset, <mask>\n"); | 977 | "commands:\tenable, disable, reset, <mask>\n"); |
| 973 | } else { | 978 | } else { |
| @@ -980,7 +985,8 @@ static int hotkey_read(char *p) | |||
| 980 | 985 | ||
| 981 | static int hotkey_write(char *buf) | 986 | static int hotkey_write(char *buf) |
| 982 | { | 987 | { |
| 983 | int res, status, mask; | 988 | int res, status; |
| 989 | u32 mask; | ||
| 984 | char *cmd; | 990 | char *cmd; |
| 985 | int do_cmd = 0; | 991 | int do_cmd = 0; |
| 986 | 992 | ||
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h index 72d62f2dabb9..e1a64f0aada9 100644 --- a/drivers/misc/thinkpad_acpi.h +++ b/drivers/misc/thinkpad_acpi.h | |||
| @@ -415,14 +415,14 @@ static int fan_write_cmd_watchdog(const char *cmd, int *rc); | |||
| 415 | */ | 415 | */ |
| 416 | 416 | ||
| 417 | static int hotkey_orig_status; | 417 | static int hotkey_orig_status; |
| 418 | static int hotkey_orig_mask; | 418 | static u32 hotkey_orig_mask; |
| 419 | 419 | ||
| 420 | static struct mutex hotkey_mutex; | 420 | static struct mutex hotkey_mutex; |
| 421 | 421 | ||
| 422 | static int hotkey_init(struct ibm_init_struct *iibm); | 422 | static int hotkey_init(struct ibm_init_struct *iibm); |
| 423 | static void hotkey_exit(void); | 423 | static void hotkey_exit(void); |
| 424 | static int hotkey_get(int *status, int *mask); | 424 | static int hotkey_get(int *status, u32 *mask); |
| 425 | static int hotkey_set(int status, int mask); | 425 | static int hotkey_set(int status, u32 mask); |
| 426 | static void hotkey_notify(struct ibm_struct *ibm, u32 event); | 426 | static void hotkey_notify(struct ibm_struct *ibm, u32 event); |
| 427 | static int hotkey_read(char *p); | 427 | static int hotkey_read(char *p); |
| 428 | static int hotkey_write(char *buf); | 428 | static int hotkey_write(char *buf); |
