]> err.no Git - linux-2.6/commitdiff
ACPI: thinkpad-acpi: add sysfs support to hotkey subdriver
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Sat, 28 Apr 2007 01:00:16 +0000 (22:00 -0300)
committerLen Brown <len.brown@intel.com>
Sun, 29 Apr 2007 01:41:20 +0000 (21:41 -0400)
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>
Documentation/thinkpad-acpi.txt
drivers/misc/thinkpad_acpi.c
drivers/misc/thinkpad_acpi.h

index e3ad7a4f7402ade52e6da91abfd4150579664f4b..ebeed589f6d7e1b5a1d6a05c29e40fb6245bd0bf 100644 (file)
@@ -134,8 +134,11 @@ end of this document.  Changes to the sysfs interface done by the kernel
 subsystems are not documented here, nor are they tracked by this
 attribute.
 
-Hot keys -- /proc/acpi/ibm/hotkey
----------------------------------
+Hot keys
+--------
+
+procfs: /proc/acpi/ibm/hotkey
+sysfs device attribute: hotkey/*
 
 Without this driver, only the Fn-F4 key (sleep button) generates an
 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
 addition, the lid microswitch and some docking station buttons may
 also generate such events.
 
-The following commands can be written to this file:
-
-       echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature
-       echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature
-       echo 0xffff > /proc/acpi/ibm/hotkey -- enable all possible hot keys
-       echo 0x0000 > /proc/acpi/ibm/hotkey -- disable all possible hot keys
-       ... any other 4-hex-digit mask ...
-       echo reset > /proc/acpi/ibm/hotkey -- restore the original mask
-
 The bit mask allows some control over which hot keys generate ACPI
 events. Not all bits in the mask can be modified. Not all bits that
 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*
 be used through the "ThinkPad Buttons" utility, see
 http://www.nongnu.org/tpb/
 
+procfs notes:
+
+The following commands can be written to the /proc/acpi/ibm/hotkey file:
+
+       echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature
+       echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature
+       echo 0xffff > /proc/acpi/ibm/hotkey -- enable all possible hot keys
+       echo 0x0000 > /proc/acpi/ibm/hotkey -- disable all possible hot keys
+       ... any other 4-hex-digit mask ...
+       echo reset > /proc/acpi/ibm/hotkey -- restore the original mask
+
+sysfs notes:
+
+       The hot keys attributes are in a hotkey/ subdirectory off the
+       thinkpad device.
+
+       bios_enabled:
+               Returns the status of the hot keys feature when
+               thinkpad-acpi was loaded.  Upon module unload, the hot
+               key feature status will be restored to this value.
+
+               0: hot keys were disabled
+               1: hot keys were enabled
+
+       bios_mask:
+               Returns the hot keys mask when thinkpad-acpi was loaded.
+               Upon module unload, the hot keys mask will be restored
+               to this value.
+
+       enable:
+               Enables/disables the hot keys feature, and reports
+               current status of the hot keys feature.
+
+               0: disables the hot keys feature / feature disabled
+               1: enables the hot keys feature / feature enabled
+
+       mask:
+               bit mask to enable ACPI event generation for each hot
+               key (see above).  Returns the current status of the hot
+               keys mask, and allows one to modify it.
+
+
 Bluetooth -- /proc/acpi/ibm/bluetooth
 -------------------------------------
 
index a56526500c1895d4d689119196634b342de2c047..83a8d984e709c3d54461f4180c4f5a5400b57149 100644 (file)
@@ -706,6 +706,108 @@ static struct ibm_struct thinkpad_acpi_driver_data = {
 static int hotkey_orig_status;
 static int hotkey_orig_mask;
 
+static struct attribute_set *hotkey_dev_attributes = NULL;
+
+/* sysfs hotkey enable ------------------------------------------------- */
+static ssize_t hotkey_enable_show(struct device *dev,
+                          struct device_attribute *attr,
+                          char *buf)
+{
+       int res, status, mask;
+
+       res = hotkey_get(&status, &mask);
+       if (res)
+               return res;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", status);
+}
+
+static ssize_t hotkey_enable_store(struct device *dev,
+                           struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       unsigned long t;
+       int res, status, mask;
+
+       if (parse_strtoul(buf, 1, &t))
+               return -EINVAL;
+
+       res = hotkey_get(&status, &mask);
+       if (!res)
+               res = hotkey_set(t, mask);
+
+       return (res) ? res : count;
+}
+
+static struct device_attribute dev_attr_hotkey_enable =
+       __ATTR(enable, S_IWUSR | S_IRUGO,
+               hotkey_enable_show, hotkey_enable_store);
+
+/* sysfs hotkey mask --------------------------------------------------- */
+static ssize_t hotkey_mask_show(struct device *dev,
+                          struct device_attribute *attr,
+                          char *buf)
+{
+       int res, status, mask;
+
+       res = hotkey_get(&status, &mask);
+       if (res)
+               return res;
+
+       return snprintf(buf, PAGE_SIZE, "0x%04x\n", mask);
+}
+
+static ssize_t hotkey_mask_store(struct device *dev,
+                           struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       unsigned long t;
+       int res, status, mask;
+
+       if (parse_strtoul(buf, 0xffff, &t))
+               return -EINVAL;
+
+       res = hotkey_get(&status, &mask);
+       if (!res)
+               hotkey_set(status, t);
+
+       return (res) ? res : count;
+}
+
+static struct device_attribute dev_attr_hotkey_mask =
+       __ATTR(mask, S_IWUSR | S_IRUGO,
+               hotkey_mask_show, hotkey_mask_store);
+
+/* sysfs hotkey bios_enabled ------------------------------------------- */
+static ssize_t hotkey_bios_enabled_show(struct device *dev,
+                          struct device_attribute *attr,
+                          char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_orig_status);
+}
+
+static struct device_attribute dev_attr_hotkey_bios_enabled =
+       __ATTR(bios_enabled, S_IRUGO, hotkey_bios_enabled_show, NULL);
+
+/* sysfs hotkey bios_mask ---------------------------------------------- */
+static ssize_t hotkey_bios_mask_show(struct device *dev,
+                          struct device_attribute *attr,
+                          char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "0x%04x\n", hotkey_orig_mask);
+}
+
+static struct device_attribute dev_attr_hotkey_bios_mask =
+       __ATTR(bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL);
+
+/* --------------------------------------------------------------------- */
+
+static struct attribute *hotkey_mask_attributes[] = {
+       &dev_attr_hotkey_mask.attr,
+       &dev_attr_hotkey_bios_enabled.attr,
+       &dev_attr_hotkey_bios_mask.attr,
+};
+
 static int __init hotkey_init(struct ibm_init_struct *iibm)
 {
        int res;
@@ -722,6 +824,15 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
                str_supported(tp_features.hotkey));
 
        if (tp_features.hotkey) {
+               hotkey_dev_attributes = create_attr_set(4,
+                                               TPACPI_HOTKEY_SYSFS_GROUP);
+               if (!hotkey_dev_attributes)
+                       return -ENOMEM;
+               res = add_to_attr_set(hotkey_dev_attributes,
+                               &dev_attr_hotkey_enable.attr);
+               if (res)
+                       return res;
+
                /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
                   A30, R30, R31, T20-22, X20-21, X22-24 */
                tp_features.hotkey_mask =
@@ -731,6 +842,16 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
                        str_supported(tp_features.hotkey_mask));
 
                res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask);
+               if (!res && tp_features.hotkey_mask) {
+                       res = add_many_to_attr_set(hotkey_dev_attributes,
+                               hotkey_mask_attributes,
+                               ARRAY_SIZE(hotkey_mask_attributes));
+               }
+               if (!res)
+                       res = register_attr_set_with_sysfs(
+                                       hotkey_dev_attributes,
+                                       &tpacpi_pdev->dev.kobj);
+
                if (res)
                        return res;
        }
@@ -748,6 +869,11 @@ static void hotkey_exit(void)
                if (res)
                        printk(IBM_ERR "failed to restore hotkey to BIOS defaults\n");
        }
+
+       if (hotkey_dev_attributes) {
+               delete_attr_set(hotkey_dev_attributes, &tpacpi_pdev->dev.kobj);
+               hotkey_dev_attributes = NULL;
+       }
 }
 
 static void hotkey_notify(struct ibm_struct *ibm, u32 event)
@@ -798,6 +924,7 @@ static int hotkey_set(int status, int mask)
        return 0;
 }
 
+/* procfs -------------------------------------------------------------- */
 static int hotkey_read(char *p)
 {
        int res, status, mask;
index a9e70936825696b4f27af746fe4d87ca4ab071d5..7615adb381c85d9504c20a3a5584506562081ecc 100644 (file)
@@ -414,6 +414,8 @@ static int fan_write_cmd_watchdog(const char *cmd, int *rc);
  * Hotkey subdriver
  */
 
+#define TPACPI_HOTKEY_SYSFS_GROUP "hotkey"
+
 static int hotkey_orig_status;
 static int hotkey_orig_mask;