* Re: [PATCH v4 02/10] Input: cap11xx - remove unused register macros
From: sashiko-bot @ 2026-06-17 20:21 UTC (permalink / raw)
To: Jun Yan; +Cc: linux-input, dmitry.torokhov, robh, devicetree, conor+dt
In-Reply-To: <20260617150318.753148-3-jerrysteve1101@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [Medium] The patch fails to remove unused definitions in `cap11xx_volatile_reg` despite the commit message claiming otherwise.
Pre-existing issues:
- [High] The threaded interrupt handler unconditionally returns IRQ_HANDLED even when I2C operations fail to clear the hardware interrupt source, risking an IRQ storm.
--
commit 8aa29f5d8b4eefa859454cdb0496fecf07ff5aa8
Author: Jun Yan <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.
> Remove unused register address macros and unused definitions in
> the cap11xx_reg_defaults array and cap11xx_volatile_reg.
[Severity: Medium]
Will this patch actually remove the unused definitions in
cap11xx_volatile_reg?
The commit message states they are removed, but the patch doesn't modify
that function.
> diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
> index 485d8ba97723..fae26f035186 100644
> --- a/drivers/input/keyboard/cap11xx.c
> +++ b/drivers/input/keyboard/cap11xx.c
> @@ -20,53 +20,24 @@
> #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))
[Severity: Medium]
Should this macro also have been removed?
Because cap11xx_volatile_reg() was not updated, this macro and its
corresponding case entries:
case CAP11XX_REG_SENOR_DELTA(0):
case CAP11XX_REG_SENOR_DELTA(1):
were left in the file.
[ ... ]
> static bool cap11xx_volatile_reg(struct device *dev, unsigned int reg)
[Severity: High]
This isn't a bug introduced by this patch, but could the error handling
in cap11xx_thread_func() risk an IRQ storm?
If an I2C communication error occurs during the interrupt handler:
cap11xx_thread_func() {
...
if (ret < 0)
goto out;
...
out:
return IRQ_HANDLED;
}
Because this uses IRQF_ONESHOT, returning IRQ_HANDLED instructs the IRQ
subsystem to unmask the interrupt. Since the device's interrupt status
was never cleared due to the I2C failure, the interrupt line will remain
asserted.
Will this cause the interrupt to immediately fire again when unmasked,
creating an infinite loop?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260617150318.753148-1-jerrysteve1101@gmail.com?part=2
^ permalink raw reply
* Re: [PATCH 2/9] iio: orientation: hid-sensor-incl-3d: Fix race between callback registration and device exposure
From: Pandruvada, Srinivas @ 2026-06-17 19:50 UTC (permalink / raw)
To: jic23@kernel.org, sanjayembeddedse@gmail.com
Cc: dlechner@baylibre.com, archana.patni@linux.intel.com,
hongyan.song@intel.com, linux-iio@vger.kernel.org,
nuno.sa@analog.com, linux-kernel@vger.kernel.org,
jikos@kernel.org, andy@kernel.org, linux-input@vger.kernel.org
In-Reply-To: <3FED088A-651B-4E8B-840B-1B92CB4DF6F4@gmail.com>
On Thu, 2026-06-18 at 00:07 +0530, Sanjay Chitroda wrote:
>
>
> On 15 June 2026 7:06:43 pm IST, "Pandruvada, Srinivas"
> <srinivas.pandruvada@intel.com> wrote:
> > On Sun, 2026-06-14 at 19:24 +0100, Jonathan Cameron wrote:
> > > On Mon, 8 Jun 2026 15:34:05 +0000
> > > "Pandruvada, Srinivas" <srinivas.pandruvada@intel.com> wrote:
> > >
> > > > On Sat, 2026-06-06 at 17:07 +0530, Sanjay Chitroda wrote:
> > > > > From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
> > > > >
> > > > > The driver registers the IIO device before completing sensor
> > > > > hub
> > > > > callback registration and unregisters callbacks while the IIO
> > > > > device
> > > > > is still exposed during teardown.
> > > > >
> > > > > This creates race windows in both probe and remove paths,
> > > > > which
> > > > > can
> > > > > lead to NULL pointer dereferences or use-after-free.
> > > >
> > > > Reordering is fine, but can you show how this use after free is
> > > > possible?
> > > Agreed - I'm not seeing a definite issue so more info needed.
> > > For now I'm going to mark this changes-requested in patchwork.
> > >
> > > It might be a touch slow if someone manages to get buffered
> > > capture
> > > up before the callbacks are available, but I think that just
> > > means
> > > dropping a few samples?
> >
> >
> > Correct.
> >
> > Thanks,
> > Srinivas
>
> Hi Jonathan and Srinivas,
>
Hi Sanjay,
> Thanks for the review and for pointing this out.
>
> After analyzing and investigating the interaction between callback
> registration and iio_device_register().
>
> Found that read_raw() (on-demand access) and buffered IIO (streaming)
> operate via different paths. The primary impact is loss/stable
> samples rather than data corruption or system instability.
>
> Given this, I believe the change does not strictly qualify as a "fix"
> for a user-visible regression, but rather as an improvement to
> tighten ordering and avoid a potential race window.
>
> Treating this as a improvement patch rather than a bug fix with
> potential following commit message in v2.
>
> .............
>
> iio: orientation: hid-sensor-incl-3d: Avoid race between callback
> setup and device exposure
>
> The driver currently exposes the IIO device to userspace before
> completing sensor hub callback registration, and similarly removes
> callbacks while the device can still be accessed during teardown.
>
> This creates a timing window where userspace may enable the buffer
> before callbacks are available. In such cases:
> - samples can be dropped,
> - buffered reads may observe stale or no data.
>
> Reorder probe and remove paths to ensure callbacks are active before
> device exposure and are removed after device is no longer accessible.
>
> This avoids a race window leading to data loss.
>
Looks good.
Thanks,
Srinivas
> .............
>
> Welcome your feedback and valuable input for v2.
>
> Thanks, Sanjay
>
> >
> > >
> > > Jonathan
> > >
> > > >
> > > > Thanks,
> > > > Srinivas
> > >
^ permalink raw reply
* Re: [PATCH 00/11] HID: iio: warning clean up and prefer kernel coding style
From: Sanjay Chitroda @ 2026-06-17 19:03 UTC (permalink / raw)
To: Maxwell Doose
Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Jiri Kosina, Srinivas Pandruvada, linux-iio, linux-kernel,
linux-input, Zhang Lixu
In-Reply-To: <CAKqfh0GEeyQ3UMuMupevgPfCon+zccAv302sV5YKCETWMua-xA@mail.gmail.com>
On 17 June 2026 1:00:37 pm IST, Maxwell Doose <m32285159@gmail.com> wrote:
>On Tue, Jun 16, 2026 at 5:26 AM Sanjay Chitroda
><sanjayembeddedse@gmail.com> wrote:
>>
>> Hi all,
>>
>> This series updates HID IIO drivers to resolve checkpatch and
>> kernel coding style issue.
>>
>> This improves readability and follow standard kernel coding style
>> No functional changes are introduced.
>>
>> Testing:
>> - Compiled with W=1 for each patch in the series
>>
>> ---
>> Sanjay Chitroda (11):
>> iio: hid-sensors: add missing blank line after declarations
>> iio: humidity: hid-sensor-humidity: align parenthesis for readability
>> iio: gyro: hid-sensor-gyro-3d: align parenthesis for readability
>> iio: magnetometer: hid-sensor-magn-3d: align parenthesis for readability
>> iio: humidity: hid-sensor-humidity: use common device for devres
>> iio: position: hid-sensor-custom-intel-hinge: use common device for devres
>> iio: temperature: hid-sensor-temperature: use common device for devres
>> iio: hid-sensor-magn-3d: use ! instead of explicit NULL check
>> iio: hid-sensor-rotation: use ! instead of explicit NULL check
>> iio: hid-sensor-incl-3d: use ! instead of explicit NULL check
>> iio: hid-sensor-accel-3d: use ! instead of explicit NULL check
>>
>> drivers/iio/accel/hid-sensor-accel-3d.c | 2 +-
>> .../iio/common/hid-sensors/hid-sensor-trigger.c | 3 +
>> drivers/iio/gyro/hid-sensor-gyro-3d.c | 58 ++++++++--------
>> drivers/iio/humidity/hid-sensor-humidity.c | 48 ++++++-------
>> drivers/iio/magnetometer/hid-sensor-magn-3d.c | 80 +++++++++++-----------
>> drivers/iio/orientation/hid-sensor-incl-3d.c | 2 +-
>> drivers/iio/orientation/hid-sensor-rotation.c | 2 +-
>> .../iio/position/hid-sensor-custom-intel-hinge.c | 2 +-
>> drivers/iio/temperature/hid-sensor-temperature.c | 4 +-
>> 9 files changed, 102 insertions(+), 99 deletions(-)
>
>Firstly, for all of the style patches (1-4, 8-11):
>
>Reviewed-by: Maxwell Doose <m32285159@gmail.com>
>
Hi Maxwell,
Thank you for the review.
>with Andy's comments.
>
>Secondly, the style fixes are all churn. It would honestly be much
>much better if you were to squash those (even despite the
>one-logical-change-per-patch rule).
I agree with squashing 1-4, common HID drivers-specific changes which cover all HID IIO drivers.
However, this series updates 4 HID drivers, while several other HID IIO drivers needs coding style cleanup.
I'd like to ask Jonathan for his opinion on whether all alignment coding style should be handled in single change, individual change or some logic specific HIO IIO drivers split.
Additionally, 5-7 haven't received any comment/tag. I can consider all changes in v2 and also rebase on latest iio/testing tree to incorporate u32 usage_id change.
Thanks, Sanjay
>
^ permalink raw reply
* Re: [PATCH 2/9] iio: orientation: hid-sensor-incl-3d: Fix race between callback registration and device exposure
From: Sanjay Chitroda @ 2026-06-17 18:37 UTC (permalink / raw)
To: Pandruvada, Srinivas, jic23@kernel.org
Cc: dlechner@baylibre.com, archana.patni@linux.intel.com,
hongyan.song@intel.com, linux-iio@vger.kernel.org,
nuno.sa@analog.com, linux-kernel@vger.kernel.org,
jikos@kernel.org, andy@kernel.org, linux-input@vger.kernel.org
In-Reply-To: <50ce20dec63080dde13336c6af41c0bf4de43426.camel@intel.com>
On 15 June 2026 7:06:43 pm IST, "Pandruvada, Srinivas" <srinivas.pandruvada@intel.com> wrote:
>On Sun, 2026-06-14 at 19:24 +0100, Jonathan Cameron wrote:
>> On Mon, 8 Jun 2026 15:34:05 +0000
>> "Pandruvada, Srinivas" <srinivas.pandruvada@intel.com> wrote:
>>
>> > On Sat, 2026-06-06 at 17:07 +0530, Sanjay Chitroda wrote:
>> > > From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
>> > >
>> > > The driver registers the IIO device before completing sensor hub
>> > > callback registration and unregisters callbacks while the IIO
>> > > device
>> > > is still exposed during teardown.
>> > >
>> > > This creates race windows in both probe and remove paths, which
>> > > can
>> > > lead to NULL pointer dereferences or use-after-free.
>> >
>> > Reordering is fine, but can you show how this use after free is
>> > possible?
>> Agreed - I'm not seeing a definite issue so more info needed.
>> For now I'm going to mark this changes-requested in patchwork.
>>
>> It might be a touch slow if someone manages to get buffered capture
>> up before the callbacks are available, but I think that just means
>> dropping a few samples?
>
>
>Correct.
>
>Thanks,
>Srinivas
Hi Jonathan and Srinivas,
Thanks for the review and for pointing this out.
After analyzing and investigating the interaction between callback registration and iio_device_register().
Found that read_raw() (on-demand access) and buffered IIO (streaming) operate via different paths. The primary impact is loss/stable samples rather than data corruption or system instability.
Given this, I believe the change does not strictly qualify as a "fix" for a user-visible regression, but rather as an improvement to tighten ordering and avoid a potential race window.
Treating this as a improvement patch rather than a bug fix with potential following commit message in v2.
.............
iio: orientation: hid-sensor-incl-3d: Avoid race between callback setup and device exposure
The driver currently exposes the IIO device to userspace before completing sensor hub callback registration, and similarly removes callbacks while the device can still be accessed during teardown.
This creates a timing window where userspace may enable the buffer before callbacks are available. In such cases:
- samples can be dropped,
- buffered reads may observe stale or no data.
Reorder probe and remove paths to ensure callbacks are active before device exposure and are removed after device is no longer accessible.
This avoids a race window leading to data loss.
.............
Welcome your feedback and valuable input for v2.
Thanks, Sanjay
>
>>
>> Jonathan
>>
>> >
>> > Thanks,
>> > Srinivas
>>
^ permalink raw reply
* Re: [PATCH v2] HID: wacom: avoid copying Bluetooth input reports
From: Jason Gerecke @ 2026-06-17 16:55 UTC (permalink / raw)
To: Ruoyu Wang
Cc: Ping Cheng, Jason Gerecke, Jiri Kosina, Benjamin Tissoires,
linux-input, linux-kernel
In-Reply-To: <20260617072035.3373487-1-ruoyuw560@gmail.com>
On Wed, Jun 17, 2026 at 12:21 AM Ruoyu Wang <ruoyuw560@gmail.com> wrote:
>
> wacom_intuos_bt_irq() duplicates the received Bluetooth report with
> kmemdup() so that it can pass 10-byte input report payloads to the
> common Intuos parser. The helper then copies each payload back into
> wacom->data before calling wacom_intuos_irq().
>
> Avoid the allocation and copy by temporarily pointing wacom->data at the
> current 10-byte payload while the common parser runs, then restoring the
> original report pointer. The Bluetooth report parser keeps using the
> original report buffer for dispatch and battery parsing, while the common
> parser sees the same payload bytes as before.
>
> This also removes the unchecked kmemdup() result from the Bluetooth IRQ
> path.
>
> Suggested-by: Jason Gerecke <jason.gerecke@wacom.com>
> Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
Thanks for the update! The sashiko warnings reveal an existing issue
with this function triggering unaligned memory accesses. I don't think
the warnings should block this particular patch, but instead remind us
that some kind of dedicated alignment cleanup patch would be a good
idea.
Reviewed-by: Jason Gerecke <jason.gerecke@wacom.com>
Jason (she/they)
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one /
(That is to say, eight) to the two, /
But you can’t take seven from three, /
So you look at the sixty-fours....
> ---
> Changes in v2:
> - Replace the kmemdup()/memcpy() path with temporary wacom->data pointer
> substitution, as suggested by Jason.
>
> drivers/hid/wacom_wac.c | 8 +++++---
> 1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
> index da1f0ea85625d..a29bf051ada7c 100644
> --- a/drivers/hid/wacom_wac.c
> +++ b/drivers/hid/wacom_wac.c
> @@ -1192,8 +1192,11 @@ static int int_dist(int x1, int y1, int x2, int y2)
> static void wacom_intuos_bt_process_data(struct wacom_wac *wacom,
> unsigned char *data)
> {
> - memcpy(wacom->data, data, 10);
> + u8 *saved_data = wacom->data;
> +
> + wacom->data = data;
> wacom_intuos_irq(wacom);
> + wacom->data = saved_data;
>
> input_sync(wacom->pen_input);
> if (wacom->pad_input)
> @@ -1202,7 +1205,7 @@ static void wacom_intuos_bt_process_data(struct wacom_wac *wacom,
>
> static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
> {
> - u8 *data = kmemdup(wacom->data, len, GFP_KERNEL);
> + u8 *data = wacom->data;
> int i = 1;
> unsigned power_raw, battery_capacity, bat_charging, ps_connected;
>
> @@ -1242,7 +1245,6 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len)
> break;
> }
>
> - kfree(data);
> return 0;
> }
>
> --
> 2.51.0
>
^ permalink raw reply
* Re: hid-lg-g15: possible use-after-free of devm data via work scheduled from a report
From: Hans de Goede @ 2026-06-17 16:24 UTC (permalink / raw)
To: Maoyi Xie, Jiri Kosina, Benjamin Tissoires; +Cc: linux-input, linux-kernel
In-Reply-To: <178169820506.2930960.12219303668828186338@maoyixie.com>
Hi,
On 17-Jun-26 14:10, Maoyi Xie wrote:
> Hi all,
>
> I think the lg-g15 driver can read freed memory on disconnect. I would
> appreciate it if you could check my reading before I send a patch.
>
> The per device state is allocated with devm in lg_g15_probe().
>
> g15 = devm_kzalloc(&hdev->dev, sizeof(*g15), GFP_KERNEL);
>
> That struct contains a work item, and the report handlers schedule it
> straight from device input. For example in lg_g15_event().
>
> /* Backlight cycle button pressed? */
> if (data[1] & 0x80)
> schedule_work(&g15->work);
>
> The same schedule_work(&g15->work) call also runs in lg_g15_v2_event() and
> lg_g510_leds_event(). The worker lg_g15_leds_changed_work() does a
> container_of() back to g15 and dereferences g15->mutex and g15->leds.
>
> The driver has a probe but no remove callback, and there is no
> cancel_work_sync() anywhere in the file. So if a report schedules the work
> and the keyboard is then removed, devm frees g15 while the work is still
> pending or running, and the worker touches the freed object.
>
> The attacker model is a Logitech G15 class keyboard that sends one report
> with the backlight cycle bit set and then disconnects. That can be a
> malicious device or an unlucky unplug.
>
> I reproduced the freed while pending pattern under KASAN on 7.1-rc7. The
> workqueue picked up the orphaned work after the object was freed, and KASAN
> reported a slab-use-after-free read.
>
> The fix I tried is a small remove callback that cancels the work before the
> devm teardown frees g15.
>
> static void lg_g15_remove(struct hid_device *hdev)
> {
> struct lg_g15_data *g15 = hid_get_drvdata(hdev);
>
> if (g15)
> cancel_work_sync(&g15->work);
>
> hid_hw_stop(hdev);
> }
>
> and wiring it up with .remove = lg_g15_remove. The g15 NULL guard mirrors the
> existing check in lg_g15_raw_event().
>
> Does this look like a real issue to you, and is the remove plus
> cancel_work_sync the approach you would want? If so I am happy to send a
> proper patch with a Fixes tag against 97b741aba918.
Thank you for reporting this. Yes this looks like a real issue (possible race
on device unplug).
As for your suggested solution, that looks good but g15->work is not always
initialized. For example in the g15->model == G13 case lg_g15_probe() does
not initialize it.
I don't think you should cancel an uninitialized work. Trying to queue it
will cause a WARN() backtrace to trigger, not sure if cancel also enforces
this.
So you should add a test for `g15->work.func != NULL` or just `g15->work.func`
before cancelling.
With that fixed, a proper patch fixing this would be much appreciated.
Regards,
Hans
^ permalink raw reply
* Re: [PATCH 0/4] HID: wacom: add report length validation in irq handlers
From: Jason Gerecke @ 2026-06-17 15:55 UTC (permalink / raw)
To: Jiri Kosina
Cc: Jinmo Yang, linux-input, benjamin.tissoires, linux-kernel, stable,
Ping Cheng, Jason Gerecke
In-Reply-To: <9o1psn77-q665-0rp6-pnnq-9179802p2nsp@xreary.bet>
On Wed, Jun 10, 2026 at 9:19 AM Jiri Kosina <jikos@kernel.org> wrote:
>
> On Sun, 17 May 2026, Jinmo Yang wrote:
>
> > Several wacom IRQ handler sub-functions access fixed offsets in the raw
> > HID report buffer without validating the buffer length. wacom_wac_irq()
> > receives the length from wacom_raw_event() but does not validate it
> > before dispatching to the sub-functions, which do not receive the length
> > parameter.
> >
> > A malicious USB device can declare a small HID report in its descriptor
> > and send a matching short report that passes the HID core size check
> > (csize >= rsize), but the driver assumes a full-size hardware report
> > layout, leading to slab-out-of-bounds reads.
> >
> > Note: this is not mitigated by the recent HID core bounds checking
> > series which validates actual_size >= declared_size. An attacker
> > controls both the descriptor (declared size) and the sent data (actual
> > size), so the core check passes. Driver-level validation against the
> > expected hardware report layout is still necessary.
> >
> > Tested with KASAN on Linux 7.1-rc3 (slab-out-of-bounds confirmed) and
> > verified kernel panic on a production device via uhid.
> >
> > Jinmo Yang (4):
> > HID: wacom: validate report length for PL and PTU handlers
> > HID: wacom: validate report length for DTU handler
> > HID: wacom: validate report length for DTUS handler
> > HID: wacom: validate report length for 24HDT and 27QHDT handlers
> >
Two main comments:
1) I would prefer each of these commits to pass 'len' as a value into
the sub-functions and perform the checks there. We already do this
with several of the sub-functions, and it would be good to be
consistent in where the checks are performed.
2) Please define new WACOM_PKGLEN_* values in drivers/hid/wacom_wac.h
and use these definitions rather than magic numbers. E.g. `#define
WACOM_PKGLEN_PL 8` to cover the PL case.
Jason (she/they)
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one /
(That is to say, eight) to the two, /
But you can’t take seven from three, /
So you look at the sixty-fours....
> > drivers/hid/wacom_wac.c | 15 +++++++++++++++
> > 1 file changed, 15 insertions(+)
>
> CCing Ping and Jason for their review. Thanks in advance,
>
> --
> Jiri Kosina
> SUSE Labs
>
>
^ permalink raw reply
* Re: [PATCH 0/3] HID: iio: callback API signature match for usage_id
From: Andy Shevchenko @ 2026-06-17 15:52 UTC (permalink / raw)
To: Sanjay Chitroda
Cc: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
Nuno Sá, Andy Shevchenko, linux-input, linux-iio,
linux-kernel
In-Reply-To: <20260616-16-jun-hid-iio-u32-api-type-v1-0-952c74195f46@gmail.com>
On Tue, Jun 16, 2026 at 06:55:19PM +0530, Sanjay Chitroda wrote:
>
> Most of HID IIO driver has correct 'u32' type of usage_id with
> https://lore.kernel.org/all/20260610-6-june-hid-iio-correct-usage-id-v2-0-c3c5f0720493@gmail.com/
> series which is applied on iio/testing branch.
>
> On top of the same, this series updates remaining HID IIO drivers
> to use 'u32' for the usage_id parameter.
>
> Pending list of HID IIO drivers are extracted with command line:
> find drivers/iio/ -type f -name "*hid*" | xargs grep -A 5 static | \
> grep -E -A 5 "_proc_event\(|_capture_sample\(|_parse_report\(" --color | \
> grep usage_id
I recommend to get used with `git grep ...` which is more powerful and much
faster (on a Git index).
git grep -lw 'u[^3].* usage_id' -- drivers/iio/
for the list of files, and
git grep -np -w 'u[^3].* usage_id' -- drivers/iio/
for a better view.
(It gives one false positive, though :-)
> This matches expected callback API type as HID usage IDs are
> defined as 32-bit values.
>
> No functional changes are introduced.
>
> Testing:
> - Compiled with W=1 for each patch in the series
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Jonathan, it seems the missing part of the initial unification. Please, apply
to your testing branch.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH v4 01/10] Input: cap11xx - clean up duplicate log and add probe error logs
From: Jun Yan @ 2026-06-17 15:02 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Jun Yan, linux-input, devicetree, linux-kernel
In-Reply-To: <20260617150318.753148-1-jerrysteve1101@gmail.com>
Duplicated device detection log exists at line 537 and line 542,
which brings redundant 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 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 v4 10/10] Input: cap11xx - add support for CAP1114
From: Jun Yan @ 2026-06-17 15:02 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Jun Yan, linux-input, devicetree, linux-kernel
In-Reply-To: <20260617150318.753148-1-jerrysteve1101@gmail.com>
CAP1114 is a 14-channel capacitive touch sensor with 11 LED outputs
and hardware reset support.
The CAP1114 uses two 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 | 73 ++++++++++++++++++++++++++++++--
1 file changed, 69 insertions(+), 4 deletions(-)
diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 275eb79a7193..865c58533eb9 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -18,6 +18,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)
@@ -83,6 +89,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;
@@ -99,6 +106,8 @@ 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_CONFIG2, 0x40 },
};
@@ -107,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:
case CAP11XX_REG_SENOR_DELTA(0):
case CAP11XX_REG_SENOR_DELTA(1):
case CAP11XX_REG_SENOR_DELTA(2):
@@ -292,6 +307,17 @@ 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);
@@ -320,6 +346,21 @@ 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 &= GENMASK(5, 0);
+ 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));
@@ -369,10 +410,16 @@ 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,
- priv->model->led_output_control_reg_base,
- BIT(led->reg),
- value ? BIT(led->reg) : 0);
+ 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);
}
static int cap11xx_init_leds(struct device *dev,
@@ -403,6 +450,14 @@ static int cap11xx_init_leds(struct device *dev,
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);
@@ -581,6 +636,14 @@ static const struct cap11xx_hw_model cap1106_model = {
.has_repeat_en = true,
};
+static const struct cap11xx_hw_model cap1114_model = {
+ .product_id = 0x3a,
+ .num_channels = 14, .num_leds = 11, .num_sensor_thresholds = 8,
+ .led_output_control_reg_base = CAP1114_REG_LED_OUTPUT_CONTROL1,
+ .sensor_input_reg_base = CAP1114_REG_BUTTON_STATUS1,
+ .has_grouped_sensors = true,
+};
+
static const struct cap11xx_hw_model cap1126_model = {
.product_id = 0x53,
.num_channels = 6, .num_leds = 2, .num_sensor_thresholds = 6,
@@ -637,6 +700,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 },
@@ -649,6 +713,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
* [PATCH v4 09/10] dt-bindings: input: microchip,cap11xx: Add CAP1114 support
From: Jun Yan @ 2026-06-17 15:02 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Jun Yan, Conor Dooley, linux-input, devicetree, linux-kernel
In-Reply-To: <20260617150318.753148-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, add its datasheet URL,
update the maximum of LED channel reg, and add constraint for
linux,keycodes.
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.
Update description for microchip,input-threshold: CAP1114 only provides
eight threshold entries, which does not match its total channel count.
CAP1114 does not support microchip,signal-guard and
microchip,calib-sensitivity.
Add CAP1114 to the unsupported enum list.
Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
---
.../bindings/input/microchip,cap11xx.yaml | 39 +++++++++++++++++--
1 file changed, 36 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
index b97e5b2735f1..2a37ac252c37 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
@@ -140,7 +144,7 @@ properties:
The number of entries must correspond to the number of channels.
patternProperties:
- "^led@[0-7]$":
+ "^led@[0-9a]$":
type: object
description: CAP11xx LEDs
$ref: /schemas/leds/common.yaml#
@@ -149,7 +153,7 @@ patternProperties:
reg:
description: LED channel number
minimum: 0
- maximum: 7
+ maximum: 10
label: true
@@ -178,6 +182,21 @@ allOf:
properties:
reset-gpios: false
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - microchip,cap1114
+ then:
+ properties:
+ linux,keycodes:
+ minItems: 14
+ else:
+ properties:
+ linux,keycodes:
+ maxItems: 8
+
- if:
properties:
compatible:
@@ -205,12 +224,26 @@ allOf:
reg:
maximum: 1
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - microchip,cap1188
+ then:
+ patternProperties:
+ "^led@":
+ properties:
+ reg:
+ maximum: 7
+
- if:
properties:
compatible:
contains:
enum:
- microchip,cap1106
+ - microchip,cap1114
- microchip,cap1126
- microchip,cap1188
- microchip,cap1203
--
2.54.0
^ permalink raw reply related
* [PATCH v4 08/10] Input: cap11xx - guard unsupported DT properties before parsing
From: Jun Yan @ 2026-06-17 15:02 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Jun Yan, linux-input, devicetree, linux-kernel
In-Reply-To: <20260617150318.753148-1-jerrysteve1101@gmail.com>
Check of_property_present() before parsing microchip,calib-sensitivity
and microchip,signal-guard, so that models which do not support these
properties (e.g. CAP1114) skip the parsing entirely.
This prevents a potential buffer overflow in calib_sensitivities[8] and
signal_guard_inputs_mask when a model with more than 8 channels
(CAP1114 has 14) would otherwise call of_property_read_u32_array()
with num_channels as the element count.
Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
---
drivers/input/keyboard/cap11xx.c | 52 +++++++++++++++++---------------
1 file changed, 27 insertions(+), 25 deletions(-)
diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 0f19ee036e78..275eb79a7193 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -231,10 +231,13 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv)
}
}
- if (!of_property_read_u32_array(node, "microchip,calib-sensitivity",
- priv->calib_sensitivities,
- priv->model->num_channels)) {
- if (priv->model->has_sensitivity_control) {
+ if (of_property_present(node, "microchip,calib-sensitivity")) {
+ if (!priv->model->has_sensitivity_control) {
+ dev_warn(dev,
+ "This model doesn't support 'calib-sensitivity'\n");
+ } else if (!of_property_read_u32_array(node, "microchip,calib-sensitivity",
+ priv->calib_sensitivities,
+ priv->model->num_channels)) {
for (i = 0; i < priv->model->num_channels; i++) {
if (!is_power_of_2(priv->calib_sensitivities[i]) ||
priv->calib_sensitivities[i] > 4) {
@@ -254,32 +257,31 @@ static int cap11xx_init_keys(struct cap11xx_priv *priv)
if (error)
return error;
}
- } else {
- dev_warn(dev,
- "This model doesn't support 'calib-sensitivity'\n");
}
}
- for (i = 0; i < priv->model->num_channels; i++) {
- if (!of_property_read_u32_index(node, "microchip,signal-guard",
- i, &u32_val)) {
- if (u32_val > 1)
- return -EINVAL;
- if (u32_val)
- priv->signal_guard_inputs_mask |= 0x01 << i;
- }
- }
-
- if (priv->signal_guard_inputs_mask) {
- if (priv->model->has_signal_guard) {
- error = regmap_write(priv->regmap,
- CAP11XX_REG_SIGNAL_GUARD_ENABLE,
- priv->signal_guard_inputs_mask);
- if (error)
- return error;
- } else {
+ if (of_property_present(node, "microchip,signal-guard")) {
+ if (!priv->model->has_signal_guard) {
dev_warn(dev,
"This model doesn't support 'signal-guard'\n");
+ } else {
+ for (i = 0; i < priv->model->num_channels; i++) {
+ if (!of_property_read_u32_index(node, "microchip,signal-guard",
+ i, &u32_val)) {
+ if (u32_val > 1)
+ return -EINVAL;
+ if (u32_val)
+ priv->signal_guard_inputs_mask |= 0x01 << i;
+ }
+ }
+
+ if (priv->signal_guard_inputs_mask) {
+ error = regmap_write(priv->regmap,
+ CAP11XX_REG_SIGNAL_GUARD_ENABLE,
+ priv->signal_guard_inputs_mask);
+ if (error)
+ return error;
+ }
}
}
--
2.54.0
^ permalink raw reply related
* [PATCH v4 07/10] Input: cap11xx - refactor code for better CAP1114 support.
From: Jun Yan @ 2026-06-17 15:02 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Jun Yan, linux-input, devicetree, linux-kernel
In-Reply-To: <20260617150318.753148-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 1db4a9090705..0f19ee036e78 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/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -36,7 +37,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
@@ -77,10 +77,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;
};
@@ -211,8 +215,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]);
@@ -286,10 +290,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;
}
@@ -308,7 +314,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;
@@ -362,7 +368,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);
}
@@ -374,6 +380,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;
@@ -387,15 +394,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(min(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);
+
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;
@@ -561,41 +571,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,
+ .num_channels = 6, .num_leds = 0, .num_sensor_thresholds = 6,
+ .sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
.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,
+ .num_channels = 6, .num_leds = 2, .num_sensor_thresholds = 6,
+ .led_output_control_reg_base = CAP11XX_REG_LED_OUTPUT_CONTROL,
+ .sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
.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,
+ .num_channels = 8, .num_leds = 8, .num_sensor_thresholds = 8,
+ .led_output_control_reg_base = CAP11XX_REG_LED_OUTPUT_CONTROL,
+ .sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
.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,
+ .num_channels = 3, .num_leds = 0, .num_sensor_thresholds = 3,
+ .sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
+ .has_repeat_en = true,
};
static const struct cap11xx_hw_model cap1206_model = {
- .product_id = 0x67, .num_channels = 6, .num_leds = 0,
+ .product_id = 0x67,
+ .num_channels = 6, .num_leds = 0, .num_sensor_thresholds = 6,
+ .sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
+ .has_repeat_en = true,
};
static const struct cap11xx_hw_model cap1293_model = {
- .product_id = 0x6f, .num_channels = 3, .num_leds = 0,
+ .product_id = 0x6f,
+ .num_channels = 3, .num_leds = 0, .num_sensor_thresholds = 3,
+ .sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
.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,
+ .num_channels = 8, .num_leds = 0, .num_sensor_thresholds = 8,
+ .sensor_input_reg_base = CAP11XX_REG_SENSOR_INPUT,
.has_gain = true,
+ .has_repeat_en = true,
.has_sensitivity_control = true,
.has_signal_guard = true,
};
--
2.54.0
^ permalink raw reply related
* [PATCH v4 06/10] Input: cap11xx - add reset gpio support
From: Jun Yan @ 2026-06-17 15:02 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Jun Yan, linux-input, devicetree, linux-kernel
In-Reply-To: <20260617150318.753148-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 fae26f035186..1db4a9090705 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/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
@@ -44,6 +45,9 @@
#define CAP11XX_MANUFACTURER_ID 0x5d
+#define CAP11XX_T_RST_FILT_MIN_US 10000
+#define CAP11XX_T_RST_ON_MIN_MS 400
+
#ifdef CONFIG_LEDS_CLASS
struct cap11xx_led {
struct cap11xx_priv *priv;
@@ -56,6 +60,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;
@@ -459,6 +464,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_HIGH);
+ 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) {
+ usleep_range(CAP11XX_T_RST_FILT_MIN_US, CAP11XX_T_RST_FILT_MIN_US * 2);
+ gpiod_set_value_cansleep(priv->reset_gpio, 0);
+ msleep(CAP11XX_T_RST_ON_MIN_MS);
+ }
+
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 v4 05/10] dt-bindings: input: microchip,cap11xx: Add reset-gpios property
From: Jun Yan @ 2026-06-17 15:02 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Jun Yan, Conor Dooley, linux-input, devicetree, linux-kernel
In-Reply-To: <20260617150318.753148-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>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../bindings/input/microchip,cap11xx.yaml | 25 +++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
index 798035e942af..b97e5b2735f1 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.
@@ -157,6 +164,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:
@@ -207,6 +228,8 @@ additionalProperties: false
examples:
- |
+ #include <dt-bindings/gpio/gpio.h>
+
i2c {
#address-cells = <1>;
#size-cells = <0>;
@@ -228,6 +251,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 v4 04/10] dt-bindings: input: microchip,cap11xx: Add microchip,cap1126 LED reg constraints
From: Jun Yan @ 2026-06-17 15:02 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Jun Yan, Conor Dooley, linux-input, devicetree, linux-kernel
In-Reply-To: <20260617150318.753148-1-jerrysteve1101@gmail.com>
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>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../bindings/input/microchip,cap11xx.yaml | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
index eabf06a1163e..798035e942af 100644
--- a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
+++ b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
@@ -171,6 +171,19 @@ allOf:
patternProperties:
"^led@": false
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - microchip,cap1126
+ then:
+ patternProperties:
+ "^led@":
+ properties:
+ reg:
+ maximum: 1
+
- if:
properties:
compatible:
--
2.54.0
^ permalink raw reply related
* [PATCH v4 03/10] dt-bindings: input: microchip,cap11xx: Update datasheet URL and LED reg range
From: Jun Yan @ 2026-06-17 15:02 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Jun Yan, Conor Dooley, linux-input, devicetree, linux-kernel
In-Reply-To: <20260617150318.753148-1-jerrysteve1101@gmail.com>
- Add datasheet links for all supported CAP11xx variants.
- Update LED node regex and replace enum constraints with minimum/maximum
for LED reg ranges in preparation for CAP1114 support.
CAP1114 has 11 LED channels. minimum/maximum constraints are easier to
maintain than long enum lists when expanding channel count later.
Drop unnecessary led unit-address pattern.
Signed-off-by: Jun Yan <jerrysteve1101@gmail.com>
Acked-by: Conor Dooley <conor.dooley@microchip.com>
---
.../bindings/input/microchip,cap11xx.yaml | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml b/Documentation/devicetree/bindings/input/microchip,cap11xx.yaml
index 7ade03f1b32b..eabf06a1163e 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>
@@ -131,7 +140,9 @@ patternProperties:
properties:
reg:
- enum: [0, 1, 2, 3, 4, 5, 6, 7]
+ description: LED channel number
+ minimum: 0
+ maximum: 7
label: true
@@ -158,7 +169,7 @@ allOf:
- microchip,cap1298
then:
patternProperties:
- "^led@[0-7]$": false
+ "^led@": false
- if:
properties:
--
2.54.0
^ permalink raw reply related
* [PATCH v4 02/10] Input: cap11xx - remove unused register macros
From: Jun Yan @ 2026-06-17 15:02 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Jun Yan, linux-input, devicetree, linux-kernel
In-Reply-To: <20260617150318.753148-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 | 51 --------------------------------
1 file changed, 51 deletions(-)
diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 485d8ba97723..fae26f035186 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -20,53 +20,24 @@
#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 +82,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)
--
2.54.0
^ permalink raw reply related
* [PATCH v4 00/10] Input: cap11xx - Add support for CAP1114
From: Jun Yan @ 2026-06-17 15:02 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.
Patches 1-4 perform driver cleanup and DT binding tweaks.
Patches 5-6 add reset-gpios support for CAP11xx.
Patches 7-10 add support for CAP1114.
Changes in v4:
- Revert cleanup operation for CAP11XX_REG_SENSOR_DELTA.
- Move the LED unit-address update operation to the CAP1114 support patch.
- Limit the CAP1114 LED unit-address range from 0x0 to 0xa.
- Link to v3:
https://lore.kernel.org/all/20260615142103.352163-1-jerrysteve1101@gmail.com/
Changes in v3:
- Simplified the logic of the reset pin operation.
- Adjust linux,keycodes configuration for CAP11xx.
- Drop unnecessary CAP11XX_REG_SENSOR_THRESH(8).
- Checks for the presence of microchip,calib-sensitivity and
microchip,signal-guard properties before processing them.
- Link to v2:
https://lore.kernel.org/all/20260612072237.1177304-1-jerrysteve1101@gmail.com/
Changes in v2:
- Drop LED property tweaks, keep only reg changes and node regex
update in DT bindings.
- Split microchip,cap1126 LED reg constraints into a separate patch.
- Replace usleep_range() with msleep() for 500 ms delay during
reset pin handling.
- Add missing <linux/delay.h> for usleep_range() and msleep().
- Add CAP1114 to unsupported enum for microchip,signal-guard and
microchip,calib-sensitivity
- Add constraint for linux,keycodes to support CAP1114.
- When reading CAP1114 button status, mask STATUS1 to bits 0-5
and OR with STATUS2.
- Adjust code style.
- Link to v1:
https://lore.kernel.org/all/20260606150458.250606-1-jerrysteve1101@gmail.com
Jun Yan (10):
Input: cap11xx - clean up duplicate log and add probe error logs
Input: cap11xx - remove unused register macros
dt-bindings: input: microchip,cap11xx: Update datasheet URL and LED
reg range
dt-bindings: input: microchip,cap11xx: Add microchip,cap1126 LED reg
constraints
dt-bindings: input: microchip,cap11xx: Add reset-gpios property
Input: cap11xx - add reset gpio support
Input: cap11xx - refactor code for better CAP1114 support.
Input: cap11xx - guard unsupported DT properties before parsing
dt-bindings: input: microchip,cap11xx: Add CAP1114 support
Input: cap11xx - add support for CAP1114
.../bindings/input/microchip,cap11xx.yaml | 90 +++++-
drivers/input/keyboard/cap11xx.c | 274 +++++++++++-------
2 files changed, 254 insertions(+), 110 deletions(-)
--
2.54.0
^ permalink raw reply
* Re: [PATCH v4 4/5] HID: asus: add support for xgm led
From: Antheas Kapenekakis @ 2026-06-17 13:45 UTC (permalink / raw)
To: Denis Benato
Cc: linux-kernel, linux-input, Benjamin Tissoires, Jiri Kosina,
Luke D . Jones, Mateusz Schyboll, Denis Benato, Connor Belli
In-Reply-To: <5006ff55-846e-4812-bc89-b270fbef6ccc@linux.dev>
On Wed, 17 Jun 2026 at 02:18, Denis Benato <denis.benato@linux.dev> wrote:
>
>
> On 6/15/26 23:55, Antheas Kapenekakis wrote:
> > On Mon, 15 Jun 2026 at 18:51, Denis Benato <denis.benato@linux.dev> wrote:
> >> XG mobile stations have very bright leds behind the fan that can be
> >> turned either ON or OFF: add a cled interface to allow controlling the
> >> brightness of those red leds.
> >>
> >> Signed-off-by: Denis Benato <denis.benato@linux.dev>
> >> ---
> >> drivers/hid/hid-asus.c | 91 ++++++++++++++++++++++++++++++++++++++++++
> >> 1 file changed, 91 insertions(+)
> >>
> >> diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
> >> index 6896730efafc..e68a6d93369d 100644
> >> --- a/drivers/hid/hid-asus.c
> >> +++ b/drivers/hid/hid-asus.c
> >> @@ -51,6 +51,8 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
> >> #define FEATURE_KBD_LED_REPORT_ID1 0x5d
> >> #define FEATURE_KBD_LED_REPORT_ID2 0x5e
> >>
> >> +#define ROG_XGM_REPORT_SIZE 300
> >> +
> >> #define ROG_ALLY_REPORT_SIZE 64
> >> #define ROG_ALLY_X_MIN_MCU 313
> >> #define ROG_ALLY_MIN_MCU 319
> >> @@ -143,6 +145,11 @@ struct asus_worker {
> >> bool removed;
> >> };
> >>
> >> +struct asus_xgm_led {
> >> + struct led_classdev cdev;
> >> + struct hid_device *hdev;
> >> +};
> >> +
> >> struct asus_touchpad_info {
> >> int max_x;
> >> int max_y;
> >> @@ -169,6 +176,7 @@ struct asus_drvdata {
> >> unsigned long battery_next_query;
> >> struct asus_hid_listener listener;
> >> bool fn_lock;
> >> + struct asus_xgm_led *xgm_led;
> >> };
> >>
> >> static int asus_report_battery(struct asus_drvdata *, u8 *, int);
> >> @@ -1119,6 +1127,26 @@ static int asus_battery_probe(struct hid_device *hdev)
> >> return ret;
> >> }
> >>
> >> +static int asus_xgm_led_set(struct led_classdev *led_cdev, enum led_brightness value)
> >> +{
> >> + const u8 buf[ROG_XGM_REPORT_SIZE] = {
> >> + FEATURE_KBD_LED_REPORT_ID2, 0xC5, (value) ? 0x50 : 0x00
> >> + };
> >> + struct asus_xgm_led *xgm = container_of(led_cdev, struct asus_xgm_led, cdev);
> >> + int ret;
> >> +
> >> + ret = asus_kbd_set_report(xgm->hdev, buf, ROG_XGM_REPORT_SIZE);
> >> + if (ret < 0) {
> >> + hid_err(xgm->hdev, "Unable to set XG mobile led state: %d\n", ret);
> >> + return ret;
> >> + } else if (ret != ROG_XGM_REPORT_SIZE) {
> >> + hid_err(xgm->hdev, "Unexpected partial transfer to XG mobile: %d\n", ret);
> >> + return -EIO;
> >> + }
> >> +
> >> + return 0;
> >> +}
> >> +
> >> static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
> >> {
> >> struct input_dev *input = hi->input;
> >> @@ -1343,9 +1371,52 @@ static int asus_start_multitouch(struct hid_device *hdev)
> >> return 0;
> >> }
> >>
> >> +static int asus_xgm_init(struct hid_device *hdev, struct asus_drvdata *drvdata)
> >> +{
> >> + const char *name;
> >> + int ret;
> >> +
> >> + drvdata->xgm_led = devm_kzalloc(&hdev->dev, sizeof(*drvdata->xgm_led), GFP_KERNEL);
> >> + if (drvdata->xgm_led == NULL)
> >> + return -ENOMEM;
> >> +
> >> + name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "asus:xgm-%s:led",
> >> + strlen(hdev->uniq) ? hdev->uniq : dev_name(&hdev->dev));
> >> +
> >> + if (name == NULL) {
> >> + ret = -ENOMEM;
> >> + goto asus_xgm_init_err;
> >> + }
> >> +
> >> + drvdata->xgm_led->hdev = hdev;
> >> + drvdata->xgm_led->cdev.name = name;
> >> + drvdata->xgm_led->cdev.brightness = 1;
> >> + drvdata->xgm_led->cdev.max_brightness = 1;
> >> + drvdata->xgm_led->cdev.brightness_set_blocking = asus_xgm_led_set;
> >> +
> >> + /* LED state is arbitrary on boot, set a default */
> >> + ret = asus_xgm_led_set(&drvdata->xgm_led->cdev, drvdata->xgm_led->cdev.brightness);
> >> + if (ret) {
> >> + hid_err(hdev, "Asus failed to set xgm led: %d\n", ret);
> >> + goto asus_xgm_init_err;
> >> + }
> >> +
> >> + ret = devm_led_classdev_register(&hdev->dev, &drvdata->xgm_led->cdev);
> >> + if (ret) {
> >> + hid_err(hdev, "Asus failed to register xgm led: %d\n", ret);
> >> + goto asus_xgm_init_err;
> >> + }
> >> +
> >> + return 0;
> >> +asus_xgm_init_err:
> >> + drvdata->xgm_led = NULL;
> >> + return ret;
> >> +}
> >> +
> >> static int __maybe_unused asus_resume(struct hid_device *hdev)
> >> {
> >> struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
> >> + int ret;
> >>
> >> /*
> >> * If we have a backlight listener registered, restore the previous state,
> >> @@ -1355,7 +1426,17 @@ static int __maybe_unused asus_resume(struct hid_device *hdev)
> >> if (drvdata->listener.brightness_set)
> >> asus_kbd_backlight_set(&drvdata->listener, drvdata->kbd_backlight_brightness);
> >>
> >> + if (drvdata->xgm_led) {
> >> + ret = asus_xgm_led_set(&drvdata->xgm_led->cdev, drvdata->xgm_led->cdev.brightness);
> >> + if (ret) {
> >> + hid_err(hdev, "Asus failed to restore xgm brightness: %d\n", ret);
> >> + goto asus_resume_err;
> >> + }
> >> + }
> >> +
> >> return 0;
> >> +asus_resume_err:
> >> + return ret;
> >> }
> >>
> >> static int __maybe_unused asus_reset_resume(struct hid_device *hdev)
> >> @@ -1484,6 +1565,16 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
> >> }
> >> }
> >>
> >> + if (asus_has_report_id(hdev, FEATURE_KBD_REPORT_ID) &&
> >> + ((hdev->product == USB_DEVICE_ID_ASUSTEK_XGM_2022) ||
> >> + (hdev->product == USB_DEVICE_ID_ASUSTEK_XGM_2023))) {
> >> + ret = asus_xgm_init(hdev, drvdata);
> >> + if (ret) {
> >> + hid_err(hdev, "Failed to initialize xg mobile: %d\n", ret);
> >> + goto err_stop_hw;
> >> + }
> >> + }
> >> +
> > reset_resume has a special meaning and perhaps should not have been
> > used for this driver at all. Check if resume works and if it does use
> > that instead.
> I am not using reset_resume for xgm.
>
> reset_resume will become important to recover the ally,
For that, review the V2 s2idle series I have sent, it should drop that
codepath and work for all ally units
Sorry, misread the hunk again, I was looking at probe and confused it
with the resume check. The patch should be fine, you use resume.
Antheas
> but for xg mobile is unused (and useless).
> > Other than that and the refactor patch I'd rather see separately, the
> > other 4 patches look fine to me.
> Fair, I'll wait for maintainers to tell what they like the most
> and go from there.
>
> I agree there are things not really much related here
> but at least this way the order to apply them is clear.
> > Reviewed-by: Antheas Kapenekakis <lkml@antheas.dev>
> Thanks,
> Denis
> > Best,
> > Antheas
> >
> >> /* Laptops keyboard backlight is always at 0x5a */
> >> if (is_vendor && (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT) &&
> >> (asus_has_report_id(hdev, FEATURE_KBD_REPORT_ID)) &&
> >> --
> >> 2.47.3
> >>
> >>
>
^ permalink raw reply
* hid-lg-g15: possible use-after-free of devm data via work scheduled from a report
From: Maoyi Xie @ 2026-06-17 12:10 UTC (permalink / raw)
To: Hans de Goede, Jiri Kosina, Benjamin Tissoires; +Cc: linux-input, linux-kernel
Hi all,
I think the lg-g15 driver can read freed memory on disconnect. I would
appreciate it if you could check my reading before I send a patch.
The per device state is allocated with devm in lg_g15_probe().
g15 = devm_kzalloc(&hdev->dev, sizeof(*g15), GFP_KERNEL);
That struct contains a work item, and the report handlers schedule it
straight from device input. For example in lg_g15_event().
/* Backlight cycle button pressed? */
if (data[1] & 0x80)
schedule_work(&g15->work);
The same schedule_work(&g15->work) call also runs in lg_g15_v2_event() and
lg_g510_leds_event(). The worker lg_g15_leds_changed_work() does a
container_of() back to g15 and dereferences g15->mutex and g15->leds.
The driver has a probe but no remove callback, and there is no
cancel_work_sync() anywhere in the file. So if a report schedules the work
and the keyboard is then removed, devm frees g15 while the work is still
pending or running, and the worker touches the freed object.
The attacker model is a Logitech G15 class keyboard that sends one report
with the backlight cycle bit set and then disconnects. That can be a
malicious device or an unlucky unplug.
I reproduced the freed while pending pattern under KASAN on 7.1-rc7. The
workqueue picked up the orphaned work after the object was freed, and KASAN
reported a slab-use-after-free read.
The fix I tried is a small remove callback that cancels the work before the
devm teardown frees g15.
static void lg_g15_remove(struct hid_device *hdev)
{
struct lg_g15_data *g15 = hid_get_drvdata(hdev);
if (g15)
cancel_work_sync(&g15->work);
hid_hw_stop(hdev);
}
and wiring it up with .remove = lg_g15_remove. The g15 NULL guard mirrors the
existing check in lg_g15_raw_event().
Does this look like a real issue to you, and is the remove plus
cancel_work_sync the approach you would want? If so I am happy to send a
proper patch with a Fixes tag against 97b741aba918.
Thanks,
Maoyi
https://maoyixie.com/
^ permalink raw reply
* [PATCH v3] Input: synaptics - disable InterTouch on ThinkPad T440p (board id 2722)
From: Raphaël Larocque @ 2026-06-17 11:45 UTC (permalink / raw)
To: linux-input; +Cc: linux-kernel, dmitry.torokhov, Raphaël Larocque
In-Reply-To: <20260616171137.19069-1-rlarocque@disroot.org>
The Lenovo ThinkPad T440p (PNP ID LEN0036, board id 2722) has a
Synaptics touchpad whose SMBus companion is not ready at boot and
takes ~200 s to appear. During this window the touchpad
and pointer are completely unresponsive on approximately 50% of
boots, making the machine unusable until the companion finally
registers.
The device is in the topbuttonpad_pnp_ids[] SMBus allowlist, so the
kernel attempts to use SMBus/RMI4 mode by default. When the companion
is not ready, psmouse_smbus_init() leaves breadcrumbs and returns
-EAGAIN, the PS/2 fallback path is taken, but the device does not
function properly until the companion appears and RMI4 takes over.
Disable SMBus InterTouch for PNP ID LEN0036 with board id 2722 so
the touchpad and TrackPoint work immediately via PS/2 from boot.
Users can still force SMBus with psmouse.synaptics_intertouch=1 if
needed.
Tested-by: Raphaël Larocque <rlarocque@disroot.org>
Signed-off-by: Raphaël Larocque <rlarocque@disroot.org>
---
drivers/input/mouse/synaptics.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index c70502e24031..dd11ffdd51ae 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -1837,6 +1837,16 @@ static int synaptics_setup_intertouch(struct psmouse *psmouse,
return -ENXIO;
}
+
+ /* Disable intertouch on known-broken board revisions */
+ if (psmouse_matches_pnp_id(psmouse,
+ (const char * const []){"LEN0036", NULL}) &&
+ info->board_id == 2722) {
+ psmouse_info(psmouse,
+ "Disabling intertouch for board id %u\n",
+ info->board_id);
+ return -ENXIO;
+ }
}
psmouse_info(psmouse, "Trying to set up SMBus access\n");
--
2.53.0
^ permalink raw reply related
* Re: [PATCH 1/4] dt-bindings: input: Add binding for Qualcomm SPMI PMIC haptics
From: Fenglin Wu @ 2026-06-17 11:02 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: linux-arm-msm, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Lee Jones, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, David Collins, Subbaraman Narayanamurthy,
Kamal Wadhwa, kernel, linux-input, devicetree, linux-kernel
In-Reply-To: <20260617-wakeful-gorilla-of-feminism-75287c@quoll>
On 6/17/2026 6:35 PM, Krzysztof Kozlowski wrote:
> On Tue, Jun 16, 2026 at 03:08:24AM -0700, Fenglin Wu wrote:
>> ....
>> +
>> + qcom,lra-period-us:
>> + description:
>> + LRA actuator initial resonance period in microseconds
>> + (1,000,000 / resonant_freq_hz). Used to configure T_LRA-based play
>> + rates and the auto-resonance zero-crossing window.
> This does not feel like static characteristic. Isn't period depending on
> intensity of vibration you want to have? Why would that be fixed per
> board?
This period is specifically used for playbacks that require
auto-resonance to be enabled, which I referred to as "T_LRA-based" and
"auto-resonance zero-crossing window." It plays a key role in the
"DIRECT_PLAY" mode, which produces a constant vibration effect. To
adjust the vibration intensity during this constant effect, the hardware
does it by scaling the peak voltage of the driver signals, rather than
changing the frequency.
>> + minimum: 5
>> + maximum: 20475
>> +
>> +required:
>> + - compatible
>> + - reg
>> + - reg-names
>> + - interrupts
>> + - interrupt-names
>> + - qcom,vmax-mv
>> + - qcom,lra-period-us
>> +
> Best regards,
> Krzysztof
>
^ permalink raw reply
* Re: [PATCH 0/4] input: misc: Add an initial driver for haptics inside Qcom PMIH010x PMIC
From: Krzysztof Kozlowski @ 2026-06-17 10:42 UTC (permalink / raw)
To: Fenglin Wu
Cc: linux-arm-msm, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Lee Jones, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, David Collins, Subbaraman Narayanamurthy,
Kamal Wadhwa, kernel, linux-input, devicetree, linux-kernel
In-Reply-To: <20260616-qcom-spmi-haptics-v1-0-d24e422de6b4@oss.qualcomm.com>
On Tue, Jun 16, 2026 at 03:08:23AM -0700, Fenglin Wu wrote:
Here - the first sentence - is where you mention merging
constraints/strategy/dependencies. Your MFD patch depends on ealier
ones.
> Qualcomm PMIH010x PMIC has a haptics module inside and it could drive
> a LRA actuator with several play modes, including: DIRECT_PLAY, FIFO,
> PAT_MEM, SWR, etc. Add an initial driver to support two of the play
> modes using the input force-feedback framework:
>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 1/4] dt-bindings: input: Add binding for Qualcomm SPMI PMIC haptics
From: Krzysztof Kozlowski @ 2026-06-17 10:35 UTC (permalink / raw)
To: Fenglin Wu
Cc: linux-arm-msm, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Lee Jones, Stephen Boyd, Bjorn Andersson,
Konrad Dybcio, David Collins, Subbaraman Narayanamurthy,
Kamal Wadhwa, kernel, linux-input, devicetree, linux-kernel
In-Reply-To: <20260616-qcom-spmi-haptics-v1-1-d24e422de6b4@oss.qualcomm.com>
On Tue, Jun 16, 2026 at 03:08:24AM -0700, Fenglin Wu wrote:
> Add binding document for the haptics module inside Qualcomm PMIH010X.
A nit, subject: drop second/last, redundant "binding for". The
"dt-bindings" prefix is already stating that these are bindings.
See also:
https://elixir.bootlin.com/linux/v7.1-rc7/source/Documentation/devicetree/bindings/submitting-patches.rst#L23
>
> Assisted-by: Claude:claude-4-6-sonnet
> Signed-off-by: Fenglin Wu <fenglin.wu@oss.qualcomm.com>
> ---
> .../bindings/input/qcom,spmi-haptics.yaml | 119 +++++++++++++++++++++
> 1 file changed, 119 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/input/qcom,spmi-haptics.yaml b/Documentation/devicetree/bindings/input/qcom,spmi-haptics.yaml
> new file mode 100644
> index 000000000000..0e26d68563dc
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/input/qcom,spmi-haptics.yaml
Filenamem should match compatible.
> @@ -0,0 +1,119 @@
> +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/input/qcom,spmi-haptics.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Haptics device inside Qualcomm Technologies, Inc. PMIH010X
> +
> +maintainers:
> + - Fenglin Wu <fenglin.wu@oss.qualcomm.com>
> +
...
> +properties:
> + compatible:
> + const: qcom,pmih010x-haptics
Don't use Claude. It does not understand DT. Please read writing
bindings document or DTS101 slides. You cannot have wildcards.
> +
> + reg:
> + items:
> + - description: HAP_CFG module base address
> + - description: HAP_PTN module base address
> +
> + reg-names:
> + items:
> + - const: hap-cfg
cfg
> + - const: hap-ptn
ptn
> +
> + interrupts:
> + maxItems: 1
> +
> + interrupt-names:
> + items:
> + - const: fifo-empty
> +
> + qcom,vmax-mv:
And claude did not tell you that this is not correct? If so, please
don't use it. It's crap tool if it cannot get the basics of DT (was
mentioned on talks many times, is documented etc).
You need proper suffix.
> + description:
> + Maximum allowed output driving voltage in millivolts, rounded to the
> + nearest 50 mV step. This is the peak driving voltage in DIRECT_PLAY mode
> + which outputs sinusoidal waveforms. The value should be equal to the square
> + root of 2 times the Vrms voltage of the LRA.
> + $ref: /schemas/types.yaml#/definitions/uint32
> + minimum: 50
> + maximum: 10000
> +
> + qcom,lra-period-us:
> + description:
> + LRA actuator initial resonance period in microseconds
> + (1,000,000 / resonant_freq_hz). Used to configure T_LRA-based play
> + rates and the auto-resonance zero-crossing window.
This does not feel like static characteristic. Isn't period depending on
intensity of vibration you want to have? Why would that be fixed per
board?
> + minimum: 5
> + maximum: 20475
> +
> +required:
> + - compatible
> + - reg
> + - reg-names
> + - interrupts
> + - interrupt-names
> + - qcom,vmax-mv
> + - qcom,lra-period-us
> +
Best regards,
Krzysztof
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox