Linux Input/HID development
 help / color / mirror / Atom feed
* Re: [PATCH 1/2] HID: sensor-hub: Add sensor_hub_input_attr_read_values() for multi-byte reads
From: Andy Shevchenko @ 2026-06-10 10:52 UTC (permalink / raw)
  To: Zhang Lixu
  Cc: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada,
	Benjamin Tissoires, David Lechner, Nuno Sá, Andy Shevchenko,
	linux-input, linux-iio, linux-kernel
In-Reply-To: <20260610082911.157232-2-lixu.zhang@intel.com>

On Wed, Jun 10, 2026 at 04:29:09PM +0800, Zhang Lixu wrote:

> sensor_hub_input_attr_get_raw_value() is limited to returning a single
> 32-bit value, which is insufficient for sensors that report data larger
> than 32 bits, such as a quaternion with four s16 elements.
> 
> Add sensor_hub_input_attr_read_values() that accepts a caller-provided
> buffer and accumulates incoming data until the buffer is full. The two
> paths are distinguished in sensor_hub_raw_event() by pending.max_raw_size
> being non-zero, preserving backward compatibility.

I have reviewed that internally and checked public version which LGTM,
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [PATCH 2/2] iio: hid-sensor-rotation: Fix stale or zero output when reading raw values
From: sashiko-bot @ 2026-06-10  8:40 UTC (permalink / raw)
  To: Zhang Lixu; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260610082911.157232-3-lixu.zhang@intel.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] Stack Use-After-Free / Memory Corruption via synchronous HID read
- [High] PM Runtime Usage Counter Underflow due to missing error check
--

commit 4651e39f1dd649401d6eaaef3b3ae792bc120ba0
Author: Zhang Lixu <lixu.zhang@intel.com>

iio: hid-sensor-rotation: Fix stale or zero output when reading raw values

This commit fixes stale or zero output in dev_rot_read_raw by explicitly
powering up the sensor and issuing a synchronous GET_REPORT to receive
the full quaternion data into a local buffer.

> diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c
> index 4a11e45550991..1c6f02374f3ce 100644
> --- a/drivers/iio/orientation/hid-sensor-rotation.c
> +++ b/drivers/iio/orientation/hid-sensor-rotation.c
> @@ -86,6 +86,13 @@ static int dev_rot_read_raw(struct iio_dev *indio_dev,
>  				long mask)
>  {
>  	struct dev_rot_state *rot_state = iio_priv(indio_dev);
> +	struct hid_sensor_hub_device *hsdev = rot_state->common_attributes.hsdev;
> +	struct hid_sensor_hub_attribute_info *info = &rot_state->quaternion;
> +	u32 usage_id = HID_USAGE_SENSOR_ORIENT_QUATERNION;
> +	union {
> +		s16 val16[4];
> +		s32 val32[4];
> +	} raw_buf;
>  	int ret_type;
>  	int i;
>  
> @@ -95,8 +102,37 @@ static int dev_rot_read_raw(struct iio_dev *indio_dev,
>  	switch (mask) {
>  	case IIO_CHAN_INFO_RAW:
>  		if (size >= 4) {
> -			for (i = 0; i < 4; ++i)
> -				vals[i] = rot_state->scan.sampled_vals[i];
> +			if (info->size <= 0 || info->size > sizeof(raw_buf))
> +				return -EINVAL;
> +
> +			hid_sensor_power_state(&rot_state->common_attributes, true);

[Severity: High]
Should the return value of this power-on call be checked?

If hid_sensor_power_state fails, pm_runtime_resume_and_get cleans up its
PM usage count increment, leaving the net usage count unchanged.

Because this error is ignored, the code unconditionally calls
hid_sensor_power_state false later on, which invokes
pm_runtime_put_autosuspend and drops the usage counter by 1.

Does this cause the PM usage counter to underflow when power-on fails?

> +
> +			ret_type = sensor_hub_input_attr_read_values(hsdev,
> +								     hsdev->usage,
> +								     usage_id,
> +								     info->report_id,
> +								     SENSOR_HUB_SYNC,
> +								     info->size,
> +								     (u8 *)&raw_buf);

[Severity: Critical]
Can this corrupt the stack if the synchronous read is interrupted?

By passing a pointer to the stack-allocated raw_buf into
sensor_hub_input_attr_read_values, the driver relies on the wait
completing successfully.

If the wait is interrupted by a signal sent to the userspace process,
or if it times out:

drivers/hid/hid-sensor-hub.c:sensor_hub_input_attr_read_values() {
    ...
    cycles = wait_for_completion_interruptible_timeout(&hsdev->pending.ready,
                                                       HZ * 5);
    if (cycles == 0)
        ret = -ETIMEDOUT;
    else if (cycles < 0)
        ret = cycles;

    hsdev->pending.status = false;
    ...
}

The function locklessly clears hsdev->pending.status and returns, destroying
the raw_buf stack frame.

However, the concurrent HID interrupt handler sensor_hub_raw_event might
have already evaluated hsdev->pending.status as true under the lock, and
could proceed to memcpy into the now-freed stack pointer.

> +
> +			hid_sensor_power_state(&rot_state->common_attributes, false);
> +
> +			if (ret_type < 0)
> +				return ret_type;

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260610082911.157232-1-lixu.zhang@intel.com?part=2

^ permalink raw reply

* Re: [PATCH 1/2] HID: sensor-hub: Add sensor_hub_input_attr_read_values() for multi-byte reads
From: sashiko-bot @ 2026-06-10  8:38 UTC (permalink / raw)
  To: Zhang Lixu; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260610082911.157232-2-lixu.zhang@intel.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [Critical] Missing spinlock acquisition in the timeout/abort path of `sensor_hub_input_attr_read_values` leads to race conditions, use-after-free, and stack memory corruption.

Pre-existing issues:
- [High] Reading past the end of short HID reports exposes uninitialized kernel heap memory.
- [High] Repeated field matches in `sensor_hub_raw_event()` cause uncontrolled `kmemdup()` allocations, leaking memory.
--

commit b3186306e6632f94df0275d5e172210ae3044b54
Author: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>

HID: sensor-hub: Add sensor_hub_input_attr_read_values() for multi-byte reads

This commit introduces sensor_hub_input_attr_read_values() to allow
multi-byte reads for sensors reporting data larger than 32 bits. It
uses a caller-provided buffer to accumulate incoming data in
sensor_hub_raw_event() until the buffer is full.

> diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
> --- a/drivers/hid/hid-sensor-hub.c
> +++ b/drivers/hid/hid-sensor-hub.c

[ ... ]

> +	if (flag == SENSOR_HUB_SYNC) {
> +		cycles = wait_for_completion_interruptible_timeout(&hsdev->pending.ready,
> +								   HZ * 5);
> +		if (cycles == 0)
> +			ret = -ETIMEDOUT;
> +		else if (cycles < 0)
> +			ret = cycles;
> +
> +		hsdev->pending.status = false;

[Severity: Critical]
Does setting this status flag without acquiring the data->lock introduce a
race condition?

If wait_for_completion_interruptible_timeout() times out or is interrupted,
this locklessly sets hsdev->pending.status = false and returns. Concurrently,
the interrupt handler sensor_hub_raw_event() might have already observed
status as true and could be mid-copy into the caller-provided buffer.

Returning early would invalidate the caller-provided buffer, and the
interrupt handler might subsequently overwrite the destroyed stack frame.

> +	}
> +	mutex_unlock(hsdev->mutex_ptr);
> +
> +	return ret;
> +}

[ ... ]

> @@ -518,12 +568,27 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
>  					      hsdev->pending.attr_usage_id ==
>  					      report->field[i]->logical)) {
>  			hid_dbg(hdev, "data was pending ...\n");
> -			hsdev->pending.raw_data = kmemdup(ptr, sz, GFP_ATOMIC);
> -			if (hsdev->pending.raw_data)
> -				hsdev->pending.raw_size = sz;
> -			else
> -				hsdev->pending.raw_size = 0;
> -			complete(&hsdev->pending.ready);
> +			if (hsdev->pending.max_raw_size) {
> +				if (hsdev->pending.index < hsdev->pending.max_raw_size) {
> +					avail = hsdev->pending.max_raw_size - hsdev->pending.index;
> +					copy_size = clamp(sz, 0U, avail);
> +
> +					memcpy(hsdev->pending.raw_data + hsdev->pending.index,
> +					       ptr, copy_size);

[Severity: Critical]
As mentioned above, if sensor_hub_input_attr_read_values() aborts early,
could this memcpy() write into an invalidated stack buffer?

> +					hsdev->pending.index += copy_size;
> +					if (hsdev->pending.index >= hsdev->pending.max_raw_size) {
> +						hsdev->pending.raw_size = hsdev->pending.index;
> +						complete(&hsdev->pending.ready);
> +					}
> +				}
> +			} else {
> +				hsdev->pending.raw_data = kmemdup(ptr, sz, GFP_ATOMIC);

[Severity: High]
This is a pre-existing issue, but does this allocation leak memory if a
crafted HID report contains multiple duplicate fields matching the
requested usage?

If the device rapidly spams events while a reader is waiting, each match
could trigger a new kmemdup, overwriting the hsdev->pending.raw_data
pointer and permanently leaking the previously allocated blocks.

> +				if (hsdev->pending.raw_data)
> +					hsdev->pending.raw_size = sz;
> +				else
> +					hsdev->pending.raw_size = 0;
> +				complete(&hsdev->pending.ready);
> +			}
>  		}
>  		if (callback->capture_sample) {
>  			if (report->field[i]->logical)

[Severity: High]
This is a pre-existing issue, but does the loop advancing ptr expose
uninitialized heap memory on short reports?

Looking at the loop in sensor_hub_raw_event():

	for (i = 0; i < report->maxfield; ++i) {
		...
		sz = (report->field[i]->report_size *
					report->field[i]->report_count)/8;
		...
		ptr += sz;
	}

The pointer is unconditionally advanced by the expected sizes defined in
the report descriptor. Since sensor_hub_raw_event() ignores the actual
size argument representing the received packet length, a maliciously
short packet could cause the driver to read past the initialized packet
bounds.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260610082911.157232-1-lixu.zhang@intel.com?part=1

^ permalink raw reply

* [PATCH 2/2] iio: hid-sensor-rotation: Fix stale or zero output when reading raw values
From: Zhang Lixu @ 2026-06-10  8:29 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada,
	Benjamin Tissoires
  Cc: David Lechner, Nuno Sá, Andy Shevchenko, linux-input,
	linux-iio, linux-kernel, lixu.zhang
In-Reply-To: <20260610082911.157232-1-lixu.zhang@intel.com>

When reading the raw quaternion attribute (in_rot_quaternion_raw), the
driver currently returns either all zeros (if the sensor was never enabled)
or stale data (if the sensor was previously enabled) because it reads from
the internal buffer without explicitly requesting a new sample from the
sensor.

To fix this, power up the sensor, call sensor_hub_input_attr_read_values()
to issue a synchronous GET_REPORT and receive the full quaternion data
directly into a local buffer, then decode the four components.

Signed-off-by: Zhang Lixu <lixu.zhang@intel.com>
---
 drivers/iio/orientation/hid-sensor-rotation.c | 40 ++++++++++++++++++-
 1 file changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c
index 4a11e45550991..1c6f02374f3ce 100644
--- a/drivers/iio/orientation/hid-sensor-rotation.c
+++ b/drivers/iio/orientation/hid-sensor-rotation.c
@@ -86,6 +86,13 @@ static int dev_rot_read_raw(struct iio_dev *indio_dev,
 				long mask)
 {
 	struct dev_rot_state *rot_state = iio_priv(indio_dev);
+	struct hid_sensor_hub_device *hsdev = rot_state->common_attributes.hsdev;
+	struct hid_sensor_hub_attribute_info *info = &rot_state->quaternion;
+	u32 usage_id = HID_USAGE_SENSOR_ORIENT_QUATERNION;
+	union {
+		s16 val16[4];
+		s32 val32[4];
+	} raw_buf;
 	int ret_type;
 	int i;
 
@@ -95,8 +102,37 @@ static int dev_rot_read_raw(struct iio_dev *indio_dev,
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
 		if (size >= 4) {
-			for (i = 0; i < 4; ++i)
-				vals[i] = rot_state->scan.sampled_vals[i];
+			if (info->size <= 0 || info->size > sizeof(raw_buf))
+				return -EINVAL;
+
+			hid_sensor_power_state(&rot_state->common_attributes, true);
+
+			ret_type = sensor_hub_input_attr_read_values(hsdev,
+								     hsdev->usage,
+								     usage_id,
+								     info->report_id,
+								     SENSOR_HUB_SYNC,
+								     info->size,
+								     (u8 *)&raw_buf);
+
+			hid_sensor_power_state(&rot_state->common_attributes, false);
+
+			if (ret_type < 0)
+				return ret_type;
+
+			switch (info->size) {
+			case sizeof(raw_buf.val16):
+				for (i = 0; i < ARRAY_SIZE(raw_buf.val16); i++)
+					vals[i] = raw_buf.val16[i];
+				break;
+			case sizeof(raw_buf.val32):
+				for (i = 0; i < ARRAY_SIZE(raw_buf.val32); i++)
+					vals[i] = raw_buf.val32[i];
+				break;
+			default:
+				return -EINVAL;
+			}
+
 			ret_type = IIO_VAL_INT_MULTIPLE;
 			*val_len =  4;
 		} else
-- 
2.43.0


^ permalink raw reply related

* [PATCH 1/2] HID: sensor-hub: Add sensor_hub_input_attr_read_values() for multi-byte reads
From: Zhang Lixu @ 2026-06-10  8:29 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada,
	Benjamin Tissoires
  Cc: David Lechner, Nuno Sá, Andy Shevchenko, linux-input,
	linux-iio, linux-kernel, lixu.zhang
In-Reply-To: <20260610082911.157232-1-lixu.zhang@intel.com>

From: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>

sensor_hub_input_attr_get_raw_value() is limited to returning a single
32-bit value, which is insufficient for sensors that report data larger
than 32 bits, such as a quaternion with four s16 elements.

Add sensor_hub_input_attr_read_values() that accepts a caller-provided
buffer and accumulates incoming data until the buffer is full. The two
paths are distinguished in sensor_hub_raw_event() by pending.max_raw_size
being non-zero, preserving backward compatibility.

Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Co-developed-by: Zhang Lixu <lixu.zhang@intel.com>
Signed-off-by: Zhang Lixu <lixu.zhang@intel.com>
---
 drivers/hid/hid-sensor-hub.c   | 77 +++++++++++++++++++++++++++++++---
 include/linux/hid-sensor-hub.h | 25 +++++++++++
 2 files changed, 96 insertions(+), 6 deletions(-)

diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index 90666ff629def..34f710c465b80 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -286,6 +286,54 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id,
 }
 EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
 
+int sensor_hub_input_attr_read_values(struct hid_sensor_hub_device *hsdev,
+				      u32 usage_id, u32 attr_usage_id,
+				      u32 report_id,
+				      enum sensor_hub_read_flags flag,
+				      u32 buffer_size, u8 *buffer)
+{
+	struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
+	struct hid_report *report;
+	unsigned long flags;
+	long cycles;
+	int ret;
+
+	report = sensor_hub_report(report_id, hsdev->hdev, HID_INPUT_REPORT);
+	if (!report)
+		return -EINVAL;
+
+	mutex_lock(hsdev->mutex_ptr);
+	if (flag == SENSOR_HUB_SYNC) {
+		memset(&hsdev->pending, 0, sizeof(hsdev->pending));
+		init_completion(&hsdev->pending.ready);
+		hsdev->pending.usage_id = usage_id;
+		hsdev->pending.attr_usage_id = attr_usage_id;
+		hsdev->pending.max_raw_size = buffer_size;
+		hsdev->pending.raw_data = buffer;
+
+		spin_lock_irqsave(&data->lock, flags);
+		hsdev->pending.status = true;
+		spin_unlock_irqrestore(&data->lock, flags);
+	}
+	mutex_lock(&data->mutex);
+	hid_hw_request(hsdev->hdev, report, HID_REQ_GET_REPORT);
+	mutex_unlock(&data->mutex);
+	ret = 0;
+	if (flag == SENSOR_HUB_SYNC) {
+		cycles = wait_for_completion_interruptible_timeout(&hsdev->pending.ready,
+								   HZ * 5);
+		if (cycles == 0)
+			ret = -ETIMEDOUT;
+		else if (cycles < 0)
+			ret = cycles;
+
+		hsdev->pending.status = false;
+	}
+	mutex_unlock(hsdev->mutex_ptr);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(sensor_hub_input_attr_read_values);
 
 int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
 					u32 usage_id,
@@ -478,6 +526,8 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
 	struct hid_collection *collection = NULL;
 	void *priv = NULL;
 	struct hid_sensor_hub_device *hsdev = NULL;
+	u32 copy_size;
+	u32 avail;
 
 	hid_dbg(hdev, "sensor_hub_raw_event report id:0x%x size:%d type:%d\n",
 			 report->id, size, report->type);
@@ -518,12 +568,27 @@ static int sensor_hub_raw_event(struct hid_device *hdev,
 					      hsdev->pending.attr_usage_id ==
 					      report->field[i]->logical)) {
 			hid_dbg(hdev, "data was pending ...\n");
-			hsdev->pending.raw_data = kmemdup(ptr, sz, GFP_ATOMIC);
-			if (hsdev->pending.raw_data)
-				hsdev->pending.raw_size = sz;
-			else
-				hsdev->pending.raw_size = 0;
-			complete(&hsdev->pending.ready);
+			if (hsdev->pending.max_raw_size) {
+				if (hsdev->pending.index < hsdev->pending.max_raw_size) {
+					avail = hsdev->pending.max_raw_size - hsdev->pending.index;
+					copy_size = clamp(sz, 0U, avail);
+
+					memcpy(hsdev->pending.raw_data + hsdev->pending.index,
+					       ptr, copy_size);
+					hsdev->pending.index += copy_size;
+					if (hsdev->pending.index >= hsdev->pending.max_raw_size) {
+						hsdev->pending.raw_size = hsdev->pending.index;
+						complete(&hsdev->pending.ready);
+					}
+				}
+			} else {
+				hsdev->pending.raw_data = kmemdup(ptr, sz, GFP_ATOMIC);
+				if (hsdev->pending.raw_data)
+					hsdev->pending.raw_size = sz;
+				else
+					hsdev->pending.raw_size = 0;
+				complete(&hsdev->pending.ready);
+			}
 		}
 		if (callback->capture_sample) {
 			if (report->field[i]->logical)
diff --git a/include/linux/hid-sensor-hub.h b/include/linux/hid-sensor-hub.h
index e710565531085..ab5cc8db3fbb3 100644
--- a/include/linux/hid-sensor-hub.h
+++ b/include/linux/hid-sensor-hub.h
@@ -43,6 +43,8 @@ struct hid_sensor_hub_attribute_info {
  * @attr_usage_id:	Usage Id of a field, e.g. X-axis for a gyro.
  * @raw_size:		Response size for a read request.
  * @raw_data:		Place holder for received response.
+ * @index:		Current write index into raw_data for multi-byte reads.
+ * @max_raw_size:	Total buffer size for multi-byte reads; 0 for single-value reads.
  */
 struct sensor_hub_pending {
 	bool status;
@@ -51,6 +53,8 @@ struct sensor_hub_pending {
 	u32 attr_usage_id;
 	int raw_size;
 	u8  *raw_data;
+	u32 index;
+	u32 max_raw_size;
 };
 
 /**
@@ -183,6 +187,27 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
 					bool is_signed
 );
 
+/**
+ * sensor_hub_input_attr_read_values() - Synchronous multi-byte read request
+ * @hsdev:		Hub device instance.
+ * @usage_id:		Attribute usage id of parent physical device as per spec
+ * @attr_usage_id:	Attribute usage id as per spec
+ * @report_id:		Report id to look for
+ * @flag:		Synchronous or asynchronous read
+ * @buffer_size:	Size of the buffer in bytes
+ * @buffer:		Buffer to store the read data
+ *
+ * Issues a synchronous or asynchronous read request for an input attribute,
+ * accumulating data into the provided buffer until it is full.
+ * Return: 0 on success, -ETIMEDOUT if the device did not respond, or a
+ * negative error code.
+ */
+int sensor_hub_input_attr_read_values(struct hid_sensor_hub_device *hsdev,
+				      u32 usage_id, u32 attr_usage_id,
+				      u32 report_id,
+				      enum sensor_hub_read_flags flag,
+				      u32 buffer_size, u8 *buffer);
+
 /**
 * sensor_hub_set_feature() - Feature set request
 * @hsdev:	Hub device instance.
-- 
2.43.0


^ permalink raw reply related

* [PATCH 0/2] HID: iio: Fix stale or zero quaternion reads with multi-byte read helper
From: Zhang Lixu @ 2026-06-10  8:29 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada,
	Benjamin Tissoires
  Cc: David Lechner, Nuno Sá, Andy Shevchenko, linux-input,
	linux-iio, linux-kernel, lixu.zhang

When reading in_rot_quaternion_raw from hid-sensor-rotation, the driver
returns either all zeros (if the sensor was never enabled) or stale data
(if previously enabled), because it reads from an internal buffer without
requesting a fresh sample from the device.

This series fixes the issue in two steps:

1. Add sensor_hub_input_attr_read_values() to the HID sensor hub core.
   Unlike sensor_hub_input_attr_get_raw_value(), which is limited to a
   single 32-bit value, the new helper accepts a caller-provided buffer
   and accumulates incoming input report data until the buffer is full.
   The two code paths are distinguished in sensor_hub_raw_event() by
   pending.max_raw_size being non-zero, preserving backward compatibility.

2. Switch hid-sensor-rotation to use the new helper for raw quaternion
   reads. It now powers up the sensor, issues a synchronous GET_REPORT,
   and receives all four quaternion components directly into a local
   buffer before decoding them, eliminating stale or zero output.

Srinivas Pandruvada (1):
  HID: sensor-hub: Add sensor_hub_input_attr_read_values() for
    multi-byte reads

Zhang Lixu (1):
  iio: hid-sensor-rotation: Fix stale or zero output when reading raw
    values

 drivers/hid/hid-sensor-hub.c                  | 77 +++++++++++++++++--
 drivers/iio/orientation/hid-sensor-rotation.c | 40 +++++++++-
 include/linux/hid-sensor-hub.h                | 25 ++++++
 3 files changed, 134 insertions(+), 8 deletions(-)


base-commit: 49e02880ec0a8c378e811bc9d85da188d7c6204c
-- 
2.43.0


^ permalink raw reply

* [PATCH] Input: synaptics-rmi4 - unregister function handlers on physical driver registration failure
From: Haoxiang Li @ 2026-06-10  6:46 UTC (permalink / raw)
  To: dmitry.torokhov, git, Marge.Yang, kees, jiapeng.chong
  Cc: linux-input, linux-kernel, Haoxiang Li, stable

If rmi_register_physical_driver() fails, the current error path
unregisters only the RMI bus. The function handlers registered
earlier remain registered with the driver core.

Add a separate error path to unregister the function handlers
before unregistering the bus in this failure case.

Fixes: d6e680837ec5 ("Input: synaptics-rmi4 - fix function name in kerneldoc")
Cc: stable@vger.kernel.org
Signed-off-by: Haoxiang Li <haoxiang_li2024@163.com>
---
 drivers/input/rmi4/rmi_bus.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
index 687cb987bc13..ade57e2a7201 100644
--- a/drivers/input/rmi4/rmi_bus.c
+++ b/drivers/input/rmi4/rmi_bus.c
@@ -455,11 +455,13 @@ static int __init rmi_bus_init(void)
 	if (error) {
 		pr_err("%s: error registering the RMI physical driver: %d\n",
 			__func__, error);
-		goto err_unregister_bus;
+		goto err_unregister_function_handlers;
 	}
 
 	return 0;
 
+err_unregister_function_handlers:
+	rmi_unregister_function_handlers();
 err_unregister_bus:
 	bus_unregister(&rmi_bus_type);
 	return error;
-- 
2.25.1


^ permalink raw reply related

* Re: [PATCH] Input: ipaq-micro-keys - fix potential deadlock
From: sashiko-bot @ 2026-06-10  6:16 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <aij-pfaKK-Nna7wf@google.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

Pre-existing issues:
- [High] ipaq_micro_str() fails to null-terminate a stack-allocated string before passing it to kstrdup().
- [Medium] micro_key_receive() accesses the message payload without checking if the length is greater than zero.
- [Medium] Potential off-by-one error in keycode array indexing.
--

commit cc960c88f9bd89346f2cb6d8461bbe44bd01c18b
Author: Dmitry Torokhov <dmitry.torokhov@gmail.com>

Input: ipaq-micro-keys - fix potential deadlock

This commit fixes a lock inversion deadlock in the ipaq-micro-keys driver.
It updates micro_key_start() and micro_key_stop() to use guard(spinlock_irq)
instead of guard(spinlock), ensuring interrupts are disabled while the lock
is held in process context.

> diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c
> index ca7ec054b1cef..63d589253e465 100644
> --- a/drivers/input/keyboard/ipaq-micro-keys.c
> +++ b/drivers/input/keyboard/ipaq-micro-keys.c

[ ... ]

> @@ -54,7 +54,7 @@ static void micro_key_receive(void *data, int len, unsigned char *msg)

[Severity: Medium]
This isn't a bug introduced by this patch, but could this code read
uninitialized or stale memory if len is zero?

In micro_key_receive():

    down = 0x80 & msg[0];
    key  = 0x7f & msg[0];

The parent MFD driver parses serial messages and can validly produce a
payload with a length of 0. When this happens, micro_process_char() skips
writing to the buffer, leaving it with stale data. 

Since micro_key_receive() reads msg[0] without checking if len > 0, does
this cause the driver to report phantom key events based on old hardware
traffic?

[Severity: Medium]
This is a pre-existing issue, but does this array indexing have an
off-by-one error?

In micro_key_receive():

    if (key < ARRAY_SIZE(micro_keycodes)) {
        input_report_key(keys->input, keys->codes[key], down);
        input_sync(keys->input);
    }

If the hardware sends 1-based codes (for example, 1 for Record and 9
for Down), using the hardware key value directly as a zero-based index means
a value of 1 maps to index 1 instead of 0.

Furthermore, if the hardware sends 9 for the Down button, the event would be
dropped entirely since 9 < 9 evaluates to false. Should the index be
decremented before lookup if the device uses 1-based indexing?

>  
>  static void micro_key_start(struct ipaq_micro_keys *keys)
>  {
> -	guard(spinlock)(&keys->micro->lock);
> +	guard(spinlock_irq)(&keys->micro->lock);
>  
>  	keys->micro->key = micro_key_receive;
>  	keys->micro->key_data = keys;
> @@ -62,7 +62,7 @@ static void micro_key_start(struct ipaq_micro_keys *keys)
>  
>  static void micro_key_stop(struct ipaq_micro_keys *keys)
>  {
> -	guard(spinlock)(&keys->micro->lock);
> +	guard(spinlock_irq)(&keys->micro->lock);
>  
>  	keys->micro->key = NULL;
>  	keys->micro->key_data = NULL;

[Severity: High]
This is also a pre-existing issue in a related file, but does this code
cause an out-of-bounds stack read?

In drivers/mfd/ipaq-micro.c:ipaq_micro_str():

    for (i = 0; i < len / 2; i++)
        retstr[i] = wchar[i * 2];
    return kstrdup(retstr, GFP_KERNEL);

The array retstr is filled without an explicit null terminator. When
kstrdup() is called, it relies on strlen(), which will read past the valid
copied characters into uninitialized stack memory until it hits a random null
byte.

Could this leak kernel stack contents when the string is later printed?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/aij-pfaKK-Nna7wf@google.com?part=1

^ permalink raw reply

* Re: [PATCH v1] Input: Drop unused assignments from pnp_device_id arrays
From: Dmitry Torokhov @ 2026-06-10  6:12 UTC (permalink / raw)
  To: Uwe Kleine-König (The Capable Hub)
  Cc: Kees Cook, Werner Sembach, Christoffer Sandberg, feng, gongqi,
	linux-input, linux-kernel
In-Reply-To: <f987c14dea1d3236d3889e5cf96c01eef6a2445d.1781016727.git.u.kleine-koenig@baylibre.com>

Hi Uwe,

On Tue, Jun 09, 2026 at 04:53:25PM +0200, Uwe Kleine-König (The Capable Hub) wrote:
> Explicitly assigning .driver_data in drivers that don't use this member
> is silly and a bit irritating. Drop these. Also simplify the list
> terminator entry to be just empty to match what most other device_id
> tables do.
> 
> There is no changed semantic, not even a change in the compiled result.
> 
> Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
> ---
>  drivers/input/gameport/ns558.c        | 46 +++++++++++-----------
>  drivers/input/serio/i8042-acpipnpio.h | 56 +++++++++++++--------------
>  2 files changed, 51 insertions(+), 51 deletions(-)
> 
> diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
> index fdece6ec1df3..f70a96c4f1fd 100644
> --- a/drivers/input/gameport/ns558.c
> +++ b/drivers/input/gameport/ns558.c
> @@ -148,29 +148,29 @@ static int ns558_isa_probe(int io)
>  #ifdef CONFIG_PNP
>  
>  static const struct pnp_device_id pnp_devids[] = {
> -	{ .id = "@P@0001", .driver_data = 0 }, /* ALS 100 */
> -	{ .id = "@P@0020", .driver_data = 0 }, /* ALS 200 */
> -	{ .id = "@P@1001", .driver_data = 0 }, /* ALS 100+ */
> -	{ .id = "@P@2001", .driver_data = 0 }, /* ALS 120 */
> -	{ .id = "ASB16fd", .driver_data = 0 }, /* AdLib NSC16 */
> -	{ .id = "AZT3001", .driver_data = 0 }, /* AZT1008 */
> -	{ .id = "CDC0001", .driver_data = 0 }, /* Opl3-SAx */
> -	{ .id = "CSC0001", .driver_data = 0 }, /* CS4232 */
> -	{ .id = "CSC000f", .driver_data = 0 }, /* CS4236 */
> -	{ .id = "CSC0101", .driver_data = 0 }, /* CS4327 */
> -	{ .id = "CTL7001", .driver_data = 0 }, /* SB16 */
> -	{ .id = "CTL7002", .driver_data = 0 }, /* AWE64 */
> -	{ .id = "CTL7005", .driver_data = 0 }, /* Vibra16 */
> -	{ .id = "ENS2020", .driver_data = 0 }, /* SoundscapeVIVO */
> -	{ .id = "ESS0001", .driver_data = 0 }, /* ES1869 */
> -	{ .id = "ESS0005", .driver_data = 0 }, /* ES1878 */
> -	{ .id = "ESS6880", .driver_data = 0 }, /* ES688 */
> -	{ .id = "IBM0012", .driver_data = 0 }, /* CS4232 */
> -	{ .id = "OPT0001", .driver_data = 0 }, /* OPTi Audio16 */
> -	{ .id = "YMH0006", .driver_data = 0 }, /* Opl3-SA */
> -	{ .id = "YMH0022", .driver_data = 0 }, /* Opl3-SAx */
> -	{ .id = "PNPb02f", .driver_data = 0 }, /* Generic */
> -	{ .id = "", },
> +	{ .id = "@P@0001" }, /* ALS 100 */
> +	{ .id = "@P@0020" }, /* ALS 200 */
> +	{ .id = "@P@1001" }, /* ALS 100+ */
> +	{ .id = "@P@2001" }, /* ALS 120 */
> +	{ .id = "ASB16fd" }, /* AdLib NSC16 */
> +	{ .id = "AZT3001" }, /* AZT1008 */
> +	{ .id = "CDC0001" }, /* Opl3-SAx */
> +	{ .id = "CSC0001" }, /* CS4232 */
> +	{ .id = "CSC000f" }, /* CS4236 */
> +	{ .id = "CSC0101" }, /* CS4327 */
> +	{ .id = "CTL7001" }, /* SB16 */
> +	{ .id = "CTL7002" }, /* AWE64 */
> +	{ .id = "CTL7005" }, /* Vibra16 */
> +	{ .id = "ENS2020" }, /* SoundscapeVIVO */
> +	{ .id = "ESS0001" }, /* ES1869 */
> +	{ .id = "ESS0005" }, /* ES1878 */
> +	{ .id = "ESS6880" }, /* ES688 */
> +	{ .id = "IBM0012" }, /* CS4232 */
> +	{ .id = "OPT0001" }, /* OPTi Audio16 */
> +	{ .id = "YMH0006" }, /* Opl3-SA */
> +	{ .id = "YMH0022" }, /* Opl3-SAx */
> +	{ .id = "PNPb02f" }, /* Generic */
> +	{ }

This goes BOOOM! You have to keep empty .id string as terminator.

Thanks.

-- 
Dmitry

^ permalink raw reply

* Re: [PATCHv2] input: ipaq-micro-keys: simplify allocation
From: Dmitry Torokhov @ 2026-06-10  6:08 UTC (permalink / raw)
  To: Rosen Penev; +Cc: linux-input, open list
In-Reply-To: <20260609213532.25181-1-rosenp@gmail.com>

On Tue, Jun 09, 2026 at 02:35:32PM -0700, Rosen Penev wrote:
> Embed the keycode array in the struct to have a single allocation.
> 
> Signed-off-by: Rosen Penev <rosenp@gmail.com>

Applied, thank you.

-- 
Dmitry

^ permalink raw reply

* [PATCH] Input: ipaq-micro-keys - fix potential deadlock
From: Dmitry Torokhov @ 2026-06-10  6:05 UTC (permalink / raw)
  To: linux-input; +Cc: linux-kernel

The driver acquires the micro->lock spinlock in process context (in
micro_key_start() and micro_key_stop()) without disabling interrupts.
However, this lock is also acquired in hardirq context by the MFD core
rx handler (micro_rx_msg()) which is called from the serial ISR.

This can lead to a lock inversion deadlock if the interrupt fires on the
same CPU while the process context holds the lock.

Fix this by using guard(spinlock_irq) instead of guard(spinlock) in
micro_key_start() and micro_key_stop() to disable interrupts while
holding the lock.

Reported-by: sashiko-bot@kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/keyboard/ipaq-micro-keys.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c
index ca7ec054b1ce..63d589253e46 100644
--- a/drivers/input/keyboard/ipaq-micro-keys.c
+++ b/drivers/input/keyboard/ipaq-micro-keys.c
@@ -54,7 +54,7 @@ static void micro_key_receive(void *data, int len, unsigned char *msg)
 
 static void micro_key_start(struct ipaq_micro_keys *keys)
 {
-	guard(spinlock)(&keys->micro->lock);
+	guard(spinlock_irq)(&keys->micro->lock);
 
 	keys->micro->key = micro_key_receive;
 	keys->micro->key_data = keys;
@@ -62,7 +62,7 @@ static void micro_key_start(struct ipaq_micro_keys *keys)
 
 static void micro_key_stop(struct ipaq_micro_keys *keys)
 {
-	guard(spinlock)(&keys->micro->lock);
+	guard(spinlock_irq)(&keys->micro->lock);
 
 	keys->micro->key = NULL;
 	keys->micro->key_data = NULL;
-- 
2.54.0.1099.g489fc7bff1-goog


-- 
Dmitry

^ permalink raw reply related

* [PATCH] HID: add quirk for IBM SK-8845 keyboard
From: TheDragonWhoAte @ 2026-06-10  4:09 UTC (permalink / raw)
  To: linux-input@vger.kernel.org
  Cc: Jiri Kosina, Benjamin Tissoires, linux-kernel@vger.kernel.org

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

HID: add quirk for IBM SK-8845 keyboard

The TrackPoint on the IBM SK-8845 (Synaptics 06cb:0009) sends corrupted
input events when bound to the synaptics_usb driver. Moving the stick
generates random BTN_LEFT/BTN_RIGHT/BTN_MIDDLE events instead of
REL_X/REL_Y movement.

Force the device to bind to hid-generic instead by setting
HID_QUIRK_IGNORE_SPECIAL_DRIVER.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=221624

Note: This quirk disables two-finger scrolling on the touchpad. That's a trade-off, but without it the TrackPoint is completely unusable. The real fix would be to make synaptics_usb handle this device properly, so both the touchpad gestures and the TrackPoint work. That's beyond this patch.

Signed-off-by: TheDragonWhoAte <TheDragonWhoAte@protonmail.com>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-HID-add-quirk-for-IBM-SK-8845-keyboard.patch --]
[-- Type: text/x-patch; name=0001-HID-add-quirk-for-IBM-SK-8845-keyboard.patch, Size: 2037 bytes --]

From 0bc38d7fac65dc07f48e074130329924adf5744b Mon Sep 17 00:00:00 2001
From: thedragonwhoate <thedragonwhoate@protonmail.com>
Date: Wed, 10 Jun 2026 06:38:03 +0300
Subject: [PATCH] HID: add quirk for IBM SK-8845 keyboard
To: linux-input@vger.kernel.org

The TrackPoint on the IBM SK-8845 (Synaptics 06cb:0009) sends corrupted
input events when bound to the synaptics_usb driver. Moving the stick
generates random BTN_LEFT/BTN_RIGHT/BTN_MIDDLE events instead of
REL_X/REL_Y movement.

Force the device to bind to hid-generic instead by setting
HID_QUIRK_IGNORE_SPECIAL_DRIVER.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=221624

Note: This quirk disables two-finger scrolling on the touchpad. That's a trade-off, but without it the TrackPoint is completely unusable. The real fix would be to make synaptics_usb handle this device properly, so both the touchpad gestures and the TrackPoint work. That's beyond this patch.

Signed-off-by: thedragonwhoate <thedragonwhoate@protonmail.com>
---
 drivers/hid/hid-quirks.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 57d8efdd9..c8394b896 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -203,6 +203,7 @@ static const struct hid_device_id hid_quirks[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103), HID_QUIRK_NO_INIT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DELL_K12A), HID_QUIRK_NO_INIT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DELL_K15A), HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_COMP_TP), HID_QUIRK_IGNORE_SPECIAL_DRIVER },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD), HID_QUIRK_BADPAD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS), HID_QUIRK_MULTI_INPUT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882), HID_QUIRK_NOGET },
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH 1/2] HID: lenovo: Add support for ThinkPad X13 Folio keyboard
From: Vishnu Sankar @ 2026-06-09 23:05 UTC (permalink / raw)
  To: jikos, bentiss, derekjohn.clark, mpearson-lenovo
  Cc: vsankar, linux-input, linux-kernel
In-Reply-To: <20260522050632.8079-1-vishnuocv@gmail.com>

Hi Jiri / Benjamin,

Gently pinging on this series.
Is there anything blocking acceptance or any changes needed from my side?
The series has been tested on physical hardware.

Thank you!

Vishnu

On Fri, May 22, 2026 at 2:07 PM Vishnu Sankar <vishnuocv@gmail.com> wrote:
>
> From: Vishnu Sankar <vishnuocv@gmail.com>
>
> Add USB ID support for the ThinkPad X13 detachable keyboard.
> The Keyboard uses the same HID raw event protocol as the ThinkPad
> X12 Gen 2. The functionality stays the same with X12 Gen 2 Keyboards.
>
> Also declare KEY_PERFORMANCE capability in lenovo_input_configured()
> for X13 detachable, allowing userspace to discover the key via evdev
> capability bits.
>
> Signed-off-by: Vishnu Sankar <vishnuocv@gmail.com>
> ---
>  drivers/hid/hid-ids.h    |  1 +
>  drivers/hid/hid-lenovo.c | 21 +++++++++++++++++----
>  2 files changed, 18 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 4657d96fb083..064be2333a00 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -874,6 +874,7 @@
>  #define USB_DEVICE_ID_LENOVO_X1_TAB3   0x60b5
>  #define USB_DEVICE_ID_LENOVO_X12_TAB   0x60fe
>  #define USB_DEVICE_ID_LENOVO_X12_TAB2  0x61ae
> +#define USB_DEVICE_ID_LENOVO_X13_TAB   0x62af
>  #define USB_DEVICE_ID_LENOVO_YOGABOOK9I        0x6161
>  #define USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E    0x600e
>  #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D     0x608d
> diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
> index a6b73e03c16b..35b00619f045 100644
> --- a/drivers/hid/hid-lenovo.c
> +++ b/drivers/hid/hid-lenovo.c
> @@ -504,6 +504,7 @@ static int lenovo_input_mapping(struct hid_device *hdev,
>                                                                usage, bit, max);
>         case USB_DEVICE_ID_LENOVO_X12_TAB:
>         case USB_DEVICE_ID_LENOVO_X12_TAB2:
> +       case USB_DEVICE_ID_LENOVO_X13_TAB:
>         case USB_DEVICE_ID_LENOVO_X1_TAB:
>         case USB_DEVICE_ID_LENOVO_X1_TAB2:
>         case USB_DEVICE_ID_LENOVO_X1_TAB3:
> @@ -620,6 +621,7 @@ static ssize_t attr_fn_lock_store(struct device *dev,
>                 break;
>         case USB_DEVICE_ID_LENOVO_X12_TAB:
>         case USB_DEVICE_ID_LENOVO_X12_TAB2:
> +       case USB_DEVICE_ID_LENOVO_X13_TAB:
>         case USB_DEVICE_ID_LENOVO_TP10UBKBD:
>         case USB_DEVICE_ID_LENOVO_X1_TAB:
>         case USB_DEVICE_ID_LENOVO_X1_TAB2:
> @@ -791,9 +793,10 @@ static int lenovo_raw_event(struct hid_device *hdev,
>          * Lenovo TP X12 Tab KBD's Fn+XX is HID raw data defined. Report ID is 0x03
>          * e.g.: Raw data received for MIC mute is 0x00020003.
>          */
> -       if (unlikely((hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB
> -                       || hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB2)
> -                       && size >= 3 && report->id == 0x03))
> +       if (unlikely((hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB ||
> +                     hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB2 ||
> +                     hdev->product == USB_DEVICE_ID_LENOVO_X13_TAB) &&
> +                     size >= 3 && report->id == 0x03))
>                 return lenovo_raw_event_TP_X12_tab(hdev, le32_to_cpu(*(__le32 *)data));
>
>         return 0;
> @@ -877,6 +880,7 @@ static int lenovo_event(struct hid_device *hdev, struct hid_field *field,
>                 return lenovo_event_cptkbd(hdev, field, usage, value);
>         case USB_DEVICE_ID_LENOVO_X12_TAB:
>         case USB_DEVICE_ID_LENOVO_X12_TAB2:
> +       case USB_DEVICE_ID_LENOVO_X13_TAB:
>         case USB_DEVICE_ID_LENOVO_TP10UBKBD:
>         case USB_DEVICE_ID_LENOVO_X1_TAB:
>         case USB_DEVICE_ID_LENOVO_X1_TAB2:
> @@ -1161,6 +1165,7 @@ static int lenovo_led_brightness_set(struct led_classdev *led_cdev,
>                 break;
>         case USB_DEVICE_ID_LENOVO_X12_TAB:
>         case USB_DEVICE_ID_LENOVO_X12_TAB2:
> +       case USB_DEVICE_ID_LENOVO_X13_TAB:
>         case USB_DEVICE_ID_LENOVO_TP10UBKBD:
>         case USB_DEVICE_ID_LENOVO_X1_TAB:
>         case USB_DEVICE_ID_LENOVO_X1_TAB2:
> @@ -1355,7 +1360,8 @@ static int lenovo_probe_tp10ubkbd(struct hid_device *hdev)
>          */
>
>         data->fn_lock = !(hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB ||
> -                       hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB2);
> +                       hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB2 ||
> +                       hdev->product == USB_DEVICE_ID_LENOVO_X13_TAB);
>
>         lenovo_led_set_tp10ubkbd(hdev, TP10UBKBD_FN_LOCK_LED, data->fn_lock);
>
> @@ -1402,6 +1408,7 @@ static int lenovo_probe(struct hid_device *hdev,
>                 break;
>         case USB_DEVICE_ID_LENOVO_X12_TAB:
>         case USB_DEVICE_ID_LENOVO_X12_TAB2:
> +       case USB_DEVICE_ID_LENOVO_X13_TAB:
>         case USB_DEVICE_ID_LENOVO_TP10UBKBD:
>         case USB_DEVICE_ID_LENOVO_X1_TAB:
>         case USB_DEVICE_ID_LENOVO_X1_TAB2:
> @@ -1490,6 +1497,7 @@ static void lenovo_remove(struct hid_device *hdev)
>                 break;
>         case USB_DEVICE_ID_LENOVO_X12_TAB:
>         case USB_DEVICE_ID_LENOVO_X12_TAB2:
> +       case USB_DEVICE_ID_LENOVO_X13_TAB:
>         case USB_DEVICE_ID_LENOVO_TP10UBKBD:
>         case USB_DEVICE_ID_LENOVO_X1_TAB:
>         case USB_DEVICE_ID_LENOVO_X1_TAB2:
> @@ -1517,6 +1525,9 @@ static int lenovo_input_configured(struct hid_device *hdev,
>                                                 hi->input->propbit);
>                         }
>                         break;
> +               case USB_DEVICE_ID_LENOVO_X13_TAB:
> +                       input_set_capability(hi->input, EV_KEY, KEY_PERFORMANCE);
> +                       break;
>         }
>
>         return 0;
> @@ -1551,6 +1562,8 @@ static const struct hid_device_id lenovo_devices[] = {
>                      USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X12_TAB) },
>         { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
>                      USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X12_TAB2) },
> +       { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
> +                    USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X13_TAB) },
>         { HID_DEVICE(BUS_I2C, HID_GROUP_GENERIC,
>                      USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_YOGA_SLIM_7X_KEYBOARD) },
>         { }
> --
> 2.54.0
>


-- 

Regards,

      Vishnu Sankar

^ permalink raw reply

* Re: (subset) [PATCH v2 00/10] gpiolib: fence off legacy interfaces
From: Kevin Hilman @ 2026-06-09 22:25 UTC (permalink / raw)
  To: linux-gpio, Arnd Bergmann
  Cc: linux-kernel, Arnd Bergmann, Christian Lamparter, Johannes Berg,
	Aaro Koskinen, Andreas Kemnade, Roger Quadros, Tony Lindgren,
	Thomas Bogendoerfer, John Paul Adrian Glaubitz, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin,
	Linus Walleij, Bartosz Golaszewski, Dmitry Torokhov, Lee Jones,
	Pavel Machek, Matti Vaittinen, Florian Fainelli, Jonas Gorski,
	Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, linux-wireless, linux-omap,
	linux-arm-kernel, linux-mips, linux-sh, linux-input, linux-leds,
	netdev
In-Reply-To: <20260520183815.2510387-1-arnd@kernel.org>


On Wed, 20 May 2026 20:38:05 +0200, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
> 
> This is an update of all the patches that are still required before
> we can actually turn off CONFIG_GPIOLIB_LEGACY for most platforms
> in the final patch of this series.
> 
> I originally posted this as a series in
> https://lore.kernel.org/all/20250808151822.536879-1-arnd@kernel.org/
> 
> [...]

Applied, thanks!

[09/10] ARM: dts: omap2: add stlc4560 spi-wireless node
        commit: c5a0ac76b364bbd1d4fb7e440edabcd2a369343c

Best regards,
-- 
Kevin Hilman (TI) <khilman@baylibre.com>


^ permalink raw reply

* Re: [PATCHv2] input: ipaq-micro-keys: simplify allocation
From: sashiko-bot @ 2026-06-09 21:44 UTC (permalink / raw)
  To: Rosen Penev; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260609213532.25181-1-rosenp@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Potential deadlock in `micro_key_start()` and `micro_key_stop()` due to taking a spinlock without disabling interrupts, which is also taken in a hardirq handler.
--

commit 59a420f5a26f394b8f84d4e056f388e517d6f808
Author: Rosen Penev <rosenp@gmail.com>

input: ipaq-micro-keys: simplify allocation

This commit simplifies the keycode array allocation in the ipaq-micro-keys
driver. By embedding the array directly into the device structure, it removes
the need for a separate devm_kmemdup_array() call during probe.

> diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c
> index ca7ec054b1cef..695ef3c2081a4 100644
> --- a/drivers/input/keyboard/ipaq-micro-keys.c
> +++ b/drivers/input/keyboard/ipaq-micro-keys.c

[ ... ]

> @@ -102,10 +102,7 @@ static int micro_key_probe(struct platform_device *pdev)
>  
>  	keys->input->keycodesize = sizeof(micro_keycodes[0]);
>  	keys->input->keycodemax = ARRAY_SIZE(micro_keycodes);
> -	keys->codes = devm_kmemdup_array(&pdev->dev, micro_keycodes, keys->input->keycodemax,
> -					 keys->input->keycodesize, GFP_KERNEL);
> -	if (!keys->codes)
> -		return -ENOMEM;
> +	memcpy(keys->codes, micro_keycodes, sizeof(keys->codes));
>  
>  	keys->input->keycode = keys->codes;

[Severity: High]
This isn't a bug introduced by this patch, but could the lock usage in
micro_key_start() and micro_key_stop() cause a deadlock if an interrupt
fires?

Looking at drivers/input/keyboard/ipaq-micro-keys.c, the micro->lock is
acquired in process context without disabling interrupts:

micro_key_start() {
    guard(spinlock)(&keys->micro->lock);
    ...
}

If a serial interrupt fires on the same CPU while the process context holds
the lock, the interrupt handler micro_serial_isr() runs, processes the
character, and calls micro_rx_msg().

micro_rx_msg() in drivers/mfd/ipaq-micro.c then attempts to acquire the same
lock in hardirq context:

    spin_lock(&micro->lock);

Does this sequence lead to a lock inversion deadlock? Should the process
context functions use guard(spinlock_irqsave) or guard(spinlock_irq)
instead?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260609213532.25181-1-rosenp@gmail.com?part=1

^ permalink raw reply

* [PATCHv2] input: ipaq-micro-keys: simplify allocation
From: Rosen Penev @ 2026-06-09 21:35 UTC (permalink / raw)
  To: linux-input; +Cc: Dmitry Torokhov, open list

Embed the keycode array in the struct to have a single allocation.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 v2: use regular array instead of flexible array member.
 drivers/input/keyboard/ipaq-micro-keys.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c
index ca7ec054b1ce..695ef3c2081a 100644
--- a/drivers/input/keyboard/ipaq-micro-keys.c
+++ b/drivers/input/keyboard/ipaq-micro-keys.c
@@ -20,12 +20,6 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/ipaq-micro.h>

