[PATCH] thinkpad-acpi: add sysfs nodes for thinkpad hardware mute button with led.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



New thinkpad introduces new BIOS interfaces (aml methods) to control
hardware mute and its led. The patch checks whether new new methods
are present and provides new sysfs nodes to interfact with BIOS
aml methods.

Signed-off-by: Alex Hung <alex.hung@xxxxxxxxxxxxx>
---
 drivers/platform/x86/thinkpad_acpi.c |  113 ++++++++++++++++++++++++++++++++++
 1 file changed, 113 insertions(+)

diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index cc6b1c4..7be7877 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -1040,6 +1040,8 @@ static int add_many_to_attr_set(struct attribute_set *s,
 	int i, res;
 
 	for (i = 0; i < count; i++) {
+		if (attr[i] == NULL)
+			continue;
 		res = add_to_attr_set(s, attr[i]);
 		if (res)
 			return res;
@@ -2622,6 +2624,108 @@ static void hotkey_inputdev_close(struct input_dev *dev)
 		hotkey_poll_setup_safe(false);
 }
 
+static int hotkey_get_mute_state(void)
+{
+	int state;
+	acpi_handle temp;
+
+	if (!ACPI_SUCCESS(acpi_get_handle(hkey_handle, "GSMS", &temp)))
+		return 0;
+
+	if (!acpi_evalf(hkey_handle, &state, "GSMS", "dd"))
+		return -EIO;
+
+	if (state & (1 << 31)) {
+		pr_warning("getting mute state failed.\n");
+		return -EIO;
+	}
+
+	pr_info("get hardware mute = %s.\n", state & 1 ? "muted" : "unmuted");
+
+	return state;
+}
+
+static void hotkey_set_mute_state(int state)
+{
+	int output;
+
+	if (!acpi_evalf(hkey_handle, &output, "SSMS", "dd", state))
+		return;
+
+	if (output & (1 << 31)) {
+		pr_warning("setting hardware mute state failed.\n");
+		return;
+	}
+
+	pr_info("set hardware mute state to %s.\n", state ? "on" : "off");
+}
+
+static void hotkey_set_mute_support(int support)
+{
+	int output;
+
+	if (!acpi_evalf(hkey_handle, &output, "SHDA", "dd", support))
+		return;
+
+	if (output & (1 << 31)) {
+		pr_warning("setting hardware support failed.\n");
+		return;
+	}
+
+	pr_info("%s hardware mute support.\n", support ? "disable" : "enable");
+}
+
+/* sysfs mute support ------------------------------------------------- */
+static ssize_t hardware_mute_support_store(struct device *dev,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	unsigned long t;
+
+	if (parse_strtoul(buf, 1, &t))
+		return -EINVAL;
+
+	if (t != 0 && t != 1)
+		return -EINVAL;
+
+	hotkey_set_mute_support(t);
+
+	return count;
+}
+
+static struct device_attribute dev_attr_hardware_mute_support =
+	__ATTR(hardware_mute_support, S_IWUSR,
+		NULL, hardware_mute_support_store);
+
+/* sysfs mute enable ------------------------------------------------- */
+static ssize_t hardware_mute_enable_show(struct device *dev,
+			   struct device_attribute *attr,
+			   char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_get_mute_state() & 0x01);
+}
+
+static ssize_t hardware_mute_enable_store(struct device *dev,
+			    struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	unsigned long t;
+
+	if (parse_strtoul(buf, 1, &t))
+		return -EINVAL;
+
+	if (t != 0 && t != 1)
+		return -EINVAL;
+
+	hotkey_set_mute_state(t);
+
+	return count;
+}
+
+static struct device_attribute dev_attr_hardware_mute_enable =
+	__ATTR(hardware_mute_enable, S_IWUSR | S_IRUGO,
+		hardware_mute_enable_show, hardware_mute_enable_store);
+
 /* sysfs hotkey enable ------------------------------------------------- */
 static ssize_t hotkey_enable_show(struct device *dev,
 			   struct device_attribute *attr,
@@ -2942,6 +3046,8 @@ static void hotkey_wakeup_hotunplug_complete_notify_change(void)
 /* --------------------------------------------------------------------- */
 
 static struct attribute *hotkey_attributes[] __initdata = {
+	&dev_attr_hardware_mute_enable.attr,
+	&dev_attr_hardware_mute_support.attr,
 	&dev_attr_hotkey_enable.attr,
 	&dev_attr_hotkey_bios_enabled.attr,
 	&dev_attr_hotkey_bios_mask.attr,
@@ -3263,6 +3369,13 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
 					NULL);
 	if (!hotkey_dev_attributes)
 		return -ENOMEM;
+
+	if (!(hotkey_get_mute_state() & 0x100)) {
+		hotkey_attributes[0] = NULL;
+		hotkey_attributes[1] = NULL;
+	} else
+		hotkey_set_mute_support(1);
+
 	res = add_many_to_attr_set(hotkey_dev_attributes,
 			hotkey_attributes,
 			ARRAY_SIZE(hotkey_attributes));
-- 
1.7.9.5


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
ibm-acpi-devel mailing list
ibm-acpi-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/ibm-acpi-devel


[Index of Archives]     [Linux ACPI]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Photo]     [Yosemite Photos]     [Yosemite Advice]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Device Mapper]

  Powered by Linux