Linux Input/HID development
 help / color / mirror / Atom feed
* [PATCH 3/7] iio: light: hid-sensor-als: use u32 instead of unsigned
From: Sanjay Chitroda @ 2026-06-06 12:17 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko
  Cc: linux-input, linux-iio, linux-kernel, Sanjay Chitroda
In-Reply-To: <20260606-6-june-hid-iio-correct-usage-id-v1-0-dd4a6820b674@gmail.com>

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

Prefer 'u32' instead of bare 'unsigned' variable to improve code
clarity and consistency with kernel style.

Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/light/hid-sensor-als.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index d72e260b8266..ae2fda8dc500 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -241,7 +241,7 @@ static const struct iio_info als_info = {
 
 /* Callback handler to send event after all samples are received and captured */
 static int als_proc_event(struct hid_sensor_hub_device *hsdev,
-				unsigned usage_id,
+				u32 usage_id,
 				void *priv)
 {
 	struct iio_dev *indio_dev = platform_get_drvdata(priv);
@@ -263,7 +263,7 @@ static int als_proc_event(struct hid_sensor_hub_device *hsdev,
 
 /* Capture samples in local storage */
 static int als_capture_sample(struct hid_sensor_hub_device *hsdev,
-				unsigned usage_id,
+				u32 usage_id,
 				size_t raw_len, char *raw_data,
 				void *priv)
 {
@@ -305,7 +305,7 @@ static int als_capture_sample(struct hid_sensor_hub_device *hsdev,
 /* Parse report which is specific to an usage id*/
 static int als_parse_report(struct platform_device *pdev,
 				struct hid_sensor_hub_device *hsdev,
-				unsigned usage_id,
+				u32 usage_id,
 				struct als_state *st)
 {
 	struct iio_chan_spec *channels;

-- 
2.34.1


^ permalink raw reply related

* [PATCH 4/7] iio: light: hid-sensor-prox: use u32 instead of unsigned
From: Sanjay Chitroda @ 2026-06-06 12:17 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko
  Cc: linux-input, linux-iio, linux-kernel, Sanjay Chitroda
In-Reply-To: <20260606-6-june-hid-iio-correct-usage-id-v1-0-dd4a6820b674@gmail.com>

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

Prefer 'u32' instead of bare 'unsigned' variable to improve code
clarity and consistency with kernel style.

Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/light/hid-sensor-prox.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
index edc9274a2c07..9059f00f0ced 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -166,7 +166,7 @@ static const struct iio_info prox_info = {
 
 /* Callback handler to send event after all samples are received and captured */
 static int prox_proc_event(struct hid_sensor_hub_device *hsdev,
-				unsigned usage_id,
+				u32 usage_id,
 				void *priv)
 {
 	struct iio_dev *indio_dev = platform_get_drvdata(priv);
@@ -183,7 +183,7 @@ static int prox_proc_event(struct hid_sensor_hub_device *hsdev,
 
 /* Capture samples in local storage */
 static int prox_capture_sample(struct hid_sensor_hub_device *hsdev,
-				unsigned usage_id,
+				u32 usage_id,
 				size_t raw_len, char *raw_data,
 				void *priv)
 {

-- 
2.34.1


^ permalink raw reply related

* [PATCH 5/7] iio: orientation: hid-sensor-incl-3d: use u32 instead of unsigned
From: Sanjay Chitroda @ 2026-06-06 12:17 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko
  Cc: linux-input, linux-iio, linux-kernel, Sanjay Chitroda
In-Reply-To: <20260606-6-june-hid-iio-correct-usage-id-v1-0-dd4a6820b674@gmail.com>

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

Prefer 'u32' instead of bare 'unsigned' variable to improve code
clarity and consistency with kernel style.

Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/orientation/hid-sensor-incl-3d.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
index 4e23a598a3fb..c7fbff498be7 100644
--- a/drivers/iio/orientation/hid-sensor-incl-3d.c
+++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
@@ -189,7 +189,7 @@ static const struct iio_info incl_3d_info = {
 
 /* Callback handler to send event after all samples are received and captured */
 static int incl_3d_proc_event(struct hid_sensor_hub_device *hsdev,
-				unsigned usage_id,
+				u32 usage_id,
 				void *priv)
 {
 	struct iio_dev *indio_dev = platform_get_drvdata(priv);
@@ -212,7 +212,7 @@ static int incl_3d_proc_event(struct hid_sensor_hub_device *hsdev,
 
 /* Capture samples in local storage */
 static int incl_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
-				unsigned usage_id,
+				u32 usage_id,
 				size_t raw_len, char *raw_data,
 				void *priv)
 {
@@ -247,7 +247,7 @@ static int incl_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
 static int incl_3d_parse_report(struct platform_device *pdev,
 				struct hid_sensor_hub_device *hsdev,
 				struct iio_chan_spec *channels,
-				unsigned usage_id,
+				u32 usage_id,
 				struct incl_3d_state *st)
 {
 	int ret;

-- 
2.34.1


^ permalink raw reply related

* [PATCH 6/7] iio: orientation: hid-sensor-rotation: use u32 instead of unsigned
From: Sanjay Chitroda @ 2026-06-06 12:17 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko
  Cc: linux-input, linux-iio, linux-kernel, Sanjay Chitroda
In-Reply-To: <20260606-6-june-hid-iio-correct-usage-id-v1-0-dd4a6820b674@gmail.com>

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

Prefer 'u32' instead of bare 'unsigned' variable to improve code
clarity and consistency with kernel style.

Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/orientation/hid-sensor-rotation.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c
index 4a11e4555099..20563d8efaf6 100644
--- a/drivers/iio/orientation/hid-sensor-rotation.c
+++ b/drivers/iio/orientation/hid-sensor-rotation.c
@@ -176,7 +176,7 @@ static const struct iio_info dev_rot_info = {
 
 /* Callback handler to send event after all samples are received and captured */
 static int dev_rot_proc_event(struct hid_sensor_hub_device *hsdev,
-				unsigned usage_id,
+				u32 usage_id,
 				void *priv)
 {
 	struct iio_dev *indio_dev = platform_get_drvdata(priv);
@@ -209,7 +209,7 @@ static int dev_rot_proc_event(struct hid_sensor_hub_device *hsdev,
 
 /* Capture samples in local storage */
 static int dev_rot_capture_sample(struct hid_sensor_hub_device *hsdev,
-				unsigned usage_id,
+				u32 usage_id,
 				size_t raw_len, char *raw_data,
 				void *priv)
 {
@@ -240,7 +240,7 @@ static int dev_rot_capture_sample(struct hid_sensor_hub_device *hsdev,
 /* Parse report which is specific to an usage id*/
 static int dev_rot_parse_report(struct platform_device *pdev,
 				struct hid_sensor_hub_device *hsdev,
-				unsigned usage_id,
+				u32 usage_id,
 				struct dev_rot_state *st)
 {
 	int ret;

-- 
2.34.1


^ permalink raw reply related

* [PATCH 7/7] iio: pressure: hid-sensor-press: use u32 instead of unsigned
From: Sanjay Chitroda @ 2026-06-06 12:17 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko
  Cc: linux-input, linux-iio, linux-kernel, Sanjay Chitroda
In-Reply-To: <20260606-6-june-hid-iio-correct-usage-id-v1-0-dd4a6820b674@gmail.com>

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

Prefer 'u32' instead of bare 'unsigned' variable to improve code
clarity and consistency with kernel style.

Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/pressure/hid-sensor-press.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
index a039b99d9851..3e47a10d72a8 100644
--- a/drivers/iio/pressure/hid-sensor-press.c
+++ b/drivers/iio/pressure/hid-sensor-press.c
@@ -155,7 +155,7 @@ static const struct iio_info press_info = {
 
 /* Callback handler to send event after all samples are received and captured */
 static int press_proc_event(struct hid_sensor_hub_device *hsdev,
-				unsigned usage_id,
+				u32 usage_id,
 				void *priv)
 {
 	struct iio_dev *indio_dev = platform_get_drvdata(priv);
@@ -176,7 +176,7 @@ static int press_proc_event(struct hid_sensor_hub_device *hsdev,
 
 /* Capture samples in local storage */
 static int press_capture_sample(struct hid_sensor_hub_device *hsdev,
-				unsigned usage_id,
+				u32 usage_id,
 				size_t raw_len, char *raw_data,
 				void *priv)
 {
@@ -204,7 +204,7 @@ static int press_capture_sample(struct hid_sensor_hub_device *hsdev,
 static int press_parse_report(struct platform_device *pdev,
 				struct hid_sensor_hub_device *hsdev,
 				struct iio_chan_spec *channels,
-				unsigned usage_id,
+				u32 usage_id,
 				struct press_state *st)
 {
 	int ret;

-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH 2/7] iio: accel: hid-sensor-accel-3d: use u32 instead of unsigned
From: sashiko-bot @ 2026-06-06 12:27 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260606-6-june-hid-iio-correct-usage-id-v1-2-dd4a6820b674@gmail.com>

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

Pre-existing issues:
- [High] Unsafe memory access via out-of-bounds read and unaligned dereference.
--

commit f0677ef9176d20b908a2aa7a22d8817abe7925a7
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: accel: hid-sensor-accel-3d: use u32 instead of unsigned

This commit updates the hid-sensor-accel-3d driver to use u32 instead of
unsigned for the usage_id variables. This improves code clarity and maintains
consistency with kernel coding styles.

> diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
> --- a/drivers/iio/accel/hid-sensor-accel-3d.c
> +++ b/drivers/iio/accel/hid-sensor-accel-3d.c

[ ... ]

> @@ -247,7 +247,7 @@ static int accel_3d_proc_event(struct hid_sensor_hub_device *hsdev,
>  
>  /* Capture samples in local storage */
>  static int accel_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
> -				unsigned usage_id,
> +				u32 usage_id,
>  				size_t raw_len, char *raw_data,
>  				void *priv)
>  {
>  	struct iio_dev *indio_dev = platform_get_drvdata(priv);
>  	struct accel_3d_state *accel_state = iio_priv(indio_dev);
>  	int offset;
>  	int ret = -EINVAL;
>  
>  	switch (usage_id) {
>  	case HID_USAGE_SENSOR_ACCEL_X_AXIS:
>  	case HID_USAGE_SENSOR_ACCEL_Y_AXIS:
>  	case HID_USAGE_SENSOR_ACCEL_Z_AXIS:
>  		offset = usage_id - HID_USAGE_SENSOR_ACCEL_X_AXIS;
>  		accel_state->scan.accel_val[CHANNEL_SCAN_INDEX_X + offset] =
>  						*(u32 *)raw_data;

[Severity: High]
This is a pre-existing issue, but I noticed a potential problem with how
raw_data is accessed here. Does this direct cast to a 32-bit integer pointer
assume that raw_len is always at least 4 bytes and that raw_data is always
4-byte aligned?

If a device provides a smaller report, could this result in an out-of-bounds
read? Also, since raw_data comes from a HID report buffer, could this trigger
an alignment fault on architectures with strict alignment requirements if the
data is unaligned?

>  		ret = 0;
>  	break;
>  	case HID_USAGE_SENSOR_TIME_TIMESTAMP:
>  		accel_state->timestamp =
>  			hid_sensor_convert_timestamp(
>  					&accel_state->common_attributes,
>  					*(int64_t *)raw_data);

[Severity: High]
This is also a pre-existing issue, but similar to the above, does this direct
cast to a 64-bit integer pointer require raw_len to be at least 8 bytes and
raw_data to be 8-byte aligned?

Would it be safer to use get_unaligned() and check raw_len before
dereferencing these pointers to avoid potential slab-out-of-bounds panics
or alignment faults?

>  		ret = 0;
>  	break;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-6-june-hid-iio-correct-usage-id-v1-0-dd4a6820b674@gmail.com?part=2

^ permalink raw reply

* Re: [PATCH 4/7] iio: light: hid-sensor-prox: use u32 instead of unsigned
From: sashiko-bot @ 2026-06-06 12:27 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260606-6-june-hid-iio-correct-usage-id-v1-4-dd4a6820b674@gmail.com>

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

Pre-existing issues:
- [High] Direct casting of the raw HID byte stream pointer (`raw_data`) to `u16 *` and `u32 *` causes unaligned memory accesses and misinterprets little-endian HID data on big-endian architectures.
--

commit e810e65c50acb8fcba7f1cd54ed67e25dac1f409
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: light: hid-sensor-prox: use u32 instead of unsigned

This patch updates the usage_id parameter to use u32 instead of a bare
unsigned type. This improves code clarity and consistency with standard
kernel style.

> diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
> index edc9274a2c076..9059f00f0cedf 100644
> --- a/drivers/iio/light/hid-sensor-prox.c
> +++ b/drivers/iio/light/hid-sensor-prox.c
[ ... ]
> @@ -183,7 +183,7 @@ static int prox_proc_event(struct hid_sensor_hub_device *hsdev,
>  
>  /* Capture samples in local storage */
>  static int prox_capture_sample(struct hid_sensor_hub_device *hsdev,
> -				unsigned usage_id,
> +				u32 usage_id,
>  				size_t raw_len, char *raw_data,
>  				void *priv)
>  {

[Severity: High]
This is a pre-existing issue, but since you are updating types in this
function, could we also address how the raw_data pointer is accessed?

Further down in prox_capture_sample(), the raw HID byte stream is directly
cast to u16 and u32 pointers:

	switch (raw_len) {
	case 1:
		prox_state->human_presence[chan] = *(u8 *)raw_data * multiplier;
		return 0;
	case 2:
		prox_state->human_presence[chan] = *(u16 *)raw_data * multiplier;
		return 0;
	case 4:
		prox_state->human_presence[chan] = *(u32 *)raw_data * multiplier;
		return 0;
	}

Can this sequence cause unaligned memory accesses or endianness issues?

Because HID fields are tightly packed and can have arbitrary lengths, the
raw_data pointer is not guaranteed to be 2-byte or 4-byte aligned.
Dereferencing it directly could trigger unaligned access traps on
architectures that do not natively support them.

Additionally, HID reports are transmitted in little-endian format over the
wire. Reading them via a direct cast evaluates them in host byte-order,
which could yield corrupted data on big-endian architectures.

Would it be better to use get_unaligned_le16() and get_unaligned_le32()
here to safely extract the payload?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-6-june-hid-iio-correct-usage-id-v1-0-dd4a6820b674@gmail.com?part=4

^ permalink raw reply

* Re: [PATCH 6/7] iio: orientation: hid-sensor-rotation: use u32 instead of unsigned
From: sashiko-bot @ 2026-06-06 12:27 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260606-6-june-hid-iio-correct-usage-id-v1-6-dd4a6820b674@gmail.com>

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

Pre-existing issues:
- [High] Out-of-bounds read and information leak due to unverified raw_len in dev_rot_capture_sample().
- [High] Unaligned and endian-unsafe access when parsing HID raw byte streams.
--

commit 1678aae0ba9cfb6e8824b0811f3f770a159c5a16
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: orientation: hid-sensor-rotation: use u32 instead of unsigned

This commit replaces bare unsigned types with u32 for usage_id parameters
across the HID sensor rotation driver to improve code clarity and
consistency with kernel style.

> --- a/drivers/iio/orientation/hid-sensor-rotation.c
> +++ b/drivers/iio/orientation/hid-sensor-rotation.c

[ ... ]

> @@ -209,7 +209,7 @@ static int dev_rot_proc_event(struct hid_sensor_hub_device *hsdev,
>  
>  /* Capture samples in local storage */
>  static int dev_rot_capture_sample(struct hid_sensor_hub_device *hsdev,
> -				unsigned usage_id,
> +				u32 usage_id,
>  				size_t raw_len, char *raw_data,
>  				void *priv)
>  {

[Severity: High]
This is a pre-existing issue, but does this function perform unaligned and
endian-unsafe reads?

Looking further down in dev_rot_capture_sample(), when raw_data is accessed:

        if (raw_len / 4 == sizeof(s16)) {
            rot_state->scan.sampled_vals[0] = ((s16 *)raw_data)[0];
            rot_state->scan.sampled_vals[1] = ((s16 *)raw_data)[1];
            rot_state->scan.sampled_vals[2] = ((s16 *)raw_data)[2];
            rot_state->scan.sampled_vals[3] = ((s16 *)raw_data)[3];

Since raw_data points to a byte array from a tightly packed HID report, it
is not guaranteed to be aligned to a 2-byte boundary. Casting directly to
s16 pointers might cause bus errors or panics on architectures that do not
support unaligned loads. 

Also, native CPU casts will read garbage values on big-endian architectures. 
Should this use get_unaligned_le16() instead?

[Severity: High]
This isn't a bug introduced by this patch, but can the fallback memcpy 
result in an out-of-bounds read?

If raw_len is not exactly 8 bytes, the code unconditionally copies 16 bytes:

        } else {
            memcpy(&rot_state->scan.sampled_vals, raw_data,
                   sizeof(rot_state->scan.sampled_vals));
        }

If a malformed or malicious HID descriptor specifies a size smaller than
16 bytes, this would read past the end of the raw_data buffer into adjacent
kernel memory. 

The copied data could then be pushed to userspace via iio_push_to_buffers(),
potentially creating an information leak.

[Severity: High]
This is a pre-existing issue, but does the timestamp handling also have
bounds checking and alignment issues?

Later in the same function:

    } else if (usage_id == HID_USAGE_SENSOR_TIME_TIMESTAMP) {
        rot_state->timestamp = hid_sensor_convert_timestamp(
                                    &rot_state->common_attributes,
                                    *(s64 *)raw_data);

The raw_data pointer is cast directly to a 64-bit integer without verifying
that raw_len is at least 8 bytes. 

Similar to the unaligned reads above, a direct cast to an s64 pointer on an
unaligned buffer could cause bus errors on certain architectures, and it is
also not endian-safe.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-6-june-hid-iio-correct-usage-id-v1-0-dd4a6820b674@gmail.com?part=6

^ permalink raw reply

* Re: [PATCH 3/7] iio: light: hid-sensor-als: use u32 instead of unsigned
From: sashiko-bot @ 2026-06-06 12:28 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260606-6-june-hid-iio-correct-usage-id-v1-3-dd4a6820b674@gmail.com>

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

Pre-existing issues:
- [High] Unconditional casting and dereferencing of `raw_data` to `u32*` and `s64*` without checking `raw_len` causes out-of-bounds reads, kernel memory disclosure, unaligned access exceptions, and incorrect endianness handling.
--

commit 7ad652d49fe4e7dcab137b42945a51bbeaea25a3
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: light: hid-sensor-als: use u32 instead of unsigned

This commit updates the HID sensor ALS driver to use 'u32' instead of a bare
'unsigned' variable for the usage_id parameter. This improves code clarity
and consistency with kernel style.

> --- a/drivers/iio/light/hid-sensor-als.c
> +++ b/drivers/iio/light/hid-sensor-als.c

[ ... ]

>  /* Capture samples in local storage */
>  static int als_capture_sample(struct hid_sensor_hub_device *hsdev,
> -				unsigned usage_id,
> +				u32 usage_id,
>  				size_t raw_len, char *raw_data,
>  				void *priv)
>  {
>  	struct iio_dev *indio_dev = platform_get_drvdata(priv);
>  	struct als_state *als_state = iio_priv(indio_dev);
>  	int ret = -EINVAL;
>  	u32 sample_data = *(u32 *)raw_data;

[Severity: High]
This isn't a bug introduced by this patch, but does this direct cast cause
out-of-bounds reads or unaligned accesses if raw_len is less than 4 or
raw_data is unaligned?

Since raw_len is derived from the HID report descriptor, a malicious or
malfunctioning device could specify a smaller field size, potentially exposing
adjacent kernel memory. Should this code check raw_len and use something like
get_unaligned_le32() since HID data is little-endian?

>  
>  	switch (usage_id) {
>  	case HID_USAGE_SENSOR_LIGHT_ILLUM:

[ ... ]

>  	case HID_USAGE_SENSOR_TIME_TIMESTAMP:
>  		als_state->timestamp = hid_sensor_convert_timestamp(&als_state->common_attributes,
>  								    *(s64 *)raw_data);

[Severity: High]
This is also a pre-existing issue, but does this face similar risks with
8-byte reads from raw_data?

Could this trigger an out-of-bounds read if raw_len is less than 8, or cause
alignment faults on strict-alignment architectures?

>  		ret = 0;
>  		break;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-6-june-hid-iio-correct-usage-id-v1-0-dd4a6820b674@gmail.com?part=3

^ permalink raw reply

* Re: [PATCH 1/7] iio: gyro: hid-sensor-gyro-3d: use u32 instead of unsigned
From: sashiko-bot @ 2026-06-06 12:28 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260606-6-june-hid-iio-correct-usage-id-v1-1-dd4a6820b674@gmail.com>

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

Pre-existing issues:
- [High] The capture_sample callback casts the `raw_data` pointer to `u32*` and `s64*` without validating `raw_len` or pointer alignment, potentially causing out-of-bounds reads, kernel memory leaks, and unaligned access faults.
--

commit e250748ae8811d708c463dcef4e525db238816e3
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: gyro: hid-sensor-gyro-3d: use u32 instead of unsigned

This commit replaces bare unsigned variables with the u32 type in the HID
sensor 3D gyro driver to improve code clarity and adhere to kernel style
guidelines.

> diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
> index e48c25c87b6d6..bbca2111e79bb 100644
> --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
> +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
[ ... ]
> @@ -199,7 +199,7 @@ static int gyro_3d_proc_event(struct hid_sensor_hub_device *hsdev,
>  
>  /* Capture samples in local storage */
>  static int gyro_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
> -				unsigned usage_id,
> +				u32 usage_id,
>  				size_t raw_len, char *raw_data,
>  				void *priv)
>  {

[Severity: High]
This is a pre-existing issue, but looking at the rest of this function, it
appears we cast the raw_data pointer directly to u32* and s64* without checking
raw_len or alignment:

gyro_3d_capture_sample() {
	...
	gyro_state->scan.gyro_val[CHANNEL_SCAN_INDEX_X + offset] =
			*(u32 *)raw_data;
	...
	gyro_state->timestamp =
		hid_sensor_convert_timestamp(&gyro_state->common_attributes,
					     *(s64 *)raw_data);
	...
}

Could a buggy or malicious HID device supply a field size smaller than 4 or 8
bytes, leading to an out-of-bounds read that leaks kernel heap data into the
IIO buffer?

Also, since raw_data is only guaranteed to be byte-aligned, could these native
casts trigger unaligned access exceptions on architectures that do not support
unaligned loads? Would it be safer to validate raw_len and use get_unaligned()
or memcpy() here?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-6-june-hid-iio-correct-usage-id-v1-0-dd4a6820b674@gmail.com?part=1

^ permalink raw reply

* Re: [PATCH 5/7] iio: orientation: hid-sensor-incl-3d: use u32 instead of unsigned
From: sashiko-bot @ 2026-06-06 12:30 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260606-6-june-hid-iio-correct-usage-id-v1-5-dd4a6820b674@gmail.com>

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

Pre-existing issues:
- [High] Out-of-bounds read and information leak in `incl_3d_capture_sample` due to ignored `raw_len`.
- [High] Endianness mismatch in `incl_3d_capture_sample` due to direct pointer cast.
- [High] Unaligned memory access in `incl_3d_capture_sample`.
--

commit bb48c83224153ec8c20c69c57c293183eb5211a7
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: orientation: hid-sensor-incl-3d: use u32 instead of unsigned

This patch updates the hid-sensor-incl-3d driver to use u32 instead of a
bare unsigned type in callback signatures, improving code clarity and
consistency.

> diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
> index 4e23a598a3fb9..c7fbff498be7a 100644
> --- a/drivers/iio/orientation/hid-sensor-incl-3d.c
> +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c

[ ... ]

> @@ -212,7 +212,7 @@ static int incl_3d_proc_event(struct hid_sensor_hub_device *hsdev,
>  
>  /* Capture samples in local storage */
>  static int incl_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
> -				unsigned usage_id,
> +				u32 usage_id,
>  				size_t raw_len, char *raw_data,
>  				void *priv)
>  {

[Severity: High]
This is a pre-existing issue, but by ignoring raw_len in
incl_3d_capture_sample(), could we read out-of-bounds if a malicious HID
device provides a report descriptor with a smaller field size?

It appears we unconditionally cast char *raw_data to u32 * or s64 * and
dereference it:

drivers/iio/orientation/hid-sensor-incl-3d.c:incl_3d_capture_sample() {
    ...
    case HID_USAGE_SENSOR_ORIENT_TILT_X:
        incl_state->scan.incl_val[CHANNEL_SCAN_INDEX_X] = *(u32 *)raw_data;
    ...
}

If the field is placed at the end of the HID report buffer, this might
read past the allocated buffer and leak kernel heap memory into the
sensor readings.

[Severity: High]
This is a pre-existing issue, but does this direct cast also cause
incorrect sensor values on big-endian architectures?

The USB HID protocol specifies that report data is strictly little-endian,
but casting directly to u32 * and dereferencing it uses the CPU native
byte order.

[Severity: High]
This is a pre-existing issue, but can this dereference trigger alignment
exceptions on architectures that do not support unaligned accesses?

Since the pointer passed as raw_data is iteratively incremented by the
byte sizes of preceding fields, it might not be aligned to a 4-byte
boundary when we cast it to u32 * and dereference it.

Should we be extracting these values safely using helpers like
get_unaligned_le32() instead?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-6-june-hid-iio-correct-usage-id-v1-0-dd4a6820b674@gmail.com?part=5

^ permalink raw reply

* Re: [PATCH 7/7] iio: pressure: hid-sensor-press: use u32 instead of unsigned
From: sashiko-bot @ 2026-06-06 12:32 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260606-6-june-hid-iio-correct-usage-id-v1-7-dd4a6820b674@gmail.com>

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

Pre-existing issues:
- [High] Unaligned memory access and out-of-bounds read in `press_capture_sample` due to unconditional pointer cast and ignoring `raw_len`.
- [High] Stale software timestamp reused for all subsequent samples if the device lacks hardware timestamps.
--

commit a1f5a54c679fcb699d59de1d79aadcc9a8177858
Author: Sanjay Chitroda <sanjayembeddedse@gmail.com>

iio: pressure: hid-sensor-press: use u32 instead of unsigned

Prefer 'u32' instead of bare 'unsigned' variable to improve code
clarity and consistency with kernel style.

> diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
> index a039b99d9851d..3e47a10d72a89 100644
> --- a/drivers/iio/pressure/hid-sensor-press.c
> +++ b/drivers/iio/pressure/hid-sensor-press.c
> @@ -155,7 +155,7 @@ static const struct iio_info press_info = {
>  
>  /* Callback handler to send event after all samples are received and captured */
>  static int press_proc_event(struct hid_sensor_hub_device *hsdev,
> -				unsigned usage_id,
> +				u32 usage_id,
>  				void *priv)
>  {

[Severity: High]
This isn't a bug introduced by this patch, but I noticed a potential problem
with how timestamps are handled in press_proc_event().

When a hardware timestamp isn't provided, the driver generates a software
timestamp:

	if (atomic_read(&press_state->common_attributes.data_ready)) {
		if (!press_state->timestamp)
			press_state->timestamp = iio_get_time_ns(indio_dev);

		iio_push_to_buffers_with_ts(indio_dev, &press_state->scan,
					    sizeof(press_state->scan),
					    press_state->timestamp);
	}

Because press_state->timestamp is never cleared back to 0 after pushing the
buffer, will all subsequent samples incorrectly reuse the exact same timestamp
instead of generating a new one?

[ ... ]

> @@ -176,7 +176,7 @@ static int press_proc_event(struct hid_sensor_hub_device *hsdev,
>  
>  /* Capture samples in local storage */
>  static int press_capture_sample(struct hid_sensor_hub_device *hsdev,
> -				unsigned usage_id,
> +				u32 usage_id,
>  				size_t raw_len, char *raw_data,
>  				void *priv)
>  {

[Severity: High]
This is a pre-existing issue, but could this cause unaligned accesses or
out-of-bounds reads?

Looking at press_capture_sample(), raw_data is cast directly to a pointer
without using the unaligned access helpers:

	case HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE:
		press_state->scan.press_data = *(u32 *)raw_data;
		ret = 0;
		break;
	case HID_USAGE_SENSOR_TIME_TIMESTAMP:
		press_state->timestamp = hid_sensor_convert_timestamp(
			&press_state->common_attributes, *(s64 *)raw_data);

Since raw_data points into a HID report, it might not be aligned, which could
cause undefined behavior on strictly aligned architectures.

Additionally, we're unconditionally reading 4 or 8 bytes here without checking
raw_len. If the HID descriptor specifies a smaller field size, could this read
past the end of the valid data buffer?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260606-6-june-hid-iio-correct-usage-id-v1-0-dd4a6820b674@gmail.com?part=7

^ permalink raw reply

* Re: [PATCH] HID: usbhid: skip interrupt IN polling for devices with no input reports
From: Denis Benato @ 2026-06-06 12:42 UTC (permalink / raw)
  To: Antheas Kapenekakis, Ahmed Yaseen
  Cc: Jiri Kosina, Benjamin Tissoires, Ilpo Järvinen,
	Kerim Kabirov, GameBurrow, linux-usb, linux-input, linux-kernel
In-Reply-To: <CAGwozwFWbW=v2B7ruS4OUGuPhjSayw4Qxj3K+bCzwmgQu158Ng@mail.gmail.com>


On 6/5/26 14:02, Antheas Kapenekakis wrote:
> On Fri, 5 Jun 2026 at 13:40, Ahmed Yaseen <yaseen@ghoul.dev> wrote:
>> usbhid starts polling a device's interrupt IN endpoint on open
>> (usbhid_open() -> hid_start_in()). If the report descriptor declares no
>> input reports there is nothing to read there, so the poll is useless,
>> and on some composite devices it is also harmful.
> If it did have input reports, would starting the polling still cause
> issues? Because if it would, the issue is in the polling itself.
So far we haven't found an asus device that has more than one interface
that supports reading data out of if.
> Given the creativity of manufacturers when implementing hid protocols,
> I find it certain that they do use the in endpoint even without input
> reports. E.g., for feature reports. This could cause regressions.
While I mostly agree with this it is also true that the general direction
for the kernel (especially lately) has been to not do out-of-spec things
at least by default.

If things really regress it's expected to do so only an very few specific
devices with a buggy firmware, and we can think of something different
for those (hopefully very few ones).

Perhaps someone concerned with security might be interested in what
we have because it doesn't look very normal.

Note that below I have written a few ideas that maybe are worth
looking into.
>> The ASUS ROG N-Key keyboards expose a second, input-less interface used
>> only for RGB control via feature reports. Opening its hidraw node (any
>> hidraw reader does, including SDL/Steam Input or a plain cat) starts the
> cating a hidraw causing issues would be expected, so let's focus on the former.
Simply opening an hidraw should not trigger a delayed disconnect of that device,
I don't know why you would expect this to happen nor why you would
consider it acceptable. It's a bug.

Focusing on userspace software exposing the bug is not a realistic option
because over the time we found a good chunk of software doing that:
- logitech control software (forgot the name)
- open razer software
- sdl
- asusctl (obviously it opens the device albeit in the future I will change this)

and likely more given the fact not all software was identified. 
> Asusctl has a bug where if you add the quirk that separates the event
> nodes per hid, this bug is reproduced as well. I chucked it to
> complicated threading getting out of control. It is the reason we
> skipped that patch that was in my series.
I found and solved the bug already. Regardless the issue remains:
Even with no asusctl at all, if a user has one logitech mouse
(and its control software) and a razer keyboard (and its control software)
the asus N-Key device will start an endless disconnect-reconnect loop.

Any combination of two or more of those tools will trigger the issue
on some devices (weirdly enough not every model is affected):
this is not good.
> Now, you say SDL/Steam do a spurious read as well, can you identify
> the codepath so we can look into it? What devices are affected? The
> early return fixes a warning on the Z13, but it also feeds through the
> universal lamp interface on the new Xbox Allies. Is this a bug on
> those devices or keyboards? If yes, it could be caused by userspace
> hanging on that node
Sure, and I agree with you that fixing all userspace tools is desirable
but it's also unfeasible to fix them all, if we managed to do that
there will be years before everyone receives a fixed version of every
affected software and even then a core issue would remain:
linux tries to poll something it can't have anything out from.

I am much more oriented on the fact that kernel shouldn't
be doing weird things (at least not by default) so this has to
somehow be stopped regardless of how well userspace behaves.

If you have better ideas on how to fix the kernel we would
like to hear those as well.

Best regards,
Denis
> Antheas
>
>> pointless IN poll and keypress reports on the keyboard interface get
>> dropped for as long as the node stays open: a lost key-down drops a
>> letter, a lost key-up leaves the key stuck. usbmon shows the dropped
>> reports never reach the URB layer.
>>
>> The useless poll itself is long-standing; commit 4ac74ea68f64 ("HID:
>> asus: early return for ROG devices") is what exposes it on these
>> devices by keeping the input-less interface alive instead of ejecting
>> it, so its hidraw node can be opened and the poll started.
>>
>> Skip the poll in usbhid_open() when the device has no input reports.
>> Feature reports and hidraw output keep working over the control and OUT
>> endpoints, so the interface is otherwise unaffected.
I will write my review here to avoid forking the discussion:

I agree with the general idea but perhaps we can avoid
some hid devices to ever get HID_QUIRK_ALWAYS_POLL
and that might be enough to skip the problematic code?

Maybe there is value in doing this with a quirk flag in hid-asus.c
affecting the least amount of devices?

Or maybe just prevent devices with no data possibly coming out
to ever get HID_QUIRK_ALWAYS_POLL?

For how to best do this we will need to hear what Jiri and
Benjamin have to say but if they think the proposed solution
is the correct solution:

Reviewed-by: Denis Benato <denis.benato@linux.dev>
>> Fixes: 4ac74ea68f64 ("HID: asus: early return for ROG devices")
>> Tested-by: Kerim Kabirov <the.privat33r+linux@pm.me>
>> Tested-by: GameBurrow <gameburrow@pm.me>
>> Signed-off-by: Ahmed Yaseen <yaseen@ghoul.dev>
>> ---
>>  drivers/hid/usbhid/hid-core.c | 3 ++-
>>  1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
>> index 96b0181cf819..90a8b34d9305 100644
>> --- a/drivers/hid/usbhid/hid-core.c
>> +++ b/drivers/hid/usbhid/hid-core.c
>> @@ -688,7 +688,8 @@ static int usbhid_open(struct hid_device *hid)
>>
>>         set_bit(HID_OPENED, &usbhid->iofl);
>>
>> -       if (hid->quirks & HID_QUIRK_ALWAYS_POLL) {
>> +       if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) ||
>> +           list_empty(&hid->report_enum[HID_INPUT_REPORT].report_list)) {
>>                 res = 0;
>>                 goto Done;
>>         }
>> --
>> 2.54.0
>>
>>
>>

^ permalink raw reply

* Re: [PATCH] HID: usbhid: skip interrupt IN polling for devices with no input reports
From: Antheas Kapenekakis @ 2026-06-06 13:13 UTC (permalink / raw)
  To: Denis Benato
  Cc: Ahmed Yaseen, Jiri Kosina, Benjamin Tissoires, Ilpo Järvinen,
	Kerim Kabirov, GameBurrow, linux-usb, linux-input, linux-kernel
In-Reply-To: <ceb5ed4b-1654-463d-9cff-4a1b91d52e92@gmail.com>

On Sat, 6 Jun 2026 at 14:42, Denis Benato <benato.denis96@gmail.com> wrote:
>
>
> On 6/5/26 14:02, Antheas Kapenekakis wrote:
> > On Fri, 5 Jun 2026 at 13:40, Ahmed Yaseen <yaseen@ghoul.dev> wrote:
> >> usbhid starts polling a device's interrupt IN endpoint on open
> >> (usbhid_open() -> hid_start_in()). If the report descriptor declares no
> >> input reports there is nothing to read there, so the poll is useless,
> >> and on some composite devices it is also harmful.
> > If it did have input reports, would starting the polling still cause
> > issues? Because if it would, the issue is in the polling itself.
> So far we haven't found an asus device that has more than one interface
> that supports reading data out of if.
> > Given the creativity of manufacturers when implementing hid protocols,
> > I find it certain that they do use the in endpoint even without input
> > reports. E.g., for feature reports. This could cause regressions.
> While I mostly agree with this it is also true that the general direction
> for the kernel (especially lately) has been to not do out-of-spec things
> at least by default.
>
> If things really regress it's expected to do so only an very few specific
> devices with a buggy firmware, and we can think of something different
> for those (hopefully very few ones).
>
> Perhaps someone concerned with security might be interested in what
> we have because it doesn't look very normal.
>
> Note that below I have written a few ideas that maybe are worth

The degradation would be silent.

> looking into.
> >> The ASUS ROG N-Key keyboards expose a second, input-less interface used
> >> only for RGB control via feature reports. Opening its hidraw node (any
> >> hidraw reader does, including SDL/Steam Input or a plain cat) starts the
> > cating a hidraw causing issues would be expected, so let's focus on the former.

Try to add spaces before and after your responses

> Simply opening an hidraw should not trigger a delayed disconnect of that device,
> I don't know why you would expect this to happen nor why you would
> consider it acceptable. It's a bug.
>
> Focusing on userspace software exposing the bug is not a realistic option
> because over the time we found a good chunk of software doing that:
> - logitech control software (forgot the name)
> - open razer software
> - sdl
> - asusctl (obviously it opens the device albeit in the future I will change this)
>
> and likely more given the fact not all software was identified.
> > Asusctl has a bug where if you add the quirk that separates the event
> > nodes per hid, this bug is reproduced as well. I chucked it to
> > complicated threading getting out of control. It is the reason we
> > skipped that patch that was in my series.
> I found and solved the bug already. Regardless the issue remains:
> Even with no asusctl at all, if a user has one logitech mouse
> (and its control software) and a razer keyboard (and its control software)
> the asus N-Key device will start an endless disconnect-reconnect loop.
>
> Any combination of two or more of those tools will trigger the issue
> on some devices (weirdly enough not every model is affected):
>
> this is not good.
> > Now, you say SDL/Steam do a spurious read as well, can you identify
> > the codepath so we can look into it? What devices are affected? The
> > early return fixes a warning on the Z13, but it also feeds through the
> > universal lamp interface on the new Xbox Allies. Is this a bug on
> > those devices or keyboards? If yes, it could be caused by userspace
> > hanging on that node
> Sure, and I agree with you that fixing all userspace tools is desirable
> but it's also unfeasible to fix them all, if we managed to do that
> there will be years before everyone receives a fixed version of every
> affected software and even then a core issue would remain:
> linux tries to poll something it can't have anything out from.
>
> I am much more oriented on the fact that kernel shouldn't
> be doing weird things (at least not by default) so this has to
> somehow be stopped regardless of how well userspace behaves.

The kernel is not doing weird things and I also did not ask you to fix
all userspace software. I asked for a reproduction scenario, as it is
not covered in the patch description. Relooking at the patch today, I
also do not understand what it does fully.

It skips enabling input interrupts (but not only that) for devices
that have no input reports. So the kernel behavior will depend on the
feature descriptor moving forward.

And that fixes a hang on the affected devices because enabling
interrupts on an endpoint without periodic input reports blocks a
parallel endpoint that does have input reports?

I would like this fix to target the actual cause that causes the block
but it is not clear to me what that is or what is affected.

Antheas

> If you have better ideas on how to fix the kernel we would
> like to hear those as well.
>
> Best regards,
> Denis
> > Antheas
> >
> >> pointless IN poll and keypress reports on the keyboard interface get
> >> dropped for as long as the node stays open: a lost key-down drops a
> >> letter, a lost key-up leaves the key stuck. usbmon shows the dropped
> >> reports never reach the URB layer.
> >>
> >> The useless poll itself is long-standing; commit 4ac74ea68f64 ("HID:
> >> asus: early return for ROG devices") is what exposes it on these
> >> devices by keeping the input-less interface alive instead of ejecting
> >> it, so its hidraw node can be opened and the poll started.
> >>
> >> Skip the poll in usbhid_open() when the device has no input reports.
> >> Feature reports and hidraw output keep working over the control and OUT
> >> endpoints, so the interface is otherwise unaffected.
> I will write my review here to avoid forking the discussion:
>
> I agree with the general idea but perhaps we can avoid
> some hid devices to ever get HID_QUIRK_ALWAYS_POLL
> and that might be enough to skip the problematic code?
>
> Maybe there is value in doing this with a quirk flag in hid-asus.c
> affecting the least amount of devices?
>
> Or maybe just prevent devices with no data possibly coming out
> to ever get HID_QUIRK_ALWAYS_POLL?
>
> For how to best do this we will need to hear what Jiri and
> Benjamin have to say but if they think the proposed solution
> is the correct solution:
>
> Reviewed-by: Denis Benato <denis.benato@linux.dev>
> >> Fixes: 4ac74ea68f64 ("HID: asus: early return for ROG devices")
> >> Tested-by: Kerim Kabirov <the.privat33r+linux@pm.me>
> >> Tested-by: GameBurrow <gameburrow@pm.me>
> >> Signed-off-by: Ahmed Yaseen <yaseen@ghoul.dev>
> >> ---
> >>  drivers/hid/usbhid/hid-core.c | 3 ++-
> >>  1 file changed, 2 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
> >> index 96b0181cf819..90a8b34d9305 100644
> >> --- a/drivers/hid/usbhid/hid-core.c
> >> +++ b/drivers/hid/usbhid/hid-core.c
> >> @@ -688,7 +688,8 @@ static int usbhid_open(struct hid_device *hid)
> >>
> >>         set_bit(HID_OPENED, &usbhid->iofl);
> >>
> >> -       if (hid->quirks & HID_QUIRK_ALWAYS_POLL) {
> >> +       if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) ||
> >> +           list_empty(&hid->report_enum[HID_INPUT_REPORT].report_list)) {
> >>                 res = 0;
> >>                 goto Done;
> >>         }
> >> --
> >> 2.54.0
> >>
> >>
> >>
>


^ permalink raw reply

* [PATCH 0/8] Input: cap11xx - Add support for CAP1114
From: Jun Yan @ 2026-06-06 15:03 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: Jun Yan, linux-input, devicetree, linux-kernel

CAP1114 is a 14-channel capacitive touch sensor with 11 LED outputs
and hardware reset support.

PATCH 1~3 mainly focus on cleaning up the driver and dt-bindings.
PATCH 4~5 add reset-gpios support for CAP11xx.
PATCH 6~8 add support for CAP1114.

Jun Yan (8):
  Input: cap11xx - clean up duplicate log and add probe error logs
  Input: cap11xx - remove unused register macros
  dt-bindings: input: microchip,cap11xx: Cleanup and refine LED
    constraints
  dt-bindings: input: microchip,cap11xx: Add reset-gpios property
  Input: cap11xx - add reset gpio support
  Input: cap11xx - refactor code for better CAP1114 support.
  dt-bindings: input: microchip,cap11xx: Add CAP1114 support
  Input: cap11xx - add support for CAP1114

 .../bindings/input/microchip,cap11xx.yaml     |  93 ++++++--
 drivers/input/keyboard/cap11xx.c              | 223 +++++++++++-------
 2 files changed, 215 insertions(+), 101 deletions(-)

-- 
2.54.0


^ permalink raw reply

* [PATCH 1/8] Input: cap11xx - clean up duplicate log and add probe error logs
From: Jun Yan @ 2026-06-06 15:03 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: Jun Yan, linux-input, devicetree, linux-kernel
In-Reply-To: <20260606150458.250606-1-jerrysteve1101@gmail.com>

Duplicated device detection log exists at line 537 and line 542,
which brings redundant repeated kernel print messages. Drop one
redundant log entry to clean up dmesg output.

Meanwhile add missing error logs when I2C communication fails
during driver probe(), helping capture abnormal hardware access
for debug.

Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
---
 drivers/input/keyboard/cap11xx.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 2447c1ae2166..485d8ba97723 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -512,7 +512,7 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client)
 
 	error = regmap_read(priv->regmap, CAP11XX_REG_PRODUCT_ID, &val);
 	if (error)
-		return error;
+		return dev_err_probe(dev, error, "Failed to read product ID\n");
 
 	if (val != cap->product_id) {
 		dev_err(dev, "Product ID: Got 0x%02x, expected 0x%02x\n",
@@ -522,7 +522,7 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client)
 
 	error = regmap_read(priv->regmap, CAP11XX_REG_MANUFACTURER_ID, &val);
 	if (error)
-		return error;
+		return dev_err_probe(dev, error, "Failed to read manufacturer ID\n");
 
 	if (val != CAP11XX_MANUFACTURER_ID) {
 		dev_err(dev, "Manufacturer ID: Got 0x%02x, expected 0x%02x\n",
@@ -531,11 +531,8 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client)
 	}
 
 	error = regmap_read(priv->regmap, CAP11XX_REG_REVISION, &rev);
-	if (error < 0)
-		return error;
-
-	dev_info(dev, "CAP11XX detected, model %s, revision 0x%02x\n",
-			 id->name, rev);
+	if (error)
+		return dev_err_probe(dev, error, "Failed to read revision\n");
 
 	priv->model = cap;
 
-- 
2.54.0


^ permalink raw reply related

* [PATCH 2/8] Input: cap11xx - remove unused register macros
From: Jun Yan @ 2026-06-06 15:03 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: Jun Yan, linux-input, devicetree, linux-kernel
In-Reply-To: <20260606150458.250606-1-jerrysteve1101@gmail.com>

Remove unused register address macros and unused definitions in
the cap11xx_reg_defaults array and cap11xx_volatile_reg.

This cleanup reduces code clutter and makes the driver easier to
maintain without affecting functionality.

Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
---
 drivers/input/keyboard/cap11xx.c | 58 --------------------------------
 1 file changed, 58 deletions(-)

diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 485d8ba97723..686174722204 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -20,53 +20,23 @@
 #define CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT	(6)
 #define CAP11XX_REG_MAIN_CONTROL_GAIN_MASK	(0xc0)
 #define CAP11XX_REG_MAIN_CONTROL_DLSEEP		BIT(4)
-#define CAP11XX_REG_GENERAL_STATUS	0x02
 #define CAP11XX_REG_SENSOR_INPUT	0x03
-#define CAP11XX_REG_NOISE_FLAG_STATUS	0x0a
-#define CAP11XX_REG_SENOR_DELTA(X)	(0x10 + (X))
 #define CAP11XX_REG_SENSITIVITY_CONTROL	0x1f
 #define CAP11XX_REG_SENSITIVITY_CONTROL_DELTA_SENSE_MASK	0x70
-#define CAP11XX_REG_CONFIG		0x20
-#define CAP11XX_REG_SENSOR_ENABLE	0x21
-#define CAP11XX_REG_SENSOR_CONFIG	0x22
-#define CAP11XX_REG_SENSOR_CONFIG2	0x23
-#define CAP11XX_REG_SAMPLING_CONFIG	0x24
-#define CAP11XX_REG_CALIBRATION		0x26
-#define CAP11XX_REG_INT_ENABLE		0x27
 #define CAP11XX_REG_REPEAT_RATE		0x28
 #define CAP11XX_REG_SIGNAL_GUARD_ENABLE	0x29
-#define CAP11XX_REG_MT_CONFIG		0x2a
-#define CAP11XX_REG_MT_PATTERN_CONFIG	0x2b
-#define CAP11XX_REG_MT_PATTERN		0x2d
-#define CAP11XX_REG_RECALIB_CONFIG	0x2f
 #define CAP11XX_REG_SENSOR_THRESH(X)	(0x30 + (X))
-#define CAP11XX_REG_SENSOR_NOISE_THRESH	0x38
-#define CAP11XX_REG_STANDBY_CHANNEL	0x40
-#define CAP11XX_REG_STANDBY_CONFIG	0x41
-#define CAP11XX_REG_STANDBY_SENSITIVITY	0x42
-#define CAP11XX_REG_STANDBY_THRESH	0x43
 #define CAP11XX_REG_CONFIG2		0x44
 #define CAP11XX_REG_CONFIG2_ALT_POL	BIT(6)
-#define CAP11XX_REG_SENSOR_BASE_CNT(X)	(0x50 + (X))
-#define CAP11XX_REG_LED_POLARITY	0x73
 #define CAP11XX_REG_LED_OUTPUT_CONTROL	0x74
 #define CAP11XX_REG_CALIB_SENSITIVITY_CONFIG	0x80
 #define CAP11XX_REG_CALIB_SENSITIVITY_CONFIG2	0x81
-
-#define CAP11XX_REG_LED_DUTY_CYCLE_1	0x90
-#define CAP11XX_REG_LED_DUTY_CYCLE_2	0x91
-#define CAP11XX_REG_LED_DUTY_CYCLE_3	0x92
 #define CAP11XX_REG_LED_DUTY_CYCLE_4	0x93
 
-#define CAP11XX_REG_LED_DUTY_MIN_MASK	(0x0f)
-#define CAP11XX_REG_LED_DUTY_MIN_MASK_SHIFT	(0)
 #define CAP11XX_REG_LED_DUTY_MAX_MASK	(0xf0)
 #define CAP11XX_REG_LED_DUTY_MAX_MASK_SHIFT	(4)
 #define CAP11XX_REG_LED_DUTY_MAX_VALUE	(15)
 
-#define CAP11XX_REG_SENSOR_CALIB	(0xb1 + (X))
-#define CAP11XX_REG_SENSOR_CALIB_LSB1	0xb9
-#define CAP11XX_REG_SENSOR_CALIB_LSB2	0xba
 #define CAP11XX_REG_PRODUCT_ID		0xfd
 #define CAP11XX_REG_MANUFACTURER_ID	0xfe
 #define CAP11XX_REG_REVISION		0xff
@@ -111,37 +81,15 @@ struct cap11xx_hw_model {
 
 static const struct reg_default cap11xx_reg_defaults[] = {
 	{ CAP11XX_REG_MAIN_CONTROL,		0x00 },
-	{ CAP11XX_REG_GENERAL_STATUS,		0x00 },
-	{ CAP11XX_REG_SENSOR_INPUT,		0x00 },
-	{ CAP11XX_REG_NOISE_FLAG_STATUS,	0x00 },
 	{ CAP11XX_REG_SENSITIVITY_CONTROL,	0x2f },
-	{ CAP11XX_REG_CONFIG,			0x20 },
-	{ CAP11XX_REG_SENSOR_ENABLE,		0x3f },
-	{ CAP11XX_REG_SENSOR_CONFIG,		0xa4 },
-	{ CAP11XX_REG_SENSOR_CONFIG2,		0x07 },
-	{ CAP11XX_REG_SAMPLING_CONFIG,		0x39 },
-	{ CAP11XX_REG_CALIBRATION,		0x00 },
-	{ CAP11XX_REG_INT_ENABLE,		0x3f },
 	{ CAP11XX_REG_REPEAT_RATE,		0x3f },
-	{ CAP11XX_REG_MT_CONFIG,		0x80 },
-	{ CAP11XX_REG_MT_PATTERN_CONFIG,	0x00 },
-	{ CAP11XX_REG_MT_PATTERN,		0x3f },
-	{ CAP11XX_REG_RECALIB_CONFIG,		0x8a },
 	{ CAP11XX_REG_SENSOR_THRESH(0),		0x40 },
 	{ CAP11XX_REG_SENSOR_THRESH(1),		0x40 },
 	{ CAP11XX_REG_SENSOR_THRESH(2),		0x40 },
 	{ CAP11XX_REG_SENSOR_THRESH(3),		0x40 },
 	{ CAP11XX_REG_SENSOR_THRESH(4),		0x40 },
 	{ CAP11XX_REG_SENSOR_THRESH(5),		0x40 },
-	{ CAP11XX_REG_SENSOR_NOISE_THRESH,	0x01 },
-	{ CAP11XX_REG_STANDBY_CHANNEL,		0x00 },
-	{ CAP11XX_REG_STANDBY_CONFIG,		0x39 },
-	{ CAP11XX_REG_STANDBY_SENSITIVITY,	0x02 },
-	{ CAP11XX_REG_STANDBY_THRESH,		0x40 },
 	{ CAP11XX_REG_CONFIG2,			0x40 },
-	{ CAP11XX_REG_LED_POLARITY,		0x00 },
-	{ CAP11XX_REG_SENSOR_CALIB_LSB1,	0x00 },
-	{ CAP11XX_REG_SENSOR_CALIB_LSB2,	0x00 },
 };
 
 static bool cap11xx_volatile_reg(struct device *dev, unsigned int reg)
@@ -149,12 +97,6 @@ static bool cap11xx_volatile_reg(struct device *dev, unsigned int reg)
 	switch (reg) {
 	case CAP11XX_REG_MAIN_CONTROL:
 	case CAP11XX_REG_SENSOR_INPUT:
-	case CAP11XX_REG_SENOR_DELTA(0):
-	case CAP11XX_REG_SENOR_DELTA(1):
-	case CAP11XX_REG_SENOR_DELTA(2):
-	case CAP11XX_REG_SENOR_DELTA(3):
-	case CAP11XX_REG_SENOR_DELTA(4):
-	case CAP11XX_REG_SENOR_DELTA(5):
 		return true;
 	}
 
-- 
2.54.0


^ permalink raw reply related

* [PATCH 3/8] dt-bindings: input: microchip,cap11xx: Cleanup and refine LED constraints
From: Jun Yan @ 2026-06-06 15:03 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: Jun Yan, linux-input, devicetree, linux-kernel
In-Reply-To: <20260606150458.250606-1-jerrysteve1101@gmail.com>

Add detailed datasheet links for all supported CAP11xx devices.

Unify LED node pattern to support all chip variants in preparation
for CAP1114 support.

Remove redundant LED properties inherited from common.yaml

Apply per-chip LED channel limits:
- CAP1126: max 2 channels (0-1)
- CAP1188: max 8 channels (0-7)
- CAP1106, CAP12xx: no LED support

Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
---
 .../bindings/input/microchip,cap11xx.yaml     | 51 ++++++++++++++-----
 1 file changed, 37 insertions(+), 14 deletions(-)

diff --git a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml 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 capacitive
   touch controllers and LED drivers. The device communication via I2C only.
 
+  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>
 
@@ -124,25 +133,21 @@ properties:
       The number of entries must correspond to the number of channels.
 
 patternProperties:
-  "^led@[0-7]$":
+  "^led@[0-9a-f]$":
     type: object
     description: CAP11xx LEDs
     $ref: /schemas/leds/common.yaml#
 
     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
 
     required:
       - reg
 
-    additionalProperties: false
+    unevaluatedProperties: false
 
 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
 
   - if:
       properties:
@@ -183,6 +201,9 @@ additionalProperties: false
 
 examples:
   - |
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/leds/common.h>
+
     i2c {
       #address-cells = <1>;
       #size-cells = <0>;
@@ -208,19 +229,21 @@ examples:
         #size-cells = <0>;
 
         led@0 {
-                label = "cap11xx:green:usr0";
                 reg = <0>;
+                function = LED_FUNCTION_INDICATOR;
+                color = <LED_COLOR_ID_GREEN>;
         };
 
         led@1 {
-                label = "cap11xx:green:usr1";
                 reg = <1>;
+                function = LED_FUNCTION_INDICATOR;
+                color = <LED_COLOR_ID_GREEN>;
         };
 
         led@2 {
-                label = "cap11xx:green:alive";
                 reg = <2>;
-                linux,default-trigger = "heartbeat";
+                function = LED_FUNCTION_INDICATOR;
+                color = <LED_COLOR_ID_GREEN>;
         };
       };
     };
-- 
2.54.0


^ permalink raw reply related

* [PATCH 4/8] dt-bindings: input: microchip,cap11xx: Add reset-gpios property
From: Jun Yan @ 2026-06-06 15:03 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: Jun Yan, linux-input, devicetree, linux-kernel
In-Reply-To: <20260606150458.250606-1-jerrysteve1101@gmail.com>

Add support for the optional reset-gpios property to describe
the active-high reset pin for CAP1126/CAP1188 devices.
Driving the GPIO high asserts reset and deep sleep, while driving
it low releases reset for normal operation.

Restrict this property to be available only on CAP1126 and CAP1188
chips, as other CAP11xx variants do not have a hardware reset pin.

Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
---
 .../bindings/input/microchip,cap11xx.yaml     | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
index 99d00f572a2d..e307628350c2 100644
--- a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
+++ b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
@@ -49,6 +49,13 @@ properties:
       device's ALERT#/CM_IRQ# pin is connected to.
       The device only has one interrupt source.
 
+  reset-gpios:
+    description: |
+      GPIO connected to the active-high RESET pin of the chip;
+      driving it high asserts reset and deep sleep, while driving
+      it low releases reset for normal operation.
+    maxItems: 1
+
   autorepeat:
     description: |
       Enables the Linux input system's autorepeat feature on the input device.
@@ -151,6 +158,20 @@ patternProperties:
 
 allOf:
   - $ref: input.yaml
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - microchip,cap1106
+              - microchip,cap1203
+              - microchip,cap1206
+              - microchip,cap1293
+              - microchip,cap1298
+    then:
+      properties:
+        reset-gpios: false
+
   - if:
       properties:
         compatible:
@@ -225,6 +246,8 @@ examples:
                          <109>,	/* KEY_PAGEDOWN */
                          <104>;	/* KEY_PAGEUP */
 
+        reset-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
+
         #address-cells = <1>;
         #size-cells = <0>;
 
-- 
2.54.0


^ permalink raw reply related

* [PATCH 5/8] Input: cap11xx - add reset gpio support
From: Jun Yan @ 2026-06-06 15:03 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: Jun Yan, linux-input, devicetree, linux-kernel
In-Reply-To: <20260606150458.250606-1-jerrysteve1101@gmail.com>

Some CAP11xx devices (CAP1126/CAP1188) have a dedicated RESET pin.
Add hardware reset operation to improve device reliability and
ensure proper initialization on probe.

Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
---
 drivers/input/keyboard/cap11xx.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 686174722204..7015aa7654ce 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -43,6 +43,10 @@
 
 #define CAP11XX_MANUFACTURER_ID	0x5d
 
+#define CAP11XX_T_RST_FILT_MIN	10000
+#define CAP11XX_T_RST_ON_MIN	400000
+#define CAP11XX_T_RST_ON_MAX	500000
+
 #ifdef CONFIG_LEDS_CLASS
 struct cap11xx_led {
 	struct cap11xx_priv *priv;
@@ -55,6 +59,7 @@ struct cap11xx_priv {
 	struct regmap *regmap;
 	struct device *dev;
 	struct input_dev *idev;
+	struct gpio_desc *reset_gpio;
 	const struct cap11xx_hw_model *model;
 
 	struct cap11xx_led *leds;
@@ -452,6 +457,17 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client)
 	if (IS_ERR(priv->regmap))
 		return PTR_ERR(priv->regmap);
 
+	priv->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(priv->reset_gpio))
+		return dev_err_probe(dev, PTR_ERR(priv->reset_gpio),
+							"Failed to get 'reset' GPIO\n");
+	if (priv->reset_gpio) {
+		gpiod_set_value_cansleep(priv->reset_gpio, 1);
+		usleep_range(CAP11XX_T_RST_FILT_MIN, CAP11XX_T_RST_FILT_MIN * 2);
+		gpiod_set_value_cansleep(priv->reset_gpio, 0);
+		usleep_range(CAP11XX_T_RST_ON_MIN, CAP11XX_T_RST_ON_MAX);
+	}
+
 	error = regmap_read(priv->regmap, CAP11XX_REG_PRODUCT_ID, &val);
 	if (error)
 		return dev_err_probe(dev, error, "Failed to read product ID\n");
-- 
2.54.0


^ permalink raw reply related

* [PATCH 6/8] Input: cap11xx - refactor code for better CAP1114 support.
From: Jun Yan @ 2026-06-06 15:03 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: Jun Yan, linux-input, devicetree, linux-kernel
In-Reply-To: <20260606150458.250606-1-jerrysteve1101@gmail.com>

Extend cap11xx_hw_model structure to support CAP1114 with
different register offsets and hardware characteristics:

- led_output_control_reg_base: different address on CAP1114
- sensor_input_reg_base: different address on CAP1114
- num_sensor_thresholds: separate value from num_channels for CAP1114
- has_repeat_en: repeat enable support, disabled by default on CAP1114

Include linux/bits.h, update the register operations related to LEDs.

Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
---
 drivers/input/keyboard/cap11xx.c | 73 +++++++++++++++++++++++---------
 1 file changed, 53 insertions(+), 20 deletions(-)

diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 7015aa7654ce..408880cf6516 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -5,6 +5,7 @@
  * (c) 2014 Daniel Mack <linux@zonque.org>
  */
 
+#include <linux/bits.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -34,7 +35,6 @@
 #define CAP11XX_REG_LED_DUTY_CYCLE_4	0x93
 
 #define CAP11XX_REG_LED_DUTY_MAX_MASK	(0xf0)
-#define CAP11XX_REG_LED_DUTY_MAX_MASK_SHIFT	(4)
 #define CAP11XX_REG_LED_DUTY_MAX_VALUE	(15)
 
 #define CAP11XX_REG_PRODUCT_ID		0xfd
@@ -76,10 +76,14 @@ struct cap11xx_priv {
 
 struct cap11xx_hw_model {
 	u8 product_id;
+	u8 led_output_control_reg_base;
+	u8 sensor_input_reg_base;
 	unsigned int num_channels;
 	unsigned int num_leds;
+	unsigned int num_sensor_thresholds;
 	bool has_gain;
 	bool has_irq_config;
+	bool has_repeat_en;
 	bool has_sensitivity_control;
 	bool has_signal_guard;
 };
@@ -204,8 +208,8 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv)
 	}
 
 	if (!of_property_read_u32_array(node, "microchip,input-threshold",
-					priv->thresholds, priv->model->num_channels)) {
-		for (i = 0; i < priv->model->num_channels; i++) {
+					priv->thresholds, priv->model->num_sensor_thresholds)) {
+		for (i = 0; i < priv->model->num_sensor_thresholds; i++) {
 			if (priv->thresholds[i] > 127) {
 				dev_err(dev, "Invalid input-threshold value %u\n",
 					priv->thresholds[i]);
@@ -279,10 +283,12 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv)
 	of_property_read_u32_array(node, "linux,keycodes",
 				   priv->keycodes, priv->model->num_channels);
 
-	/* Disable autorepeat. The Linux input system has its own handling. */
-	error = regmap_write(priv->regmap, CAP11XX_REG_REPEAT_RATE, 0);
-	if (error)
-		return error;
+	if (priv->model->has_repeat_en) {
+		/* Disable autorepeat. The Linux input system has its own handling. */
+		error = regmap_write(priv->regmap, CAP11XX_REG_REPEAT_RATE, 0);
+		if (error)
+			return error;
+	}
 
 	return 0;
 }
@@ -301,7 +307,7 @@ static irqreturn_t cap11xx_thread_func(int irq_num, void *data)
 	if (ret < 0)
 		goto out;
 
-	ret = regmap_read(priv->regmap, CAP11XX_REG_SENSOR_INPUT, &status);
+	ret = regmap_read(priv->regmap, priv->model->sensor_input_reg_base, &status);
 	if (ret < 0)
 		goto out;
 
@@ -355,7 +361,7 @@ static int cap11xx_led_set(struct led_classdev *cdev,
 	 * 0 (OFF) and 1 (ON).
 	 */
 	return regmap_update_bits(priv->regmap,
-				  CAP11XX_REG_LED_OUTPUT_CONTROL,
+				  priv->model->led_output_control_reg_base,
 				  BIT(led->reg),
 				  value ? BIT(led->reg) : 0);
 }
@@ -367,6 +373,7 @@ static int cap11xx_init_leds(struct device *dev,
 	struct cap11xx_led *led;
 	int cnt = of_get_child_count(node);
 	int error;
+	u32 duty_val;
 
 	if (!num_leds || !cnt)
 		return 0;
@@ -380,15 +387,18 @@ static int cap11xx_init_leds(struct device *dev,
 
 	priv->leds = led;
 
+	/* Set all LEDs to off */
 	error = regmap_update_bits(priv->regmap,
-				CAP11XX_REG_LED_OUTPUT_CONTROL, 0xff, 0);
+					priv->model->led_output_control_reg_base,
+					GENMASK(num_leds - 1, 0), 0);
 	if (error)
 		return error;
 
+	duty_val = FIELD_PREP(CAP11XX_REG_LED_DUTY_MAX_MASK,
+			     CAP11XX_REG_LED_DUTY_MAX_VALUE);
+
 	error = regmap_update_bits(priv->regmap, CAP11XX_REG_LED_DUTY_CYCLE_4,
-				CAP11XX_REG_LED_DUTY_MAX_MASK,
-				CAP11XX_REG_LED_DUTY_MAX_VALUE <<
-				CAP11XX_REG_LED_DUTY_MAX_MASK_SHIFT);
+				CAP11XX_REG_LED_DUTY_MAX_MASK, duty_val);
 	if (error)
 		return error;
 
@@ -554,41 +564,64 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client)
 }
 
 static const struct cap11xx_hw_model cap1106_model = {
-	.product_id = 0x55, .num_channels = 6, .num_leds = 0,
+	.product_id = 0x55,
+	.sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
+	.num_channels = 6, .num_leds = 0, .num_sensor_thresholds = 6,
 	.has_gain = true,
 	.has_irq_config = true,
+	.has_repeat_en = true,
 };
 
 static const struct cap11xx_hw_model cap1126_model = {
-	.product_id = 0x53, .num_channels = 6, .num_leds = 2,
+	.product_id = 0x53,
+	.led_output_control_reg_base = CAP11XX_REG_LED_OUTPUT_CONTROL,
+	.sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
+	.num_channels = 6, .num_leds = 2, .num_sensor_thresholds = 6,
 	.has_gain = true,
 	.has_irq_config = true,
+	.has_repeat_en = true,
 };
 
 static const struct cap11xx_hw_model cap1188_model = {
-	.product_id = 0x50, .num_channels = 8, .num_leds = 8,
+	.product_id = 0x50,
+	.led_output_control_reg_base = CAP11XX_REG_LED_OUTPUT_CONTROL,
+	.sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
+	.num_channels = 8, .num_leds = 8, .num_sensor_thresholds = 8,
 	.has_gain = true,
 	.has_irq_config = true,
+	.has_repeat_en = true,
 };
 
 static const struct cap11xx_hw_model cap1203_model = {
-	.product_id = 0x6d, .num_channels = 3, .num_leds = 0,
+	.product_id = 0x6d,
+	.sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
+	.num_channels = 3, .num_leds = 0, .num_sensor_thresholds = 3,
+	.has_repeat_en = true,
 };
 
 static const struct cap11xx_hw_model cap1206_model = {
-	.product_id = 0x67, .num_channels = 6, .num_leds = 0,
+	.product_id = 0x67,
+	.sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
+	.num_channels = 6, .num_leds = 0, .num_sensor_thresholds = 6,
+	.has_repeat_en = true,
 };
 
 static const struct cap11xx_hw_model cap1293_model = {
-	.product_id = 0x6f, .num_channels = 3, .num_leds = 0,
+	.product_id = 0x6f,
+	.sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
+	.num_channels = 3, .num_leds = 0, .num_sensor_thresholds = 3,
 	.has_gain = true,
+	.has_repeat_en = true,
 	.has_sensitivity_control = true,
 	.has_signal_guard = true,
 };
 
 static const struct cap11xx_hw_model cap1298_model = {
-	.product_id = 0x71, .num_channels = 8, .num_leds = 0,
+	.product_id = 0x71,
+	.sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
+	.num_channels = 8, .num_leds = 0, .num_sensor_thresholds = 8,
 	.has_gain = true,
+	.has_repeat_en = true,
 	.has_sensitivity_control = true,
 	.has_signal_guard = true,
 };
-- 
2.54.0


^ permalink raw reply related

* [PATCH 7/8] dt-bindings: input: microchip,cap11xx: Add CAP1114 support
From: Jun Yan @ 2026-06-06 15:04 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: Jun Yan, linux-input, devicetree, linux-kernel
In-Reply-To: <20260606150458.250606-1-jerrysteve1101@gmail.com>

CAP1114 is a 14-channel capacitive touch sensor with 11 LED outputs
and hardware reset support.

Add the compatible string for CAP1114, include its datasheet URL,
and update the maximum count of LED channels and linux,keycodes entries.

Add description for microchip,input-threshold: CAP1114 only provides eight
threshold entries, which does not match its total channel count.

Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
---
 .../bindings/input/microchip,cap11xx.yaml     | 21 +++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml 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: |
 
   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:
 
   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.
 
   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
 
     required:
       - reg
@@ -199,6 +203,19 @@ allOf:
             reg:
               maximum: 1
 
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - microchip,cap1188
+    then:
+      patternProperties:
+        "^led@":
+          properties:
+            reg:
+              maximum: 7
+
   - if:
       properties:
         compatible:
-- 
2.54.0


^ permalink raw reply related

* [PATCH 8/8] Input: cap11xx - add support for CAP1114
From: Jun Yan @ 2026-06-06 15:04 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
  Cc: Jun Yan, linux-input, devicetree, linux-kernel
In-Reply-To: <20260606150458.250606-1-jerrysteve1101@gmail.com>

CAP1114 is a 14-channel capacitive touch sensor with 11 LED outputs
and hardware reset support.

The CAP1114 uses two separate control registers for LED output
management and requires two button status registers for touch input
state reporting.

By default, channels CS8~CS14 operate as a single grouped block.
Set the corresponding register enable bit to enable these channels as
independent touch inputs. Note these channels share the input threshold
of the eighth entry, causing num_sensor_thresholds to differ from
num_channels.

Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
---
 drivers/input/keyboard/cap11xx.c | 65 +++++++++++++++++++++++++++++++-
 1 file changed, 64 insertions(+), 1 deletion(-)

diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 408880cf6516..2aba3b508947 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -17,6 +17,12 @@
 #include <linux/gpio/consumer.h>
 #include <linux/bitfield.h>
 
+#define CAP1114_REG_BUTTON_STATUS1	0x03
+#define CAP1114_REG_BUTTON_STATUS2	0x04
+#define CAP1114_REG_CONFIG2			0x40
+#define CAP1114_REG_CONFIG2_VOL_UP_DOWN	BIT(1)
+#define CAP1114_REG_LED_OUTPUT_CONTROL1	0x73
+
 #define CAP11XX_REG_MAIN_CONTROL	0x00
 #define CAP11XX_REG_MAIN_CONTROL_GAIN_SHIFT	(6)
 #define CAP11XX_REG_MAIN_CONTROL_GAIN_MASK	(0xc0)
@@ -82,6 +88,7 @@ struct cap11xx_hw_model {
 	unsigned int num_leds;
 	unsigned int num_sensor_thresholds;
 	bool has_gain;
+	bool has_grouped_sensors;
 	bool has_irq_config;
 	bool has_repeat_en;
 	bool has_sensitivity_control;
@@ -98,6 +105,9 @@ static const struct reg_default cap11xx_reg_defaults[] = {
 	{ CAP11XX_REG_SENSOR_THRESH(3),		0x40 },
 	{ CAP11XX_REG_SENSOR_THRESH(4),		0x40 },
 	{ CAP11XX_REG_SENSOR_THRESH(5),		0x40 },
+	{ CAP11XX_REG_SENSOR_THRESH(6),		0x40 },
+	{ CAP11XX_REG_SENSOR_THRESH(7),		0x40 },
+	{ CAP11XX_REG_SENSOR_THRESH(8),		0x40 },
 	{ CAP11XX_REG_CONFIG2,			0x40 },
 };
 
@@ -106,6 +116,12 @@ static bool cap11xx_volatile_reg(struct device *dev, unsigned int reg)
 	switch (reg) {
 	case CAP11XX_REG_MAIN_CONTROL:
 	case CAP11XX_REG_SENSOR_INPUT:
+	/*
+	 * CAP1114_REG_BUTTON_STATUS1 (CAP11XX_REG_SENSOR_INPUT) and
+	 * CAP1114_REG_BUTTON_STATUS2 is volatile for the CAP1114,
+	 * which supports more than 8 touch channels.
+	 */
+	case CAP1114_REG_BUTTON_STATUS2:
 		return true;
 	}
 
@@ -283,6 +299,16 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv)
 	of_property_read_u32_array(node, "linux,keycodes",
 				   priv->keycodes, priv->model->num_channels);
 
+	/*
+	 * CAP1114 needs dedicated configuration to split grouped sensors into independent inputs.
+	 */
+	if (priv->model->has_grouped_sensors) {
+		error = regmap_set_bits(priv->regmap, CAP1114_REG_CONFIG2,
+					CAP1114_REG_CONFIG2_VOL_UP_DOWN);
+		if (error)
+			return error;
+	}
+
 	if (priv->model->has_repeat_en) {
 		/* Disable autorepeat. The Linux input system has its own handling. */
 		error = regmap_write(priv->regmap, CAP11XX_REG_REPEAT_RATE, 0);
@@ -311,6 +337,20 @@ static irqreturn_t cap11xx_thread_func(int irq_num, void *data)
 	if (ret < 0)
 		goto out;
 
+	if (priv->model->num_channels > 8) {
+		unsigned int status2;
+
+		ret = regmap_read(priv->regmap, priv->model->sensor_input_reg_base + 1, &status2);
+		if (ret < 0)
+			goto out;
+
+		/*
+		 * CAP1114 STATUS1 register only contains data for the first 6 channels.
+		 * the remaining channels is stored in STATUS2.
+		 */
+		status |= FIELD_PREP(GENMASK(13, 6), status2);
+	}
+
 	for (i = 0; i < priv->idev->keycodemax; i++)
 		input_report_key(priv->idev, priv->keycodes[i],
 				 status & (1 << i));
@@ -360,7 +400,13 @@ static int cap11xx_led_set(struct led_classdev *cdev,
 	 * limitation. Brightness levels per LED are either
 	 * 0 (OFF) and 1 (ON).
 	 */
-	return regmap_update_bits(priv->regmap,
+	if (led->reg >= 8)
+		return regmap_update_bits(priv->regmap,
+					priv->model->led_output_control_reg_base + 1,
+					BIT(led->reg - 8),
+					value ? BIT(led->reg - 8) : 0);
+	else
+		return regmap_update_bits(priv->regmap,
 				  priv->model->led_output_control_reg_base,
 				  BIT(led->reg),
 				  value ? BIT(led->reg) : 0);
@@ -393,6 +439,13 @@ static int cap11xx_init_leds(struct device *dev,
 					GENMASK(num_leds - 1, 0), 0);
 	if (error)
 		return error;
+	if (num_leds > 8) {
+		error = regmap_update_bits(priv->regmap,
+						priv->model->led_output_control_reg_base + 1,
+						GENMASK(num_leds - 8 - 1, 0), 0);
+		if (error)
+			return error;
+	}
 
 	duty_val = FIELD_PREP(CAP11XX_REG_LED_DUTY_MAX_MASK,
 			     CAP11XX_REG_LED_DUTY_MAX_VALUE);
@@ -572,6 +625,14 @@ static const struct cap11xx_hw_model cap1106_model = {
 	.has_repeat_en = true,
 };
 
+static const struct cap11xx_hw_model cap1114_model = {
+	.product_id = 0x3a,
+	.led_output_control_reg_base = CAP1114_REG_LED_OUTPUT_CONTROL1,
+	.sensor_input_reg_base = CAP1114_REG_BUTTON_STATUS1,
+	.num_channels = 14, .num_leds = 11, .num_sensor_thresholds = 8,
+	.has_grouped_sensors = true,
+};
+
 static const struct cap11xx_hw_model cap1126_model = {
 	.product_id = 0x53,
 	.led_output_control_reg_base = CAP11XX_REG_LED_OUTPUT_CONTROL,
@@ -628,6 +689,7 @@ static const struct cap11xx_hw_model cap1298_model = {
 
 static const struct of_device_id cap11xx_dt_ids[] = {
 	{ .compatible = "microchip,cap1106", .data = &cap1106_model },
+	{ .compatible = "microchip,cap1114", .data = &cap1114_model },
 	{ .compatible = "microchip,cap1126", .data = &cap1126_model },
 	{ .compatible = "microchip,cap1188", .data = &cap1188_model },
 	{ .compatible = "microchip,cap1203", .data = &cap1203_model },
@@ -640,6 +702,7 @@ MODULE_DEVICE_TABLE(of, cap11xx_dt_ids);
 
 static const struct i2c_device_id cap11xx_i2c_ids[] = {
 	{ .name = "cap1106", .driver_data = (kernel_ulong_t)&cap1106_model },
+	{ .name = "cap1114", .driver_data = (kernel_ulong_t)&cap1114_model },
 	{ .name = "cap1126", .driver_data = (kernel_ulong_t)&cap1126_model },
 	{ .name = "cap1188", .driver_data = (kernel_ulong_t)&cap1188_model },
 	{ .name = "cap1203", .driver_data = (kernel_ulong_t)&cap1203_model },
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH 5/8] Input: cap11xx - add reset gpio support
From: sashiko-bot @ 2026-06-06 15:13 UTC (permalink / raw)
  To: Jun Yan; +Cc: robh, dmitry.torokhov, conor+dt, devicetree, linux-input
In-Reply-To: <20260606150458.250606-6-jerrysteve1101@gmail.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Low] Inefficient delay using usleep_range() for a large duration (400-500ms).
- [Low] Missing explicit inclusion of <linux/delay.h>.
--

commit 83de47341df3454fdb8216dc0a95948c3f158a40
Author: Jun Yan <jerrysteve1101@gmail.com>

Input: cap11xx - add reset gpio support

This commit adds hardware reset support for CAP11xx devices by toggling a
dedicated reset GPIO during the i2c probe phase. It incorporates specific
timing requirements for the reset filter and active reset duration.

> diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
> index 686174722204c..7015aa7654ce7 100644
> --- a/drivers/input/keyboard/cap11xx.c
> +++ b/drivers/input/keyboard/cap11xx.c

[ ... ]

> @@ -452,6 +457,17 @@ static int cap11xx_i2c_probe(struct i2c_client *i2c_client)
>  	if (IS_ERR(priv->regmap))
>  		return PTR_ERR(priv->regmap);
>  
> +	priv->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> +	if (IS_ERR(priv->reset_gpio))
> +		return dev_err_probe(dev, PTR_ERR(priv->reset_gpio),
> +							"Failed to get 'reset' GPIO\n");
> +	if (priv->reset_gpio) {
> +		gpiod_set_value_cansleep(priv->reset_gpio, 1);
> +		usleep_range(CAP11XX_T_RST_FILT_MIN, CAP11XX_T_RST_FILT_MIN * 2);
> +		gpiod_set_value_cansleep(priv->reset_gpio, 0);
> +		usleep_range(CAP11XX_T_RST_ON_MIN, CAP11XX_T_RST_ON_MAX);

[Severity: Low]
Does this regression introduce unnecessary overhead by using usleep_range()
for a 400-500ms delay in cap11xx_i2c_probe()?

According to kernel timer guidelines, usleep_range() is designed for short
delays (10us to 20ms) and sets up high-resolution timers. For delays longer
than 20ms, using msleep() or fsleep() avoids unnecessary overhead and
expensive CPU wakeups.

[Severity: Low]
Could this regression in header dependencies be avoided by explicitly
including <linux/delay.h> since we are now calling usleep_range() here?

While the code might compile due to implicit inclusion via other headers,
relying on implicit includes can sometimes lead to build failures on other
architectures or if intermediate headers are refactored in the future.

> +	}
> +
>  	error = regmap_read(priv->regmap, CAP11XX_REG_PRODUCT_ID, &val);
>  	if (error)
>  		return dev_err_probe(dev, error, "Failed to read product ID\n");

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

^ permalink raw reply

* Re: [PATCH 7/8] dt-bindings: input: microchip,cap11xx: Add CAP1114 support
From: sashiko-bot @ 2026-06-06 15:16 UTC (permalink / raw)
  To: Jun Yan; +Cc: robh, dmitry.torokhov, devicetree, linux-input, conor+dt
In-Reply-To: <20260606150458.250606-8-jerrysteve1101@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The new `microchip,cap1114` compatible string was omitted from the `if-then` conditional block that restricts `microchip,signal-guard` and `microchip,calib-sensitivity` for prior CAP11xx generations.
--

commit 5c58a6baee363da7434a9782efa913c250015130
Author: Jun Yan <jerrysteve1101@gmail.com>

dt-bindings: input: microchip,cap11xx: Add CAP1114 support

This commit adds device tree binding support for the CAP1114 capacitive
touch sensor. It updates the compatible string list, maximum LED channel
counts, and keycode entries.

> diff --git a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
> index e307628350c24..08233386a4336 100644
> --- a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
> +++ b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
[ ... ]
> @@ -26,6 +27,7 @@ properties:
>    compatible:
>      enum:
>        - microchip,cap1106
> +      - microchip,cap1114
>        - microchip,cap1126
>        - microchip,cap1188
>        - microchip,cap1203

[Severity: Medium]
Since microchip,cap1114 is being added here, could this validation
regression be avoided by also appending it to the if-then conditional
block further down the schema that restricts microchip,signal-guard and
microchip,calib-sensitivity?

Documentation/devicetree/bindings/input/microchip,cap11xx.yaml:
  - if:
      properties:
        compatible:
          contains:
            enum:
              - microchip,cap1106
              - microchip,cap1126
              - microchip,cap1188
              - microchip,cap1203
              - microchip,cap1206
    then:
      properties:
        microchip,signal-guard: false
        microchip,calib-sensitivity: false

Since the maxItems for these properties remains at 8 (and CAP1114 has 14
channels), it appears CAP1114 does not support them either. Omitting the
new compatible string from this block allows device trees with these
unsupported properties to pass schema validation.

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

^ 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