-struct ipaq_micro_keys {
-	struct ipaq_micro *micro;
-	struct input_dev *input;
-	u16 *codes;
-};
-
 static const u16 micro_keycodes[] = {
 	KEY_RECORD,		/* 1:  Record button			*/
 	KEY_CALENDAR,		/* 2:  Calendar				*/
@@ -38,6 +32,12 @@ static const u16 micro_keycodes[] = {
 	KEY_DOWN,		/* 9:  Down				*/
 };

+struct ipaq_micro_keys {
+	struct ipaq_micro *micro;
+	struct input_dev *input;
+	u16 codes[ARRAY_SIZE(micro_keycodes)];
+};
+
 static void micro_key_receive(void *data, int len, unsigned char *msg)
 {
 	struct ipaq_micro_keys *keys = data;
@@ -102,10 +102,7 @@ static int micro_key_probe(struct platform_device *pdev)

 	keys->input->keycodesize = sizeof(micro_keycodes[0]);
 	keys->input->keycodemax = ARRAY_SIZE(micro_keycodes);
-	keys->codes = devm_kmemdup_array(&pdev->dev, micro_keycodes, keys->input->keycodemax,
-					 keys->input->keycodesize, GFP_KERNEL);
-	if (!keys->codes)
-		return -ENOMEM;
+	memcpy(keys->codes, micro_keycodes, sizeof(keys->codes));

 	keys->input->keycode = keys->codes;

--
2.54.0


^ permalink raw reply related

* Re: [PATCH] HID: pidff: Use correct effect type in effect update
From: sashiko-bot @ 2026-06-09 16:21 UTC (permalink / raw)
  To: Oleg Makarenko; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260609160031.493353-1-oleg@makarenk.ooo>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Pre-existing out-of-bounds read in `pidff_find_effects` leading to potential kernel panic (local DoS via crafted USB device).
--

commit 07c3b678f1bae4a1c16dfff6971345dc4b180f89
Author: Oleg Makarenko <oleg@makarenk.ooo>

HID: pidff: Use correct effect type in effect update

This commit fixes an issue where the effect type from the last created effect
was incorrectly used when updating existing effects. It ensures the correct
effect type ID is sent to the device, fixing force feedback in games that
manage multiple simultaneous effects.

> diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
> index c45f182d04480..5f4395f7c6458 100644
> --- a/drivers/hid/usbhid/hid-pidff.c
> +++ b/drivers/hid/usbhid/hid-pidff.c

[ ... ]

[Severity: High]
This isn't a bug introduced by this patch, but looking at pidff_find_effects()
in this same file:

drivers/hid/usbhid/hid-pidff.c:pidff_find_effects() {
...
	for (i = 0; i < ARRAY_SIZE(pidff_effect_types); i++) {
		int pidff_type = pidff->type_id[i];

		if (pidff->set_effect_type->usage[pidff_type].hid !=
		    pidff->create_new_effect_type->usage[pidff_type].hid) {
			hid_err(pidff->hid,
				"effect type number %d is invalid\n", i);
			return -1;
		}
	}
...
}

Could this code cause an out-of-bounds read if a malicious USB device is
plugged in?

The type_id array is populated with 1-based logical indices, but pidff_type is
used directly as a 0-based index to access the usage arrays.

If the device descriptor defines many usages in create_new_effect_type but
very few in set_effect_type, would pidff_type exceed
set_effect_type->maxusage and read past the end of the array?

Does this risk a kernel panic if the read crosses page boundaries during
device probe?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260609160031.493353-1-oleg@makarenk.ooo?part=1

^ permalink raw reply

* [PATCH] HID: pidff: Use correct effect type in effect update
From: Oleg Makarenko @ 2026-06-09 16:00 UTC (permalink / raw)
  To: jikos, bentiss
  Cc: Oleg Makarenko, stable, Oliver Roundtree, Ryno Kotzé,
	Tomasz Pakuła, Anssi Hannula, Dmitry Torokhov, linux-input,
	linux-usb, linux-kernel

When updating an existing effect, the effect type from the last created
effect was sent to the device instead of the updated one.
This caused incorrect reports when a game creates multiple different
effects and updates only one that is not the last created.

Fixes FFB in multiple games that create multiple simultaneous effects
(Forza Horizon 5/6).

Fixes: 224ee88fe395 ("Input: add force feedback driver for PID devices")
Cc: <stable@vger.kernel.org>
Tested-by: Oliver Roundtree <oroundtree1@gmail.com>
Co-developed-by: Ryno Kotzé <lemon.xah@gmail.com>
Signed-off-by: Ryno Kotzé <lemon.xah@gmail.com>
Signed-off-by: Oleg Makarenko <oleg@makarenk.ooo>
---
 drivers/hid/usbhid/hid-pidff.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index c45f182d0448..5f4395f7c645 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -522,7 +522,7 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
 	pidff->set_effect[PID_EFFECT_BLOCK_INDEX].value[0] =
 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
 	pidff->set_effect_type->value[0] =
-		pidff->create_new_effect_type->value[0];
+		pidff_get_effect_type_id(pidff, effect);
 
 	pidff_set_duration(&pidff->set_effect[PID_DURATION],
 			   effect->replay.length);
-- 
2.54.0


^ permalink raw reply related

* [PATCH v1] Input: Drop unused assignments from pnp_device_id arrays
From: Uwe Kleine-König (The Capable Hub) @ 2026-06-09 14:53 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Kees Cook, Werner Sembach, Christoffer Sandberg, feng, gongqi,
	linux-input, linux-kernel

Explicitly assigning .driver_data in drivers that don't use this member
is silly and a bit irritating. Drop these. Also simplify the list
terminator entry to be just empty to match what most other device_id
tables do.

There is no changed semantic, not even a change in the compiled result.

Signed-off-by: Uwe Kleine-König (The Capable Hub) <u.kleine-koenig@baylibre.com>
---
 drivers/input/gameport/ns558.c        | 46 +++++++++++-----------
 drivers/input/serio/i8042-acpipnpio.h | 56 +++++++++++++--------------
 2 files changed, 51 insertions(+), 51 deletions(-)

diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
index fdece6ec1df3..f70a96c4f1fd 100644
--- a/drivers/input/gameport/ns558.c
+++ b/drivers/input/gameport/ns558.c
@@ -148,29 +148,29 @@ static int ns558_isa_probe(int io)
 #ifdef CONFIG_PNP
 
 static const struct pnp_device_id pnp_devids[] = {
-	{ .id = "@P@0001", .driver_data = 0 }, /* ALS 100 */
-	{ .id = "@P@0020", .driver_data = 0 }, /* ALS 200 */
-	{ .id = "@P@1001", .driver_data = 0 }, /* ALS 100+ */
-	{ .id = "@P@2001", .driver_data = 0 }, /* ALS 120 */
-	{ .id = "ASB16fd", .driver_data = 0 }, /* AdLib NSC16 */
-	{ .id = "AZT3001", .driver_data = 0 }, /* AZT1008 */
-	{ .id = "CDC0001", .driver_data = 0 }, /* Opl3-SAx */
-	{ .id = "CSC0001", .driver_data = 0 }, /* CS4232 */
-	{ .id = "CSC000f", .driver_data = 0 }, /* CS4236 */
-	{ .id = "CSC0101", .driver_data = 0 }, /* CS4327 */
-	{ .id = "CTL7001", .driver_data = 0 }, /* SB16 */
-	{ .id = "CTL7002", .driver_data = 0 }, /* AWE64 */
-	{ .id = "CTL7005", .driver_data = 0 }, /* Vibra16 */
-	{ .id = "ENS2020", .driver_data = 0 }, /* SoundscapeVIVO */
-	{ .id = "ESS0001", .driver_data = 0 }, /* ES1869 */
-	{ .id = "ESS0005", .driver_data = 0 }, /* ES1878 */
-	{ .id = "ESS6880", .driver_data = 0 }, /* ES688 */
-	{ .id = "IBM0012", .driver_data = 0 }, /* CS4232 */
-	{ .id = "OPT0001", .driver_data = 0 }, /* OPTi Audio16 */
-	{ .id = "YMH0006", .driver_data = 0 }, /* Opl3-SA */
-	{ .id = "YMH0022", .driver_data = 0 }, /* Opl3-SAx */
-	{ .id = "PNPb02f", .driver_data = 0 }, /* Generic */
-	{ .id = "", },
+	{ .id = "@P@0001" }, /* ALS 100 */
+	{ .id = "@P@0020" }, /* ALS 200 */
+	{ .id = "@P@1001" }, /* ALS 100+ */
+	{ .id = "@P@2001" }, /* ALS 120 */
+	{ .id = "ASB16fd" }, /* AdLib NSC16 */
+	{ .id = "AZT3001" }, /* AZT1008 */
+	{ .id = "CDC0001" }, /* Opl3-SAx */
+	{ .id = "CSC0001" }, /* CS4232 */
+	{ .id = "CSC000f" }, /* CS4236 */
+	{ .id = "CSC0101" }, /* CS4327 */
+	{ .id = "CTL7001" }, /* SB16 */
+	{ .id = "CTL7002" }, /* AWE64 */
+	{ .id = "CTL7005" }, /* Vibra16 */
+	{ .id = "ENS2020" }, /* SoundscapeVIVO */
+	{ .id = "ESS0001" }, /* ES1869 */
+	{ .id = "ESS0005" }, /* ES1878 */
+	{ .id = "ESS6880" }, /* ES688 */
+	{ .id = "IBM0012" }, /* CS4232 */
+	{ .id = "OPT0001" }, /* OPTi Audio16 */
+	{ .id = "YMH0006" }, /* Opl3-SA */
+	{ .id = "YMH0022" }, /* Opl3-SAx */
+	{ .id = "PNPb02f" }, /* Generic */
+	{ }
 };
 
 MODULE_DEVICE_TABLE(pnp, pnp_devids);
diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h
index 8ebdf4fb9030..412f82d7a303 100644
--- a/drivers/input/serio/i8042-acpipnpio.h
+++ b/drivers/input/serio/i8042-acpipnpio.h
@@ -1539,22 +1539,22 @@ static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *
 }
 
 static const struct pnp_device_id pnp_kbd_devids[] = {
-	{ .id = "PNP0300", .driver_data = 0 },
-	{ .id = "PNP0301", .driver_data = 0 },
-	{ .id = "PNP0302", .driver_data = 0 },
-	{ .id = "PNP0303", .driver_data = 0 },
-	{ .id = "PNP0304", .driver_data = 0 },
-	{ .id = "PNP0305", .driver_data = 0 },
-	{ .id = "PNP0306", .driver_data = 0 },
-	{ .id = "PNP0309", .driver_data = 0 },
-	{ .id = "PNP030a", .driver_data = 0 },
-	{ .id = "PNP030b", .driver_data = 0 },
-	{ .id = "PNP0320", .driver_data = 0 },
-	{ .id = "PNP0343", .driver_data = 0 },
-	{ .id = "PNP0344", .driver_data = 0 },
-	{ .id = "PNP0345", .driver_data = 0 },
-	{ .id = "CPQA0D7", .driver_data = 0 },
-	{ .id = "", },
+	{ .id = "PNP0300" },
+	{ .id = "PNP0301" },
+	{ .id = "PNP0302" },
+	{ .id = "PNP0303" },
+	{ .id = "PNP0304" },
+	{ .id = "PNP0305" },
+	{ .id = "PNP0306" },
+	{ .id = "PNP0309" },
+	{ .id = "PNP030a" },
+	{ .id = "PNP030b" },
+	{ .id = "PNP0320" },
+	{ .id = "PNP0343" },
+	{ .id = "PNP0344" },
+	{ .id = "PNP0345" },
+	{ .id = "CPQA0D7" },
+	{ }
 };
 MODULE_DEVICE_TABLE(pnp, pnp_kbd_devids);
 
@@ -1569,18 +1569,18 @@ static struct pnp_driver i8042_pnp_kbd_driver = {
 };
 
 static const struct pnp_device_id pnp_aux_devids[] = {
-	{ .id = "AUI0200", .driver_data = 0 },
-	{ .id = "FJC6000", .driver_data = 0 },
-	{ .id = "FJC6001", .driver_data = 0 },
-	{ .id = "PNP0f03", .driver_data = 0 },
-	{ .id = "PNP0f0b", .driver_data = 0 },
-	{ .id = "PNP0f0e", .driver_data = 0 },
-	{ .id = "PNP0f12", .driver_data = 0 },
-	{ .id = "PNP0f13", .driver_data = 0 },
-	{ .id = "PNP0f19", .driver_data = 0 },
-	{ .id = "PNP0f1c", .driver_data = 0 },
-	{ .id = "SYN0801", .driver_data = 0 },
-	{ .id = "", },
+	{ .id = "AUI0200" },
+	{ .id = "FJC6000" },
+	{ .id = "FJC6001" },
+	{ .id = "PNP0f03" },
+	{ .id = "PNP0f0b" },
+	{ .id = "PNP0f0e" },
+	{ .id = "PNP0f12" },
+	{ .id = "PNP0f13" },
+	{ .id = "PNP0f19" },
+	{ .id = "PNP0f1c" },
+	{ .id = "SYN0801" },
+	{ },
 };
 MODULE_DEVICE_TABLE(pnp, pnp_aux_devids);
 

base-commit: a87737435cfa134f9cdcc696ba3080759d04cf72
-- 
2.47.3


^ permalink raw reply related

* Re: [PATCH 7/8] dt-bindings: input: microchip,cap11xx: Add CAP1114 support
From: Conor Dooley @ 2026-06-09 14:31 UTC (permalink / raw)
  To: Jun Yan
  Cc: conor+dt, devicetree, dmitry.torokhov, krzk+dt, linux-input,
	linux-kernel, robh
In-Reply-To: <20260609140827.850117-1-jerrysteve1101@gmail.com>

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

On Tue, Jun 09, 2026 at 10:08:27PM +0800, Jun Yan wrote:
> > On Sat, Jun 06, 2026 at 11:04:00PM +0800, Jun Yan wrote:
> > > CAP1114 is a 14-channel capacitive touch sensor with 11 LED outputs
> > > and hardware reset support.
> > >=20
> > > Add the compatible string for CAP1114, include its datasheet URL,
> > > and update the maximum count of LED channels and linux,keycodes entries.
> > >=20
> > > Add description for microchip,input-threshold: CAP1114 only provides eight
> > > threshold entries, which does not match its total channel count.
> > >=20
> > > Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
> > > ---
> > >  .../bindings/input/microchip,cap11xx.yaml     | 21 +++++++++++++++++--
> > >  1 file changed, 19 insertions(+), 2 deletions(-)
> > >=20
> > > diff --git a/Documentation/devicetree/bindings/input/microchip,cap11xx.ya=
> > ml b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
> > > index e307628350c2..08233386a433 100644
> > > --- a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
> > > +++ b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
> > > @@ -12,6 +12,7 @@ description: |
> > > =20
> > >    For more product information please see the links below:
> > >      CAP1106: https://ww1.microchip.com/downloads/en/DeviceDoc/00001624B.=
> > pdf
> > > +    CAP1114: https://ww1.microchip.com/downloads/en/DeviceDoc/00002444A.=
> > pdf
> > >      CAP1126: https://ww1.microchip.com/downloads/en/DeviceDoc/00001623B.=
> > pdf
> > >      CAP1188: https://ww1.microchip.com/downloads/en/DeviceDoc/00001620C.=
> > pdf
> > >      CAP1203: https://ww1.microchip.com/downloads/en/DeviceDoc/00001572B.=
> > pdf
> > > @@ -26,6 +27,7 @@ properties:
> > >    compatible:
> > >      enum:
> > >        - microchip,cap1106
> > > +      - microchip,cap1114
> > >        - microchip,cap1126
> > >        - microchip,cap1188
> > >        - microchip,cap1203
> > > @@ -62,7 +64,7 @@ properties:
> > > =20
> > >    linux,keycodes:
> > >      minItems: 3
> > > -    maxItems: 8
> > > +    maxItems: 14
> > >      description: |
> > >        Specifies an array of numeric keycode values to
> > >        be used for the channels. If this property is
> > > @@ -122,6 +124,8 @@ properties:
> > >        is required for a touch to be registered, making the touch sensor =
> > less
> > >        sensitive.
> > >        The number of entries must correspond to the number of channels.
> > > +      CAP1114 is an exception where channels 8~14 reuse the eighth entry=
> > 's
> > > +      threshold, so counts differ.
> > > =20
> > >    microchip,calib-sensitivity:
> > >      $ref: /schemas/types.yaml#/definitions/uint32-array
> > > @@ -149,7 +153,7 @@ patternProperties:
> > >        reg:
> > >          description: LED channel number
> > >          minimum: 0
> > > -        maximum: 7
> > > +        maximum: 10
> > > =20
> > >      required:
> > >        - reg
> > > @@ -199,6 +203,19 @@ allOf:
> > >              reg:
> > >                maximum: 1
> > > =20
> > > +  - if:
> > > +      properties:
> > > +        compatible:
> > > +          contains:
> > > +            enum:
> > > +              - microchip,cap1188
> > 
> > I don't understand this restriction, shouldn't this be
> > if: properties: compatible: not: contains: microchip,cap1114
> > so that the constraints before your change are retained?
> > 
> 
> Previously, the LED reg property had a default maximum of 7 for CAP1188. 
> With the addition of CAP1114, the default maximum is now 11. 
> An if-then constraint is added to limit the LED count for CAP1188.

Ah, is this because cap1188 is the only existing device in the binding
that actually has LEDs?

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

^ permalink raw reply

* Re: [PATCH 7/8] dt-bindings: input: microchip,cap11xx: Add CAP1114 support
From: Jun Yan @ 2026-06-09 14:08 UTC (permalink / raw)
  To: conor
  Cc: conor+dt, devicetree, dmitry.torokhov, jerrysteve1101, krzk+dt,
	linux-input, linux-kernel, robh
In-Reply-To: <20260608-broadly-reunion-09fc8eca5e87@spud>

> On Sat, Jun 06, 2026 at 11:04:00PM +0800, Jun Yan wrote:
> > CAP1114 is a 14-channel capacitive touch sensor with 11 LED outputs
> > and hardware reset support.
> >=20
> > Add the compatible string for CAP1114, include its datasheet URL,
> > and update the maximum count of LED channels and linux,keycodes entries.
> >=20
> > Add description for microchip,input-threshold: CAP1114 only provides eight
> > threshold entries, which does not match its total channel count.
> >=20
> > Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
> > ---
> >  .../bindings/input/microchip,cap11xx.yaml     | 21 +++++++++++++++++--
> >  1 file changed, 19 insertions(+), 2 deletions(-)
> >=20
> > diff --git a/Documentation/devicetree/bindings/input/microchip,cap11xx.ya=
> ml b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
> > index e307628350c2..08233386a433 100644
> > --- a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
> > +++ b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
> > @@ -12,6 +12,7 @@ description: |
> > =20
> >    For more product information please see the links below:
> >      CAP1106: https://ww1.microchip.com/downloads/en/DeviceDoc/00001624B.=
> pdf
> > +    CAP1114: https://ww1.microchip.com/downloads/en/DeviceDoc/00002444A.=
> pdf
> >      CAP1126: https://ww1.microchip.com/downloads/en/DeviceDoc/00001623B.=
> pdf
> >      CAP1188: https://ww1.microchip.com/downloads/en/DeviceDoc/00001620C.=
> pdf
> >      CAP1203: https://ww1.microchip.com/downloads/en/DeviceDoc/00001572B.=
> pdf
> > @@ -26,6 +27,7 @@ properties:
> >    compatible:
> >      enum:
> >        - microchip,cap1106
> > +      - microchip,cap1114
> >        - microchip,cap1126
> >        - microchip,cap1188
> >        - microchip,cap1203
> > @@ -62,7 +64,7 @@ properties:
> > =20
> >    linux,keycodes:
> >      minItems: 3
> > -    maxItems: 8
> > +    maxItems: 14
> >      description: |
> >        Specifies an array of numeric keycode values to
> >        be used for the channels. If this property is
> > @@ -122,6 +124,8 @@ properties:
> >        is required for a touch to be registered, making the touch sensor =
> less
> >        sensitive.
> >        The number of entries must correspond to the number of channels.
> > +      CAP1114 is an exception where channels 8~14 reuse the eighth entry=
> 's
> > +      threshold, so counts differ.
> > =20
> >    microchip,calib-sensitivity:
> >      $ref: /schemas/types.yaml#/definitions/uint32-array
> > @@ -149,7 +153,7 @@ patternProperties:
> >        reg:
> >          description: LED channel number
> >          minimum: 0
> > -        maximum: 7
> > +        maximum: 10
> > =20
> >      required:
> >        - reg
> > @@ -199,6 +203,19 @@ allOf:
> >              reg:
> >                maximum: 1
> > =20
> > +  - if:
> > +      properties:
> > +        compatible:
> > +          contains:
> > +            enum:
> > +              - microchip,cap1188
> 
> I don't understand this restriction, shouldn't this be
> if: properties: compatible: not: contains: microchip,cap1114
> so that the constraints before your change are retained?
> 

Previously, the LED reg property had a default maximum of 7 for CAP1188. 
With the addition of CAP1114, the default maximum is now 11. 
An if-then constraint is added to limit the LED count for CAP1188.

> Also, you don't add a new constraint for linux,keycodes, so now it is
> permitted to have > 8 entries for existing devices.
> 

OK. I will add the relevant constraints in V2.

> pw-bot: changes-requested
> 
> Thanks,
> Conor.
> 
> > +    then:
> > +      patternProperties:
> > +        "^led@":
> > +          properties:
> > +            reg:
> > +              maximum: 7
> > +
> >    - if:
> >        properties:
> >          compatible:
> > --=20
> > 2.54.0
> >=20

^ permalink raw reply

* Re: [PATCH 3/8] dt-bindings: input: microchip,cap11xx: Cleanup and refine LED constraints
From: Jun Yan @ 2026-06-09 13:56 UTC (permalink / raw)
  To: conor
  Cc: conor+dt, devicetree, dmitry.torokhov, jerrysteve1101, krzk+dt,
	linux-input, linux-kernel, robh
In-Reply-To: <20260608-mooned-ambiguous-02493b8d383e@spud>

> On Sat, Jun 06, 2026 at 11:03:56PM +0800, Jun Yan wrote:
> > Add detailed datasheet links for all supported CAP11xx devices.
> >=20
> > Unify LED node pattern to support all chip variants in preparation
> > for CAP1114 support.
> >=20
> > Remove redundant LED properties inherited from common.yaml
> >=20
> > Apply per-chip LED channel limits:
> > - CAP1126: max 2 channels (0-1)
> > - CAP1188: max 8 channels (0-7)
> > - CAP1106, CAP12xx: no LED support
> >=20
> > Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
> > ---
> >  .../bindings/input/microchip,cap11xx.yaml     | 51 ++++++++++++++-----
> >  1 file changed, 37 insertions(+), 14 deletions(-)
> >=20
> > diff --git a/Documentation/devicetree/bindings/input/microchip,cap11xx.ya=
> ml b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
> > index 7ade03f1b32b..99d00f572a2d 100644
> > --- a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
> > +++ b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
> > @@ -10,6 +10,15 @@ description: |
> >    The Microchip CAP1xxx Family of RightTouchTM multiple-channel capaciti=
> ve
> >    touch controllers and LED drivers. The device communication via I2C on=
> ly.
> > =20
> > +  For more product information please see the links below:
> > +    CAP1106: https://ww1.microchip.com/downloads/en/DeviceDoc/00001624B.=
> pdf
> > +    CAP1126: https://ww1.microchip.com/downloads/en/DeviceDoc/00001623B.=
> pdf
> > +    CAP1188: https://ww1.microchip.com/downloads/en/DeviceDoc/00001620C.=
> pdf
> > +    CAP1203: https://ww1.microchip.com/downloads/en/DeviceDoc/00001572B.=
> pdf
> > +    CAP1206: https://ww1.microchip.com/downloads/en/DeviceDoc/00001567B.=
> pdf
> > +    CAP1293: https://ww1.microchip.com/downloads/en/DeviceDoc/00001566B.=
> pdf
> > +    CAP1298: https://ww1.microchip.com/downloads/en/DeviceDoc/00001571B.=
> pdf
> > +
> >  maintainers:
> >    - Rob Herring <robh@kernel.org>
> > =20
> > @@ -124,25 +133,21 @@ properties:
> >        The number of entries must correspond to the number of channels.
> > =20
> >  patternProperties:
> > -  "^led@[0-7]$":
> > +  "^led@[0-9a-f]$":
> >      type: object
> >      description: CAP11xx LEDs
> >      $ref: /schemas/leds/common.yaml#
> > =20
> >      properties:
> >        reg:
> > -        enum: [0, 1, 2, 3, 4, 5, 6, 7]
> > -
> > -      label: true
> > -
> > -      linux,default-trigger: true
> > -
> > -      default-state: true
> > +        description: LED channel number
> > +        minimum: 0
> > +        maximum: 7
> > =20
> >      required:
> >        - reg
> > =20
> > -    additionalProperties: false
> > +    unevaluatedProperties: false
> 
> > Remove redundant LED properties inherited from common.yaml
> 
> But the pattern here suggests they aren't redundant, this is how you say
> "these properties are the only common ones allowed". You need to explain
> why other ones are valid to change this.
> 

I checked other LED dt-bindings and related driver code. 
This change is not suitable and will be dropped in V2.

> pw-bot: changes-requested
> (a commit message change is required at least)
> 
> > =20
> >  allOf:
> >    - $ref: input.yaml
> > @@ -158,7 +163,20 @@ allOf:
> >                - microchip,cap1298
> >      then:
> >        patternProperties:
> > -        "^led@[0-7]$": false
> > +        "^led@": false
> > +
> > +  - if:
> > +      properties:
> > +        compatible:
> > +          contains:
> > +            enum:
> > +              - microchip,cap1126
> > +    then:
> > +      patternProperties:
> > +        "^led@":
> > +          properties:
> > +            reg:
> > +              maximum: 1
> 
> I think these changes to permitted properties should be a standalone
> patch.

Agreed. I will split these changes into a standalone patch for V2.

> Thanks,
> Conor.
> 
> > =20
> >    - if:
> >        properties:
> > @@ -183,6 +201,9 @@ additionalProperties: false
> > =20
> >  examples:
> >    - |
> > +    #include <dt-bindings/gpio/gpio.h>
> > +    #include <dt-bindings/leds/common.h>
> > +
> >      i2c {
> >        #address-cells =3D <1>;
> >        #size-cells =3D <0>;
> > @@ -208,19 +229,21 @@ examples:
> >          #size-cells =3D <0>;
> > =20
> >          led@0 {
> > -                label =3D "cap11xx:green:usr0";
> >                  reg =3D <0>;
> > +                function =3D LED_FUNCTION_INDICATOR;
> > +                color =3D <LED_COLOR_ID_GREEN>;
> >          };
> > =20
> >          led@1 {
> > -                label =3D "cap11xx:green:usr1";
> >                  reg =3D <1>;
> > +                function =3D LED_FUNCTION_INDICATOR;
> > +                color =3D <LED_COLOR_ID_GREEN>;
> >          };
> > =20
> >          led@2 {
> > -                label =3D "cap11xx:green:alive";
> >                  reg =3D <2>;
> > -                linux,default-trigger =3D "heartbeat";
> > +                function =3D LED_FUNCTION_INDICATOR;
> > +                color =3D <LED_COLOR_ID_GREEN>;
> >          };
> >        };
> >      };
> > --=20
> > 2.54.0
> >=20

