[PATCH] iio: accel: kxcjk1013: Add tablet_mode sysfs file for exercising the KIOX010A ACPI DSM

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

 



Some 360 degree hinges (yoga) style 2-in-1 devices use 2 KXCJ91008-s
to allow the OS to determine the angle between the display and the base
of the device, so that the OS can determine if the 2-in-1 is in laptop
or in tablet-mode.

On Windows both accelerometers are read by a special HingeAngleService
process; and this process calls a DSM (Device Specific Method) on the
ACPI KIOX010A device node for the sensor in the display, to let the
embedded-controller (EC) know about the mode so that it can disable the
kbd and touchpad to avoid spurious input while folded into tablet-mode.

Currently the kxcjk1013 driver calls the DSM for this once at probe time
to ensure that the builtin kbd and touchpad work.

But some users have expressed interest in using this functionality to
disable the kbd and touchpad when folded into tablet-mode as done under
Windows.

Add a tablet_mode sysfs file so that users can control the kbd/touchpad
enable/disable functionality from user-space.

Reported-by: russianneuromancer <russianneuromancer@xxxxx>
Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx>
---
 drivers/iio/accel/kxcjk-1013.c | 49 ++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c
index 560a3373ff20..f15946d87c3c 100644
--- a/drivers/iio/accel/kxcjk-1013.c
+++ b/drivers/iio/accel/kxcjk-1013.c
@@ -150,6 +150,7 @@ struct kxcjk1013_data {
 	int64_t timestamp;
 	enum kx_chipset chipset;
 	enum kx_acpi_type acpi_type;
+	bool tablet_mode;
 };
 
 enum kxcjk1013_axis {
@@ -300,6 +301,50 @@ static int kiox010a_dsm(struct device *dev, int fn_index)
 	ACPI_FREE(obj);
 	return 0;
 }
+
+static ssize_t tablet_mode_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct kxcjk1013_data *data = iio_priv(indio_dev);
+
+	return sprintf(buf, "%d\n", data->tablet_mode);
+}
+
+static ssize_t tablet_mode_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t len)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct kxcjk1013_data *data = iio_priv(indio_dev);
+	unsigned long tablet_mode;
+	int err;
+
+	err = kstrtoul(buf, 0, &tablet_mode);
+	if (err)
+		return err;
+
+	err = kiox010a_dsm(&data->client->dev,
+			   tablet_mode ? KIOX010A_SET_TABLET_MODE :
+					 KIOX010A_SET_LAPTOP_MODE);
+	if (err)
+		return err;
+
+	data->tablet_mode = tablet_mode;
+	return len;
+}
+
+static DEVICE_ATTR_RW(tablet_mode);
+
+static struct attribute *tablet_mode_attrs[] = {
+	&dev_attr_tablet_mode.attr,
+	NULL
+};
+
+static const struct attribute_group tablet_mode_attrs_group = {
+	.attrs = tablet_mode_attrs,
+};
 #endif
 
 static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
@@ -383,6 +428,10 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
 	if (data->acpi_type == ACPI_KIOX010A) {
 		/* Make sure the kbd and touchpad on 2-in-1s using 2 KXCJ91008-s work */
 		kiox010a_dsm(&data->client->dev, KIOX010A_SET_LAPTOP_MODE);
+
+		ret = devm_device_add_group(&data->client->dev, &tablet_mode_attrs_group);
+		if (ret < 0)
+			dev_warn(&data->client->dev, "Error creating tablet_mode sysfs attribute\n");
 	}
 #endif
 
-- 
2.28.0




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux