* Re: [PATCH 15/26] sh: maple: remove not needed maple_unsupported_device driver
From: sashiko-bot @ 2026-07-04 6:11 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260703-b4-maple-cleanup-v1-15-41e424964da5@gmail.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
Pre-existing issues:
- [High] Asynchronous work items are not canceled on the `maple_bus_init` error path.
- [High] Error path in `maple_bus_init` frees devices that are still linked on the global `maple_waitq`.
- [High] Directly calling `kfree` via `maple_free_dev` on `device_register` failure in `maple_attach_driver` leaks kobject state.
- [High] Re-queuing a maple packet without setting the busy flag causes list corruption.
--
commit 8ed68bea570556010f84062b91e5bd48da1f0c8d
Author: Dmitry Torokhov <dmitry.torokhov@gmail.com>
sh: maple: remove not needed maple_unsupported_device driver
This commit removes the maple_unsupported_device fallback driver since
the driver core handles devices without drivers. It also updates the
shared interrupt registrations to use &maple_bus instead of the removed
driver.
> diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
> --- a/drivers/sh/maple/maple.c
> +++ b/drivers/sh/maple/maple.c
[ ... ]
> @@ -378,7 +376,6 @@ static void maple_attach_driver(struct maple_device *mdev)
> if (matched == 0) {
> /* Driver does not exist yet */
> dev_info(&mdev->dev, "no driver found\n");
> - mdev->driver = &maple_unsupported_device;
> }
> dev_set_name(&mdev->dev, "%d:0%d.%lX", mdev->port,
> mdev->unit, function);
[Severity: High]
This isn't a regression introduced by this patch, but does the error path in
maple_attach_driver() leak kobject state?
If device_register(&mdev->dev) fails:
error = device_register(&mdev->dev);
if (error) {
dev_warn(&mdev->dev, "could not register device at"
" (%d, %d), with error 0x%X\n", mdev->unit,
mdev->port, error);
maple_free_dev(mdev);
mdev = NULL;
return;
}
maple_free_dev() directly calls kfree(). Since device_register() was
called, shouldn't failures be handled by calling put_device() to safely
invoke the release callback instead of bypassing it?
[ ... ]
> @@ -863,17 +851,14 @@ static int __init maple_bus_init(void)
> kmem_cache_destroy(maple_queue_cache);
>
> cleanup_bothirqs:
> - free_irq(HW_EVENT_VSYNC, 0);
> + free_irq(HW_EVENT_VSYNC, &maple_bus);
>
> cleanup_irq:
> - free_irq(HW_EVENT_MAPLE_DMA, 0);
> + free_irq(HW_EVENT_MAPLE_DMA, &maple_bus);
>
> cleanup_dma:
> free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES);
[Severity: High]
This is a pre-existing issue, but can this error path lead to a
use-after-free crash?
In maple_bus_init(), if initialization fails after setting the DMA
interrupt handler (for example, if KMEM_CACHE allocation fails), the error
path calls free_irq() and frees the maple_sendbuf memory.
However, it does not appear to call cancel_work_sync() for
maple_dma_process and maple_vblank_process. If an interrupt fired before
free_irq(), could the scheduled work items execute asynchronously after the
buffers are freed, dereferencing the freed memory?
[Severity: High]
This is another pre-existing issue in maple_bus_init(), but does the port
initialization loop leave dangling pointers on the global maple_waitq?
During the loop, each allocated device is immediately queued onto the
global maple_waitq via maple_add_packet():
for (i = 0; i < MAPLE_PORTS; i++) {
checked[i] = false;
empty[i] = false;
mdev[i] = maple_alloc_dev(i, 0);
if (!mdev[i]) {
while (i-- > 0)
maple_free_dev(mdev[i]);
If a subsequent allocation fails, the error handler loops backwards and
calls maple_free_dev(). However, maple_free_dev() frees mdev and mdev->mq
directly via kfree() without executing list_del() to remove them from
maple_waitq. Could this corrupt the linked list?
[Severity: High]
This is a pre-existing issue not touched by this patch, but can re-queuing
a maple packet without setting the busy flag cause list corruption?
Looking at setup_maple_commands() in drivers/sh/maple/maple.c, a
MAPLE_COMMAND_GETCOND packet is queued if mdev->busy is 0:
if (mdev->interval > 0 && atomic_read(&mdev->busy) == 0 &&
time_after(jiffies, mdev->when)) {
/* bounce if we cannot add */
add = maple_add_packet(mdev,
be32_to_cpu(mdev->devinfo.function),
MAPLE_COMMAND_GETCOND, 1, NULL);
if (!add)
mdev->when = jiffies + mdev->interval;
}
It successfully calls maple_add_packet(), which links mdev->mq->list into
maple_waitq. However, unlike other packet types, it fails to set
mdev->busy = 1.
If a concurrent userspace action (such as a read via /dev/mtdX in vmu-flash
leading to maple_vmu_read_block()) executes, would it read mdev->busy as 0,
assume the queue is free, and call maple_add_packet() again? This would
reuse the exact same mdev->mq object, executing list_add_tail() on an
already-linked node, which corrupts the list.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703-b4-maple-cleanup-v1-0-41e424964da5@gmail.com?part=15
^ permalink raw reply
* Re: [PATCH 2/3] Input: mms114 - fix endianness portability in I2C packet layout
From: sashiko-bot @ 2026-07-04 6:12 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260704060115.353049-2-dmitry.torokhov@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Race condition in suspend causes stuck touches.
- [High] Unsafe DMA buffer allocation (stack-allocated memory passed to I2C transfers).
--
commit 2e96699ad380d6d47c8e998bc41268e9b77bac90
Author: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: mms114 - fix endianness portability in I2C packet layout
The driver defines the I2C packet layout using C bitfields in struct
mms114_touch. This is not portable as the layout of bitfields within a
byte is compiler-dependent and varies with endianness. On Big Endian
systems, the fields will be parsed incorrectly.
> diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
> index 23e0283bc6b8b..84afdadb3bccc 100644
> --- a/drivers/input/touchscreen/mms114.c
> +++ b/drivers/input/touchscreen/mms114.c
[ ... ]
> @@ -325,8 +338,9 @@ static irqreturn_t mms114_interrupt(int irq, void *dev_id)
>
> for (index = 0; index < touch_size; index++) {
> t = (struct mms114_touch *)((u8 *)touch + index * event_size);
[Severity: High]
This isn't a bug introduced by this patch, but does passing stack-allocated
buffers to I2C transfer functions risk memory corruption if the I2C adapter
uses DMA?
Since kernel stacks are often allocated in vmalloc space (when
CONFIG_VMAP_STACK is enabled), they cannot be safely mapped for DMA.
In mms114_interrupt(), the touch array is stack-allocated and used as a
receive buffer:
struct mms114_touch touch[MMS114_MAX_TOUCH];
// ...
error = __mms114_read_reg(data, MMS114_INFORMATION, packet_size, touch);
Similarly, __mms114_read_reg() and mms114_write_reg() pass local stack
variables (u8 buf and u8 buf[2]) to I2C transfers.
> + unsigned int type = FIELD_GET(MMS114_FLAGS_TYPE_MASK, t->flags);
>
> - switch (t->type) {
> + switch (type) {
> case MMS114_TYPE_TOUCHSCREEN:
> mms114_process_mt(data, t);
> break;
[ ... ]
[Severity: High]
This is a pre-existing issue, but could the sequence in mms114_suspend()
have a race condition that results in stuck touches?
In mms114_suspend(), the driver injects artificial release events before
disabling the IRQ:
/* Release all touch */
for (id = 0; id < MMS114_MAX_TOUCH; id++) {
input_mt_slot(input_dev, id);
input_mt_report_slot_inactive(input_dev);
}
// ...
input_sync(input_dev);
guard(mutex)(&input_dev->mutex);
if (input_device_enabled(input_dev))
mms114_stop(data);
If a touch interrupt fires and its threaded handler (mms114_interrupt)
executes after these release events are injected but before mms114_stop()
disables the IRQ, might it report the touch as active again and leave it
stuck indefinitely after suspend?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260704060115.353049-1-dmitry.torokhov@gmail.com?part=2
^ permalink raw reply
* Re: [PATCH 25/26] Input: maplecontrol - fix style issues
From: sashiko-bot @ 2026-07-04 6:12 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260703-b4-maple-cleanup-v1-25-41e424964da5@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Missing `input_sync()` in the event reporting callback, preventing event delivery to standard userspace clients.
--
commit 85e64697864750aa3ae1b20ac7b36084615ece73
Author: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: maplecontrol - fix style issues
This commit fixes coding style and formatting issues reported by
checkpatch.pl. It switches to using BIT() macros and removes
conditionals when reporting D-PAD events.
> diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
> --- a/drivers/input/joystick/maplecontrol.c
> +++ b/drivers/input/joystick/maplecontrol.c
> @@ -35,22 +35,22 @@ static void dc_pad_callback(struct mapleq *mq)
[ ... ]
> - input_report_key(dev, BTN_SELECT, buttons & 0x0800);
> + input_report_key(dev, BTN_C, buttons & BIT(0));
> + input_report_key(dev, BTN_B, buttons & BIT(1));
> + input_report_key(dev, BTN_A, buttons & BIT(2));
> + input_report_key(dev, BTN_START, buttons & BIT(3));
> + input_report_key(dev, BTN_Z, buttons & BIT(8));
> + input_report_key(dev, BTN_Y, buttons & BIT(9));
> + input_report_key(dev, BTN_X, buttons & BIT(10));
> + input_report_key(dev, BTN_SELECT, buttons & BIT(11));
>
> input_report_abs(dev, ABS_GAS, res[10]);
> input_report_abs(dev, ABS_BRAKE, res[11]);
[Severity: High]
This is a pre-existing issue, but does dc_pad_callback() need a call to
input_sync() at the end of the event reporting block?
When the maple bus periodically invokes this callback to parse the hardware
state, all axis and key updates are pushed to the input core, but the
function returns without finalizing the packet. Modern input stacks like evdev
buffer events and wait for an EV_SYN sync event to wake up userspace.
Without a sync event after these inputs are reported, do the events remain
buffered indefinitely and fail to reach applications?
Could an input_sync(dev) call be added before the callback returns to ensure
the state updates are successfully flushed to userspace?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703-b4-maple-cleanup-v1-0-41e424964da5@gmail.com?part=25
^ permalink raw reply
* Re: [PATCH 17/26] sh: maple: implement bus-level probe/remove
From: sashiko-bot @ 2026-07-04 6:12 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260703-b4-maple-cleanup-v1-17-41e424964da5@gmail.com>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
Pre-existing issues:
- [High] Dangling function pointers in maple_device leading to execution of unloaded module code on hot-unplug.
- [High] Missing `cancel_work_sync()` in `maple_bus_init` error path leads to Use-After-Free.
- [High] Dangling hardware callback in `vmu_connect` error path leads to Use-After-Free.
- [High] NULL pointer dereference and multiple memory leaks in `vmu_disconnect`.
- [High] The driver reports input events but fails to call `input_sync()` at the end of the packet handling.
- [Medium] Memory leak of `card->mtd` array on failure path in `vmu_connect`.
--
commit 8d15bc5545d93a9d1f9f85e0e543bc57384c73cb
Author: Dmitry Torokhov <dmitry.torokhov@gmail.com>
sh: maple: implement bus-level probe/remove
Implement probe() and remove() methods for the maple bus, and update
struct maple_driver to have its own probe() and remove() members that
take struct maple_device * directly. Adjust all maple drivers to
use these new bus-level methods.
> diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
> index 955e01bcfa0c1..6864243b0b4a2 100644
> --- a/drivers/input/joystick/maplecontrol.c
> +++ b/drivers/input/joystick/maplecontrol.c
> @@ -78,7 +78,7 @@ static void dc_pad_close(struct input_dev *dev)
> }
>
> /* allow the controller to be used */
> -static int probe_maple_controller(struct device *dev)
> +static int probe_maple_controller(struct maple_device *mdev)
> {
[Severity: High]
This is a pre-existing issue, but does dc_pad_callback() fail to call
input_sync() after reporting events?
drivers/input/joystick/maplecontrol.c:dc_pad_callback() {
...
input_report_abs(dev, ABS_RY, res[15]);
}
The driver reports input events but never calls input_sync() at the end of the
packet handling. As dictated by the Input Subsystem guidelines, every logical
group of events must be followed by a call to input_sync(), otherwise events
may not be properly synchronized and delivered to userspace.
[ ... ]
> diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c
> index 8f7028ac1b56a..c34c768dfb876 100644
> --- a/drivers/mtd/maps/vmu-flash.c
> +++ b/drivers/mtd/maps/vmu-flash.c
> @@ -769,30 +769,25 @@ static void vmu_file_error(struct maple_device *mdev, void *recvbuf)
> }
>
>
> -static int probe_maple_vmu(struct device *dev)
> +static int probe_maple_vmu(struct maple_device *mdev)
> {
> - struct maple_device *mdev = to_maple_dev(dev);
> -
> mdev->can_unload = vmu_can_unload;
> mdev->fileerr_handler = vmu_file_error;
>
[Severity: High]
This is a pre-existing issue, but does this leave dangling function pointers
during device hot-unplug?
mdev->can_unload and mdev->fileerr_handler are set here, but remove_maple_vmu()
never clears them. If the module is unbound and unloaded, and the device is
subsequently physically unplugged, maple_response_none() will call the dangling
mdev->can_unload(mdev). This would jump to unmapped memory and cause a kernel
panic.
> return vmu_connect(mdev);
> }
[Severity: Medium]
This is a pre-existing issue, but does vmu_connect() leak the card->mtd array
on the packet addition failure path?
When maple_add_packet() fails, the code jumps to fail_mtd_info:
drivers/mtd/maps/vmu-flash.c:vmu_connect() {
...
fail_device_busy:
kfree(card->mtd);
fail_mtd_info:
kfree(card->parts);
...
}
This bypasses the kfree(card->mtd) cleanup block, causing a memory leak.
[Severity: High]
This is a pre-existing issue, but does vmu_connect() leave a dangling callback
if it fails?
drivers/mtd/maps/vmu-flash.c:vmu_connect() {
...
maple_getcond_callback(mdev, vmu_queryblocks, 0, MAPLE_FUNC_MEMCARD);
...
}
If vmu_connect() returns an error (like device busy or maple_add_packet failure),
it frees the 'card' structure but doesn't clear mdev->callback. If the maple
bus receives a MAPLE_RESPONSE_DATATRF, will the core unconditionally execute the
callback and attempt to use the freed 'card' structure?
> -static int remove_maple_vmu(struct device *dev)
> +static void remove_maple_vmu(struct maple_device *mdev)
> {
> - struct maple_device *mdev = to_maple_dev(dev);
> -
> vmu_disconnect(mdev);
> - return 0;
> }
[Severity: High]
This is a pre-existing issue, but can vmu_disconnect() trigger a NULL pointer
dereference?
drivers/mtd/maps/vmu-flash.c:vmu_disconnect() {
...
for (x = 0; x < card->partitions; x++) {
mpart = ((card->mtd)[x]).priv;
mpart->mdev = NULL;
...
}
Since vmu_connect() creates card->mtd as a zeroed array, card->mtd[x].priv is
NULL until vmu_queryblocks() asynchronously allocates and assigns it. If the
device is disconnected before the callback completes for all partitions, will
this blindly dereference mpart? Additionally, does this fail to free mpart,
pcache, and pcache->buffer completely, causing memory leaks on every successful
bind/unbind?
[ ... ]
> diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
> index 35aff2e57d2c8..c0715e3ace6f1 100644
> --- a/drivers/sh/maple/maple.c
> +++ b/drivers/sh/maple/maple.c
> @@ -790,7 +816,6 @@ static int __init maple_bus_init(void)
> if (retval)
> goto cleanup_device;
>
> -
> /* allocate memory for maple bus dma */
> retval = maple_get_dma_buffer();
[Severity: High]
This is a pre-existing issue, but does the error path in maple_bus_init()
fail to cancel asynchronous work, leading to a use-after-free?
drivers/sh/maple/maple.c:maple_bus_init() {
...
cleanup_irq:
free_irq(HW_EVENT_MAPLE_DMA, &maple_bus);
cleanup_dma:
free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES);
...
}
If initialization fails after the DMA or VBLANK IRQs are registered, the error
path frees the IRQs and the maple_sendbuf memory. However, it fails to cancel
the asynchronous work (maple_dma_process and maple_vblank_process). If an IRQ
fires before free_irq(), the scheduled work will execute maple_dma_handler() or
maple_vblank_handler(), which dereferences the freed maple_sendbuf memory via
maple_send().
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703-b4-maple-cleanup-v1-0-41e424964da5@gmail.com?part=17
^ permalink raw reply
* Re: [PATCH 22/26] Input: maplecontrol - convert to devm
From: sashiko-bot @ 2026-07-04 6:13 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260703-b4-maple-cleanup-v1-22-41e424964da5@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] This problem wasn't introduced by this patch, but the event reporting callback `dc_pad_callback` fails to call `input_sync()` after reporting key and absolute axis events, preventing state updates from reaching userspace promptly.
--
commit bb1e0ba07531193e46d25e174ec864860b0026be
Author: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: maplecontrol - convert to devm
Convert the driver to use managed resources to simplify resource
lifecycle management. This eliminates manual error handling in probe()
and allows removing the remove() callback entirely, as all cleanup is
handled automatically.
> diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
> index 6864243b0b4a2..3ef6652d40cb6 100644
> --- a/drivers/input/joystick/maplecontrol.c
> +++ b/drivers/input/joystick/maplecontrol.c
[ ... ]
> @@ -129,33 +130,20 @@ static int probe_maple_controller(struct maple_device *mdev)
> if (idev->keybit[BIT_WORD(BTN_JOYSTICK)])
> idev->evbit[0] |= BIT_MASK(EV_KEY);
>
> - idev->dev.parent = &mdev->dev;
> idev->name = mdev->product_name;
> idev->id.bustype = BUS_HOST;
>
> error = input_register_device(idev);
> if (error)
> - goto fail;
> - return 0;
> + return error;
>
> -fail:
> - input_free_device(idev);
> - kfree(pad);
> - return error;
> -}
[Severity: High]
This isn't a bug introduced by this patch, but I noticed the event reporting
callback dc_pad_callback() fails to call input_sync() after reporting key and
absolute axis events:
drivers/input/joystick/maplecontrol.c:dc_pad_callback() {
...
input_report_abs(dev, ABS_RX, res[14]);
input_report_abs(dev, ABS_RY, res[15]);
}
Without a final input_sync(dev), will state updates be prevented from
reaching userspace promptly, causing events to get stuck until the internal
buffers fill up?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703-b4-maple-cleanup-v1-0-41e424964da5@gmail.com?part=22
^ permalink raw reply
* Re: [PATCH 18/26] sh: maple: introduce callback_mutex in maple_device
From: sashiko-bot @ 2026-07-04 6:14 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260703-b4-maple-cleanup-v1-18-41e424964da5@gmail.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
New issues:
- [Critical] The newly introduced callback_mutex causes a guaranteed self-deadlock when enumerating vmu-flash devices.
- [Medium] The newly introduced callback_mutex is initialized dynamically but is not destroyed during the standard device release lifecycle.
Pre-existing issues:
- [High] The patch fails to prevent the Use-After-Free race condition in the vmu-flash driver because vmu_disconnect bypasses the new callback_mutex.
--
commit 29c05632bf3bdcdb9087fb8230fb421ba8176ce5
Author: Dmitry Torokhov <dmitry.torokhov@gmail.com>
sh: maple: introduce callback_mutex in maple_device
This commit introduces callback_mutex in struct maple_device to synchronize
callback registration and invocation. It is intended to prevent
use-after-free bugs if a device is removed while a callback is in flight.
> diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
> index c0715e3ace6f1..7c82b7a8a2809 100644
> --- a/drivers/sh/maple/maple.c
> +++ b/drivers/sh/maple/maple.c
> @@ -121,6 +121,7 @@ void maple_getcond_callback(struct maple_device *dev,
> void (*callback) (struct mapleq *mq),
> unsigned long interval, unsigned long function)
> {
> + guard(mutex)(&dev->callback_mutex);
[Severity: Critical]
Does this introduce a self-deadlock when a callback registers a new callback?
When enumerating a vmu-flash device, maple_dma_handler() acquires
mdev->callback_mutex and executes the callback vmu_queryblocks().
Inside vmu_queryblocks(), the driver calls maple_getcond_callback() to
configure the next phase.
Since maple_getcond_callback() unconditionally attempts to acquire the
same non-recursive mdev->callback_mutex here, won't this immediately
deadlock the maple bus workqueue?
> dev->callback = callback;
> dev->interval = interval;
> dev->function = cpu_to_be32(function);
[ ... ]
> @@ -230,11 +231,13 @@ static struct maple_device *maple_alloc_dev(int port, int unit)
> mdev->dev.bus = &maple_bus_type;
> mdev->dev.parent = &maple_bus;
> init_waitqueue_head(&mdev->maple_wait);
> + mutex_init(&mdev->callback_mutex);
> return mdev;
> }
>
> static void maple_free_dev(struct maple_device *mdev)
> {
> + mutex_destroy(&mdev->callback_mutex);
[Severity: Medium]
Is a corresponding mutex_destroy() needed in the standard device release
path?
While mutex_destroy() is added to maple_free_dev() here, if a maple device's
reference count drops to zero after device_unregister(), the release
path maple_release_device() is executed.
Will this leave stale lockdep/RT-mutex structures behind if debugging
configs are enabled, since maple_release_device() does not destroy the
mutex before calling kfree(mdev)?
> kmem_cache_free(maple_queue_cache, mdev->mq->recvbuf);
> kfree(mdev->mq);
> kfree(mdev);
[ ... ]
> @@ -655,8 +658,10 @@ static void maple_dma_handler(struct work_struct *work)
> break;
>
> case MAPLE_RESPONSE_DATATRF:
> - if (mdev->callback)
> - mdev->callback(mq);
> + scoped_guard(mutex, &mdev->callback_mutex) {
> + if (mdev->callback)
> + mdev->callback(mq);
> + }
[Severity: High]
This is a pre-existing issue, but does this actually prevent the
use-after-free race condition for all drivers?
If a user unbinds a vmu-flash device while a maple data transfer is
in-flight, vmu_disconnect() bypasses this new mutex entirely:
drivers/mtd/maps/vmu-flash.c:vmu_disconnect() {
...
mdev->callback = NULL;
card = maple_get_drvdata(mdev);
...
kfree(card);
}
Since vmu_disconnect() modifies the callback and frees the private data
without acquiring callback_mutex, can maple_dma_handler() still
concurrently dereference the freed card data here?
> atomic_set(&mdev->busy, 0);
> wake_up(&mdev->maple_wait);
> break;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260703-b4-maple-cleanup-v1-0-41e424964da5@gmail.com?part=18
^ permalink raw reply
* [PATCH] Input: elants_i2c - prevent divide-by-zero on invalid EKTH data
From: Laxman Acharya Padhya @ 2026-07-04 12:17 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, linux-kernel
elants_i2c_query_ts_info_ekth() checks the reported row, column and
oversampling values before calculating the touchscreen resolution, but
does not check the physical dimensions. If either physical dimension
is zero, DIV_ROUND_CLOSEST() divides by zero during probe.
Treat zero physical dimensions as invalid data and skip the resolution
calculation, as is already done for the other invalid information.
Fixes: 66aee90088da ("Input: add support for Elan eKTH I2C touchscreens")
Assisted-by: Codex:gpt-5
Signed-off-by: Laxman Acharya Padhya <acharyalaxman8848@gmail.com>
---
drivers/input/touchscreen/elants_i2c.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c
index 17175ad..68c5ee3 100644
--- a/drivers/input/touchscreen/elants_i2c.c
+++ b/drivers/input/touchscreen/elants_i2c.c
@@ -566,10 +566,11 @@ static int elants_i2c_query_ts_info_ekth(struct elants_data *ts)
dev_dbg(&client->dev, "phy_x=%d, phy_y=%d\n", phy_x, phy_y);
- if (rows == 0 || cols == 0 || osr == 0) {
+ if (rows == 0 || cols == 0 || osr == 0 ||
+ phy_x == 0 || phy_y == 0) {
dev_warn(&client->dev,
- "invalid trace number data: %d, %d, %d\n",
- rows, cols, osr);
+ "invalid data: rows=%u cols=%u osr=%u phy_x=%u phy_y=%u\n",
+ rows, cols, osr, phy_x, phy_y);
} else {
/* translate trace number to TS resolution */
ts->x_max = ELAN_TS_RESOLUTION(rows, osr);
--
2.51.2
^ permalink raw reply related
* Re: [PATCH] Input: elants_i2c - prevent divide-by-zero on invalid EKTH data
From: sashiko-bot @ 2026-07-04 12:28 UTC (permalink / raw)
To: Laxman Acharya Padhya; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260704121738.48071-1-acharyalaxman8848@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] A 0-byte firmware file causes out-of-bounds reads when verifying the remark ID and when sending firmware pages to the device.
- [High] Stack-allocated arrays are passed to i2c_transfer(), which is unsafe if the underlying I2C controller uses DMA.
--
commit 4ca9e1ffa7cb9eddbc7a0070d2fc1df01f66c3cd
Author: Laxman Acharya Padhya <acharyalaxman8848@gmail.com>
Input: elants_i2c - prevent divide-by-zero on invalid EKTH data
This commit adds checks for physical dimensions in the eKTH query function.
It treats zero values as invalid data and skips resolution calculations
to prevent a divide-by-zero error during probe.
Fixes: 66aee90088da ("Input: add support for Elan eKTH I2C touchscreens")
Assisted-by: Codex:gpt-5
> diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c
> index 17175adcaebbd..68c5ee3aa1904 100644
> --- a/drivers/input/touchscreen/elants_i2c.c
> +++ b/drivers/input/touchscreen/elants_i2c.c
> @@ -566,10 +566,11 @@ static int elants_i2c_query_ts_info_ekth(struct elants_data *ts)
>
> dev_dbg(&client->dev, "phy_x=%d, phy_y=%d\n", phy_x, phy_y);
>
> - if (rows == 0 || cols == 0 || osr == 0) {
> + if (rows == 0 || cols == 0 || osr == 0 ||
> + phy_x == 0 || phy_y == 0) {
> dev_warn(&client->dev,
> - "invalid trace number data: %d, %d, %d\n",
> - rows, cols, osr);
> + "invalid data: rows=%u cols=%u osr=%u phy_x=%u phy_y=%u\n",
> + rows, cols, osr, phy_x, phy_y);
> } else {
> /* translate trace number to TS resolution */
> ts->x_max = ELAN_TS_RESOLUTION(rows, osr);
[Severity: High]
This isn't a bug introduced by this patch, but while looking at
elants_i2c_query_ts_info_ekth(), could there be an issue with how the command
buffers are passed to the I2C subsystem?
drivers/input/touchscreen/elants_i2c.c:elants_i2c_query_ts_info_ekth() {
...
u8 resp[17];
const u8 get_resolution_cmd[] = {
CMD_HEADER_6B_READ, 0x00, 0x00, 0x00, 0x00, 0x00
...
error = elants_i2c_execute_command(client,
get_resolution_cmd,
sizeof(get_resolution_cmd),
resp, sizeof(resp), 1,
"get resolution");
}
When elants_i2c_execute_command() assigns these buffers directly to the I2C
message:
drivers/input/touchscreen/elants_i2c.c:elants_i2c_execute_command() {
...
msgs[0].buf = (u8 *)cmd;
...
msgs[1].buf = resp;
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
}
If the I2C controller uses DMA, doesn't passing stack-allocated buffers like
get_resolution_cmd and resp cause a DMA mapping failure since stack memory
is virtually mapped?
[Severity: High]
This is a pre-existing issue, but does the firmware update routine properly
validate an empty firmware file?
If a 0-byte firmware file is loaded, the modulo check in
elants_i2c_fw_update() evaluates to 0:
drivers/input/touchscreen/elants_i2c.c:elants_i2c_fw_update() {
...
if (fw->size % ELAN_FW_PAGESIZE) {
dev_err(&client->dev, "Invalid firmware format: %zu\n",
fw->size);
...
}
This would allow the empty firmware to proceed. Later, when validating the
remark ID, wouldn't the size calculation underflow and read out of bounds?
drivers/input/touchscreen/elants_i2c.c:elants_i2c_validate_remark_id() {
...
fw_remark_id = get_unaligned_le16(&fw->data[fw->size - 4]);
...
}
Even if validation is skipped, could the actual update routine read out of
bounds when it unconditionally sends the first page?
drivers/input/touchscreen/elants_i2c.c:elants_i2c_do_update_firmware() {
...
error = elants_i2c_send(client, fw->data, ELAN_FW_PAGESIZE);
...
}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260704121738.48071-1-acharyalaxman8848@gmail.com?part=1
^ permalink raw reply
* Re: [PATCH v2 2/2] arm64: dts: qcom: sdm845-oneplus: Update compatible to include model
From: David Heidelberg @ 2026-07-04 15:06 UTC (permalink / raw)
To: Bjorn Andersson
Cc: linux-input, devicetree, linux-kernel, linux-arm-msm, phone-devel,
Vincent Huang, Jason A. Donenfeld, Krzysztof Kozlowski,
Dmitry Torokhov, Konrad Dybcio, Rob Herring, Krzysztof Kozlowski,
Matthias Schiffer, Konrad Dybcio, Conor Dooley
In-Reply-To: <20260523-synaptics-rmi4-dt-v2-2-0645122babdc@ixit.cz>
On 23/05/2026 11:45, David Heidelberg via B4 Relay wrote:
> From: David Heidelberg <david@ixit.cz>
>
> We know the driver is reporting s3706b, introduce the compatible so we
> can more easily introduce quirks for weird touchscreen replacements in
> followup series.
>
> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> Signed-off-by: David Heidelberg <david@ixit.cz>
Bjorn,
please pick me $subj, counterpart got in (or if u want I can resend).
David
> ---
> arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
> index 6b7378cf4d493..148164d456a5a 100644
> --- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
> +++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
> @@ -475,17 +475,17 @@ bq27441_fg: bq27441-battery@55 {
> };
> };
>
> &i2c12 {
> status = "okay";
> clock-frequency = <400000>;
>
> synaptics-rmi4-i2c@20 {
> - compatible = "syna,rmi4-i2c";
> + compatible = "syna,rmi4-s3706b", "syna,rmi4-i2c";
> reg = <0x20>;
> #address-cells = <1>;
> #size-cells = <0>;
> interrupts-extended = <&tlmm 125 IRQ_TYPE_EDGE_FALLING>;
>
> pinctrl-names = "default";
> pinctrl-0 = <&ts_default_pins>;
>
>
^ permalink raw reply
* [PATCH] Input: ims-pcu - add missing MODULE_DEVICE_TABLE()
From: Pengpeng Hou @ 2026-07-04 15:17 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Pengpeng Hou,
open list:INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN)...,
linux-kernel
The driver has a match table for the usb bus wired into its driver
structure, but the table is not exported with MODULE_DEVICE_TABLE().
Add the missing MODULE_DEVICE_TABLE() entry so module alias information
is generated for automatic module loading.
This is a source-level fix. It does not claim dynamic hardware
reproduction; the evidence is the driver-owned match table, its use by
the driver registration structure, and the missing module alias
publication.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
---
drivers/input/misc/ims-pcu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index f69de9762c4e..687911d20ecf 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -2119,6 +2119,7 @@ static const struct usb_device_id ims_pcu_id_table[] = {
},
{ }
};
+MODULE_DEVICE_TABLE(usb, ims_pcu_id_table);
static const struct attribute_group *ims_pcu_sysfs_groups[] = {
&ims_pcu_attr_group,
--
2.53.0
^ permalink raw reply related
* Re: [PATCH 18/26] sh: maple: introduce callback_mutex in maple_device
From: Florian Fuchs @ 2026-07-04 15:48 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz,
Adrian McMenamin, linux-kernel, Dmitry Torokhov, linux-input,
linux-mtd, linux-sh
In-Reply-To: <20260703-b4-maple-cleanup-v1-18-41e424964da5@gmail.com>
Hi Dmitry,
On 03 Jul 22:57, Dmitry Torokhov wrote:
> The Maple bus core invokes client callbacks asynchronously from a
> workqueue (maple_dma_handler). If a device is removed (or closed) while
> a callback is in flight, it can lead to UAF bugs if the driver's private
> data is freed.
>
> Introduce callback_mutex in struct maple_device to synchronize
> callback registration/modification and callback invocation.
>
> Assisted-by: Antigravity:gemini-3.5-flash
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
> drivers/sh/maple/maple.c | 9 +++++++--
> include/linux/maple.h | 2 ++
> 2 files changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
> index c0715e3ace6f..7c82b7a8a280 100644
> --- a/drivers/sh/maple/maple.c
> +++ b/drivers/sh/maple/maple.c
> @@ -121,6 +121,7 @@ void maple_getcond_callback(struct maple_device *dev,
> void (*callback) (struct mapleq *mq),
> unsigned long interval, unsigned long function)
> {
> + guard(mutex)(&dev->callback_mutex);
> dev->callback = callback;
> dev->interval = interval;
> dev->function = cpu_to_be32(function);
> @@ -230,11 +231,13 @@ static struct maple_device *maple_alloc_dev(int port, int unit)
> mdev->dev.bus = &maple_bus_type;
> mdev->dev.parent = &maple_bus;
> init_waitqueue_head(&mdev->maple_wait);
> + mutex_init(&mdev->callback_mutex);
> return mdev;
> }
>
> static void maple_free_dev(struct maple_device *mdev)
> {
> + mutex_destroy(&mdev->callback_mutex);
> kmem_cache_free(maple_queue_cache, mdev->mq->recvbuf);
> kfree(mdev->mq);
> kfree(mdev);
> @@ -655,8 +658,10 @@ static void maple_dma_handler(struct work_struct *work)
> break;
>
> case MAPLE_RESPONSE_DATATRF:
> - if (mdev->callback)
> - mdev->callback(mq);
> + scoped_guard(mutex, &mdev->callback_mutex) {
> + if (mdev->callback)
> + mdev->callback(mq);
> + }
> atomic_set(&mdev->busy, 0);
> wake_up(&mdev->maple_wait);
> break;
> diff --git a/include/linux/maple.h b/include/linux/maple.h
> index 641cf3330409..48ed7558b8ab 100644
> --- a/include/linux/maple.h
> +++ b/include/linux/maple.h
> @@ -3,6 +3,7 @@
> #define __LINUX_MAPLE_H
>
> #include <linux/device.h>
> +#include <linux/mutex.h>
> #include <mach/maple.h>
>
> /* Maple Bus command and response codes */
> @@ -75,6 +76,7 @@ struct maple_device {
> char product_licence[64];
> atomic_t busy;
> wait_queue_head_t maple_wait;
> + struct mutex callback_mutex;
> struct device dev;
> };
>
>
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>
Thank you so much for your efforts. I can confirm sashikos finding in my
test (that I saw later), that this patch hangs the bus if a VMU memcard
is inserted. So that the peripherals don't work anymore after insertion
of the memcard. With a last log like:
Dreamcast_visual_memory 3:01.E: VMU at (3, 1) is busy
Regards
Florian
^ permalink raw reply
* [PATCH] HID: bpf: Fix signedness bug in hid_bpf_hw_request
From: Guangshuo Li @ 2026-07-04 16:07 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires, Kees Cook, Puranjay Mohan,
Johan Hovold, Guangshuo Li, linux-input, linux-kernel, bpf
hid_bpf_hw_request() clamps the return value of hid_hw_raw_request() to
the size of the caller supplied buffer before copying data back to the
BPF buffer.
However, ret is signed while size is unsigned. If hid_hw_raw_request()
returns a negative error code, the comparison promotes ret to size_t.
This makes the negative value look like a very large positive value, so
the error is clamped to size. The following memcpy() then treats the
failed request as a successful transfer and copies stale data back to
the caller.
Only clamp positive return values. This preserves negative error codes
while still preventing oversized successful returns from overflowing the
caller supplied buffer.
Fixes: 2b658c1c442e ("HID: bpf: prevent buffer overflow in hid_hw_request")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
drivers/hid/bpf/hid_bpf_dispatch.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index d0130658091b..b13f911e5944 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c
@@ -446,7 +446,7 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
(u64)(long)ctx,
true); /* prevent infinite recursions */
- if (ret > size)
+ if (ret > 0 && ret > size)
ret = size;
if (ret > 0)
memcpy(buf, dma_data, ret);
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] HID: bpf: Fix signedness bug in hid_bpf_hw_request
From: sashiko-bot @ 2026-07-04 16:41 UTC (permalink / raw)
To: Guangshuo Li; +Cc: dmitry.torokhov, bpf, linux-input
In-Reply-To: <20260704160703.156298-1-lgs201920130244@gmail.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Integer overflow in hid_bpf_get_data on 32-bit platforms leads to out-of-bounds pointer return.
- [Critical] Missing bounds check on `size` in `dispatch_hid_bpf_device_event` leads to a kernel heap buffer overflow.
- [High] Dereference of ZERO_SIZE_PTR when processing a 0-length HID report in hid_bpf_hw_request.
--
commit 8a657f92f1d0d08c3cf3bdf8cdaf0b05c7deec72
Author: Guangshuo Li <lgs201920130244@gmail.com>
Subject: HID: bpf: Fix signedness bug in hid_bpf_hw_request
This patch clamps positive return values from hid_hw_raw_request() to the
size of the caller-supplied buffer. It preserves negative error codes while
preventing oversized successful returns from overflowing the buffer.
> diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
> index d0130658091b0..b13f911e5944a 100644
> --- a/drivers/hid/bpf/hid_bpf_dispatch.c
> +++ b/drivers/hid/bpf/hid_bpf_dispatch.c
> @@ -446,7 +446,7 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
> (u64)(long)ctx,
> true); /* prevent infinite recursions */
>
[Severity: High]
This is a pre-existing issue, but does this code safely handle 0-length HID
reports?
In __hid_bpf_hw_check_params(), the size can be capped to 0. This causes the
subsequent kmemdup() to return ZERO_SIZE_PTR. The dma_data pointer is then
unconditionally dereferenced in hid_hw_raw_request() when accessing
dma_data[0], which could cause a crash.
> - if (ret > size)
> + if (ret > 0 && ret > size)
> ret = size;
> if (ret > 0)
> memcpy(buf, dma_data, ret);
[Severity: Critical]
This is a pre-existing issue, but can the bounds check in hid_bpf_get_data()
overflow on 32-bit platforms?
drivers/hid/bpf/hid_bpf_dispatch.c:hid_bpf_get_data() {
[ ... ]
if (rdwr_buf_size + offset > ctx->allocated_size)
return NULL;
return ctx_kern->data + offset;
}
The addition of rdwr_buf_size and offset could wrap around, bypassing the
bounds check and potentially returning an out-of-bounds pointer.
[Severity: Critical]
This is a pre-existing issue, but is there a missing bounds check on size in
dispatch_hid_bpf_device_event()?
drivers/hid/bpf/hid_bpf_dispatch.c:dispatch_hid_bpf_device_event() {
[ ... ]
memset(ctx_kern.data, 0, hdev->bpf.allocated_data);
memcpy(ctx_kern.data, data, *size);
[ ... ]
}
The memcpy() uses the provided size without validating it against
hdev->bpf.allocated_data. This could lead to a heap buffer overflow if a
larger size is provided, such as through a UHID_INPUT event.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260704160703.156298-1-lgs201920130244@gmail.com?part=1
^ permalink raw reply
* Re: [PATCH v5 0/9] HID: steelseries: split out Arctis driver and add Nova 7 Gen2 support
From: Colin Blower @ 2026-07-04 17:39 UTC (permalink / raw)
To: Sriman Achanta, Jiri Kosina, Benjamin Tissoires
Cc: linux-input, linux-kernel, Bastien Nocera, Simon Wood,
Christian Mayer
In-Reply-To: <cover.1782840133.git.srimanachanta@gmail.com>
I can help test two other SteelSeries Arctis devices, the Nova 7
(0x2202) and Nova 7X (0x2206). I know support was dropped between
v3 and v4.
Link:
https://lore.kernel.org/lkml/20260623172310.272708-1-srimanachanta@gmail.com/#t
On Tue, 23 Jun 2026 13:23:00 -0400, Sriman Achanta wrote:
> Changes since v3:
...
> - Limit new device support to the Arctis Nova 7 Gen2 family, the only
> hardware I can test.
I patched back in Nova 7X (0x2206) support locally (Archlinux 6.18.37-1-
lts) and it reports battery status with no obvious issues. I only
tested basic audio out and report of battery status via dongle. I'm
not sure what a complete test matrix would look like. I did not test
Nova 7 (0x2202).
Here is my patch on top of v5 in case it is relevant, but this is mostly
from what was dropped in v3. Not meant to be a clean submission, happy
to send a proper formatted patch if useful.
---
drivers/hid/hid-ids.h | 1 +
drivers/hid/hid-quirks.c | 1 +
drivers/hid/hid-steelseries-arctis.c | 21 +++++++++++++++++++++
3 files changed, 23 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 4856469da073..e5faaeb67c92 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -1320,6 +1320,7 @@
#define USB_DEVICE_ID_STEELSERIES_SRWS1 0x1410
#define USB_DEVICE_ID_STEELSERIES_ARCTIS_1_X 0x12b6
#define USB_DEVICE_ID_STEELSERIES_ARCTIS_9 0x12c2
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X 0x2206
#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_2026 0x22a1
#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_P_2026 0x22a7
#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_2026 0x22a5
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 23f3590a83ab..57c72a6c29f3 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -716,6 +716,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_1_X) },
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_9) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X) },
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_2026) },
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_P_2026) },
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_2026) },
diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
index 31d31f3f4b0e..e5070b28018b 100644
--- a/drivers/hid/hid-steelseries-arctis.c
+++ b/drivers/hid/hid-steelseries-arctis.c
@@ -168,6 +168,16 @@ static void steelseries_arctis_9_parse_status(struct steelseries_device *sd,
sd->battery_charging = false;
}
}
+static void steelseries_arctis_nova_7_parse_status(struct steelseries_device *sd, u8 *data, int size)
+{
+ if (size < 4)
+ return;
+ if (data[0] == 0xb0) {
+ sd->headset_connected = (data[1] == 0x03);
+ sd->battery_capacity = steelseries_map_capacity(data[2], 0x00, 0x04);
+ sd->battery_charging = (data[3] == 0x01);
+ }
+}
static void steelseries_arctis_nova_7_gen2_parse_status(struct steelseries_device *sd,
u8 *data, int size)
@@ -219,6 +229,13 @@ static const struct steelseries_device_info arctis_nova_7_gen2_info = {
.parse_status = steelseries_arctis_nova_7_gen2_parse_status,
};
+static const struct steelseries_device_info arctis_nova_7_info = {
+ .sync_interface = 3,
+ .capabilities = SS_CAP_BATTERY,
+ .request_status = steelseries_arctis_nova_request_status,
+ .parse_status = steelseries_arctis_nova_7_parse_status,
+};
+
/*
* Headset wireless status and battery infrastructure
*/
@@ -599,6 +616,10 @@ static const struct hid_device_id steelseries_arctis_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
USB_DEVICE_ID_STEELSERIES_ARCTIS_9),
.driver_data = (unsigned long)&arctis_9_info },
+ { /* SteelSeries Arctis Nova 7X (0x2206) */
+ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+ USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X),
+ .driver_data = (unsigned long)&arctis_nova_7_info },
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_2026),
.driver_data = (unsigned long)&arctis_nova_7_gen2_info },
^ permalink raw reply related
* Re: [PATCH 05/10] mailbox: apple: Add DockChannel FIFO controller
From: Yureka Lilian @ 2026-07-04 20:14 UTC (permalink / raw)
To: michael.reeves077, Sven Peter, Janne Grunau, Neal Gompa,
Jassi Brar, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Hector Martin, Joerg Roedel (AMD), Will Deacon, Robin Murphy,
Dmitry Torokhov, Jiri Kosina, Benjamin Tissoires
Cc: asahi, linux-arm-kernel, linux-kernel, devicetree, iommu,
linux-input
In-Reply-To: <20260630-apple-mtp-keyboard-final-v1-5-506d936a1707@gmail.com>
On 6/30/26 14:54, Michael Reeves via B4 Relay wrote:
> From: Michael Reeves <michael.reeves077@gmail.com>
>
> DockChannel is a hardware FIFO used by Apple coprocessors for
> low-latency byte-stream communication with the AP.
>
> Add a mailbox controller that preallocates RX storage, tracks IRQ
> enable state in software, and reports TX completion from the TX-empty
> interrupt.
>
> Reject messages larger than the FIFO and return -EBUSY while the
> previous message is still pending. This keeps the provider usable for
> future small-message clients such as serial transports without a TX
> worker.
>
> Co-developed-by: Hector Martin <marcan@marcan.st>
> Signed-off-by: Hector Martin <marcan@marcan.st>
> Signed-off-by: Michael Reeves <michael.reeves077@gmail.com>
> ---
> MAINTAINERS | 2 +
> drivers/mailbox/Kconfig | 12 +
> drivers/mailbox/Makefile | 2 +
> drivers/mailbox/apple-dockchannel.c | 380 ++++++++++++++++++++++++++++++
> include/linux/mailbox/apple-dockchannel.h | 29 +++
> 5 files changed, 425 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1f3c2cdb6e19..ed68452c0ad6 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2628,6 +2628,7 @@ F: drivers/input/touchscreen/apple_z2.c
> F: drivers/iommu/apple-dart.c
> F: drivers/iommu/io-pgtable-dart.c
> F: drivers/irqchip/irq-apple-aic.c
> +F: drivers/mailbox/apple-dockchannel.c
> F: drivers/mfd/macsmc.c
> F: drivers/nvme/host/apple.c
> F: drivers/nvmem/apple-efuses.c
> @@ -2646,6 +2647,7 @@ F: drivers/video/backlight/apple_dwi_bl.c
> F: drivers/watchdog/apple_wdt.c
> F: include/dt-bindings/interrupt-controller/apple-aic.h
> F: include/dt-bindings/pinctrl/apple.h
> +F: include/linux/mailbox/apple-dockchannel.h
> F: include/linux/mfd/macsmc.h
> F: include/linux/soc/apple/*
> F: include/uapi/drm/asahi_drm.h
> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> index 3062ee352f78..f1af76d19f1e 100644
> --- a/drivers/mailbox/Kconfig
> +++ b/drivers/mailbox/Kconfig
> @@ -36,6 +36,18 @@ config ARM_MHU_V3
> that provides different means of transports: supported extensions
> will be discovered and possibly managed at probe-time.
>
> +config APPLE_DOCKCHANNEL
> + tristate "Apple DockChannel FIFO mailbox"
> + depends on ARCH_APPLE || COMPILE_TEST
> + depends on HAS_IOMEM
> + depends on OF
> + help
> + DockChannel is a hardware FIFO used on Apple Silicon SoCs for
> + communication between the application processor and co-processors.
> + This driver exposes DockChannel FIFOs through the mailbox framework.
> +
> + Say Y here if you have an M2 or later Apple MacBook.
> +
> config AST2700_MBOX
> tristate "ASPEED AST2700 IPC driver"
> depends on ARCH_ASPEED || COMPILE_TEST
> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> index 944d8ea39f34..4f3405064269 100644
> --- a/drivers/mailbox/Makefile
> +++ b/drivers/mailbox/Makefile
> @@ -11,6 +11,8 @@ obj-$(CONFIG_ARM_MHU_V2) += arm_mhuv2.o
>
> obj-$(CONFIG_ARM_MHU_V3) += arm_mhuv3.o
>
> +obj-$(CONFIG_APPLE_DOCKCHANNEL) += apple-dockchannel.o
> +
> obj-$(CONFIG_AST2700_MBOX) += ast2700-mailbox.o
>
> obj-$(CONFIG_CV1800_MBOX) += cv1800-mailbox.o
> diff --git a/drivers/mailbox/apple-dockchannel.c b/drivers/mailbox/apple-dockchannel.c
> new file mode 100644
> index 000000000000..bae183db1307
> --- /dev/null
> +++ b/drivers/mailbox/apple-dockchannel.c
> @@ -0,0 +1,380 @@
> +// SPDX-License-Identifier: GPL-2.0-only OR MIT
> +/*
> + * Apple DockChannel mailbox controller
> + *
> + * Copyright The Asahi Linux Contributors
> + *
> + * DockChannel is a byte FIFO used by Apple co-processors. This driver exposes a
> + * single FIFO pair as a Linux mailbox channel and moves payload bytes with PIO.
> + * There is no DMA involved, so relaxed MMIO accessors are sufficient for the
> + * FIFO accesses themselves.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/mailbox/apple-dockchannel.h>
> +#include <linux/mailbox_controller.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/spinlock.h>
> +#include <linux/unaligned.h>
> +
> +#define APPLE_DOCKCHANNEL_FIFO_SIZE 0x800
> +
> +#define IRQ_MASK 0x0
> +#define IRQ_FLAG 0x4
> +
> +#define IRQ_TX BIT(2)
> +#define IRQ_RX BIT(3)
> +
> +#define CONFIG_TX_THRESH 0x0
> +#define CONFIG_RX_THRESH 0x4
> +
> +#define DATA_TX8 0x4
> +#define DATA_TX32 0x10
> +#define DATA_TX_FREE 0x14
> +#define DATA_RX8 0x1c
> +#define DATA_RX32 0x28
> +#define DATA_RX_COUNT 0x2c
> +
> +struct apple_dockchannel {
> + struct device *dev;
> + struct mbox_controller controller;
> + struct mbox_chan chan;
> +
> + void __iomem *irq_base;
> + void __iomem *config_base;
> + void __iomem *data_base;
> + int irq;
> +
> + spinlock_t lock; /* protects IRQ mask and TX state */
> + u32 irq_mask;
> +
> + const u8 *tx_buf;
> + size_t tx_len;
> + size_t tx_pos;
> + bool tx_active;
> +
> + u8 rx_buf[APPLE_DOCKCHANNEL_FIFO_SIZE];
> +};
> +
> +static void apple_dockchannel_irq_update(struct apple_dockchannel *dc,
> + u32 bits, bool enable)
> +{
> + if (enable)
> + dc->irq_mask |= bits;
> + else
> + dc->irq_mask &= ~bits;
> + writel_relaxed(dc->irq_mask, dc->irq_base + IRQ_MASK);
> +}
> +
> +static void apple_dockchannel_irq_enable(struct apple_dockchannel *dc, u32 bits)
> +{
> + /*
> + * IRQ_FLAG is write-to-clear. Clear stale latched flags before
> + * unmasking so the next interrupt reflects current FIFO state.
> + */
> + writel_relaxed(bits, dc->irq_base + IRQ_FLAG);
> + apple_dockchannel_irq_update(dc, bits, true);
> +}
> +
> +static void apple_dockchannel_irq_disable(struct apple_dockchannel *dc, u32 bits)
> +{
> + apple_dockchannel_irq_update(dc, bits, false);
> +}
> +
> +static bool apple_dockchannel_tx_empty(struct apple_dockchannel *dc)
> +{
> + return readl_relaxed(dc->data_base + DATA_TX_FREE) ==
> + APPLE_DOCKCHANNEL_FIFO_SIZE;
> +}
> +
> +static void apple_dockchannel_write_pending(struct apple_dockchannel *dc)
> +{
> + size_t left = dc->tx_len - dc->tx_pos;
> + const u8 *p = dc->tx_buf + dc->tx_pos;
> +
> + while (left) {
> + size_t avail;
> + size_t block;
> +
> + avail = readl_relaxed(dc->data_base + DATA_TX_FREE);
> + if (!avail)
> + break;
> +
> + block = min(left, avail);
> +
> + while (block >= sizeof(u32)) {
> + writel_relaxed(get_unaligned_le32(p),
> + dc->data_base + DATA_TX32);
> + p += sizeof(u32);
> + left -= sizeof(u32);
> + block -= sizeof(u32);
> + }
> +
> + while (block) {
> + writeb_relaxed(*p++, dc->data_base + DATA_TX8);
This must be writel_relaxed, as writeb_relaxed in this mmio region will
cause an SError. This is why we have separate addresses putting 8-bits
and 32-bits into the FIFO I guess.
> + left--;
> + block--;
> + }
> + }
> +
> + dc->tx_pos = dc->tx_len - left;
> +}
> +
> +static void apple_dockchannel_read(struct apple_dockchannel *dc, void *buf,
> + size_t count)
> +{
> + u8 *p = buf;
> + size_t left = count;
> +
> + while (left >= sizeof(u32)) {
> + put_unaligned_le32(readl_relaxed(dc->data_base + DATA_RX32), p);
> + p += sizeof(u32);
> + left -= sizeof(u32);
> + }
> +
> + while (left) {
> + /*
> + * The byte FIFO register returns the byte in bits [15:8] on
> + * these instances.
> + */
> + *p++ = readl_relaxed(dc->data_base + DATA_RX8) >> 8;
> + left--;
> + }
> +}
> +
> +static int apple_dockchannel_send_data(struct mbox_chan *chan, void *data)
> +{
> + struct apple_dockchannel *dc = chan->con_priv;
> + struct apple_dockchannel_msg *msg = data;
> + unsigned long flags;
> +
> + if (!msg || !msg->data || !msg->len)
> + return -EINVAL;
> +
> + if (msg->len > APPLE_DOCKCHANNEL_FIFO_SIZE)
> + return -EMSGSIZE;
> +
> + spin_lock_irqsave(&dc->lock, flags);
> +
> + if (dc->tx_active || !apple_dockchannel_tx_empty(dc)) {
> + spin_unlock_irqrestore(&dc->lock, flags);
> + return -EBUSY;
> + }
> +
> + dc->tx_buf = msg->data;
> + dc->tx_len = msg->len;
> + dc->tx_pos = 0;
> + dc->tx_active = true;
> +
> + apple_dockchannel_write_pending(dc);
> + writel_relaxed(APPLE_DOCKCHANNEL_FIFO_SIZE,
> + dc->config_base + CONFIG_TX_THRESH);
> + apple_dockchannel_irq_enable(dc, IRQ_TX);
> +
> + spin_unlock_irqrestore(&dc->lock, flags);
> +
> + return 0;
> +}
> +
> +static int apple_dockchannel_startup(struct mbox_chan *chan)
> +{
> + struct apple_dockchannel *dc = chan->con_priv;
> + unsigned long flags;
> +
> + spin_lock_irqsave(&dc->lock, flags);
> + /*
> + * The mailbox framework has no per-client RX threshold. Use byte
> + * granularity because UART-style DockChannel clients require it.
> + */
> + writel_relaxed(1, dc->config_base + CONFIG_RX_THRESH);
> + apple_dockchannel_irq_enable(dc, IRQ_RX);
> + spin_unlock_irqrestore(&dc->lock, flags);
> +
> + enable_irq(dc->irq);
> +
> + return 0;
> +}
> +
> +static void apple_dockchannel_shutdown(struct mbox_chan *chan)
> +{
> + struct apple_dockchannel *dc = chan->con_priv;
> + unsigned long flags;
> +
> + disable_irq(dc->irq);
> +
> + spin_lock_irqsave(&dc->lock, flags);
> + apple_dockchannel_irq_disable(dc, IRQ_TX | IRQ_RX);
> + dc->tx_active = false;
> + spin_unlock_irqrestore(&dc->lock, flags);
> +}
> +
> +static const struct mbox_chan_ops apple_dockchannel_mbox_ops = {
> + .send_data = apple_dockchannel_send_data,
> + .startup = apple_dockchannel_startup,
> + .shutdown = apple_dockchannel_shutdown,
> +};
> +
> +static irqreturn_t apple_dockchannel_irq(int irq, void *data)
> +{
> + struct apple_dockchannel *dc = data;
> + u32 flags;
> + u32 pending;
> + bool tx_done = false;
> +
> + flags = readl_relaxed(dc->irq_base + IRQ_FLAG);
> +
> + spin_lock(&dc->lock);
> +
> + pending = flags & dc->irq_mask & (IRQ_TX | IRQ_RX);
> + if (!pending)
> + goto out_unlock_none;
> +
> + if (pending & IRQ_TX) {
> + if (apple_dockchannel_tx_empty(dc)) {
> + apple_dockchannel_irq_disable(dc, IRQ_TX);
> + tx_done = dc->tx_active;
> + dc->tx_active = false;
> + } else {
> + pending &= ~IRQ_TX;
> + }
> + }
> +
> + writel_relaxed(pending, dc->irq_base + IRQ_FLAG);
> +
> + spin_unlock(&dc->lock);
> +
> + if (tx_done)
> + mbox_chan_txdone(&dc->chan, 0);
> +
> + if (pending & IRQ_RX)
> + return IRQ_WAKE_THREAD;
> +
> + if (pending)
> + return IRQ_HANDLED;
> +
> + return IRQ_NONE;
> +
> +out_unlock_none:
> + spin_unlock(&dc->lock);
> +
> + if (flags & (IRQ_TX | IRQ_RX))
> + writel_relaxed(flags & (IRQ_TX | IRQ_RX),
> + dc->irq_base + IRQ_FLAG);
> +
> + return IRQ_NONE;
> +}
> +
> +static irqreturn_t apple_dockchannel_irq_thread(int irq, void *data)
> +{
> + struct apple_dockchannel *dc = data;
> +
> + for (;;) {
> + struct apple_dockchannel_msg msg;
> + size_t avail;
> +
> + avail = readl_relaxed(dc->data_base + DATA_RX_COUNT);
> + if (!avail)
> + break;
> +
> + avail = min_t(size_t, avail, APPLE_DOCKCHANNEL_FIFO_SIZE);
> +
> + apple_dockchannel_read(dc, dc->rx_buf, avail);
> +
> + msg.data = dc->rx_buf;
> + msg.len = avail;
> + mbox_chan_received_data(&dc->chan, &msg);
> + }
> +
> + return IRQ_HANDLED;
> +}
> +
> +static struct mbox_chan *
> +apple_dockchannel_of_xlate(struct mbox_controller *mbox,
> + const struct of_phandle_args *spec)
> +{
> + if (spec->args_count != 0)
> + return ERR_PTR(-EINVAL);
> +
> + return &mbox->chans[0];
> +}
> +
> +static int apple_dockchannel_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct apple_dockchannel *dc;
> + int ret;
> +
> + dc = devm_kzalloc(dev, sizeof(*dc), GFP_KERNEL);
> + if (!dc)
> + return -ENOMEM;
> +
> + dc->dev = dev;
> + spin_lock_init(&dc->lock);
> + platform_set_drvdata(pdev, dc);
> +
> + dc->irq_base = devm_platform_ioremap_resource_byname(pdev, "irq");
> + if (IS_ERR(dc->irq_base))
> + return PTR_ERR(dc->irq_base);
> +
> + dc->config_base = devm_platform_ioremap_resource_byname(pdev, "config");
> + if (IS_ERR(dc->config_base))
> + return PTR_ERR(dc->config_base);
> +
> + dc->data_base = devm_platform_ioremap_resource_byname(pdev, "data");
> + if (IS_ERR(dc->data_base))
> + return PTR_ERR(dc->data_base);
> +
> + writel_relaxed(0, dc->irq_base + IRQ_MASK);
> + writel_relaxed(~0, dc->irq_base + IRQ_FLAG);
> +
> + dc->irq = platform_get_irq(pdev, 0);
> + if (dc->irq < 0)
> + return dc->irq;
> +
> + ret = devm_request_threaded_irq(dev, dc->irq, apple_dockchannel_irq,
> + apple_dockchannel_irq_thread, IRQF_ONESHOT,
> + dev_name(dev), dc);
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to request IRQ\n");
> +
> + disable_irq(dc->irq);
> +
> + dc->chan.con_priv = dc;
> + dc->controller.dev = dev;
> + dc->controller.ops = &apple_dockchannel_mbox_ops;
> + dc->controller.chans = &dc->chan;
> + dc->controller.num_chans = 1;
> + dc->controller.txdone_irq = true;
> + dc->controller.of_xlate = apple_dockchannel_of_xlate;
> +
> + ret = devm_mbox_controller_register(dev, &dc->controller);
> + if (ret)
> + return dev_err_probe(dev, ret, "failed to register mailbox\n");
> +
> + return 0;
> +}
> +
> +static const struct of_device_id apple_dockchannel_of_match[] = {
> + { .compatible = "apple,t8122-dockchannel" },
> + { .compatible = "apple,t8112-dockchannel" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, apple_dockchannel_of_match);
> +
> +static struct platform_driver apple_dockchannel_driver = {
> + .driver = {
> + .name = "apple-dockchannel",
> + .of_match_table = apple_dockchannel_of_match,
> + },
> + .probe = apple_dockchannel_probe,
> +};
> +module_platform_driver(apple_dockchannel_driver);
> +
> +MODULE_DESCRIPTION("Apple DockChannel mailbox controller");
> +MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
> +MODULE_AUTHOR("Michael Reeves <michael.reeves077@gmail.com>");
> +MODULE_LICENSE("Dual MIT/GPL");
> diff --git a/include/linux/mailbox/apple-dockchannel.h b/include/linux/mailbox/apple-dockchannel.h
> new file mode 100644
> index 000000000000..04d2fc44f12f
> --- /dev/null
> +++ b/include/linux/mailbox/apple-dockchannel.h
> @@ -0,0 +1,29 @@
> +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
> +/*
> + * Apple DockChannel mailbox message format.
> + *
> + * Copyright The Asahi Linux Contributors
> + */
> +
> +#ifndef _LINUX_MAILBOX_APPLE_DOCKCHANNEL_H_
> +#define _LINUX_MAILBOX_APPLE_DOCKCHANNEL_H_
> +
> +#include <linux/types.h>
> +
> +/**
> + * struct apple_dockchannel_msg - DockChannel mailbox payload
> + * @data: Pointer to the byte stream payload
> + * @len: Number of payload bytes
> + *
> + * For TX, @data must remain valid until mbox_send_message() completes or the
> + * client receives tx_done in non-blocking mode.
> + *
> + * For RX, @data is owned by the controller and is valid only for the duration
> + * of the rx_callback.
> + */
> +struct apple_dockchannel_msg {
> + void *data;
> + size_t len;
> +};
> +
> +#endif /* _LINUX_MAILBOX_APPLE_DOCKCHANNEL_H_ */
>
^ permalink raw reply
* Re: [PATCH v2 2/6] iio: hid-sensors: align function parenthesis for readability
From: Jonathan Cameron @ 2026-07-04 23:07 UTC (permalink / raw)
To: srinivas pandruvada
Cc: Andy Shevchenko, Sanjay Chitroda via B4 Relay, sanjayembeddedse,
David Lechner, Nuno Sá, Andy Shevchenko, Jiri Kosina,
linux-iio, linux-kernel, linux-input
In-Reply-To: <e753606a89dbed26389d8c5ee8b2e4f0dafcd2f3.camel@linux.intel.com>
On Fri, 03 Jul 2026 18:09:39 -0700
srinivas pandruvada <srinivas.pandruvada@linux.intel.com> wrote:
> On Fri, 2026-07-03 at 15:52 +0300, Andy Shevchenko wrote:
> > On Thu, Jul 02, 2026 at 06:20:15PM +0100, Jonathan Cameron wrote:
> > > On Thu, 02 Jul 2026 21:47:59 +0530
> > > Sanjay Chitroda via B4 Relay
> > > <devnull+sanjayembeddedse.gmail.com@kernel.org> wrote:
> > >
> > > > Adjust alignment of parentheses across HID sensor IIO drivers to
> > > > improve readability and maintain consistency with kernel coding
> > > > style.
> > > >
> > > > While updating the formatting, group related arguments
> > > > consistently in
> > > > multi-line function signatures where appropriate.
> > > >
> > > > No functional change intended.
> > >
> > > Whilst I appreciate this code isn't quite in line with standards
> > > and usually like that stuff to be fixed up, in this particular case
> > > this is a massive amount of churn. That churn will make
> > > backporting
> > > fixes etc messier, so I'd like input on whether others consider
> > > this
> > > one worthwhile. Jiri, Srinivas, Andy etc. What do you think?
> >
> > I am fine as long as Srinivas is. I understand pros and cons of this,
> > but from
> > time to time we have patches à la this one that messes up with
> > backporting but
> > were accepted as a good part of some bigger series.
>
> I am fine. I guess we will deal with backporting issues as they appear.
We'll go ahead. So Sanjay, please send a new version rebased on
what I picked up already and with those inconsistencies tidied up.
Thanks,
Jonathan
>
> Thanks,
> Srinivas
>
^ permalink raw reply
* [PATCH v2 0/2] HID: logitech-hidpp: fix Signature M650 side button timing
From: Elliot Douglas @ 2026-07-04 23:10 UTC (permalink / raw)
To: linux-input; +Cc: lains, hadess, jikos, bentiss, linux-kernel, edouglas7358
In-Reply-To: <20260613175109.44365-1-edouglas7358@gmail.com>
The Logitech Signature M650 over Bluetooth exposes its side buttons in the
normal mouse report, but the reported BTN_SIDE/BTN_EXTRA events are short
click-like events emitted around button release rather than physical
press/release events with the real hold duration. The device appears to reserve
the held side-button state for a built-in gesture mode: holding a side button
long enough, or holding it while using the wheel for horizontal scrolling, can
mean the normal mouse report never emits a usable side-button press at all.
That makes the buttons unusable for standard Linux hold actions such as
push-to-talk, drag modifiers, or remapping rules that depend on key-up timing.
When HID++ 2.0 feature 0x1b04, SpecialKeysMseButtons /
REPROG_CONTROLS_V4, temporarily diverts the same controls, the device sends
diverted-control notifications with real press and release timing. This series
adds quirk-gated support for those notifications and enables it for the
Bluetooth Signature M650.
Before enabling diversion, the driver verifies that each mapped control is
present in the device's HID++ control table and is advertised as a divertable
mouse control.
The kernel only programs temporary diversion when the device connects. It
does not continuously force the setting. A userspace HID++ tool such as
Solaar can still issue HID++ commands through hidraw; if Solaar changes the
reporting mode for the same controls afterwards, the last writer wins. That
means Solaar can still take over those controls for custom actions, but the
kernel will no longer receive the diverted button notifications for normal
evdev reporting until the kernel diverts the controls again, for example after
reconnect. While the controls remain diverted, hidraw clients should still
receive the raw reports and the kernel reports the matching evdev state.
The diverted M650 controls are reported as BTN_BACK and BTN_FORWARD. Logitech's
Signature M650 getting-started page labels these physical controls as
Back/Forward buttons and describes their default page-navigation behavior:
https://support.logi.com/hc/en-nz/articles/4414473810583-Getting-Started-Signature-M650
The reprogrammable-control support is per-product and parses the full HID++
divertedButtonsEvent pressed-control list, so it can support devices with more
buttons without relying on a single last-control release heuristic. Only the
Signature M650 opts in for now. Other Logitech devices should only be enabled
after their HID++ control IDs and divertedButtonsEvent behavior are captured
and verified.
There is evidence that this is not unique to the M650. A prior MX Anywhere 3
patch used the same HID++ feature to fix thumb buttons that only activated on
release, and Logitech documents side-button + wheel horizontal scrolling for
both the MX Anywhere 3/3S and Signature M650. Solaar's device reports and rules
documentation also show HID++ divertable back/forward controls on MX Master 3
and MX Master 3S class devices. This series remains conservative and only
enables the device tested here.
Tested with a Logitech Signature M650 L over Bluetooth, HID ID
0005:046D:B02A. Baseline evtest showed short release-time BTN_SIDE/BTN_EXTRA
events. Earlier local testing of the same HID++ diversion path showed real
hold-duration press/release events, including holds longer than 4 seconds for
both buttons.
Changes in v2:
- Replace the profile/count wrapper with NULL-terminated mapping arrays.
- Cache the selected reprogrammable-control mapping in struct hidpp_device.
- Add a named constant for the M650 Bluetooth product ID.
- Use common Back/Forward names for the 0x0053/0x0056 HID++ control IDs.
Elliot Douglas (2):
HID: logitech-hidpp: add HID++ 2.0 reprogrammable button support
HID: logitech-hidpp: enable reprogrammable buttons on Signature M650
drivers/hid/hid-logitech-hidpp.c | 225 ++++++++++++++++++++++++++++++-
1 file changed, 224 insertions(+), 1 deletion(-)
base-commit: f0866517be9345d8245d32b722574b8aecccb348
--
2.54.0
^ permalink raw reply
* [PATCH v2 1/2] HID: logitech-hidpp: add HID++ 2.0 reprogrammable button support
From: Elliot Douglas @ 2026-07-04 23:10 UTC (permalink / raw)
To: linux-input; +Cc: lains, hadess, jikos, bentiss, linux-kernel, edouglas7358
In-Reply-To: <cover.1783094954.git.edouglas7358@gmail.com>
Some Logitech HID++ 2.0 mice can report diverted reprogrammable controls
through HID++ feature 0x1b04, SpecialKeysMseButtons / REPROG_CONTROLS_V4,
instead of the normal HID mouse report.
Add a quirk-gated event path for those controls. The handler temporarily
diverts verified per-product controls, parses divertedButtonsEvent as the
current pressed-control list, and reports the corresponding evdev key state
for every mapped control.
Keep the control mappings in per-product arrays so adding support for
another mouse does not change the evdev capabilities advertised by
already-supported devices.
Documentation for feature 0x1b04 describes divertedButtonsEvent as a list
of currently pressed diverted buttons, which is the event format handled
here.
Link: https://lekensteyn.nl/files/logitech/x1b04_specialkeysmsebuttons.html
Signed-off-by: Elliot Douglas <edouglas7358@gmail.com>
---
drivers/hid/hid-logitech-hidpp.c | 205 +++++++++++++++++++++++++++++++
1 file changed, 205 insertions(+)
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 70ba1a5e40d8..f9189e14fb78 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -76,6 +76,7 @@ MODULE_PARM_DESC(disable_tap_to_click,
#define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(28)
#define HIDPP_QUIRK_WIRELESS_STATUS BIT(29)
#define HIDPP_QUIRK_RESET_HI_RES_SCROLL BIT(30)
+#define HIDPP_QUIRK_HIDPP_REPROG_CONTROLS_BTNS BIT(31)
/* These are just aliases for now */
#define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS
@@ -178,6 +179,8 @@ struct hidpp_scroll_counter {
unsigned long long last_time;
};
+struct hidpp_reprog_control_mapping;
+
struct hidpp_device {
struct hid_device *hid_dev;
struct input_dev *input;
@@ -205,6 +208,8 @@ struct hidpp_device {
struct hidpp_scroll_counter vertical_wheel_counter;
u8 wireless_feature_index;
+ u8 reprog_controls_feature_index;
+ const struct hidpp_reprog_control_mapping *reprog_controls;
int hires_wheel_multiplier;
u8 hires_wheel_feature_index;
@@ -3601,6 +3606,195 @@ static int hidpp10_extra_mouse_buttons_raw_event(struct hidpp_device *hidpp,
return 1;
}
+/* -------------------------------------------------------------------------- */
+/* HID++2.0 reprogrammable controls */
+/* -------------------------------------------------------------------------- */
+
+#define HIDPP_PAGE_REPROG_CONTROLS_V4 0x1b04
+
+#define HIDPP_REPROG_CONTROLS_GET_COUNT 0x00
+#define HIDPP_REPROG_CONTROLS_GET_CID_INFO 0x10
+#define HIDPP_REPROG_CONTROLS_SET_CONTROL_REPORTING 0x30
+
+#define HIDPP_REPROG_CONTROLS_FLAG_MOUSE BIT(0)
+#define HIDPP_REPROG_CONTROLS_FLAG_DIVERT BIT(5)
+
+#define HIDPP_REPROG_CONTROLS_TEMPORARY_DIVERTED BIT(0)
+#define HIDPP_REPROG_CONTROLS_CHANGE_TEMPORARY_DIVERT BIT(1)
+
+#define HIDPP_REPROG_CONTROLS_EVENT_DIVERTED 0x00
+
+struct hidpp_reprog_control_mapping {
+ u16 control;
+ u16 code;
+};
+
+static const struct hidpp_reprog_control_mapping *
+hidpp20_reprog_controls_get_mappings(struct hidpp_device *hidpp)
+{
+ return NULL;
+}
+
+static int hidpp20_reprog_controls_get_count(struct hidpp_device *hidpp)
+{
+ struct hidpp_report response;
+ u8 feature_index = hidpp->reprog_controls_feature_index;
+ u8 cmd = HIDPP_REPROG_CONTROLS_GET_COUNT;
+ int ret;
+
+ ret = hidpp_send_fap_command_sync(hidpp, feature_index, cmd, NULL, 0,
+ &response);
+ if (ret > 0)
+ return -EPROTO;
+ if (ret)
+ return ret;
+
+ return response.fap.params[0];
+}
+
+static int hidpp20_reprog_controls_get_cid_info(struct hidpp_device *hidpp,
+ u8 index, u16 *control,
+ u8 *flags)
+{
+ struct hidpp_report response;
+ u8 feature_index = hidpp->reprog_controls_feature_index;
+ u8 cmd = HIDPP_REPROG_CONTROLS_GET_CID_INFO;
+ int ret;
+
+ ret = hidpp_send_fap_command_sync(hidpp, feature_index, cmd, &index,
+ sizeof(index), &response);
+ if (ret > 0)
+ return -EPROTO;
+ if (ret)
+ return ret;
+
+ *control = get_unaligned_be16(&response.fap.params[0]);
+ *flags = response.fap.params[4];
+
+ return 0;
+}
+
+static bool hidpp20_reprog_controls_find_control(struct hidpp_device *hidpp,
+ u16 control)
+{
+ int count, ret;
+ u16 cid;
+ u8 flags;
+ int i;
+
+ count = hidpp20_reprog_controls_get_count(hidpp);
+ if (count < 0)
+ return false;
+
+ for (i = 0; i < count; i++) {
+ ret = hidpp20_reprog_controls_get_cid_info(hidpp, i, &cid,
+ &flags);
+ if (ret)
+ return false;
+
+ if (cid == control)
+ return (flags & HIDPP_REPROG_CONTROLS_FLAG_MOUSE) &&
+ (flags & HIDPP_REPROG_CONTROLS_FLAG_DIVERT);
+ }
+
+ return false;
+}
+
+static int hidpp20_reprog_controls_set_control_reporting(struct hidpp_device *hidpp,
+ u16 control, u8 flags)
+{
+ struct hidpp_report response;
+ u8 params[5];
+
+ put_unaligned_be16(control, ¶ms[0]);
+ params[2] = flags;
+ put_unaligned_be16(control, ¶ms[3]);
+
+ return hidpp_send_fap_command_sync(hidpp,
+ hidpp->reprog_controls_feature_index,
+ HIDPP_REPROG_CONTROLS_SET_CONTROL_REPORTING,
+ params, sizeof(params), &response);
+}
+
+static void hidpp20_reprog_controls_connect(struct hidpp_device *hidpp)
+{
+ const struct hidpp_reprog_control_mapping *mapping;
+ u8 flags = HIDPP_REPROG_CONTROLS_TEMPORARY_DIVERTED |
+ HIDPP_REPROG_CONTROLS_CHANGE_TEMPORARY_DIVERT;
+
+ if (!(hidpp->quirks & HIDPP_QUIRK_HIDPP_REPROG_CONTROLS_BTNS))
+ return;
+
+ if (!hidpp->reprog_controls)
+ return;
+
+ if (hidpp_root_get_feature(hidpp, HIDPP_PAGE_REPROG_CONTROLS_V4,
+ &hidpp->reprog_controls_feature_index))
+ return;
+
+ for (mapping = hidpp->reprog_controls; mapping->control; mapping++) {
+ if (!hidpp20_reprog_controls_find_control(hidpp, mapping->control))
+ continue;
+
+ hidpp20_reprog_controls_set_control_reporting(hidpp,
+ mapping->control,
+ flags);
+ }
+}
+
+static int hidpp20_reprog_controls_raw_event(struct hidpp_device *hidpp,
+ u8 *data, int size)
+{
+ const struct hidpp_reprog_control_mapping *mapping;
+ struct hidpp_report *report = (struct hidpp_report *)data;
+ u16 controls[4];
+ bool pressed;
+ unsigned int i, j;
+
+ if (!(hidpp->quirks & HIDPP_QUIRK_HIDPP_REPROG_CONTROLS_BTNS) ||
+ !hidpp->input ||
+ !hidpp->reprog_controls ||
+ hidpp->reprog_controls_feature_index == 0xff)
+ return 0;
+
+ if (size < HIDPP_REPORT_LONG_LENGTH ||
+ report->fap.feature_index != hidpp->reprog_controls_feature_index ||
+ report->fap.funcindex_clientid != HIDPP_REPROG_CONTROLS_EVENT_DIVERTED)
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(controls); i++)
+ controls[i] = get_unaligned_be16(&report->fap.params[i * 2]);
+
+ for (mapping = hidpp->reprog_controls; mapping->control; mapping++) {
+ pressed = false;
+
+ for (j = 0; j < ARRAY_SIZE(controls); j++) {
+ if (controls[j] == mapping->control) {
+ pressed = true;
+ break;
+ }
+ }
+
+ input_report_key(hidpp->input, mapping->code, pressed);
+ }
+
+ input_sync(hidpp->input);
+
+ return 1;
+}
+
+static void hidpp20_reprog_controls_populate_input(struct hidpp_device *hidpp,
+ struct input_dev *input_dev)
+{
+ const struct hidpp_reprog_control_mapping *mapping;
+
+ if (!hidpp->reprog_controls)
+ return;
+
+ for (mapping = hidpp->reprog_controls; mapping->control; mapping++)
+ input_set_capability(input_dev, EV_KEY, mapping->code);
+}
+
static void hidpp10_extra_mouse_buttons_populate_input(
struct hidpp_device *hidpp, struct input_dev *input_dev)
{
@@ -3859,6 +4053,9 @@ static void hidpp_populate_input(struct hidpp_device *hidpp,
if (hidpp->quirks & HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS)
hidpp10_extra_mouse_buttons_populate_input(hidpp, input);
+
+ if (hidpp->quirks & HIDPP_QUIRK_HIDPP_REPROG_CONTROLS_BTNS)
+ hidpp20_reprog_controls_populate_input(hidpp, input);
}
static int hidpp_input_configured(struct hid_device *hdev,
@@ -3971,6 +4168,10 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
return ret;
}
+ ret = hidpp20_reprog_controls_raw_event(hidpp, data, size);
+ if (ret != 0)
+ return ret;
+
if (hidpp->quirks & HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS) {
ret = hidpp10_consumer_keys_raw_event(hidpp, data, size);
if (ret != 0)
@@ -4264,6 +4465,8 @@ static void hidpp_connect_event(struct work_struct *work)
return;
}
+ hidpp20_reprog_controls_connect(hidpp);
+
if (hidpp->quirks & HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS) {
ret = hidpp10_consumer_keys_connect(hidpp);
if (ret)
@@ -4436,6 +4639,8 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
hidpp->hid_dev = hdev;
hidpp->name = hdev->name;
hidpp->quirks = id->driver_data;
+ hidpp->reprog_controls_feature_index = 0xff;
+ hidpp->reprog_controls = hidpp20_reprog_controls_get_mappings(hidpp);
hid_set_drvdata(hdev, hidpp);
ret = hid_parse(hdev);
--
2.54.0
^ permalink raw reply related
* [PATCH v2 2/2] HID: logitech-hidpp: enable reprogrammable buttons on Signature M650
From: Elliot Douglas @ 2026-07-04 23:10 UTC (permalink / raw)
To: linux-input; +Cc: lains, hadess, jikos, bentiss, linux-kernel, edouglas7358
In-Reply-To: <cover.1783094954.git.edouglas7358@gmail.com>
The Bluetooth Signature M650 exposes its side buttons through the normal
mouse report, but the observed events are short click-like events emitted
around release rather than physical press/release state.
The device appears to use the held side-button state for its built-in
gesture and side-button + wheel horizontal-scroll mode. As a result,
holding a side button long enough can prevent the normal mouse report from
emitting a usable button event at all.
HID++ REPROG_CONTROLS_V4 diversion for control IDs 0x0053 and 0x0056
provides real press and release timing for those same controls. Logitech
documents the Signature M650 side buttons as Back/Forward buttons, so
report the diverted controls as BTN_BACK and BTN_FORWARD.
The HID++ 0x1b04 documentation lists those control IDs as Back and
Forward. The driver still verifies that the controls are present in the
device control table and advertised as divertable before changing their
reporting mode.
Link: https://support.logi.com/hc/en-nz/articles/4414473810583-Getting-Started-Signature-M650
Signed-off-by: Elliot Douglas <edouglas7358@gmail.com>
---
drivers/hid/hid-logitech-hidpp.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index f9189e14fb78..e71dd2457e80 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -3624,14 +3624,30 @@ static int hidpp10_extra_mouse_buttons_raw_event(struct hidpp_device *hidpp,
#define HIDPP_REPROG_CONTROLS_EVENT_DIVERTED 0x00
+#define HIDPP_REPROG_CONTROL_BACK 0x0053
+#define HIDPP_REPROG_CONTROL_FORWARD 0x0056
+
+#define HIDPP_PRODUCT_SIGNATURE_M650 0xb02a
+
struct hidpp_reprog_control_mapping {
u16 control;
u16 code;
};
+static const struct hidpp_reprog_control_mapping m650_reprog_control_mappings[] = {
+ { HIDPP_REPROG_CONTROL_BACK, BTN_BACK },
+ { HIDPP_REPROG_CONTROL_FORWARD, BTN_FORWARD },
+ { }
+};
+
static const struct hidpp_reprog_control_mapping *
hidpp20_reprog_controls_get_mappings(struct hidpp_device *hidpp)
{
+ switch (hidpp->hid_dev->product) {
+ case HIDPP_PRODUCT_SIGNATURE_M650:
+ return m650_reprog_control_mappings;
+ }
+
return NULL;
}
@@ -4911,7 +4927,9 @@ static const struct hid_device_id hidpp_devices[] = {
{ /* MX Vertical mouse over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb020) },
{ /* Signature M650 over Bluetooth */
- HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb02a) },
+ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
+ HIDPP_PRODUCT_SIGNATURE_M650),
+ .driver_data = HIDPP_QUIRK_HIDPP_REPROG_CONTROLS_BTNS },
{ /* MX Master 3 mouse over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb023) },
{ /* MX Anywhere 3 mouse over Bluetooth */
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v2 1/2] HID: logitech-hidpp: add HID++ 2.0 reprogrammable button support
From: sashiko-bot @ 2026-07-04 23:23 UTC (permalink / raw)
To: Elliot Douglas; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <d4c48a9d36c738abd02a0430a6ca8a5a792fb3ea.1783094954.git.edouglas7358@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Dangling pointer `hidpp->input` leads to Use-After-Free if `input_register_device()` fails.
- [High] Unbounded 64-byte structure copy in `hidpp_raw_hidpp_event` causes a Kernel Heap Out-of-Bounds Read.
--
commit 13dc21807e8eb6f76d9029e89353e4bd2e6aa1c3
Author: Elliot Douglas <edouglas7358@gmail.com>
Subject: HID: logitech-hidpp: add HID++ 2.0 reprogrammable button support
Some Logitech HID++ 2.0 mice can report diverted reprogrammable controls
through HID++ feature 0x1b04, SpecialKeysMseButtons / REPROG_CONTROLS_V4,
instead of the normal HID mouse report.
Link: https://lekensteyn.nl/files/logitech/x1b04_specialkeysmsebuttons.html
> diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
> index 70ba1a5e40d8e..f9189e14fb780 100644
> --- a/drivers/hid/hid-logitech-hidpp.c
> +++ b/drivers/hid/hid-logitech-hidpp.c
[ ... ]
> @@ -3601,6 +3606,195 @@ static int hidpp10_extra_mouse_buttons_raw_event(struct hidpp_device *hidpp,
[ ... ]
> +static int hidpp20_reprog_controls_raw_event(struct hidpp_device *hidpp,
> + u8 *data, int size)
> +{
> + const struct hidpp_reprog_control_mapping *mapping;
> + struct hidpp_report *report = (struct hidpp_report *)data;
> + u16 controls[4];
> + bool pressed;
> + unsigned int i, j;
> +
> + if (!(hidpp->quirks & HIDPP_QUIRK_HIDPP_REPROG_CONTROLS_BTNS) ||
> + !hidpp->input ||
[Severity: High]
This is a pre-existing issue, but could this lead to a use-after-free?
Looking at hidpp_connect_event(), if input_register_device() fails, it
cleans up by calling input_free_device() but leaves the hidpp->input
pointer dangling:
ret = input_register_device(input);
if (ret) {
input_free_device(input);
return;
}
Because hid_device_io_start() has already enabled incoming packets before
this point, could a newly arriving event trigger this new
hidpp20_reprog_controls_raw_event() handler, pass the !hidpp->input check,
and dereference the freed pointer?
> + !hidpp->reprog_controls ||
> + hidpp->reprog_controls_feature_index == 0xff)
> + return 0;
[ ... ]
> @@ -3971,6 +4168,10 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
> return ret;
> }
>
> + ret = hidpp20_reprog_controls_raw_event(hidpp, data, size);
> + if (ret != 0)
> + return ret;
> +
[Severity: High]
This is a pre-existing issue, but does hidpp_raw_hidpp_event() perform an
out-of-bounds read on the incoming data buffer?
Earlier in this function, if the packet matches a pending question, it does
a direct structure assignment:
if (hidpp_match_answer(question, report) ||
hidpp_match_error(question, report)) {
*answer = *report;
Since struct hidpp_report is a 64-byte packed structure, won't this pointer
assignment perform a fixed 64-byte copy regardless of the actual size of the
received buffer (which could be as small as 7 bytes for a
REPORT_ID_HIDPP_SHORT packet)?
Could this copy adjacent heap memory into the answer buffer, potentially
leaking it when the data is parsed later?
> if (hidpp->quirks & HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS) {
> ret = hidpp10_consumer_keys_raw_event(hidpp, data, size);
> if (ret != 0)
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1783094954.git.edouglas7358@gmail.com?part=1
^ permalink raw reply
* Re: [PATCH] Input: ims-pcu - add missing MODULE_DEVICE_TABLE()
From: Dmitry Torokhov @ 2026-07-04 23:35 UTC (permalink / raw)
To: Pengpeng Hou
Cc: open list:INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN)...,
linux-kernel
In-Reply-To: <20260704151730.42772-1-pengpeng@iscas.ac.cn>
On Sat, Jul 04, 2026 at 11:17:30PM +0800, Pengpeng Hou wrote:
> The driver has a match table for the usb bus wired into its driver
> structure, but the table is not exported with MODULE_DEVICE_TABLE().
>
> Add the missing MODULE_DEVICE_TABLE() entry so module alias information
> is generated for automatic module loading.
>
> This is a source-level fix. It does not claim dynamic hardware
> reproduction; the evidence is the driver-owned match table, its use by
> the driver registration structure, and the missing module alias
> publication.
>
> Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Applied, thank you.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v2 1/7] Input: elan_i2c - Wait for initialization after enabling regulator supply
From: Dmitry Torokhov @ 2026-07-04 23:44 UTC (permalink / raw)
To: Chen-Yu Tsai
Cc: Matthias Brugger, AngeloGioacchino Del Regno, Benson Leung,
Tzung-Bi Shih, Jiri Kosina, Andi Shyti, linux-mediatek,
devicetree, linux-arm-kernel, chrome-platform, linux-input,
linux-i2c, linux-kernel
In-Reply-To: <20260703115601.1323491-2-wenst@chromium.org>
Hi Chen-Yu,
On Fri, Jul 03, 2026 at 07:55:54PM +0800, Chen-Yu Tsai wrote:
> Elan trackpad controllers require some delay after enabling power to
> the controller for the hardware and firmware to initialize:
>
> - 2ms for hardware initialization
> - 100ms for firmware initialization
>
> Until then, the hardware will not respond to I2C transfers. This was
> observed on the MT8173 Chromebooks after the regulator supply for the
> trackpad was changed to "not always on".
>
> Add proper delays after regulator_enable() calls. To avoid impacting
> the boot time of existing devices that have the power rails always on,
> skip the delay if the regulator supply was already enabled. In this
> case the regulator is either always on, was on by default at power up,
> or was left on by some other driver, such as the I2C OF component
> prober. Either way the controller has had ample time to initialize.
Unfortunately we do not know that [it had ample time]. For this code be
reliable we need to record the time at which given regulator was turned
on and then execute/adjust the delay as needed. Until we have it we need
to assume the regulator was enabled at the time of regulator_enable()
call.
I am not concerned with increased boot time too much given the driver is
set up for asynchronous probing.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH 18/26] sh: maple: introduce callback_mutex in maple_device
From: Dmitry Torokhov @ 2026-07-04 23:50 UTC (permalink / raw)
To: Florian Fuchs
Cc: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz,
Adrian McMenamin, linux-kernel, linux-input, linux-mtd, linux-sh
In-Reply-To: <akkrQJfxSCvUptC4@lithos>
Hi Florian,
On Sat, Jul 04, 2026 at 05:48:16PM +0200, Florian Fuchs wrote:
> Hi Dmitry,
>
> On 03 Jul 22:57, Dmitry Torokhov wrote:
> > The Maple bus core invokes client callbacks asynchronously from a
> > workqueue (maple_dma_handler). If a device is removed (or closed) while
> > a callback is in flight, it can lead to UAF bugs if the driver's private
> > data is freed.
> >
> > Introduce callback_mutex in struct maple_device to synchronize
> > callback registration/modification and callback invocation.
...
>
> Thank you so much for your efforts. I can confirm sashikos finding in my
> test (that I saw later),
Thank you for giving the series a spin!
> that this patch hangs the bus if a VMU memcard
> is inserted. So that the peripherals don't work anymore after insertion
> of the memcard. With a last log like:
> Dreamcast_visual_memory 3:01.E: VMU at (3, 1) is busy
Yes, indeed, I overlooked the vmu-flash use case. I will introduce a
lockless way of setting up the callback and a wrapper that takes the
lock and that should solve the deadlock in vmu-flash driver.
I wonder if you had a chance top try out the preceding patches and if
they worked for you? If they do and you can add your tested-by I should
be able to pick up at least the input patches that do not need maple
core changes...
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v2 2/2] iio: inkern: Use namespaced exports
From: Jonathan Cameron @ 2026-07-05 1:07 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Romain Gantois, MyungJoo Ham, Chanwoo Choi, Guenter Roeck,
Peter Rosin, David Lechner, Nuno Sá, Andy Shevchenko,
Lars-Peter Clausen, Michael Hennerich, Mariel Tinaco, Kevin Tsai,
Linus Walleij, Eugen Hristev, Vinod Koul, Kishon Vijay Abraham I,
Sebastian Reichel, Chen-Yu Tsai, Hans de Goede,
Support Opensource, Paul Cercueil, Iskren Chernev,
Krzysztof Kozlowski, Marek Szyprowski, Matheus Castello,
Saravanan Sekar, Matthias Brugger, AngeloGioacchino Del Regno,
Casey Connolly, Pali Rohár, Orson Zhai, Baolin Wang,
Chunyan Zhang, Amit Kucheria, Thara Gopinath, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Claudiu Beznea,
Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
Sylwester Nawrocki, Olivier Moysan, Arnaud Pouliquen,
Maxime Coquelin, Alexandre Torgue, Thomas Petazzoni, linux-kernel,
linux-hwmon, linux-iio, linux-input, linux-phy, linux-pm,
linux-mips, linux-mediatek, linux-arm-msm, linux-sound,
linux-stm32, Sebastian Reichel, Andy Shevchenko
In-Reply-To: <20260603182052.7d23c067@jic23-huawei>
On Wed, 3 Jun 2026 18:20:52 +0100
Jonathan Cameron <jic23@kernel.org> wrote:
> On Sun, 22 Mar 2026 15:24:21 -0700
> Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
>
> > On Tue, Dec 09, 2025 at 09:25:56AM +0100, Romain Gantois wrote:
> > > Use namespaced exports for IIO consumer API functions.
> > >
> > > This will make it easier to manage the IIO export surface. Consumer drivers
> > > will only be provided access to a specific set of functions, thereby
> > > restricting usage of internal IIO functions by other parts of the kernel.
> > >
> > > This change cannot be split into several parts without breaking
> > > bisectability, thus all of the affected drivers are modified at once.
> > >
> > > Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com> # for power-supply
> > > Acked-by: Guenter Roeck <linux@roeck-us.net>
> > > Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
> > > Signed-off-by: Romain Gantois <romain.gantois@bootlin.com>
> >
> > For input:
> >
> > Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> >
> > Thanks.
> >
>
> For anyone wondering what happened to this... I forgot to apply this at the
> beginning of the cycle and by the time I remembered we had too much queued up
> so it would have been messy to do an immutable branch. Anyhow, I plan to
> sort this at start of next cycle.
Immutable branch created as: iio-inkern-namespace-ib based on v7.2-rc1
on https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
I've merged it into the testing branch of iio.git so if anyone else does
need to merge this to avoid conflicts, perhaps wait a day or two until
I've pushed it out as togreg for linux-next to pick up.
Thanks,
Jonathan
>
> Jonathan
^ permalink raw reply
* Re: [PATCH] Input: zinitix: iterate contact slots by finger count
From: Nikita Travkin @ 2026-07-05 7:13 UTC (permalink / raw)
To: Linus Walleij
Cc: Thanh Nguyen, dmitry.torokhov, linux-input, linux-kernel,
linus.walleij, timon37
In-Reply-To: <CAD++jLknVJYLc0-StNFcN67pUDRQunUJvNn-Npz+HJ-j2WXB5g@mail.gmail.com>
Linus Walleij писал(а) 30.06.2026 14:11:
> Hi Thanh,
>
> sorry for slow reply!
>
> On Wed, Apr 8, 2026 at 6:19 AM Thanh Nguyen <thanhnguyxn07@gmail.com> wrote:
>>
>> On affected devices (for example Samsung A3 2015), the value in
>> touch_event.finger_mask appears to behave as a count of reported slots
>> rather than a bitmask. Using for_each_set_bit() can then skip valid
>> contacts and break multitouch gestures.
>>
>> Keep filtering by SUB_BIT_EXIST to avoid reporting shadow contacts, but
>> iterate from slot 0 up to min(finger_mask, MAX_SUPPORTED_FINGER_NUM).
>> This follows the maintainer feedback to treat the field as a possible
>> count while preserving the anti-shadow check.
>>
>> Fixes: e941dc13fd37 ("Input: zinitix - do not report shadow fingers")
>> Link: https://bugzilla.kernel.org/show_bug.cgi?id=221278
>> Signed-off-by: Thanh Nguyen <thanhnguyxn07@gmail.com>
>> ---
>> v2:
>> - Address maintainer feedback: do not revert e941dc13fd37.
>> - Keep SUB_BIT_EXIST filtering to avoid shadow contacts.
>> - Treat finger_mask as a slot-count bound and iterate 0..min(mask, max).
>
> I can test this if need be, but maybe Nikita want to check it
> first?
>
Hi!
I've quickly checked it on my gt58 (bt532) but it made me remember that
on this device/chip it seems like only "TOUCH_MODE=0" is supported and
reported fingers don't have extra "width"/"angle" fields. (I have a
vague recollection that this was somehow related to touchkeys being
enabled or not) Otherwise on this chip (firmware? touch_mode?) the
finger count is indeed a count and not a mask.
Given we have an EXIST bit IMO it still makes sense to make this change.
Maybe also worth adding a short comment why we're treating mask as
count if Linus's devices report mask and your/mine report count...
Nikita
> Yours,
> Linus Walleij
^ 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