[PATCH] platform/x86: thinkpad_acpi: Add new sysfs to check user presence sensing status

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

 



Some Thinkpad products support Human Presence Detection (HPD) features.
Add new sysfs entry so that userspace can determine if feature is
supported or not.

Reviewed-by: Mark Pearson <mpearson-lenovo@xxxxxxxxx>
Signed-off-by: Nitin Joshi <nitjoshi@xxxxxxxxx>
---
 .../admin-guide/laptops/thinkpad-acpi.rst     | 20 +++++
 drivers/platform/x86/thinkpad_acpi.c          | 79 +++++++++++++++++++
 2 files changed, 99 insertions(+)

diff --git a/Documentation/admin-guide/laptops/thinkpad-acpi.rst b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
index 4ab0fef7d440..02e6c4306f90 100644
--- a/Documentation/admin-guide/laptops/thinkpad-acpi.rst
+++ b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
@@ -1576,6 +1576,26 @@ percentage level, above which charging will stop.
 The exact semantics of the attributes may be found in
 Documentation/ABI/testing/sysfs-class-power.
 
+User Presence Sensing Detection
+------
+
+sysfs: hpd_bios_enabled
+
+Some Thinkpad products support Human Presence Detection (HPD) features.
+Added new sysfs entry so that userspace can determine if feature related to
+HPD should be enabled or disabled.
+
+The available commands are::
+
+        cat /sys/devices/platform/thinkpad_acpi/hpd_bios_enabled
+
+BIOS status is mentioned as below:
+- 0 = Disable
+- 1 = Enable
+
+The property is read-only. If the platform doesn't have support the sysfs
+class is not created.
+
 Multiple Commands, Module Parameters
 ------------------------------------
 
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 72a10ed2017c..daf31b2a4c73 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -11039,6 +11039,80 @@ static const struct attribute_group auxmac_attr_group = {
 	.attrs = auxmac_attributes,
 };
 
+/*************************************************************************
+ * CHPD subdriver, for the Lenovo Human Presence Detection feature.
+ */
+#define CHPD_GET_SENSOR_STATUS           0x00200000
+#define CHPD_GET_BIOS_UI_STATUS          0x00100000
+
+static bool has_user_presence_sensing;
+static int hpd_bios_status;
+static int chpd_command(int command, int *output)
+{
+	acpi_handle chpd_handle;
+
+	if (ACPI_FAILURE(acpi_get_handle(hkey_handle, "CHPD", &chpd_handle))) {
+		/* Platform doesn't support CHPD */
+		return -ENODEV;
+	}
+
+	if (!acpi_evalf(chpd_handle, output, NULL, "dd", command))
+		return -EIO;
+
+	return 0;
+}
+
+/* sysfs hpd bios status */
+static ssize_t hpd_bios_enabled_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	return sysfs_emit(buf, "%d\n", hpd_bios_status);
+}
+static DEVICE_ATTR_RO(hpd_bios_enabled);
+
+static struct attribute *chpd_attributes[] = {
+	&dev_attr_hpd_bios_enabled.attr,
+	NULL
+};
+
+static umode_t chpd_attr_is_visible(struct kobject *kobj,
+					struct attribute *attr, int n)
+{
+	return has_user_presence_sensing ? attr->mode : 0;
+}
+
+static const struct attribute_group chpd_attr_group = {
+	.is_visible = chpd_attr_is_visible,
+	.attrs = chpd_attributes,
+};
+
+static int tpacpi_chpd_init(struct ibm_init_struct *iibm)
+{
+	int err, output;
+
+	err = chpd_command(CHPD_GET_SENSOR_STATUS, &output);
+	if (err)
+		return err;
+
+	if (output == 1)
+		return -ENODEV;
+
+	has_user_presence_sensing = true;
+	/* Get User Presence Sensing BIOS status */
+	err = chpd_command(CHPD_GET_BIOS_UI_STATUS, &output);
+	if (err)
+		return err;
+
+	hpd_bios_status = (output >> 1) & BIT(0);
+
+	return err;
+}
+
+static struct ibm_struct chpd_driver_data = {
+	.name = "chpd",
+};
+
 /* --------------------------------------------------------------------- */
 
 static struct attribute *tpacpi_driver_attributes[] = {
@@ -11098,6 +11172,7 @@ static const struct attribute_group *tpacpi_groups[] = {
 	&kbdlang_attr_group,
 	&dprc_attr_group,
 	&auxmac_attr_group,
+	&chpd_attr_group,
 	NULL,
 };
 
@@ -11694,6 +11769,10 @@ static struct ibm_init_struct ibms_init[] __initdata = {
 		.init = auxmac_init,
 		.data = &auxmac_data,
 	},
+	{
+		.init = tpacpi_chpd_init,
+		.data = &chpd_driver_data,
+	},
 };
 
 static int __init set_ibm_param(const char *val, const struct kernel_param *kp)
-- 
2.43.0





[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux