Linux Input/HID development
 help / color / mirror / Atom feed
* [PATCH v2 3/3] HID: tighten ioctl command parsing
From: bentiss @ 2025-08-26 12:39 UTC (permalink / raw)
  To: Jiri Kosina, Shuah Khan, Arnd Bergmann
  Cc: linux-input, linux-kselftest, linux-kernel, Benjamin Tissoires,
	Arnd Bergmann
In-Reply-To: <20250826-b4-hidraw-ioctls-v2-0-c7726b236719@kernel.org>

From: Arnd Bergmann <arnd@arndb.de>

The handling for variable-length ioctl commands in hidraw_ioctl() is
rather complex and the check for the data direction is incomplete.

Simplify this code by factoring out the various ioctls grouped by dir
and size, and using a switch() statement with the size masked out, to
ensure the rest of the command is correctly matched.

Fixes: 9188e79ec3fd ("HID: add phys and name ioctls to hidraw")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
---
 drivers/hid/hidraw.c        | 224 ++++++++++++++++++++++++--------------------
 include/uapi/linux/hidraw.h |   2 +
 2 files changed, 124 insertions(+), 102 deletions(-)

diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index c887f48756f4be2a4bac03128f2885bde96c1e39..bbd6f23bce78951c7d667ff5c1c923cee3509e3f 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -394,27 +394,15 @@ static int hidraw_revoke(struct hidraw_list *list)
 	return 0;
 }
 
-static long hidraw_ioctl(struct file *file, unsigned int cmd,
-							unsigned long arg)
+static long hidraw_fixed_size_ioctl(struct file *file, struct hidraw *dev, unsigned int cmd,
+				    void __user *arg)
 {
-	struct inode *inode = file_inode(file);
-	unsigned int minor = iminor(inode);
-	long ret = 0;
-	struct hidraw *dev;
-	struct hidraw_list *list = file->private_data;
-	void __user *user_arg = (void __user*) arg;
-
-	down_read(&minors_rwsem);
-	dev = hidraw_table[minor];
-	if (!dev || !dev->exist || hidraw_is_revoked(list)) {
-		ret = -ENODEV;
-		goto out;
-	}
+	struct hid_device *hid = dev->hid;
 
 	switch (cmd) {
 		case HIDIOCGRDESCSIZE:
-			if (put_user(dev->hid->rsize, (int __user *)arg))
-				ret = -EFAULT;
+			if (put_user(hid->rsize, (int __user *)arg))
+				return -EFAULT;
 			break;
 
 		case HIDIOCGRDESC:
@@ -422,113 +410,145 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
 				__u32 len;
 
 				if (get_user(len, (int __user *)arg))
-					ret = -EFAULT;
-				else if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
-					ret = -EINVAL;
-				else if (copy_to_user(user_arg + offsetof(
-					struct hidraw_report_descriptor,
-					value[0]),
-					dev->hid->rdesc,
-					min(dev->hid->rsize, len)))
-					ret = -EFAULT;
+					return -EFAULT;
+
+				if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
+					return -EINVAL;
+
+				if (copy_to_user(arg + offsetof(
+				    struct hidraw_report_descriptor,
+				    value[0]),
+				    hid->rdesc,
+				    min(hid->rsize, len)))
+					return -EFAULT;
+
 				break;
 			}
 		case HIDIOCGRAWINFO:
 			{
 				struct hidraw_devinfo dinfo;
 
-				dinfo.bustype = dev->hid->bus;
-				dinfo.vendor = dev->hid->vendor;
-				dinfo.product = dev->hid->product;
-				if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
-					ret = -EFAULT;
+				dinfo.bustype = hid->bus;
+				dinfo.vendor = hid->vendor;
+				dinfo.product = hid->product;
+				if (copy_to_user(arg, &dinfo, sizeof(dinfo)))
+					return -EFAULT;
 				break;
 			}
 		case HIDIOCREVOKE:
 			{
-				if (user_arg)
-					ret = -EINVAL;
-				else
-					ret = hidraw_revoke(list);
-				break;
+				struct hidraw_list *list = file->private_data;
+
+				if (arg)
+					return -EINVAL;
+
+				return hidraw_revoke(list);
 			}
 		default:
-			{
-				struct hid_device *hid = dev->hid;
-				if (_IOC_TYPE(cmd) != 'H') {
-					ret = -EINVAL;
-					break;
-				}
+			/*
+			 * None of the above ioctls can return -EAGAIN, so
+			 * use it as a marker that we need to check variable
+			 * length ioctls.
+			 */
+			return -EAGAIN;
+	}
 
-				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSFEATURE(0))) {
-					int len = _IOC_SIZE(cmd);
-					ret = hidraw_send_report(file, user_arg, len, HID_FEATURE_REPORT);
-					break;
-				}
-				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGFEATURE(0))) {
-					int len = _IOC_SIZE(cmd);
-					ret = hidraw_get_report(file, user_arg, len, HID_FEATURE_REPORT);
-					break;
-				}
+	return 0;
+}
 
-				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSINPUT(0))) {
-					int len = _IOC_SIZE(cmd);
-					ret = hidraw_send_report(file, user_arg, len, HID_INPUT_REPORT);
-					break;
-				}
-				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGINPUT(0))) {
-					int len = _IOC_SIZE(cmd);
-					ret = hidraw_get_report(file, user_arg, len, HID_INPUT_REPORT);
-					break;
-				}
+static long hidraw_rw_variable_size_ioctl(struct file *file, struct hidraw *dev, unsigned int cmd,
+					  void __user *user_arg)
+{
+	int len = _IOC_SIZE(cmd);
+
+	switch (cmd & ~IOCSIZE_MASK) {
+	case HIDIOCSFEATURE(0):
+		return hidraw_send_report(file, user_arg, len, HID_FEATURE_REPORT);
+	case HIDIOCGFEATURE(0):
+		return hidraw_get_report(file, user_arg, len, HID_FEATURE_REPORT);
+	case HIDIOCSINPUT(0):
+		return hidraw_send_report(file, user_arg, len, HID_INPUT_REPORT);
+	case HIDIOCGINPUT(0):
+		return hidraw_get_report(file, user_arg, len, HID_INPUT_REPORT);
+	case HIDIOCSOUTPUT(0):
+		return hidraw_send_report(file, user_arg, len, HID_OUTPUT_REPORT);
+	case HIDIOCGOUTPUT(0):
+		return hidraw_get_report(file, user_arg, len, HID_OUTPUT_REPORT);
+	}
 
-				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSOUTPUT(0))) {
-					int len = _IOC_SIZE(cmd);
-					ret = hidraw_send_report(file, user_arg, len, HID_OUTPUT_REPORT);
-					break;
-				}
-				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGOUTPUT(0))) {
-					int len = _IOC_SIZE(cmd);
-					ret = hidraw_get_report(file, user_arg, len, HID_OUTPUT_REPORT);
-					break;
-				}
+	return -EINVAL;
+}
 
-				/* Begin Read-only ioctls. */
-				if (_IOC_DIR(cmd) != _IOC_READ) {
-					ret = -EINVAL;
-					break;
-				}
+static long hidraw_ro_variable_size_ioctl(struct file *file, struct hidraw *dev, unsigned int cmd,
+					  void __user *user_arg)
+{
+	struct hid_device *hid = dev->hid;
+	int len = _IOC_SIZE(cmd);
+	int field_len;
+
+	switch (cmd & ~IOCSIZE_MASK) {
+	case HIDIOCGRAWNAME(0):
+		field_len = strlen(hid->name) + 1;
+		if (len > field_len)
+			len = field_len;
+		return copy_to_user(user_arg, hid->name, len) ?  -EFAULT : len;
+	case HIDIOCGRAWPHYS(0):
+		field_len = strlen(hid->phys) + 1;
+		if (len > field_len)
+			len = field_len;
+		return copy_to_user(user_arg, hid->phys, len) ?  -EFAULT : len;
+	case HIDIOCGRAWUNIQ(0):
+		field_len = strlen(hid->uniq) + 1;
+		if (len > field_len)
+			len = field_len;
+		return copy_to_user(user_arg, hid->uniq, len) ?  -EFAULT : len;
+	}
 
-				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
-					int len = strlen(hid->name) + 1;
-					if (len > _IOC_SIZE(cmd))
-						len = _IOC_SIZE(cmd);
-					ret = copy_to_user(user_arg, hid->name, len) ?
-						-EFAULT : len;
-					break;
-				}
+	return -EINVAL;
+}
 
-				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
-					int len = strlen(hid->phys) + 1;
-					if (len > _IOC_SIZE(cmd))
-						len = _IOC_SIZE(cmd);
-					ret = copy_to_user(user_arg, hid->phys, len) ?
-						-EFAULT : len;
-					break;
-				}
+static long hidraw_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct inode *inode = file_inode(file);
+	unsigned int minor = iminor(inode);
+	struct hidraw *dev;
+	struct hidraw_list *list = file->private_data;
+	void __user *user_arg = (void __user *)arg;
+	int ret;
 
-				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWUNIQ(0))) {
-					int len = strlen(hid->uniq) + 1;
-					if (len > _IOC_SIZE(cmd))
-						len = _IOC_SIZE(cmd);
-					ret = copy_to_user(user_arg, hid->uniq, len) ?
-						-EFAULT : len;
-					break;
-				}
-			}
+	down_read(&minors_rwsem);
+	dev = hidraw_table[minor];
+	if (!dev || !dev->exist || hidraw_is_revoked(list)) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (_IOC_TYPE(cmd) != 'H') {
+		ret = -EINVAL;
+		goto out;
+	}
 
+	if (_IOC_NR(cmd) > HIDIOCTL_LAST || _IOC_NR(cmd) == 0) {
 		ret = -ENOTTY;
+		goto out;
 	}
+
+	ret = hidraw_fixed_size_ioctl(file, dev, cmd, user_arg);
+	if (ret != -EAGAIN)
+		goto out;
+
+	switch (_IOC_DIR(cmd)) {
+	case (_IOC_READ | _IOC_WRITE):
+		ret = hidraw_rw_variable_size_ioctl(file, dev, cmd, user_arg);
+		break;
+	case _IOC_READ:
+		ret = hidraw_ro_variable_size_ioctl(file, dev, cmd, user_arg);
+		break;
+	default:
+		/* Any other IOC_DIR is wrong */
+		ret = -EINVAL;
+	}
+
 out:
 	up_read(&minors_rwsem);
 	return ret;
diff --git a/include/uapi/linux/hidraw.h b/include/uapi/linux/hidraw.h
index d5ee269864e07fcaba481fa285bacbd98739e44f..ebd701b3c18d9d7465880199091933f13f2e1128 100644
--- a/include/uapi/linux/hidraw.h
+++ b/include/uapi/linux/hidraw.h
@@ -48,6 +48,8 @@ struct hidraw_devinfo {
 #define HIDIOCGOUTPUT(len)    _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0C, len)
 #define HIDIOCREVOKE	      _IOW('H', 0x0D, int) /* Revoke device access */
 
+#define HIDIOCTL_LAST		_IOC_NR(HIDIOCREVOKE)
+
 #define HIDRAW_FIRST_MINOR 0
 #define HIDRAW_MAX_DEVICES 64
 /* number of reports to buffer */

-- 
2.51.0


^ permalink raw reply related

* [PATCH v2 2/3] selftests/hid: hidraw: forge wrong ioctls and tests them
From: Benjamin Tissoires @ 2025-08-26 12:39 UTC (permalink / raw)
  To: Jiri Kosina, Shuah Khan, Arnd Bergmann
  Cc: linux-input, linux-kselftest, linux-kernel, Benjamin Tissoires
In-Reply-To: <20250826-b4-hidraw-ioctls-v2-0-c7726b236719@kernel.org>

We also need coverage for when the malicious user is not using the
proper ioctls definitions and tries to work around the driver.

Suggested-by: Arnd Bergmann <arnd@kernel.org>
Co-developed-by: claude-4-sonnet
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
---
 tools/testing/selftests/hid/hidraw.c | 127 +++++++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/tools/testing/selftests/hid/hidraw.c b/tools/testing/selftests/hid/hidraw.c
index 6d61d03e2ef05e1900fe5a3938d93421717b2621..d625772f8b7cf71fd94956d3a49d54ff44e2b34d 100644
--- a/tools/testing/selftests/hid/hidraw.c
+++ b/tools/testing/selftests/hid/hidraw.c
@@ -332,6 +332,133 @@ TEST_F(hidraw, ioctl_gfeature_invalid)
 	ASSERT_EQ(errno, EIO) TH_LOG("expected EIO, got errno %d", errno);
 }
 
+/*
+ * Test ioctl with incorrect nr bits
+ */
+TEST_F(hidraw, ioctl_invalid_nr)
+{
+	char buf[256] = {0};
+	int err;
+	unsigned int bad_cmd;
+
+	/*
+	 * craft an ioctl command with wrong _IOC_NR bits
+	 */
+	bad_cmd = _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x00, sizeof(buf)); /* 0 is not valid */
+
+	/* test the ioctl */
+	err = ioctl(self->hidraw_fd, bad_cmd, buf);
+	ASSERT_LT(err, 0) TH_LOG("ioctl read-write with wrong _IOC_NR (0) should have failed");
+	ASSERT_EQ(errno, ENOTTY)
+		TH_LOG("expected ENOTTY for wrong read-write _IOC_NR (0), got errno %d", errno);
+
+	/*
+	 * craft an ioctl command with wrong _IOC_NR bits
+	 */
+	bad_cmd = _IOC(_IOC_READ, 'H', 0x00, sizeof(buf)); /* 0 is not valid */
+
+	/* test the ioctl */
+	err = ioctl(self->hidraw_fd, bad_cmd, buf);
+	ASSERT_LT(err, 0) TH_LOG("ioctl read-only with wrong _IOC_NR (0) should have failed");
+	ASSERT_EQ(errno, ENOTTY)
+		TH_LOG("expected ENOTTY for wrong read-only _IOC_NR (0), got errno %d", errno);
+
+	/* also test with bigger number */
+	bad_cmd = _IOC(_IOC_READ, 'H', 0x42, sizeof(buf)); /* 0x42 is not valid as well */
+
+	err = ioctl(self->hidraw_fd, bad_cmd, buf);
+	ASSERT_LT(err, 0) TH_LOG("ioctl read-only with wrong _IOC_NR (0x42) should have failed");
+	ASSERT_EQ(errno, ENOTTY)
+		TH_LOG("expected ENOTTY for wrong read-only _IOC_NR (0x42), got errno %d", errno);
+
+	/* also test with bigger number: 0x42 is not valid as well */
+	bad_cmd = _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x42, sizeof(buf));
+
+	err = ioctl(self->hidraw_fd, bad_cmd, buf);
+	ASSERT_LT(err, 0) TH_LOG("ioctl read-write with wrong _IOC_NR (0x42) should have failed");
+	ASSERT_EQ(errno, ENOTTY)
+		TH_LOG("expected ENOTTY for wrong read-write _IOC_NR (0x42), got errno %d", errno);
+}
+
+/*
+ * Test ioctl with incorrect type bits
+ */
+TEST_F(hidraw, ioctl_invalid_type)
+{
+	char buf[256] = {0};
+	int err;
+	unsigned int bad_cmd;
+
+	/*
+	 * craft an ioctl command with wrong _IOC_TYPE bits
+	 */
+	bad_cmd = _IOC(_IOC_WRITE|_IOC_READ, 'I', 0x01, sizeof(buf)); /* 'I' should be 'H' */
+
+	/* test the ioctl */
+	err = ioctl(self->hidraw_fd, bad_cmd, buf);
+	ASSERT_LT(err, 0) TH_LOG("ioctl with wrong _IOC_TYPE (I) should have failed");
+	ASSERT_EQ(errno, EINVAL) TH_LOG("expected EINVAL for wrong _IOC_NR, got errno %d", errno);
+}
+
+/*
+ * Test HIDIOCGFEATURE ioctl with incorrect _IOC_DIR bits
+ */
+TEST_F(hidraw, ioctl_gfeature_invalid_dir)
+{
+	__u8 buf[10] = {0};
+	int err;
+	unsigned int bad_cmd;
+
+	/* set report ID 1 in first byte */
+	buf[0] = 1;
+
+	/*
+	 * craft an ioctl command with wrong _IOC_DIR bits
+	 * HIDIOCGFEATURE should have _IOC_WRITE|_IOC_READ, let's use only _IOC_WRITE
+	 */
+	bad_cmd = _IOC(_IOC_WRITE, 'H', 0x07, sizeof(buf)); /* should be _IOC_WRITE|_IOC_READ */
+
+	/* try to get feature report with wrong direction bits */
+	err = ioctl(self->hidraw_fd, bad_cmd, buf);
+	ASSERT_LT(err, 0) TH_LOG("HIDIOCGFEATURE with wrong _IOC_DIR should have failed");
+	ASSERT_EQ(errno, EINVAL) TH_LOG("expected EINVAL for wrong _IOC_DIR, got errno %d", errno);
+
+	/* also test with only _IOC_READ */
+	bad_cmd = _IOC(_IOC_READ, 'H', 0x07, sizeof(buf)); /* should be _IOC_WRITE|_IOC_READ */
+
+	err = ioctl(self->hidraw_fd, bad_cmd, buf);
+	ASSERT_LT(err, 0) TH_LOG("HIDIOCGFEATURE with wrong _IOC_DIR should have failed");
+	ASSERT_EQ(errno, EINVAL) TH_LOG("expected EINVAL for wrong _IOC_DIR, got errno %d", errno);
+}
+
+/*
+ * Test read-only ioctl with incorrect _IOC_DIR bits
+ */
+TEST_F(hidraw, ioctl_readonly_invalid_dir)
+{
+	char buf[256] = {0};
+	int err;
+	unsigned int bad_cmd;
+
+	/*
+	 * craft an ioctl command with wrong _IOC_DIR bits
+	 * HIDIOCGRAWNAME should have _IOC_READ, let's use _IOC_WRITE
+	 */
+	bad_cmd = _IOC(_IOC_WRITE, 'H', 0x04, sizeof(buf)); /* should be _IOC_READ */
+
+	/* try to get device name with wrong direction bits */
+	err = ioctl(self->hidraw_fd, bad_cmd, buf);
+	ASSERT_LT(err, 0) TH_LOG("HIDIOCGRAWNAME with wrong _IOC_DIR should have failed");
+	ASSERT_EQ(errno, EINVAL) TH_LOG("expected EINVAL for wrong _IOC_DIR, got errno %d", errno);
+
+	/* also test with _IOC_WRITE|_IOC_READ */
+	bad_cmd = _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x04, sizeof(buf)); /* should be only _IOC_READ */
+
+	err = ioctl(self->hidraw_fd, bad_cmd, buf);
+	ASSERT_LT(err, 0) TH_LOG("HIDIOCGRAWNAME with wrong _IOC_DIR should have failed");
+	ASSERT_EQ(errno, EINVAL) TH_LOG("expected EINVAL for wrong _IOC_DIR, got errno %d", errno);
+}
+
 /*
  * Test HIDIOCSFEATURE ioctl to set feature report
  */

-- 
2.51.0


^ permalink raw reply related

* [PATCH v2 1/3] selftests/hid: hidraw: add more coverage for hidraw ioctls
From: Benjamin Tissoires @ 2025-08-26 12:39 UTC (permalink / raw)
  To: Jiri Kosina, Shuah Khan, Arnd Bergmann
  Cc: linux-input, linux-kselftest, linux-kernel, Benjamin Tissoires
In-Reply-To: <20250826-b4-hidraw-ioctls-v2-0-c7726b236719@kernel.org>

Try to ensure all ioctls are having at least one test.

Co-developed-by: claude-4-sonnet
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
---
 tools/testing/selftests/hid/hid_common.h |   6 +
 tools/testing/selftests/hid/hidraw.c     | 346 +++++++++++++++++++++++++++++++
 2 files changed, 352 insertions(+)

diff --git a/tools/testing/selftests/hid/hid_common.h b/tools/testing/selftests/hid/hid_common.h
index f77f69c6657d0f0f66beb3b50bf4b126f6f63348..8085519c47cb505b901ac80f2087dc9a1aa2b9c0 100644
--- a/tools/testing/selftests/hid/hid_common.h
+++ b/tools/testing/selftests/hid/hid_common.h
@@ -230,6 +230,12 @@ static int uhid_event(struct __test_metadata *_metadata, int fd)
 		break;
 	case UHID_SET_REPORT:
 		UHID_LOG("UHID_SET_REPORT from uhid-dev");
+
+		answer.type = UHID_SET_REPORT_REPLY;
+		answer.u.set_report_reply.id = ev.u.set_report.id;
+		answer.u.set_report_reply.err = 0; /* success */
+
+		uhid_write(_metadata, fd, &answer);
 		break;
 	default:
 		TH_LOG("Invalid event from uhid-dev: %u", ev.type);
diff --git a/tools/testing/selftests/hid/hidraw.c b/tools/testing/selftests/hid/hidraw.c
index 821db37ba4bbef82e5cf4b44b6675666f87a12ad..6d61d03e2ef05e1900fe5a3938d93421717b2621 100644
--- a/tools/testing/selftests/hid/hidraw.c
+++ b/tools/testing/selftests/hid/hidraw.c
@@ -2,6 +2,9 @@
 /* Copyright (c) 2022-2024 Red Hat */
 
 #include "hid_common.h"
+#include <linux/input.h>
+#include <string.h>
+#include <sys/ioctl.h>
 
 /* for older kernels */
 #ifndef HIDIOCREVOKE
@@ -215,6 +218,349 @@ TEST_F(hidraw, write_event_revoked)
 	pthread_mutex_unlock(&uhid_output_mtx);
 }
 
+/*
+ * Test HIDIOCGRDESCSIZE ioctl to get report descriptor size
+ */
+TEST_F(hidraw, ioctl_rdescsize)
+{
+	int desc_size = 0;
+	int err;
+
+	/* call HIDIOCGRDESCSIZE ioctl */
+	err = ioctl(self->hidraw_fd, HIDIOCGRDESCSIZE, &desc_size);
+	ASSERT_EQ(err, 0) TH_LOG("HIDIOCGRDESCSIZE ioctl failed");
+
+	/* verify the size matches our test report descriptor */
+	ASSERT_EQ(desc_size, sizeof(rdesc))
+		TH_LOG("expected size %zu, got %d", sizeof(rdesc), desc_size);
+}
+
+/*
+ * Test HIDIOCGRDESC ioctl to get report descriptor data
+ */
+TEST_F(hidraw, ioctl_rdesc)
+{
+	struct hidraw_report_descriptor desc;
+	int err;
+
+	/* get the full report descriptor */
+	desc.size = sizeof(rdesc);
+	err = ioctl(self->hidraw_fd, HIDIOCGRDESC, &desc);
+	ASSERT_EQ(err, 0) TH_LOG("HIDIOCGRDESC ioctl failed");
+
+	/* verify the descriptor data matches our test descriptor */
+	ASSERT_EQ(memcmp(desc.value, rdesc, sizeof(rdesc)), 0)
+		TH_LOG("report descriptor data mismatch");
+}
+
+/*
+ * Test HIDIOCGRDESC ioctl with smaller buffer size
+ */
+TEST_F(hidraw, ioctl_rdesc_small_buffer)
+{
+	struct hidraw_report_descriptor desc;
+	int err;
+	size_t small_size = sizeof(rdesc) / 2; /* request half the descriptor size */
+
+	/* get partial report descriptor */
+	desc.size = small_size;
+	err = ioctl(self->hidraw_fd, HIDIOCGRDESC, &desc);
+	ASSERT_EQ(err, 0) TH_LOG("HIDIOCGRDESC ioctl failed with small buffer");
+
+	/* verify we got the first part of the descriptor */
+	ASSERT_EQ(memcmp(desc.value, rdesc, small_size), 0)
+		TH_LOG("partial report descriptor data mismatch");
+}
+
+/*
+ * Test HIDIOCGRAWINFO ioctl to get device information
+ */
+TEST_F(hidraw, ioctl_rawinfo)
+{
+	struct hidraw_devinfo devinfo;
+	int err;
+
+	/* get device info */
+	err = ioctl(self->hidraw_fd, HIDIOCGRAWINFO, &devinfo);
+	ASSERT_EQ(err, 0) TH_LOG("HIDIOCGRAWINFO ioctl failed");
+
+	/* verify device info matches our test setup */
+	ASSERT_EQ(devinfo.bustype, BUS_USB)
+		TH_LOG("expected bustype 0x03, got 0x%x", devinfo.bustype);
+	ASSERT_EQ(devinfo.vendor, 0x0001)
+		TH_LOG("expected vendor 0x0001, got 0x%x", devinfo.vendor);
+	ASSERT_EQ(devinfo.product, 0x0a37)
+		TH_LOG("expected product 0x0a37, got 0x%x", devinfo.product);
+}
+
+/*
+ * Test HIDIOCGFEATURE ioctl to get feature report
+ */
+TEST_F(hidraw, ioctl_gfeature)
+{
+	__u8 buf[10] = {0};
+	int err;
+
+	/* set report ID 1 in first byte */
+	buf[0] = 1;
+
+	/* get feature report */
+	err = ioctl(self->hidraw_fd, HIDIOCGFEATURE(sizeof(buf)), buf);
+	ASSERT_EQ(err, sizeof(feature_data)) TH_LOG("HIDIOCGFEATURE ioctl failed, got %d", err);
+
+	/* verify we got the expected feature data */
+	ASSERT_EQ(buf[0], feature_data[0])
+		TH_LOG("expected feature_data[0] = %d, got %d", feature_data[0], buf[0]);
+	ASSERT_EQ(buf[1], feature_data[1])
+		TH_LOG("expected feature_data[1] = %d, got %d", feature_data[1], buf[1]);
+}
+
+/*
+ * Test HIDIOCGFEATURE ioctl with invalid report ID
+ */
+TEST_F(hidraw, ioctl_gfeature_invalid)
+{
+	__u8 buf[10] = {0};
+	int err;
+
+	/* set invalid report ID (not 1) */
+	buf[0] = 2;
+
+	/* try to get feature report */
+	err = ioctl(self->hidraw_fd, HIDIOCGFEATURE(sizeof(buf)), buf);
+	ASSERT_LT(err, 0) TH_LOG("HIDIOCGFEATURE should have failed with invalid report ID");
+	ASSERT_EQ(errno, EIO) TH_LOG("expected EIO, got errno %d", errno);
+}
+
+/*
+ * Test HIDIOCSFEATURE ioctl to set feature report
+ */
+TEST_F(hidraw, ioctl_sfeature)
+{
+	__u8 buf[10] = {0};
+	int err;
+
+	/* prepare feature report data */
+	buf[0] = 1; /* report ID */
+	buf[1] = 0x42;
+	buf[2] = 0x24;
+
+	/* set feature report */
+	err = ioctl(self->hidraw_fd, HIDIOCSFEATURE(3), buf);
+	ASSERT_EQ(err, 3) TH_LOG("HIDIOCSFEATURE ioctl failed, got %d", err);
+
+	/*
+	 * Note: The uhid mock doesn't validate the set report data,
+	 * so we just verify the ioctl succeeds
+	 */
+}
+
+/*
+ * Test HIDIOCGINPUT ioctl to get input report
+ */
+TEST_F(hidraw, ioctl_ginput)
+{
+	__u8 buf[10] = {0};
+	int err;
+
+	/* set report ID 1 in first byte */
+	buf[0] = 1;
+
+	/* get input report */
+	err = ioctl(self->hidraw_fd, HIDIOCGINPUT(sizeof(buf)), buf);
+	ASSERT_EQ(err, sizeof(feature_data)) TH_LOG("HIDIOCGINPUT ioctl failed, got %d", err);
+
+	/* verify we got the expected input data */
+	ASSERT_EQ(buf[0], feature_data[0])
+		TH_LOG("expected feature_data[0] = %d, got %d", feature_data[0], buf[0]);
+	ASSERT_EQ(buf[1], feature_data[1])
+		TH_LOG("expected feature_data[1] = %d, got %d", feature_data[1], buf[1]);
+}
+
+/*
+ * Test HIDIOCGINPUT ioctl with invalid report ID
+ */
+TEST_F(hidraw, ioctl_ginput_invalid)
+{
+	__u8 buf[10] = {0};
+	int err;
+
+	/* set invalid report ID (not 1) */
+	buf[0] = 2;
+
+	/* try to get input report */
+	err = ioctl(self->hidraw_fd, HIDIOCGINPUT(sizeof(buf)), buf);
+	ASSERT_LT(err, 0) TH_LOG("HIDIOCGINPUT should have failed with invalid report ID");
+	ASSERT_EQ(errno, EIO) TH_LOG("expected EIO, got errno %d", errno);
+}
+
+/*
+ * Test HIDIOCSINPUT ioctl to set input report
+ */
+TEST_F(hidraw, ioctl_sinput)
+{
+	__u8 buf[10] = {0};
+	int err;
+
+	/* prepare input report data */
+	buf[0] = 1; /* report ID */
+	buf[1] = 0x55;
+	buf[2] = 0xAA;
+
+	/* set input report */
+	err = ioctl(self->hidraw_fd, HIDIOCSINPUT(3), buf);
+	ASSERT_EQ(err, 3) TH_LOG("HIDIOCSINPUT ioctl failed, got %d", err);
+
+	/*
+	 * Note: The uhid mock doesn't validate the set report data,
+	 * so we just verify the ioctl succeeds
+	 */
+}
+
+/*
+ * Test HIDIOCGOUTPUT ioctl to get output report
+ */
+TEST_F(hidraw, ioctl_goutput)
+{
+	__u8 buf[10] = {0};
+	int err;
+
+	/* set report ID 1 in first byte */
+	buf[0] = 1;
+
+	/* get output report */
+	err = ioctl(self->hidraw_fd, HIDIOCGOUTPUT(sizeof(buf)), buf);
+	ASSERT_EQ(err, sizeof(feature_data)) TH_LOG("HIDIOCGOUTPUT ioctl failed, got %d", err);
+
+	/* verify we got the expected output data */
+	ASSERT_EQ(buf[0], feature_data[0])
+		TH_LOG("expected feature_data[0] = %d, got %d", feature_data[0], buf[0]);
+	ASSERT_EQ(buf[1], feature_data[1])
+		TH_LOG("expected feature_data[1] = %d, got %d", feature_data[1], buf[1]);
+}
+
+/*
+ * Test HIDIOCGOUTPUT ioctl with invalid report ID
+ */
+TEST_F(hidraw, ioctl_goutput_invalid)
+{
+	__u8 buf[10] = {0};
+	int err;
+
+	/* set invalid report ID (not 1) */
+	buf[0] = 2;
+
+	/* try to get output report */
+	err = ioctl(self->hidraw_fd, HIDIOCGOUTPUT(sizeof(buf)), buf);
+	ASSERT_LT(err, 0) TH_LOG("HIDIOCGOUTPUT should have failed with invalid report ID");
+	ASSERT_EQ(errno, EIO) TH_LOG("expected EIO, got errno %d", errno);
+}
+
+/*
+ * Test HIDIOCSOUTPUT ioctl to set output report
+ */
+TEST_F(hidraw, ioctl_soutput)
+{
+	__u8 buf[10] = {0};
+	int err;
+
+	/* prepare output report data */
+	buf[0] = 1; /* report ID */
+	buf[1] = 0x33;
+	buf[2] = 0xCC;
+
+	/* set output report */
+	err = ioctl(self->hidraw_fd, HIDIOCSOUTPUT(3), buf);
+	ASSERT_EQ(err, 3) TH_LOG("HIDIOCSOUTPUT ioctl failed, got %d", err);
+
+	/*
+	 * Note: The uhid mock doesn't validate the set report data,
+	 * so we just verify the ioctl succeeds
+	 */
+}
+
+/*
+ * Test HIDIOCGRAWNAME ioctl to get device name string
+ */
+TEST_F(hidraw, ioctl_rawname)
+{
+	char name[256] = {0};
+	char expected_name[64];
+	int err;
+
+	/* get device name */
+	err = ioctl(self->hidraw_fd, HIDIOCGRAWNAME(sizeof(name)), name);
+	ASSERT_GT(err, 0) TH_LOG("HIDIOCGRAWNAME ioctl failed, got %d", err);
+
+	/* construct expected name based on device id */
+	snprintf(expected_name, sizeof(expected_name), "test-uhid-device-%d", self->hid.dev_id);
+
+	/* verify the name matches expected pattern */
+	ASSERT_EQ(strcmp(name, expected_name), 0)
+		TH_LOG("expected name '%s', got '%s'", expected_name, name);
+}
+
+/*
+ * Test HIDIOCGRAWPHYS ioctl to get device physical address string
+ */
+TEST_F(hidraw, ioctl_rawphys)
+{
+	char phys[256] = {0};
+	char expected_phys[64];
+	int err;
+
+	/* get device physical address */
+	err = ioctl(self->hidraw_fd, HIDIOCGRAWPHYS(sizeof(phys)), phys);
+	ASSERT_GT(err, 0) TH_LOG("HIDIOCGRAWPHYS ioctl failed, got %d", err);
+
+	/* construct expected phys based on device id */
+	snprintf(expected_phys, sizeof(expected_phys), "%d", self->hid.dev_id);
+
+	/* verify the phys matches expected value */
+	ASSERT_EQ(strcmp(phys, expected_phys), 0)
+		TH_LOG("expected phys '%s', got '%s'", expected_phys, phys);
+}
+
+/*
+ * Test HIDIOCGRAWUNIQ ioctl to get device unique identifier string
+ */
+TEST_F(hidraw, ioctl_rawuniq)
+{
+	char uniq[256] = {0};
+	int err;
+
+	/* get device unique identifier */
+	err = ioctl(self->hidraw_fd, HIDIOCGRAWUNIQ(sizeof(uniq)), uniq);
+	ASSERT_GE(err, 0) TH_LOG("HIDIOCGRAWUNIQ ioctl failed, got %d", err);
+
+	/* uniq is typically empty in our test setup */
+	ASSERT_EQ(strlen(uniq), 0) TH_LOG("expected empty uniq, got '%s'", uniq);
+}
+
+/*
+ * Test device string ioctls with small buffer sizes
+ */
+TEST_F(hidraw, ioctl_strings_small_buffer)
+{
+	char small_buf[8] = {0};
+	char expected_name[64];
+	int err;
+
+	/* test HIDIOCGRAWNAME with small buffer */
+	err = ioctl(self->hidraw_fd, HIDIOCGRAWNAME(sizeof(small_buf)), small_buf);
+	ASSERT_EQ(err, sizeof(small_buf))
+		TH_LOG("HIDIOCGRAWNAME with small buffer failed, got %d", err);
+
+	/* construct expected truncated name */
+	snprintf(expected_name, sizeof(expected_name), "test-uhid-device-%d", self->hid.dev_id);
+
+	/* verify we got truncated name (first 8 chars, no null terminator guaranteed) */
+	ASSERT_EQ(strncmp(small_buf, expected_name, sizeof(small_buf)), 0)
+		TH_LOG("expected truncated name to match first %zu chars", sizeof(small_buf));
+
+	/* Note: hidraw driver doesn't guarantee null termination when buffer is too small */
+}
+
 int main(int argc, char **argv)
 {
 	return test_harness_run(argc, argv);

-- 
2.51.0


^ permalink raw reply related

* [PATCH v2 0/3] HID: hidraw: rework ioctls
From: Benjamin Tissoires @ 2025-08-26 12:39 UTC (permalink / raw)
  To: Jiri Kosina, Shuah Khan, Arnd Bergmann
  Cc: linux-input, linux-kselftest, linux-kernel, Benjamin Tissoires,
	Arnd Bergmann

Arnd sent the v1 of the series in July, and it was bogus. So with a
little help from claude-sonnet I built up the missing ioctls tests and
tried to figure out a way to apply Arnd's logic without breaking the
existing ioctls.

The end result is in patch 3/3, which makes use of subfunctions to keep
the main ioctl code path clean.

Arnd, I kept your From: and SoB fields, please shout if you are unhappy.

Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
---
changes in v2:
- add new hidraw ioctls tests
- refactor Arnd's patch to keep the existing error path logic
- link to v1: https://lore.kernel.org/linux-input/20250711072847.2836962-1-arnd@kernel.org/

---

Jiri, checkpatch.pl complains about my co-develop tag. Did we get some
consensus for AI-assisted tag?

---
Arnd Bergmann (1):
      HID: tighten ioctl command parsing

Benjamin Tissoires (2):
      selftests/hid: hidraw: add more coverage for hidraw ioctls
      selftests/hid: hidraw: forge wrong ioctls and tests them

 drivers/hid/hidraw.c                     | 224 ++++++++-------
 include/uapi/linux/hidraw.h              |   2 +
 tools/testing/selftests/hid/hid_common.h |   6 +
 tools/testing/selftests/hid/hidraw.c     | 473 +++++++++++++++++++++++++++++++
 4 files changed, 603 insertions(+), 102 deletions(-)
---
base-commit: b80a75cf6999fb79971b41eaec7af2bb4b514714
change-id: 20250825-b4-hidraw-ioctls-66f34297032a

Best regards,
-- 
Benjamin Tissoires <bentiss@kernel.org>


^ permalink raw reply

* Re: [PATCH v1] HID: mf: add support for Legion Go dual dinput modes
From: Jiri Kosina @ 2025-08-26 10:49 UTC (permalink / raw)
  To: Antheas Kapenekakis; +Cc: linux-input, linux-kernel, Benjamin Tissoires
In-Reply-To: <CAGwozwH8Px=6X1AnH+3pohqdr9Y5thi6MfzJgOGtPC2c23ksjQ@mail.gmail.com>

On Tue, 26 Aug 2025, Antheas Kapenekakis wrote:

> Can you replace mf with quirks when merging if it is more appropriate?

Done. Now in hid.git#for-6.17/upstream-fixes. Thanks,

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply

* Re: [PATCH v1] HID: mf: add support for Legion Go dual dinput modes
From: Antheas Kapenekakis @ 2025-08-26 10:46 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: linux-input, linux-kernel, Benjamin Tissoires
In-Reply-To: <404sp531-6o34-rs48-po90-5276or97q405@xreary.bet>

On Tue, 26 Aug 2025 at 12:41, Jiri Kosina <jikos@kernel.org> wrote:
>
> On Sun, 3 Aug 2025, Antheas Kapenekakis wrote:
>
> > The Legion Go features detachable controllers which support a dual
> > dinput mode. In this mode, the controllers appear under a single HID
> > device with two applications.
> >
> > Currently, both controllers appear under the same event device, causing
> > their controls to be mixed up. This patch separates the two so that
> > they can be used independently.
> >
> > In addition, the latest firmware update for the Legion Go swaps the IDs
> > to the ones used by the Legion Go 2, so add those IDs as well.
> >
> > Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
>
> Hi,
>
> thanks, the patch looks good, but what is the 'mf: ' prefix about in the
> subject/shortlog?

Hm, I referenced a previous commit while writing the header and it
might not be relevant. Can you replace mf with quirks when merging if
it is more appropriate?

Thank you,
Antheas

> --
> Jiri Kosina
> SUSE Labs
>
>


^ permalink raw reply

* Re: [PATCH v1] HID: mf: add support for Legion Go dual dinput modes
From: Jiri Kosina @ 2025-08-26 10:41 UTC (permalink / raw)
  To: Antheas Kapenekakis; +Cc: linux-input, linux-kernel, Benjamin Tissoires
In-Reply-To: <20250803160253.12956-1-lkml@antheas.dev>

On Sun, 3 Aug 2025, Antheas Kapenekakis wrote:

> The Legion Go features detachable controllers which support a dual
> dinput mode. In this mode, the controllers appear under a single HID
> device with two applications.
> 
> Currently, both controllers appear under the same event device, causing
> their controls to be mixed up. This patch separates the two so that
> they can be used independently.
> 
> In addition, the latest firmware update for the Legion Go swaps the IDs
> to the ones used by the Legion Go 2, so add those IDs as well.
> 
> Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>

Hi,

thanks, the patch looks good, but what is the 'mf: ' prefix about in the 
subject/shortlog?

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply

* Re: [PATCH] HID: elecom: add support for ELECOM M-DT2DRBK
From: Jiri Kosina @ 2025-08-26 10:40 UTC (permalink / raw)
  To: Martin Hilgendorf; +Cc: Benjamin Tissoires, linux-input, linux-kernel
In-Reply-To: <20250802134542.21692-1-martin.hilgendorf@posteo.de>

On Sat, 2 Aug 2025, Martin Hilgendorf wrote:

> The DT2DRBK trackball has 8 buttons, but the report descriptor only
> specifies 5. This patch adds the device ID and performs a similar fixup as
> for other ELECOM devices to enable the remaining 3 buttons.
> 
> Signed-off-by: Martin Hilgendorf <martin.hilgendorf@posteo.de>

Applied to hid.git#for-6.17/upstream-fixes, thanks.

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply

* Re: [PATCH] HID: tighten ioctl command parsing
From: Benjamin Tissoires @ 2025-08-26 10:13 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Arnd Bergmann, Jiri Kosina, Peter Hutterer, linux-input,
	linux-kernel
In-Reply-To: <e0557372-b029-4831-8d32-c1eb512ac736@app.fastmail.com>

On Aug 22 2025, Arnd Bergmann wrote:
> On Thu, Aug 21, 2025, at 08:56, Benjamin Tissoires wrote:
> > On Jul 11 2025, Arnd Bergmann wrote:
> >>
> >> +			break;
> >> +	}
> >>  
> >> +	hid = dev->hid;
> >> +	switch (cmd & ~IOCSIZE_MASK) {
> >
> > Jiri pinged me about this one, and I gave it a go with the existing
> > tests I have in selftests... and turns out that this changes the logic
> > of the ioctl processing.
> >
> > The removed block was in the default section of the switch/case
> > statement. Now it's added *after*, meaning that any ioctl that was
> > normally processed before are now caught in the default of the switch
> > statement below and return -ENOTTY.
> >
> > Running tools/testing/selftests/hid/hid_bpf showed that.
> 
> Ah, of course, thanks for checking and describing the issue.
> 
> Did you already come up with a fixed patch? I'm currently
> travelling and won't be able to send a v2 quickly, so if you
> have a version that works for you, let's use that instead.
> 

I spent yesterday trying to find a way to make the old behavior looks
the same than the new, and got a rather big rewrite of your patch. I'll
send this out as a v2, keeping your From and SoB, but please shout if
you are unhappy with those 2 tags.

Cheers,
Benjamin

^ permalink raw reply

* [PATCH 2/2] hid: intel-thc-hid: intel-quickspi: Add WCL Device IDs
From: Xinpeng Sun @ 2025-08-26  7:27 UTC (permalink / raw)
  To: jikos, bentiss
  Cc: srinivas.pandruvada, linux-input, linux-kernel, Xinpeng Sun
In-Reply-To: <20250826072701.991046-1-xinpeng.sun@intel.com>

Signed-off-by: Xinpeng Sun <xinpeng.sun@intel.com>
---
 drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c | 2 ++
 drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
index 5e5f179dd113..84314989dc53 100644
--- a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
+++ b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
@@ -976,6 +976,8 @@ static const struct pci_device_id quickspi_pci_tbl[] = {
 	{PCI_DEVICE_DATA(INTEL, THC_PTL_H_DEVICE_ID_SPI_PORT2, &ptl), },
 	{PCI_DEVICE_DATA(INTEL, THC_PTL_U_DEVICE_ID_SPI_PORT1, &ptl), },
 	{PCI_DEVICE_DATA(INTEL, THC_PTL_U_DEVICE_ID_SPI_PORT2, &ptl), },
+	{PCI_DEVICE_DATA(INTEL, THC_WCL_DEVICE_ID_SPI_PORT1, &ptl), },
+	{PCI_DEVICE_DATA(INTEL, THC_WCL_DEVICE_ID_SPI_PORT2, &ptl), },
 	{}
 };
 MODULE_DEVICE_TABLE(pci, quickspi_pci_tbl);
diff --git a/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h b/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h
index 6fdf674b21c5..f3532d866749 100644
--- a/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h
+++ b/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h
@@ -19,6 +19,8 @@
 #define PCI_DEVICE_ID_INTEL_THC_PTL_H_DEVICE_ID_SPI_PORT2	0xE34B
 #define PCI_DEVICE_ID_INTEL_THC_PTL_U_DEVICE_ID_SPI_PORT1	0xE449
 #define PCI_DEVICE_ID_INTEL_THC_PTL_U_DEVICE_ID_SPI_PORT2	0xE44B
+#define PCI_DEVICE_ID_INTEL_THC_WCL_DEVICE_ID_SPI_PORT1 	0x4D49
+#define PCI_DEVICE_ID_INTEL_THC_WCL_DEVICE_ID_SPI_PORT2 	0x4D4B
 
 /* HIDSPI special ACPI parameters DSM methods */
 #define ACPI_QUICKSPI_REVISION_NUM			2
-- 
2.40.1


^ permalink raw reply related

* [PATCH 1/2] hid: intel-thc-hid: intel-quicki2c: Add WCL Device IDs
From: Xinpeng Sun @ 2025-08-26  7:27 UTC (permalink / raw)
  To: jikos, bentiss
  Cc: srinivas.pandruvada, linux-input, linux-kernel, Xinpeng Sun

Signed-off-by: Xinpeng Sun <xinpeng.sun@intel.com>
---
 drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c | 2 ++
 drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
index f122fde879b9..17b1f2df8f8a 100644
--- a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
+++ b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
@@ -1019,6 +1019,8 @@ static const struct pci_device_id quicki2c_pci_tbl[] = {
 	{ PCI_DEVICE_DATA(INTEL, THC_PTL_H_DEVICE_ID_I2C_PORT2, &ptl_ddata) },
 	{ PCI_DEVICE_DATA(INTEL, THC_PTL_U_DEVICE_ID_I2C_PORT1, &ptl_ddata) },
 	{ PCI_DEVICE_DATA(INTEL, THC_PTL_U_DEVICE_ID_I2C_PORT2, &ptl_ddata) },
+	{ PCI_DEVICE_DATA(INTEL, THC_WCL_DEVICE_ID_I2C_PORT1, &ptl_ddata) },
+	{ PCI_DEVICE_DATA(INTEL, THC_WCL_DEVICE_ID_I2C_PORT2, &ptl_ddata) },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, quicki2c_pci_tbl);
diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h
index b78c8864d39e..240492a38c24 100644
--- a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h
+++ b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h
@@ -13,6 +13,8 @@
 #define PCI_DEVICE_ID_INTEL_THC_PTL_H_DEVICE_ID_I2C_PORT2	0xE34A
 #define PCI_DEVICE_ID_INTEL_THC_PTL_U_DEVICE_ID_I2C_PORT1	0xE448
 #define PCI_DEVICE_ID_INTEL_THC_PTL_U_DEVICE_ID_I2C_PORT2	0xE44A
+#define PCI_DEVICE_ID_INTEL_THC_WCL_DEVICE_ID_I2C_PORT1 	0x4D48
+#define PCI_DEVICE_ID_INTEL_THC_WCL_DEVICE_ID_I2C_PORT2 	0x4D4A
 
 /* Packet size value, the unit is 16 bytes */
 #define MAX_PACKET_SIZE_VALUE_LNL			256
-- 
2.40.1


^ permalink raw reply related

* Re: [PATCH 0/2] HID: bpf: allow bpf to rebind a driver to hid-mutltiouch
From: Peter Hutterer @ 2025-08-26  2:54 UTC (permalink / raw)
  To: Benjamin Tissoires; +Cc: Jiri Kosina, linux-input, linux-kernel
In-Reply-To: <20250821-bpf-rescan-v1-0-08f9e2bc01bb@kernel.org>

On Thu, Aug 21, 2025 at 04:38:12PM +0200, Benjamin Tissoires wrote:
> This happened while Peter was trying to fix a Viewsonic device: the HID
> device sending multiotuch data through a proprietary collection was
> handled by hid-generic, and we don't have any way of attaching it to
> hid-multitouch because the pre-scanning wasn't able to see the Contact
> ID HID usage.
> 
> After a little of back and forth, it turns out that the best solution is
> to re-scan the device when a report descriptor is changed from the BPF
> point of view.
> 
> Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>

Thanks, this series looks good to me.

Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>

Cheers,
  Peter

> ---
> Benjamin Tissoires (2):
>       HID: core: factor out hid_set_group()
>       HID: bpf: rescan the device for the group after a load/unload
> 
>  drivers/hid/hid-core.c | 44 ++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 36 insertions(+), 8 deletions(-)
> ---
> base-commit: f55f91622e6f10884d30049f6748588b3718eecd
> change-id: 20250821-bpf-rescan-d4764865c67f
> 
> Best regards,
> -- 
> Benjamin Tissoires <bentiss@kernel.org>
> 

^ permalink raw reply

* Re: [PATCH] dt-bindings: input: touchscreen: imagis: add missing minItems
From: Duje Mihanović @ 2025-08-25 18:57 UTC (permalink / raw)
  To: Conor Dooley
  Cc: Markuss Broks, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Karel Balej, David Wronek, phone-devel,
	~postmarketos/upstreaming, linux-input, devicetree, linux-kernel
In-Reply-To: <20250825-capillary-viral-b7448ca6a57e@spud>

On Monday, 25 August 2025 18:42:38 Central European Summer Time Conor Dooley wrote:
> On Sun, Aug 24, 2025 at 06:12:05PM +0200, Duje Mihanović wrote:
> > The binding currently expects exactly 5 keycodes, which matches the
> > chip's theoretical maximum but probably not the number of touch keys on
> > any phone using the IST3032C. Add a minItems value of 2 to prevent
> > dt-validate complaints.
> 
> Does this mean that there are devicetrees in the wild that use < 5
> keycodes?

Indeed.

> > 
> > +  - |
> > +    #include <dt-bindings/input/linux-event-codes.h>
> > +    #include <dt-bindings/interrupt-controller/irq.h>
> > +    i2c {
> > +      #address-cells = <1>;
> > +      #size-cells = <0>;
> > +      touchscreen@50 {
> > +        compatible = "imagis,ist3032c";
> > +        reg = <0x50>;
> > +        interrupt-parent = <&gpio>;
> > +        interrupts = <72 IRQ_TYPE_EDGE_FALLING>;
> > +        vdd-supply = <&ldo2>;
> > +        touchscreen-size-x = <480>;
> > +        touchscreen-size-y = <800>;
> > +        linux,keycodes = <KEY_APPSELECT>, <KEY_BACK>;
> 
> Does this really need a dedicated example? Why can't the property go
> into the existing one?

Only the IST3032C is currently known to support these keys and this is enforced
by the binding, so it wouldn't really make sense to add it to the 3038C
example.

Regards,
--
Duje




^ permalink raw reply

* Re: [PATCH] dt-bindings: input: touchscreen: imagis: add missing minItems
From: Conor Dooley @ 2025-08-25 16:42 UTC (permalink / raw)
  To: Duje Mihanović
  Cc: Markuss Broks, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Karel Balej, David Wronek, phone-devel,
	~postmarketos/upstreaming, linux-input, devicetree, linux-kernel
In-Reply-To: <20250824-imagis-minitems-v1-1-cea9db55e87f@dujemihanovic.xyz>

[-- Attachment #1: Type: text/plain, Size: 2271 bytes --]

On Sun, Aug 24, 2025 at 06:12:05PM +0200, Duje Mihanović wrote:
> The binding currently expects exactly 5 keycodes, which matches the
> chip's theoretical maximum but probably not the number of touch keys on
> any phone using the IST3032C. Add a minItems value of 2 to prevent
> dt-validate complaints.

Does this mean that there are devicetrees in the wild that use < 5
keycodes?

> 
> Also add another example to make sure the linux,keycodes property is
> checked.
> 
> Signed-off-by: Duje Mihanović <duje@dujemihanovic.xyz>
> ---
>  .../bindings/input/touchscreen/imagis,ist3038c.yaml    | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml b/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml
> index bd8ede3a4ad8939cef97e9b177548a8fc8386df7..0ef79343bf9a223501aff8b6a525b873e777ea20 100644
> --- a/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml
> +++ b/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml
> @@ -35,6 +35,7 @@ properties:
>  
>    linux,keycodes:
>      description: Keycodes for the touch keys
> +    minItems: 2
>      maxItems: 5
>  
>    touchscreen-size-x: true
> @@ -87,5 +88,22 @@ examples:
>          touchscreen-inverted-y;
>        };
>      };
> +  - |
> +    #include <dt-bindings/input/linux-event-codes.h>
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    i2c {
> +      #address-cells = <1>;
> +      #size-cells = <0>;
> +      touchscreen@50 {
> +        compatible = "imagis,ist3032c";
> +        reg = <0x50>;
> +        interrupt-parent = <&gpio>;
> +        interrupts = <72 IRQ_TYPE_EDGE_FALLING>;
> +        vdd-supply = <&ldo2>;
> +        touchscreen-size-x = <480>;
> +        touchscreen-size-y = <800>;
> +        linux,keycodes = <KEY_APPSELECT>, <KEY_BACK>;

Does this really need a dedicated example? Why can't the property go
into the existing one?

> +      };
> +    };
>  
>  ...
> 
> ---
> base-commit: c17b750b3ad9f45f2b6f7e6f7f4679844244f0b9
> change-id: 20250824-imagis-minitems-4a71387ce61b
> 
> Best regards,
> -- 
> Duje Mihanović <duje@dujemihanovic.xyz>
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* Re: [PATCH RFC 1/3] dt-bindings: input: elan: Introduce Elan eKTP1059 Touchpad
From: Conor Dooley @ 2025-08-25 16:40 UTC (permalink / raw)
  To: Andreas Kemnade
  Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Henrik Rydberg, Tony Lindgren, hns, linux-input, devicetree,
	linux-kernel, linux-omap
In-Reply-To: <20250825-ektp-submit-v1-1-1dd476c1277b@kemnade.info>

[-- Attachment #1: Type: text/plain, Size: 1853 bytes --]

On Mon, Aug 25, 2025 at 12:07:28AM +0200, Andreas Kemnade wrote:
> The Elan eKTP1059 Touchpad is seen in the Epson Moverio BT-200
> attached via SPI. Add a binding for this chip. Little is known.
> 
> Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
> ---
>  .../devicetree/bindings/input/elan,ektp1059.yaml   | 45 ++++++++++++++++++++++
>  1 file changed, 45 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/input/elan,ektp1059.yaml b/Documentation/devicetree/bindings/input/elan,ektp1059.yaml
> new file mode 100644
> index 000000000000..a10256a271e0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/elan,ektp1059.yaml
> @@ -0,0 +1,45 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/input/elan,ektp1059.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Elantech SPI Touchpad
> +
> +maintainers:
> +  - Andreas Kemnade <andreas@kemnade.info>
> +
> +allOf:
> +  - $ref: touchscreen/touchscreen.yaml#
> +
> +properties:
> +  compatible:
> +    const: elan,ektp1059
> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupts:
> +    maxItems: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - interrupts
> +
> +additionalProperties: false

Shouldn't this be unevalutedProperties: false, since you want to make
use of what's in touchscreen.yaml?

> +
> +examples:
> +  - |
> +    #include <dt-bindings/interrupt-controller/irq.h>
> +    spi {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        touchpad@0 {
> +            compatible = "elan,ektp1059";
> +            reg = <0x0>;
> +            interrupt-parent = <&gpio4>;
> +            interrupts = <0x0 IRQ_TYPE_LEVEL_LOW>;
> +        };
> +    };
> 
> -- 
> 2.39.5
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* Re: [PATCH v3 2/2] HID: Make elan touch controllers power on after panel is enabled
From: Doug Anderson @ 2025-08-25 16:29 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Pin-yen Lin, Neil Armstrong, Jessica Zhang, Maarten Lankhorst,
	Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
	Benjamin Tissoires, linux-kernel, linux-input, Chen-Yu Tsai,
	dri-devel
In-Reply-To: <pr01os80-s752-1rqp-782q-65nr8222npq7@xreary.bet>

Hi,

On Tue, Aug 19, 2025 at 1:55 AM Jiri Kosina <jikos@kernel.org> wrote:
>
> On Mon, 18 Aug 2025, Doug Anderson wrote:
>
> > > Introduce a new HID quirk to indicate that this device has to be enabled
> > > after the panel's backlight is enabled, and update the driver data for
> > > the elan devices to enable this quirk. This cannot be a I2C HID quirk
> > > because the kernel needs to acknowledge this before powering up the
> > > device and read the VID/PID. When this quirk is enabled, register
> > > .panel_enabled()/.panel_disabling() instead for the panel follower.
> > >
> > > Also rename the *panel_prepare* functions into *panel_follower* because
> > > they could be called in other situations now.
> > >
> > > Fixes: bd3cba00dcc63 ("HID: i2c-hid: elan: Add support for Elan eKTH6915 i2c-hid touchscreens")
> > > Fixes: d06651bebf99e ("HID: i2c-hid: elan: Add elan-ekth6a12nay timing")
> > >
> > > Reviewed-by: Douglas Anderson <dianders@chromium.org>
> > > Signed-off-by: Pin-yen Lin <treapking@chromium.org>

Note: cuddled the "Fixes" tags and the "Reviewed-by" tag next to each
other while applying.


> > > ---
> > >
> > > Changes in v3:
> > > - Collect review tag
> > > - Add fixes tags
> > >
> > > Changes in v2:
> > > - Rename *panel_prepare* functions to *panel_follower*
> > > - Replace after_panel_enabled flag with enabled/disabling callbacks
> > >
> > >  drivers/hid/i2c-hid/i2c-hid-core.c    | 46 ++++++++++++++++-----------
> > >  drivers/hid/i2c-hid/i2c-hid-of-elan.c | 11 ++++++-
> > >  include/linux/hid.h                   |  2 ++
> > >  3 files changed, 40 insertions(+), 19 deletions(-)
> >
> > Re-iterating my response from v2 [1] so it's still seen even if people
> > only look at the latest version. :-) If HID folks don't mind us
> > landing this through drm-misc, feel free to Ack this patch.
>
> Acked-by: Jiri Kosina <jkosina@suse.com>

Pushed to drm-misc-next with Jiri's Ack:

[2/2] HID: i2c-hid: Make elan touch controllers power on after panel is enabled
      commit: cbdd16b818eef876dd2de9d503fe7397a0666cbe

NOTE that I added "i2c-hid" into the subject prefix to make things
more consistent.

-Doug

^ permalink raw reply

* Re: [PATCH v3 1/2] drm/panel: Allow powering on panel follower after panel is enabled
From: Doug Anderson @ 2025-08-25 16:28 UTC (permalink / raw)
  To: Pin-yen Lin
  Cc: Neil Armstrong, Jessica Zhang, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Jiri Kosina,
	Benjamin Tissoires, linux-kernel, linux-input, Chen-Yu Tsai,
	dri-devel
In-Reply-To: <CAD=FV=XZK3HO8iC3VyMH+fP_XG2ogSNvUWuUcPFUxn1jU6-JZA@mail.gmail.com>

Hi,

On Mon, Aug 18, 2025 at 1:11 PM Doug Anderson <dianders@chromium.org> wrote:
>
> Hi,
>
> On Mon, Aug 18, 2025 at 4:50 AM Pin-yen Lin <treapking@chromium.org> wrote:
> >
> > Some touch controllers have to be powered on after the panel's backlight
> > is enabled. To support these controllers, introduce .panel_enabled() and
> > .panel_disabling() to panel_follower_funcs and use them to power on the
> > device after the panel and its backlight are enabled.
> >
> > Signed-off-by: Pin-yen Lin <treapking@chromium.org>
> >
> > ---
> >
> > Changes in v3:
> > - Update kernel-docs of drm_panel_add_follower() and drm_panel_remove_follower()
> > - Fix the order of calling .panel_disabling() and .panel_unpreparing()
> > - Add a blank line before the goto label
> >
> > Changes in v2:
> > - Replace after_panel_enabled flag with enabled/disabling callbacks
> >
> >  drivers/gpu/drm/drm_panel.c | 73 +++++++++++++++++++++++++++++++------
> >  include/drm/drm_panel.h     | 14 +++++++
> >  2 files changed, 76 insertions(+), 11 deletions(-)
>
> Looks good to me now.
>
> Reviewed-by: Douglas Anderson <dianders@chromium.org>
>
> If there are no objections, I'll plan to apply patch #1 next week to
> give people a little time to speak up. As per discussion in v2 [1],
> unless we hear back an "Ack" from HID maintainers then patch #2 will
> just need to wait a while before it can land in the HID tree.
>
> Question for Jessica / Neil: what do you think about landing
> ${SUBJECT} patch in drm-misc-fixes instead of drm-misc-next? This is a
> dependency for the next patch which is marked as a "Fix". It'll mean
> that the patch can make it into mainline faster so the HID patch could
> land faster. The patch is also pretty low risk...
>
> [1] https://lore.kernel.org/r/CAD=FV=UV8_XGmxC=7Z18PEnj6wKz+yZQuV_4h+LJh_MNCqszvg@mail.gmail.com/

I didn't hear anything and it didn't seem urgent enough to put in
Fixes. Pushed to drm-misc-next.

[1/2] drm/panel: Allow powering on panel follower after panel is enabled
      commit: 2eb22214c132374e11e681c44d7879c91f67f614

^ permalink raw reply

* RE: [BUG] Kernel panic in amd_sfh on Lenovo Legion Go
From: Natikar, Basavaraj @ 2025-08-25 14:10 UTC (permalink / raw)
  To: Matthew Schwartz, S-k, Shyam-sundar
  Cc: Limonciello, Mario, linux-input@vger.kernel.org
In-Reply-To: <a21abca5-4268-449d-95f1-bdd7a25894a5@linux.dev>

[AMD Official Use Only - AMD Internal Distribution Only]

Thank you, Matthew, for bringing this issue to our attention.
We will look into it and keep you updated.

Thanks,
--
Basavaraj

-----Original Message-----
From: Matthew Schwartz <matthew.schwartz@linux.dev>
Sent: Friday, August 22, 2025 12:29 AM
To: Natikar, Basavaraj <Basavaraj.Natikar@amd.com>; S-k, Shyam-sundar <Shyam-sundar.S-k@amd.com>
Cc: Limonciello, Mario <Mario.Limonciello@amd.com>; linux-input@vger.kernel.org
Subject: [BUG] Kernel panic in amd_sfh on Lenovo Legion Go

Hello,

While using my Lenovo Legion Go handheld device on SteamOS, I have had many instances of warnings and occasional kernel panics in amd_sfh_work on their 6.15.8 kernel. Using kdumpst, I was able to get some logs for the most recent kernel panic:

<4>[  662.713733] ------------[ cut here ]------------ <4>[  662.713738] list_del corruption. prev->next should be ffff8ccc66a51e88, but was ffff8ccc5fc5d0e8. (prev=ffff8ccc41425280) <4>[  662.713754] WARNING: CPU: 11 PID: 164 at lib/list_debug.c:62 __list_del_entry_valid_or_report+0xfa/0x10a
<4>[  662.714204] CPU: 11 UID: 0 PID: 164 Comm: kworker/11:1 Tainted: G        W           6.15.8-valve1-2-neptune-615-g49248f4e2ad1 #1 PREEMPT(full)  64605a591817db76b46b95d73e86c4364b25c841
<4>[  662.714214] Tainted: [W]=WARN
<4>[  662.714218] Hardware name: LENOVO 83E1/LNVNB161216, BIOS N3CN37WW 12/06/2024 <4>[  662.714223] Workqueue: events amd_sfh_work [amd_sfh] <4>[  662.714236] RIP: 0010:__list_del_entry_valid_or_report+0xfa/0x10a
<4>[  662.714245] Code: e8 cb 4a 0f 00 0f 0b e9 77 ff ff ff 4c 89 e7 e8 dc 0c 3b 00 49 8b 14 24 4c 89 e1 48 89 de 48 c7 c7 28 c7 13 b0 e8 a6 4a 0f 00 <0f> 0b e9 52 ff ff ff 5b 5d 41 5c e9 91 c6 eb ff 48 89 df e8 1e fe <4>[  662.714250] RSP: 0018:ffffd12c806e3df8 EFLAGS: 00010246 <4>[  662.714257] RAX: 0000000000000000 RBX: ffff8ccc66a51e88 RCX: 0000000000000027 <4>[  662.714262] RDX: ffff8ccf0fedbd08 RSI: 0000000000000001 RDI: ffff8ccf0fedbd00 <4>[  662.714266] RBP: ffff8ccc41425280 R08: 0000000000000000 R09: 00000000fffdffff <4>[  662.714270] R10: ffffffffb16d0120 R11: ffffd12c806e3c88 R12: ffff8ccc41425280 <4>[  662.714274] R13: ffff8ccc66a51e88 R14: 0000000000000000 R15: ffff8ccc66a51e80 <4>[  662.714278] FS:  0000000000000000(0000) GS:ffff8ccf5e88a000(0000) knlGS:0000000000000000 <4>[  662.714283] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[  662.714287] CR2: 00000000c4f52010 CR3: 0000000164de1000 CR4: 0000000000f50ef0 <4>[  662.714292] PKRU: 55555554 <4>[  662.714296] Call Trace:
<4>[  662.714301]  <TASK>
<4>[  662.714310]  amd_sfh_work.cold+0x1c/0x21 [amd_sfh 590e26be9da743ed9c42d4473ff11e552461cd54]
<4>[  662.714323]  ? srso_alias_return_thunk+0x5/0xfbef5
<4>[  662.714333]  process_one_work+0x190/0x350 <4>[  662.714344]  worker_thread+0x2d7/0x410 <4>[  662.714353]  ? __pfx_worker_thread+0x10/0x10 <4>[  662.714360]  kthread+0xf9/0x240 <4>[  662.714370]  ? __pfx_kthread+0x10/0x10 <4>[  662.714378]  ret_from_fork+0x31/0x50 <4>[  662.714388]  ? __pfx_kthread+0x10/0x10 <4>[  662.714396]  ret_from_fork_asm+0x1a/0x30 <4>[  662.714411]  </TASK> <4>[  662.714415] ---[ end trace 0000000000000000 ]--- <4>[  662.714577] Oops: general protection fault, probably for non-canonical address 0x32e31c55d8aa0687: 0000 [#1] SMP NOPTI
<4>[  662.714590] CPU: 4 UID: 0 PID: 162 Comm: kworker/4:1 Tainted: G        W           6.15.8-valve1-2-neptune-615-g49248f4e2ad1 #1 PREEMPT(full)  64605a591817db76b46b95d73e86c4364b25c841
<4>[  662.714601] Tainted: [W]=WARN
<4>[  662.714605] Hardware name: LENOVO 83E1/LNVNB161216, BIOS N3CN37WW 12/06/2024 <4>[  662.714609] Workqueue: events amd_sfh_work [amd_sfh] <4>[  662.714622] RIP: 0010:amd_sfh_work+0x31/0x150 [amd_sfh] <4>[  662.714631] Code: 00 00 41 57 41 56 41 55 41 54 55 53 48 89 fb 48 83 ec 08 4c 8b af c0 00 00 00 4c 8b 67 f8 49 8b 45 08 49 8b 4d 00 4d 8d 7d f8 <4c> 3b 28 0f 85 2b 3b 00 00 4c 3b 69 08 0f 85 21 3b 00 00 48 89 41 <4>[  662.714636] RSP: 0018:ffffd12c8068fe18 EFLAGS: 00010296 <4>[  662.714643] RAX: 32e31c55d8aa0687 RBX: ffff8ccc414251c8 RCX: dead000000000100 <4>[  662.714648] RDX: 0000000000000001 RSI: ffff8ccc42240ec6 RDI: ffff8ccc414251c8 <4>[  662.714652] RBP: ffff8ccc400b7800 R08: 8080808080808080 R09: 0000000000000000 <4>[  662.714656] R10: ffff8ccc400508c0 R11: fefefefefefefeff R12: ffff8ccc43ac4e58 <4>[  662.714659] R13: ffff8ccc66a51e88 R14: 0000000000000000 R15: ffff8ccc66a51e80 <4>[  662.714664] FS:  0000000000000000(0000) GS:ffff8ccf5e6ca000(0000) knlGS:0000000000000000 <4>[  662.714669] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[  662.714673] CR2: 00007f7ccc5f9000 CR3: 0000000164de1000 CR4: 0000000000f50ef0 <4>[  662.714678] PKRU: 55555554 <4>[  662.714681] Call Trace:
<4>[  662.714687]  <TASK>
<4>[  662.714690]  ? srso_alias_return_thunk+0x5/0xfbef5
<4>[  662.714704]  process_one_work+0x190/0x350 <4>[  662.714715]  worker_thread+0x2d7/0x410 <4>[  662.714728]  ? __pfx_worker_thread+0x10/0x10 <4>[  662.714736]  kthread+0xf9/0x240 <4>[  662.714746]  ? __pfx_kthread+0x10/0x10 <4>[  662.714755]  ret_from_fork+0x31/0x50 <4>[  662.714763]  ? __pfx_kthread+0x10/0x10 <4>[  662.714772]  ret_from_fork_asm+0x1a/0x30 <4>[  662.714787]  </TASK> <4>[  662.715218] ---[ end trace 0000000000000000 ]---

Full dmesg from pstore:

dmesg-pstore.202508210732-0: https://gist.github.com/matte-schwartz/f7d5fbc9eb6b47051fb5c3ea4d6ae32f
dmesg-pstore-202508210732-1: https://gist.github.com/matte-schwartz/a473354010a23ecb0b119024c960166d

Similar warnings in amd-sfh appeared intermittently earlier in my journal until eventually one triggered the kernel panic above.

The warnings appeared while I was leaving the device idle on Steam's GamepadUI home page while using gamescope. Because this bug is intermittent, I don't have a more reliable way to reproduce the issue other than leaving the device idle for extended periods of time.

Thanks,
Matthew

^ permalink raw reply

* Re: [PATCH v1 0/2] Input: wdt87xx_i2c - a couple of cleanups
From: Andy Shevchenko @ 2025-08-25 13:55 UTC (permalink / raw)
  To: linux-input, linux-kernel; +Cc: Dmitry Torokhov
In-Reply-To: <20250321183957.455518-1-andriy.shevchenko@linux.intel.com>

On Fri, Mar 21, 2025 at 08:39:16PM +0200, Andy Shevchenko wrote:
> A couple of cleanups related to ACPI ID table and probe function.

Any news here?

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* [PATCH RFC 3/3] ARM: dts: ti/omap: epson-bt2ws: add touchpad
From: Andreas Kemnade @ 2025-08-24 22:07 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Henrik Rydberg, Tony Lindgren, hns
  Cc: linux-input, devicetree, linux-kernel, linux-omap,
	Andreas Kemnade
In-Reply-To: <20250825-ektp-submit-v1-0-1dd476c1277b@kemnade.info>

Add the EKTP1059 based touchpad connected via SPI.

Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
 arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts | 32 +++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts b/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts
index c90f43cc2fae..746ac4761b0d 100644
--- a/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts
+++ b/arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts
@@ -429,6 +429,23 @@ MATRIX_KEY(1, 1, KEY_VOLUMEDOWN)
 	linux,input-no-autorepeat;
 };
 
+&mcspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcspi1_pins>;
+
+	touchpad@0 {
+		compatible = "elan,ektp1059";
+		reg = <0>;      /* cs0 */
+		pinctrl-names = "default";
+		pinctrl-0 = <&elan_pins>;
+		interrupt-parent = <&gpio2>;
+		interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
+		spi-max-frequency = <200000>;
+		spi-cpol;
+		spi-cpha;
+	};
+};
+
 &mcbsp2 {
 	#sound-dai-cells = <0>;
 	pinctrl-names = "default";
@@ -506,6 +523,12 @@ OMAP4_IOPAD(0x1d4, PIN_OUTPUT | MUX_MODE3) /* gpio191 */
 		>;
 	};
 
+	elan_pins: pinmux-elan-pins {
+		pinctrl-single,pins = <
+			OMAP4_IOPAD(0x78, PIN_INPUT | MUX_MODE3) /* gpio52 */
+		>;
+	};
+
 	gpio_keys_pins: pinmux-gpio-key-pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x56, PIN_INPUT_PULLUP | MUX_MODE3) /* gpio35 */
@@ -579,6 +602,15 @@ OMAP4_IOPAD(0x1ce, PIN_OUTPUT | MUX_MODE3) /* gpio27 */
 		>;
 	};
 
+	mcspi1_pins: pinmux-mcspi1-pins {
+		pinctrl-single,pins = <
+			OMAP4_IOPAD(0x132, PIN_INPUT_PULLUP | MUX_MODE0)
+			OMAP4_IOPAD(0x134, PIN_INPUT_PULLUP | MUX_MODE0)
+			OMAP4_IOPAD(0x136, PIN_OUTPUT | MUX_MODE0)
+			OMAP4_IOPAD(0x138, PIN_OUTPUT | MUX_MODE0)
+		>;
+	};
+
 	mcbsp2_pins: pinmux-mcbsp2-pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x0f6, PIN_INPUT | MUX_MODE0)       /* abe_mcbsp2_clkx */

-- 
2.39.5


^ permalink raw reply related

* [PATCH RFC 0/3] Input: add EKTP1059 Touchpad
From: Andreas Kemnade @ 2025-08-24 22:07 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Henrik Rydberg, Tony Lindgren, hns
  Cc: linux-input, devicetree, linux-kernel, linux-omap,
	Andreas Kemnade

Add a driver and bindings for the Touchpad found in the Epson Moverio
BT-200. The only information source is the driver in the vendor kernel.
Besides of cleanup it differs from it by not doing much postprocessing.

The touchpad has no buttons and can react to three simultanous touches
but positions can be used only for two touches.

This is an early RFC, maybe somebody recognizes something from other
ELAN chips.

Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
Andreas Kemnade (3):
      dt-bindings: input: elan: Introduce Elan eKTP1059 Touchpad
      Input: Add driver for Elan eKTP1059 Touchpad
      ARM: dts: ti/omap: epson-bt2ws: add touchpad

 .../devicetree/bindings/input/elan,ektp1059.yaml   |  45 ++++
 arch/arm/boot/dts/ti/omap/omap4-epson-embt2ws.dts  |  32 +++
 drivers/input/mouse/Kconfig                        |  10 +
 drivers/input/mouse/Makefile                       |   1 +
 drivers/input/mouse/elan_ektp1059.c                | 267 +++++++++++++++++++++
 5 files changed, 355 insertions(+)
---
base-commit: 1b237f190eb3d36f52dffe07a40b5eb210280e00
change-id: 20250824-ektp-submit-338c4bc30503

Best regards,
--  
Andreas Kemnade <andreas@kemnade.info>


^ permalink raw reply

* [PATCH RFC 2/3] Input: Add driver for Elan eKTP1059 Touchpad
From: Andreas Kemnade @ 2025-08-24 22:07 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Henrik Rydberg, Tony Lindgren, hns
  Cc: linux-input, devicetree, linux-kernel, linux-omap,
	Andreas Kemnade
In-Reply-To: <20250825-ektp-submit-v1-0-1dd476c1277b@kemnade.info>

Add driver for Elan eKTP1059 Touchpad connected via SPI.
No information found whether it could be alternatively connected via I2C.
No details about protocol are known, the only information is found in the
vendor kernel of the Epson Moverio BT-200, drivers/input/elan
http://epsonservice.goepson.com/downloads/VI-APS/BT200_kernel.tgz

Known issues: After some time (minutes) touching it, interrupts
stop arriving. Chances are that source of this problem is outside
of the driver.

Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
 drivers/input/mouse/Kconfig         |  10 ++
 drivers/input/mouse/Makefile        |   1 +
 drivers/input/mouse/elan_ektp1059.c | 267 ++++++++++++++++++++++++++++++++++++
 3 files changed, 278 insertions(+)

diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index 833b643f0616..5b197bd8863b 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -300,6 +300,16 @@ config MOUSE_ELAN_I2C_SMBUS
 
 	   If unsure, say Y.
 
+config MOUSE_ELAN_EKTP1059
+	tristate "Elan EKTP1059 Touchpad"
+	depends on SPI
+	help
+	  Say Y here if you have an Elan ETKP1059 touchpad connected
+	  via SPI.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called elan_ektp1059.
+
 config MOUSE_INPORT
 	tristate "InPort/MS/ATIXL busmouse"
 	depends on ISA
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
index a1336d5bee6f..f6160a4c97c7 100644
--- a/drivers/input/mouse/Makefile
+++ b/drivers/input/mouse/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_MOUSE_ATARI)		+= atarimouse.o
 obj-$(CONFIG_MOUSE_BCM5974)		+= bcm5974.o
 obj-$(CONFIG_MOUSE_CYAPA)		+= cyapatp.o
 obj-$(CONFIG_MOUSE_ELAN_I2C)		+= elan_i2c.o
+obj-$(CONFIG_MOUSE_ELAN_EKTP1059)	+= elan_ektp1059.o
 obj-$(CONFIG_MOUSE_GPIO)		+= gpio_mouse.o
 obj-$(CONFIG_MOUSE_INPORT)		+= inport.o
 obj-$(CONFIG_MOUSE_LOGIBM)		+= logibm.o
diff --git a/drivers/input/mouse/elan_ektp1059.c b/drivers/input/mouse/elan_ektp1059.c
new file mode 100644
index 000000000000..a8ed7ba20e64
--- /dev/null
+++ b/drivers/input/mouse/elan_ektp1059.c
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Elantech eKTP1059 SPI Touchpad
+ * Copyright (C) 2025 Andreas Kemnade <andreas@kemnade.info>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/spi/spi.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/kthread.h>
+
+#define TOUCHPAD_WIDTH		4000
+#define TOUCHPAD_HEIGHT		2426
+#define TOUCH_AREA		20
+#define PRESSURE_MAX 256
+
+struct elan_tp_spi {
+	struct input_dev *input_touch;
+	struct spi_device *spi;
+};
+
+static int elan_spi_write(struct elan_tp_spi *elanspi, const void *buf, size_t len)
+{
+	/*
+	 * running this as single transfer with word_delay set
+	 * results in an irq storm. Epson vendor kernel uses a single spi_sync
+	 * multiple 1 byte transfers.
+	 */
+	size_t i;
+	int err;
+
+	for (i = 0 ; i < len; i++) {
+		err = spi_write(elanspi->spi, buf, 1);
+		if (err)
+			return err;
+
+		udelay(100);
+	}
+	return 0;
+}
+
+static int elan_spi_read(struct elan_tp_spi *elanspi, void *buf, size_t len)
+{
+	/* reads 0x51 on sync */
+	struct spi_transfer t = { 0 };
+	int err;
+	size_t i;
+
+	for (i = 0; i < len; i++) {
+		u8 dummy = 0xff;
+
+		t.len = 1;
+		t.tx_buf = &dummy;
+		t.rx_buf = buf + i;
+		err = spi_sync_transfer(elanspi->spi, &t, 1);
+		if (err)
+			return err;
+
+		udelay(80);
+	}
+	return 0;
+}
+
+static irqreturn_t elan_tp_irq_handler(int irq, void *dev_id)
+{
+	struct elan_tp_spi *elanspi = dev_id;
+	u8 buf[14];
+	int fingercnt = 0;
+	int x, y, pres, width;
+
+	if (elan_spi_read(elanspi, buf, 14))
+		return IRQ_HANDLED;
+
+	if (buf[13] != 0x1)
+		return IRQ_HANDLED;
+
+	fingercnt = (buf[1] & 0xC0) >> 6;
+	input_report_key(elanspi->input_touch, BTN_TOUCH, fingercnt != 0);
+	input_report_key(elanspi->input_touch, BTN_TOOL_FINGER, fingercnt == 1);
+	input_report_key(elanspi->input_touch, BTN_TOOL_DOUBLETAP, fingercnt == 2);
+	input_report_key(elanspi->input_touch, BTN_TOOL_TRIPLETAP, fingercnt == 3);
+
+	x = buf[2] & 0xf;
+	x = x << 8;
+	x |= buf[3];
+	y = buf[5] & 0xf;
+	y = y << 8;
+	y |= buf[6];
+
+	pres = (buf[2] & 0xf0) | ((buf[5] & 0xf0) >> 4);
+	width = ((buf[1] & 0x30) >> 2) | ((buf[4] & 0x30) >> 4);
+
+	input_report_abs(elanspi->input_touch, ABS_PRESSURE, pres);
+	input_report_abs(elanspi->input_touch, ABS_TOOL_WIDTH, width);
+
+	if (fingercnt != 0) {
+		input_report_abs(elanspi->input_touch, ABS_X, x);
+		input_report_abs(elanspi->input_touch, ABS_Y, y);
+	}
+
+	input_mt_slot(elanspi->input_touch, 0);
+	input_mt_report_slot_state(elanspi->input_touch, MT_TOOL_FINGER, fingercnt == 1);
+
+	if (fingercnt != 0) {
+		input_report_abs(elanspi->input_touch, ABS_MT_POSITION_X, x);
+		input_report_abs(elanspi->input_touch, ABS_MT_POSITION_Y, y);
+	}
+	dev_dbg(&elanspi->spi->dev, "1: X: %d Y: %d pres: %d width: %d\n",
+		x, y, pres, width);
+
+	if (fingercnt >= 2) {
+		x = buf[8] & 0xf;
+		x = x << 8;
+		x |= buf[9];
+		y = buf[11] & 0xf;
+		y = y << 8;
+		y |= buf[12];
+		input_mt_slot(elanspi->input_touch, 1);
+		input_mt_report_slot_state(elanspi->input_touch, MT_TOOL_FINGER, 1);
+		input_report_abs(elanspi->input_touch, ABS_MT_POSITION_X, x);
+		input_report_abs(elanspi->input_touch, ABS_MT_POSITION_Y, y);
+		dev_dbg(&elanspi->spi->dev, "2: X: %d Y: %d\n", x, y);
+	} else {
+		input_mt_slot(elanspi->input_touch, 1);
+		input_mt_report_slot_state(elanspi->input_touch, MT_TOOL_FINGER, 0);
+	}
+
+	input_sync(elanspi->input_touch);
+
+	return IRQ_HANDLED;
+}
+
+static int handle_hello_package(struct elan_tp_spi *elanspi)
+{
+	u8 buf_recv[4];
+	int rc;
+
+	rc = elan_spi_read(elanspi, buf_recv, 4);
+	if (rc != 0)
+		return rc;
+
+	/* 0xa0, 0x7, 0x0, 0x0 after boot */
+	dev_dbg(&elanspi->spi->dev,
+		"dump hello packet: %x, %x, %x, %x\n",
+		buf_recv[0], buf_recv[1], buf_recv[2], buf_recv[3]);
+
+	return 0;
+}
+
+static int init_touchpad(struct elan_tp_spi *elanspi)
+{
+	u8 buf_cmd[4] = {0x5B, 0x10, 0xC, 0x1};
+	u8 buf[14];
+	int ret;
+
+	ret = elan_spi_write(elanspi, buf_cmd, 4);
+
+	if (ret != 0)
+		return ret;
+
+	msleep(20);
+	elan_spi_read(elanspi, buf, 14);
+
+	return 0;
+}
+
+static int elan_ektp1059_probe(struct spi_device *spi)
+{
+	int status = 0;
+	struct elan_tp_spi *elanspi;
+	struct input_dev *input_touch;
+
+	spi->bits_per_word = 8;
+	status = spi_setup(spi);
+
+	elanspi = devm_kzalloc(&spi->dev,
+			       sizeof(struct elan_tp_spi), GFP_KERNEL);
+	if (!elanspi)
+		return -ENOMEM;
+
+	input_touch = devm_input_allocate_device(&spi->dev);
+	if (!input_touch)
+		return dev_err_probe(&spi->dev, PTR_ERR(input_touch),
+				     "create input touch device failed\n");
+
+	elanspi->input_touch = input_touch;
+
+	elanspi->spi = spi;
+	spi_set_drvdata(spi, elanspi);
+
+	input_touch->name = "elan-touchpad";
+	input_set_abs_params(input_touch, ABS_MT_POSITION_X, 0, TOUCHPAD_WIDTH, 0, 0);
+	input_set_abs_params(input_touch, ABS_MT_POSITION_Y, 0, TOUCHPAD_HEIGHT, 0, 0);
+	input_set_abs_params(input_touch, ABS_MT_PRESSURE, 0, PRESSURE_MAX, 0, 0);
+	input_set_abs_params(input_touch, ABS_TOOL_WIDTH, 0, TOUCH_AREA, 0, 0);
+	input_mt_init_slots(input_touch, 3, INPUT_MT_POINTER | INPUT_MT_SEMI_MT);
+	input_set_drvdata(input_touch, elanspi);
+
+	status = input_register_device(input_touch);
+	if (status < 0)
+		return dev_err_probe(&elanspi->spi->dev, status, "input_register_device failed\n");
+
+	status = handle_hello_package(elanspi);
+	if (status < 0)
+		return dev_err_probe(&elanspi->spi->dev, status, "handle hello package failed\n");
+
+	status = init_touchpad(elanspi);
+	if (status < 0)
+		return dev_err_probe(&spi->dev, status, "init touchpad failed!\n");
+
+	status = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
+					   elan_tp_irq_handler, IRQF_ONESHOT,
+					   spi->dev.driver->name, elanspi);
+	if (status < 0)
+		return dev_err_probe(&spi->dev, status, "request_irq failed\n");
+
+	return 0;
+}
+
+static int elan_ektp1059_suspend(struct device *dev)
+{
+	disable_irq(to_spi_device(dev)->irq);
+	return 0;
+}
+
+static int elan_ektp1059_resume(struct device *dev)
+{
+	enable_irq(to_spi_device(dev)->irq);
+	return 0;
+}
+
+static const struct spi_device_id elan_ektp1059_id[] = {
+	{ "ektp1059", 0 },
+	{},
+};
+MODULE_DEVICE_TABLE(spi, elan_ektp1059_id);
+
+static const struct of_device_id elan_ektp1059_of_spi_match[] = {
+	{ .compatible = "elan,ektp1059" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, elan_ektp1059_of_spi_match);
+
+static SIMPLE_DEV_PM_OPS(elan_ektp1059_pm, elan_ektp1059_suspend, elan_ektp1059_resume);
+
+static struct spi_driver elan_ektp1059_driver = {
+	.driver	= {
+		.name	 = "elan_ektp1059",
+		.of_match_table = elan_ektp1059_of_spi_match,
+		.pm = pm_ptr(&elan_ektp1059_pm),
+	},
+	.id_table = elan_ektp1059_id,
+	.probe	= elan_ektp1059_probe,
+};
+
+module_spi_driver(elan_ektp1059_driver);
+
+MODULE_DESCRIPTION("Elan eKTP1059 SPI touch pad");
+MODULE_LICENSE("GPL");

-- 
2.39.5


^ permalink raw reply related

* [PATCH RFC 1/3] dt-bindings: input: elan: Introduce Elan eKTP1059 Touchpad
From: Andreas Kemnade @ 2025-08-24 22:07 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Henrik Rydberg, Tony Lindgren, hns
  Cc: linux-input, devicetree, linux-kernel, linux-omap,
	Andreas Kemnade
In-Reply-To: <20250825-ektp-submit-v1-0-1dd476c1277b@kemnade.info>

The Elan eKTP1059 Touchpad is seen in the Epson Moverio BT-200
attached via SPI. Add a binding for this chip. Little is known.

Signed-off-by: Andreas Kemnade <andreas@kemnade.info>
---
 .../devicetree/bindings/input/elan,ektp1059.yaml   | 45 ++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/Documentation/devicetree/bindings/input/elan,ektp1059.yaml b/Documentation/devicetree/bindings/input/elan,ektp1059.yaml
new file mode 100644
index 000000000000..a10256a271e0
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/elan,ektp1059.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/elan,ektp1059.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Elantech SPI Touchpad
+
+maintainers:
+  - Andreas Kemnade <andreas@kemnade.info>
+
+allOf:
+  - $ref: touchscreen/touchscreen.yaml#
+
+properties:
+  compatible:
+    const: elan,ektp1059
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        touchpad@0 {
+            compatible = "elan,ektp1059";
+            reg = <0x0>;
+            interrupt-parent = <&gpio4>;
+            interrupts = <0x0 IRQ_TYPE_LEVEL_LOW>;
+        };
+    };

-- 
2.39.5


^ permalink raw reply related

* [PATCH] dt-bindings: input: touchscreen: imagis: add missing minItems
From: Duje Mihanović @ 2025-08-24 16:12 UTC (permalink / raw)
  To: Markuss Broks, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: Karel Balej, David Wronek, phone-devel, ~postmarketos/upstreaming,
	linux-input, devicetree, linux-kernel, Duje Mihanović

The binding currently expects exactly 5 keycodes, which matches the
chip's theoretical maximum but probably not the number of touch keys on
any phone using the IST3032C. Add a minItems value of 2 to prevent
dt-validate complaints.

Also add another example to make sure the linux,keycodes property is
checked.

Signed-off-by: Duje Mihanović <duje@dujemihanovic.xyz>
---
 .../bindings/input/touchscreen/imagis,ist3038c.yaml    | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml b/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml
index bd8ede3a4ad8939cef97e9b177548a8fc8386df7..0ef79343bf9a223501aff8b6a525b873e777ea20 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/imagis,ist3038c.yaml
@@ -35,6 +35,7 @@ properties:
 
   linux,keycodes:
     description: Keycodes for the touch keys
+    minItems: 2
     maxItems: 5
 
   touchscreen-size-x: true
@@ -87,5 +88,22 @@ examples:
         touchscreen-inverted-y;
       };
     };
+  - |
+    #include <dt-bindings/input/linux-event-codes.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+    i2c {
+      #address-cells = <1>;
+      #size-cells = <0>;
+      touchscreen@50 {
+        compatible = "imagis,ist3032c";
+        reg = <0x50>;
+        interrupt-parent = <&gpio>;
+        interrupts = <72 IRQ_TYPE_EDGE_FALLING>;
+        vdd-supply = <&ldo2>;
+        touchscreen-size-x = <480>;
+        touchscreen-size-y = <800>;
+        linux,keycodes = <KEY_APPSELECT>, <KEY_BACK>;
+      };
+    };
 
 ...

---
base-commit: c17b750b3ad9f45f2b6f7e6f7f4679844244f0b9
change-id: 20250824-imagis-minitems-4a71387ce61b

Best regards,
-- 
Duje Mihanović <duje@dujemihanovic.xyz>


^ permalink raw reply related

* Re: [PATCH] Input: iqs7222 - avoid enabling unused interrupts
From: Jeff LaBundy @ 2025-08-24 15:26 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input
In-Reply-To: <jqtokes6treccrh4xuawyiidydhsitpl6kbyqov2ge2vroklrn@ly7uxtl6fnbf>

Hi Dmitry,

On Sun, Aug 17, 2025 at 06:00:46PM -0700, Dmitry Torokhov wrote:
> Hi Jeff,
> 
> On Sun, Aug 17, 2025 at 07:20:22PM -0500, Jeff LaBundy wrote:
> > If a proximity event node is defined so as to specify the wake-up
> > properties of the touch surface, the proximity event interrupt is
> > enabled unconditionally. This may result in unwanted interrupts.
> > 
> > Solve this problem by enabling the interrupt only if the event is
> > mapped to a key or switch code.
> 
> Should I tag this for stable?

Thank you for checking; I'm sorry for the delayed response. Yes, I
think it's fine to tag this for stable.

I didn't CC stable@ originally because I saw this patch as more of
an optimization than a bug fix, but it's low risk enough that it's
fine to include in stable kernels too.

> 
> > 
> > Signed-off-by: Jeff LaBundy <jeff@labundy.com>
> > ---
> >  drivers/input/misc/iqs7222.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c
> > index 80b917944b51..ea26f85b9e9e 100644
> > --- a/drivers/input/misc/iqs7222.c
> > +++ b/drivers/input/misc/iqs7222.c
> > @@ -2424,6 +2424,9 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222,
> >  		if (error)
> >  			return error;
> >  
> > +		if (!iqs7222->kp_type[chan_index][i])
> > +			continue;
> > +
> >  		if (!dev_desc->event_offset)
> >  			continue;
> >  
> 
> Thanks.
> 
> -- 
> Dmitry

Kind regards,
Jeff LaBundy

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox