diff options
| author | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2007-04-27 21:00:16 -0400 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2007-04-28 21:41:20 -0400 |
| commit | a0416420e2c6244792d6f308183ad57c40532078 (patch) | |
| tree | dcd0600b74f3e4a120843d2f6cd7f6faa4e64ec0 | |
| parent | d94a7f16cad7700f8d2b142cc13cfba5387af3db (diff) | |
ACPI: thinkpad-acpi: add sysfs support to hotkey subdriver
Add the hotkey sysfs support.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Signed-off-by: Len Brown <len.brown@intel.com>
| -rw-r--r-- | Documentation/thinkpad-acpi.txt | 58 | ||||
| -rw-r--r-- | drivers/misc/thinkpad_acpi.c | 127 | ||||
| -rw-r--r-- | drivers/misc/thinkpad_acpi.h | 2 |
3 files changed, 176 insertions, 11 deletions
diff --git a/Documentation/thinkpad-acpi.txt b/Documentation/thinkpad-acpi.txt index e3ad7a4f7402..ebeed589f6d7 100644 --- a/Documentation/thinkpad-acpi.txt +++ b/Documentation/thinkpad-acpi.txt | |||
| @@ -134,8 +134,11 @@ end of this document. Changes to the sysfs interface done by the kernel | |||
| 134 | subsystems are not documented here, nor are they tracked by this | 134 | subsystems are not documented here, nor are they tracked by this |
| 135 | attribute. | 135 | attribute. |
| 136 | 136 | ||
| 137 | Hot keys -- /proc/acpi/ibm/hotkey | 137 | Hot keys |
| 138 | --------------------------------- | 138 | -------- |
| 139 | |||
| 140 | procfs: /proc/acpi/ibm/hotkey | ||
| 141 | sysfs device attribute: hotkey/* | ||
| 139 | 142 | ||
| 140 | Without this driver, only the Fn-F4 key (sleep button) generates an | 143 | Without this driver, only the Fn-F4 key (sleep button) generates an |
| 141 | ACPI event. With the driver loaded, the hotkey feature enabled and the | 144 | ACPI event. With the driver loaded, the hotkey feature enabled and the |
| @@ -149,15 +152,6 @@ All labeled Fn-Fx key combinations generate distinct events. In | |||
| 149 | addition, the lid microswitch and some docking station buttons may | 152 | addition, the lid microswitch and some docking station buttons may |
| 150 | also generate such events. | 153 | also generate such events. |
| 151 | 154 | ||
| 152 | The following commands can be written to this file: | ||
| 153 | |||
| 154 | echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature | ||
| 155 | echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature | ||
| 156 | echo 0xffff > /proc/acpi/ibm/hotkey -- enable all possible hot keys | ||
| 157 | echo 0x0000 > /proc/acpi/ibm/hotkey -- disable all possible hot keys | ||
| 158 | ... any other 4-hex-digit mask ... | ||
| 159 | echo reset > /proc/acpi/ibm/hotkey -- restore the original mask | ||
| 160 | |||
| 161 | 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 |
| 162 | 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 |
| 163 | can be modified do anything. Not all hot keys can be individually | 157 | can be modified do anything. Not all hot keys can be individually |
| @@ -189,6 +183,48 @@ buttons do not generate ACPI events even with this driver. They *can* | |||
| 189 | be used through the "ThinkPad Buttons" utility, see | 183 | be used through the "ThinkPad Buttons" utility, see |
| 190 | http://www.nongnu.org/tpb/ | 184 | http://www.nongnu.org/tpb/ |
| 191 | 185 | ||
| 186 | procfs notes: | ||
| 187 | |||
| 188 | The following commands can be written to the /proc/acpi/ibm/hotkey file: | ||
| 189 | |||
| 190 | echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature | ||
| 191 | echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature | ||
| 192 | echo 0xffff > /proc/acpi/ibm/hotkey -- enable all possible hot keys | ||
| 193 | echo 0x0000 > /proc/acpi/ibm/hotkey -- disable all possible hot keys | ||
| 194 | ... any other 4-hex-digit mask ... | ||
| 195 | echo reset > /proc/acpi/ibm/hotkey -- restore the original mask | ||
| 196 | |||
| 197 | sysfs notes: | ||
| 198 | |||
| 199 | The hot keys attributes are in a hotkey/ subdirectory off the | ||
| 200 | thinkpad device. | ||
| 201 | |||
| 202 | bios_enabled: | ||
| 203 | Returns the status of the hot keys feature when | ||
| 204 | thinkpad-acpi was loaded. Upon module unload, the hot | ||
| 205 | key feature status will be restored to this value. | ||
| 206 | |||
| 207 | 0: hot keys were disabled | ||
| 208 | 1: hot keys were enabled | ||
| 209 | |||
| 210 | bios_mask: | ||
| 211 | Returns the hot keys mask when thinkpad-acpi was loaded. | ||
| 212 | Upon module unload, the hot keys mask will be restored | ||
| 213 | to this value. | ||
| 214 | |||
| 215 | enable: | ||
| 216 | Enables/disables the hot keys feature, and reports | ||
| 217 | current status of the hot keys feature. | ||
| 218 | |||
| 219 | 0: disables the hot keys feature / feature disabled | ||
| 220 | 1: enables the hot keys feature / feature enabled | ||
| 221 | |||
| 222 | mask: | ||
| 223 | bit mask to enable ACPI event generation for each hot | ||
| 224 | key (see above). Returns the current status of the hot | ||
| 225 | keys mask, and allows one to modify it. | ||
| 226 | |||
| 227 | |||
| 192 | Bluetooth -- /proc/acpi/ibm/bluetooth | 228 | Bluetooth -- /proc/acpi/ibm/bluetooth |
| 193 | ------------------------------------- | 229 | ------------------------------------- |
| 194 | 230 | ||
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index a56526500c18..83a8d984e709 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
| @@ -706,6 +706,108 @@ static struct ibm_struct thinkpad_acpi_driver_data = { | |||
| 706 | static int hotkey_orig_status; | 706 | static int hotkey_orig_status; |
| 707 | static int hotkey_orig_mask; | 707 | static int hotkey_orig_mask; |
| 708 | 708 | ||
| 709 | static struct attribute_set *hotkey_dev_attributes = NULL; | ||
| 710 | |||
| 711 | /* sysfs hotkey enable ------------------------------------------------- */ | ||
| 712 | static ssize_t hotkey_enable_show(struct device *dev, | ||
| 713 | struct device_attribute *attr, | ||
| 714 | char *buf) | ||
| 715 | { | ||
| 716 | int res, status, mask; | ||
| 717 | |||
| 718 | res = hotkey_get(&status, &mask); | ||
| 719 | if (res) | ||
| 720 | return res; | ||
| 721 | |||
| 722 | return snprintf(buf, PAGE_SIZE, "%d\n", status); | ||
| 723 | } | ||
| 724 | |||
| 725 | static ssize_t hotkey_enable_store(struct device *dev, | ||
| 726 | struct device_attribute *attr, | ||
| 727 | const char *buf, size_t count) | ||
| 728 | { | ||
| 729 | unsigned long t; | ||
| 730 | int res, status, mask; | ||
| 731 | |||
| 732 | if (parse_strtoul(buf, 1, &t)) | ||
| 733 | return -EINVAL; | ||
| 734 | |||
| 735 | res = hotkey_get(&status, &mask); | ||
| 736 | if (!res) | ||
| 737 | res = hotkey_set(t, mask); | ||
| 738 | |||
| 739 | return (res) ? res : count; | ||
| 740 | } | ||
| 741 | |||
| 742 | static struct device_attribute dev_attr_hotkey_enable = | ||
| 743 | __ATTR(enable, S_IWUSR | S_IRUGO, | ||
| 744 | hotkey_enable_show, hotkey_enable_store); | ||
| 745 | |||
| 746 | /* sysfs hotkey mask --------------------------------------------------- */ | ||
| 747 | static ssize_t hotkey_mask_show(struct device *dev, | ||
| 748 | struct device_attribute *attr, | ||
| 749 | char *buf) | ||
| 750 | { | ||
| 751 | int res, status, mask; | ||
| 752 | |||
| 753 | res = hotkey_get(&status, &mask); | ||
| 754 | if (res) | ||
| 755 | return res; | ||
| 756 | |||
| 757 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", mask); | ||
| 758 | } | ||
| 759 | |||
| 760 | static ssize_t hotkey_mask_store(struct device *dev, | ||
| 761 | struct device_attribute *attr, | ||
| 762 | const char *buf, size_t count) | ||
| 763 | { | ||
| 764 | unsigned long t; | ||
| 765 | int res, status, mask; | ||
| 766 | |||
| 767 | if (parse_strtoul(buf, 0xffff, &t)) | ||
| 768 | return -EINVAL; | ||
| 769 | |||
| 770 | res = hotkey_get(&status, &mask); | ||
| 771 | if (!res) | ||
| 772 | hotkey_set(status, t); | ||
| 773 | |||
| 774 | return (res) ? res : count; | ||
| 775 | } | ||
| 776 | |||
| 777 | static struct device_attribute dev_attr_hotkey_mask = | ||
| 778 | __ATTR(mask, S_IWUSR | S_IRUGO, | ||
| 779 | hotkey_mask_show, hotkey_mask_store); | ||
| 780 | |||
| 781 | /* sysfs hotkey bios_enabled ------------------------------------------- */ | ||
| 782 | static ssize_t hotkey_bios_enabled_show(struct device *dev, | ||
| 783 | struct device_attribute *attr, | ||
| 784 | char *buf) | ||
| 785 | { | ||
| 786 | return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_orig_status); | ||
| 787 | } | ||
| 788 | |||
| 789 | static struct device_attribute dev_attr_hotkey_bios_enabled = | ||
| 790 | __ATTR(bios_enabled, S_IRUGO, hotkey_bios_enabled_show, NULL); | ||
| 791 | |||
| 792 | /* sysfs hotkey bios_mask ---------------------------------------------- */ | ||
| 793 | static ssize_t hotkey_bios_mask_show(struct device *dev, | ||
| 794 | struct device_attribute *attr, | ||
| 795 | char *buf) | ||
| 796 | { | ||
| 797 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", hotkey_orig_mask); | ||
| 798 | } | ||
| 799 | |||
| 800 | static struct device_attribute dev_attr_hotkey_bios_mask = | ||
| 801 | __ATTR(bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL); | ||
| 802 | |||
| 803 | /* --------------------------------------------------------------------- */ | ||
| 804 | |||
| 805 | static struct attribute *hotkey_mask_attributes[] = { | ||
| 806 | &dev_attr_hotkey_mask.attr, | ||
| 807 | &dev_attr_hotkey_bios_enabled.attr, | ||
| 808 | &dev_attr_hotkey_bios_mask.attr, | ||
| 809 | }; | ||
| 810 | |||
| 709 | static int __init hotkey_init(struct ibm_init_struct *iibm) | 811 | static int __init hotkey_init(struct ibm_init_struct *iibm) |
| 710 | { | 812 | { |
| 711 | int res; | 813 | int res; |
| @@ -722,6 +824,15 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 722 | str_supported(tp_features.hotkey)); | 824 | str_supported(tp_features.hotkey)); |
| 723 | 825 | ||
| 724 | if (tp_features.hotkey) { | 826 | if (tp_features.hotkey) { |
| 827 | hotkey_dev_attributes = create_attr_set(4, | ||
| 828 | TPACPI_HOTKEY_SYSFS_GROUP); | ||
| 829 | if (!hotkey_dev_attributes) | ||
| 830 | return -ENOMEM; | ||
| 831 | res = add_to_attr_set(hotkey_dev_attributes, | ||
| 832 | &dev_attr_hotkey_enable.attr); | ||
| 833 | if (res) | ||
| 834 | return res; | ||
| 835 | |||
| 725 | /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, | 836 | /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, |
| 726 | A30, R30, R31, T20-22, X20-21, X22-24 */ | 837 | A30, R30, R31, T20-22, X20-21, X22-24 */ |
| 727 | tp_features.hotkey_mask = | 838 | tp_features.hotkey_mask = |
| @@ -731,6 +842,16 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 731 | str_supported(tp_features.hotkey_mask)); | 842 | str_supported(tp_features.hotkey_mask)); |
| 732 | 843 | ||
| 733 | res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask); | 844 | res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask); |
| 845 | if (!res && tp_features.hotkey_mask) { | ||
| 846 | res = add_many_to_attr_set(hotkey_dev_attributes, | ||
| 847 | hotkey_mask_attributes, | ||
| 848 | ARRAY_SIZE(hotkey_mask_attributes)); | ||
| 849 | } | ||
| 850 | if (!res) | ||
| 851 | res = register_attr_set_with_sysfs( | ||
| 852 | hotkey_dev_attributes, | ||
| 853 | &tpacpi_pdev->dev.kobj); | ||
| 854 | |||
| 734 | if (res) | 855 | if (res) |
| 735 | return res; | 856 | return res; |
| 736 | } | 857 | } |
| @@ -748,6 +869,11 @@ static void hotkey_exit(void) | |||
| 748 | if (res) | 869 | if (res) |
| 749 | printk(IBM_ERR "failed to restore hotkey to BIOS defaults\n"); | 870 | printk(IBM_ERR "failed to restore hotkey to BIOS defaults\n"); |
| 750 | } | 871 | } |
| 872 | |||
| 873 | if (hotkey_dev_attributes) { | ||
| 874 | delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj); | ||
| 875 | hotkey_dev_attributes = NULL; | ||
| 876 | } | ||
| 751 | } | 877 | } |
| 752 | 878 | ||
| 753 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) | 879 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) |
| @@ -798,6 +924,7 @@ static int hotkey_set(int status, int mask) | |||
| 798 | return 0; | 924 | return 0; |
| 799 | } | 925 | } |
| 800 | 926 | ||
| 927 | /* procfs -------------------------------------------------------------- */ | ||
| 801 | static int hotkey_read(char *p) | 928 | static int hotkey_read(char *p) |
| 802 | { | 929 | { |
| 803 | int res, status, mask; | 930 | int res, status, mask; |
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h index a9e709368256..7615adb381c8 100644 --- a/drivers/misc/thinkpad_acpi.h +++ b/drivers/misc/thinkpad_acpi.h | |||
| @@ -414,6 +414,8 @@ static int fan_write_cmd_watchdog(const char *cmd, int *rc); | |||
| 414 | * Hotkey subdriver | 414 | * Hotkey subdriver |
| 415 | */ | 415 | */ |
| 416 | 416 | ||
| 417 | #define TPACPI_HOTKEY_SYSFS_GROUP "hotkey" | ||
| 418 | |||
| 417 | static int hotkey_orig_status; | 419 | static int hotkey_orig_status; |
| 418 | static int hotkey_orig_mask; | 420 | static int hotkey_orig_mask; |
| 419 | 421 | ||