^ permalink raw reply

* Re: [PATCH v3] HID: i2c-hid: Refactor _DSM helper and add i2c-hid-acpi-prp0001 driver
From: Hans de Goede @ 2026-06-09 13:07 UTC (permalink / raw)
  To: 谢致邦 (XIE Zhibang), linux-input,
	dmitry.torokhov, bentiss
  Cc: dianders, jikos, linux-kernel, sashiko-bot, sashiko-reviews,
	superm1
In-Reply-To: <tencent_C2BEF7C0584BFE713DC7B41FFD7007B6D30A@qq.com>

Hi,

On 9-Jun-26 12:10, 谢致邦 (XIE Zhibang) wrote:
> Hi Hans,
> 
> Thanks for the review.
> 
> The current header-based approach lets i2c-hid-acpi-prp0001.c work
> independently by just including a header for the _DSM helper. Switching
> to EXPORT_SYMBOL_GPL would force prp0001 to depend on i2c-hid-acpi —
> a Kconfig "depends on I2C_HID_ACPI", plus module-level dependency at
> load time — all for sharing a single function. I find that hard to
> accept.
> 
> I understand that adding a new header for one prototype is unusual,
> though it contains only a single static inline function and introduces
> no runtime dependency between the two drivers.
> 
> Looking back at the full discussion: Benjamin made it clear from the
> start that he doesn't want i2c-hid-of.c handling ACPI _DSM fallback.
> His line is that ACPI devices and OF devices should each go through
> their own drivers without cross-contamination. If you still prefer
> exporting the function from i2c-hid-acpi.c, then prp0001 would have to
> drag i2c-hid-acpi along with it — an independent leaf driver turned
> into something that can't stand alone.

Well it is a special case/version of the ACPI driver so depending
on it seems fine to me.

Anyways if you prefer the inline function in header solution that is
fine with me.

Lets see what bentiss has to say about this.

Regards,

Hans


^ permalink raw reply

* Re: [PATCH v3 4/4] HID: wacom: Fix teardown order in wacom_mode_change_work
From: sashiko-bot @ 2026-06-09 12:48 UTC (permalink / raw)
  To: Lee Jones; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260609121353.3743782-4-lee@kernel.org>

Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Missing synchronization between sibling device removal and `wacom_mode_change_work` leads to Use-After-Free and double `hid_hw_stop()`.
- [Critical] Missing synchronization allows multiple `wacom_mode_change_work` instances to execute concurrently on both siblings, leading to double teardown and state corruption.
- [Critical] Error paths in `wacom_parse_and_register()` after `hid_hw_start()` fail to call `hid_hw_stop()`, leaving hardware IRQs active after releasing resources.
- [High] If `wacom_parse_and_register()` fails for the first sibling device, the second device is permanently left in a stopped and uninitialized state.
- [High] Pending background workqueues and timers are not cancelled before releasing device resources in `wacom_mode_change_work`, violating subsystem teardown guidelines and causing UAF.
- [High] `wacom_remove()` cancels `mode_change_work` after stopping the hardware, creating a race that leaves the device started and permanently leaks HID interfaces.
--

commit 0812538ee6f90ea0ab3dbb1250c3e8460816a993
Author: Lee Jones <lee@kernel.org>

HID: wacom: Fix teardown order in wacom_mode_change_work

wacom_mode_change_work() called wacom_release_resources() before
hid_hw_stop(), which could lead to a crash if hardware IRQs fire and
dereference the nullified shared pointer. This commit fixes the teardown
order to call hid_hw_stop() first.

> diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
> index 1b019e3331b45..378dddbf7ec5b 100644
> --- a/drivers/hid/wacom_sys.c
> +++ b/drivers/hid/wacom_sys.c
> @@ -2835,16 +2835,16 @@ static void wacom_mode_change_work(struct work_struct *work)
>  
>  	if (pen) {

[Severity: Critical]
This is a pre-existing issue, but is it possible for the shared device
pointers to be dereferenced after they are freed?

In wacom_mode_change_work(), the sibling device pointers are fetched:

    struct hid_device *pen = rcu_access_pointer(shared->pen);
    ...

These pointers are accessed without holding an rcu_read_lock or acquiring
a device reference. If a sibling device is concurrently unbound,
wacom_remove() clears the shared pointer and calls synchronize_rcu(), but
it would not wait for this worker. Could this result in a use-after-free
when hid_hw_stop() is called on the stale pointer?

[Severity: Critical]
This isn't a bug introduced by this patch, but does this function have
sufficient synchronization if mode change events arrive concurrently on
both pen and touch interfaces?

Since the code unconditionally operates on both sibling devices without
locking:

    wacom1 = hid_get_drvdata(pen);
    hid_hw_stop(wacom1->hdev);
    wacom_release_resources(wacom1);

If both devices independently schedule their own mode_change_work, could
both workers run simultaneously and race to call wacom_release_resources()
on the exact same pointers, potentially causing a double-free in the
devres core?

>  		wacom1 = hid_get_drvdata(pen);
> -		wacom_release_resources(wacom1);
>  		hid_hw_stop(wacom1->hdev);
> +		wacom_release_resources(wacom1);

[Severity: High]
This is a pre-existing issue, but are we certain all background tasks
are cancelled before releasing resources here?

Unlike wacom_remove(), wacom_mode_change_work() does not cancel pending
tasks like init_work before calling wacom_release_resources(). Since
wacom_release_resources() destroys devres allocations (such as led groups),
could a delayed wacom_init_work() execute concurrently and access these
freed structures, resulting in a use-after-free?

>  		wacom1->wacom_wac.has_mode_change = true;
>  		wacom1->wacom_wac.is_direct_mode = is_direct;
>  	}
>  
>  	if (touch) {
>  		wacom2 = hid_get_drvdata(touch);
> -		wacom_release_resources(wacom2);
>  		hid_hw_stop(wacom2->hdev);
> +		wacom_release_resources(wacom2);
>  		wacom2->wacom_wac.has_mode_change = true;
>  		wacom2->wacom_wac.is_direct_mode = is_direct;
>  	}

[Severity: High]
This isn't a bug introduced by this patch, but what happens to the second
device if re-registration fails for the first one?

Looking at the rest of wacom_mode_change_work():

    if (wacom1) {
        error = wacom_parse_and_register(wacom1, false);
        if (error)
            return;
    }
    if (wacom2) {
        ...
    }

If wacom_parse_and_register() fails for wacom1, the early return bypasses
the initialization for wacom2. Does this permanently leave the touch
interface hardware stopped and its resources released without recovery?

[Severity: Critical]
This is a pre-existing issue, but is there a missing hardware teardown
in the error handling path of wacom_parse_and_register()?

When an error occurs after hid_hw_start() succeeds:

drivers/hid/wacom_sys.c:wacom_parse_and_register() {
    ...
fail_quirks:
    hid_hw_stop(hdev);
fail:
    wacom_release_resources(wacom);
    return error;
}

The goto fail jumps past hid_hw_stop(hdev). Does this leave the hid
hardware running while its resources are freed, allowing subsequent
hardware irqs to trigger wacom_raw_event() and cause a use-after-free?

[Severity: High]
This isn't a bug introduced by this patch, but does wacom_remove()
cancel the mode_change_work too late?

In wacom_remove(), the cancellation happens after stopping the hardware:

drivers/hid/wacom_sys.c:wacom_remove() {
    hid_hw_stop(hdev);
    cancel_delayed_work_sync(&wacom->init_work);
    ...
    cancel_work_sync(&wacom->mode_change_work);
}

If mode_change_work is pending and runs after hid_hw_stop(), it will
call wacom_parse_and_register(), which invokes hid_hw_start(hdev).
Once cancel_work_sync() returns, wacom_remove() completes without
re-stopping the hardware. Could this permanently leak the active hid
interfaces?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260609121353.3743782-1-lee@kernel.org?part=4

^ permalink raw reply

* Re: [PATCH v3 1/4] HID: wacom: Fix Use-After-Free in wacom_intuos_pad
From: sashiko-bot @ 2026-06-09 12:35 UTC (permalink / raw)
  To: Lee Jones; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260609121353.3743782-1-lee@kernel.org>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Lockless TOCTOU Use-After-Free of sibling devices in wacom_mode_change_work
--

commit bb8e808fb26bf4a0ca1a10604a506fb1d60c8173
Author: Lee Jones <lee@kernel.org>

HID: wacom: Fix Use-After-Free in wacom_intuos_pad

This commit resolves a time-of-check to time-of-use race condition in
wacom_intuos_pad() that could lead to a use-after-free. It introduces
RCU protection for the touch_input pointer, wrapping lockless readers
with rcu_read_lock() and writers with rcu_assign_pointer().

> diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
> index 2220168bf1164..7ba5898265481 100644
> --- a/drivers/hid/wacom_sys.c
> +++ b/drivers/hid/wacom_sys.c
> @@ -877,10 +877,16 @@ static void wacom_remove_shared_data(void *res)
>  		data = container_of(wacom_wac->shared, struct wacom_hdev_data,
>  				    shared);
>  
> -		if (wacom_wac->shared->touch == wacom->hdev)
> -			wacom_wac->shared->touch = NULL;
> -		else if (wacom_wac->shared->pen == wacom->hdev)
> -			wacom_wac->shared->pen = NULL;
> +		scoped_guard(mutex, &wacom_udev_list_lock) {
> +			if (wacom_wac->shared->touch == wacom->hdev) {
> +				wacom_wac->shared->touch = NULL;
> +				rcu_assign_pointer(wacom_wac->shared->touch_input, NULL);
> +			} else if (wacom_wac->shared->pen == wacom->hdev) {
> +				wacom_wac->shared->pen = NULL;
> +			}
> +		}
> +
> +		synchronize_rcu();

[Severity: High]
This is a pre-existing issue, but is it possible for a sibling device to
still be used after this synchronize_rcu() call?

Looking at wacom_mode_change_work(), it reads shared->pen and shared->touch
locklessly:

drivers/hid/wacom_sys.c:wacom_mode_change_work() {
    ...
	if (shared->pen) {
		wacom1 = hid_get_drvdata(shared->pen);
		wacom_release_resources(wacom1);
		hid_hw_stop(wacom1->hdev);
    ...
}

If a context switch occurs right after shared->pen is evaluated as true,
could a sibling device be physically disconnected, triggering
wacom_remove_shared_data() to nullify shared->pen and free the object?

Because wacom_mode_change_work() does not hold an rcu_read_lock(), this
synchronize_rcu() wouldn't block it. When the workqueue resumes, could it
pass the now-freed pointer to hid_get_drvdata() and cause a use-after-free?

>  
>  		kref_put(&data->kref, wacom_release_shared_data);
>  		wacom_wac->shared = NULL;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260609121353.3743782-1-lee@kernel.org?part=1

^ 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