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); |