Linux Input/HID development
 help / color / mirror / Atom feed
* Re: [PATCH 05/26] Input: maplecontrol - stop polling and clear callback on close
From: sashiko-bot @ 2026-07-04  6:07 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260703-b4-maple-cleanup-v1-5-41e424964da5@gmail.com>

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

Pre-existing issues:
- [High] The event reporting loop in `dc_pad_callback()` does not call `input_sync()` after reporting a group of input events.
--

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

Input: maplecontrol - stop polling and clear callback on close

In dc_pad_close(), pass NULL instead of dc_pad_callback to
maple_getcond_callback() to both stop polling and clear the callback
pointer when the input device is closed.

> diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
> index a498fc322c4d5..c66b2614e2982 100644
> --- a/drivers/input/joystick/maplecontrol.c
> +++ b/drivers/input/joystick/maplecontrol.c
> @@ -74,8 +74,7 @@ static void dc_pad_close(struct input_dev *dev)
>  {
>  	struct dc_pad *pad = dev_get_platdata(&dev->dev);
>  
> -	maple_getcond_callback(pad->mdev, dc_pad_callback, 0,
> -		MAPLE_FUNC_CONTROLLER);
> +	maple_getcond_callback(pad->mdev, NULL, 0, MAPLE_FUNC_CONTROLLER);
>  }

[Severity: High]
This isn't a bug introduced by this patch, but since dc_pad_callback() is
involved here, is there a missing call to input_sync()?

Looking at dc_pad_callback(), it reports several events without ever flushing
them:

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 input_sync(), EV_SYN/SYN_REPORT events are never generated.

Will this prevent the input core from waking up userspace readers (like
evdev), causing reported events to be indefinitely buffered until the buffer
overflows?

Since maple_dma_handler calls dc_pad_callback() on every data transfer to
report new joystick states, does this omission break event propagation and
make the joystick unresponsive for applications relying on poll() or blocking
read()?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260703-b4-maple-cleanup-v1-0-41e424964da5@gmail.com?part=5

^ permalink raw reply

* Re: [PATCH 3/3] Input: mms114 - fix Y-resolution configuration
From: sashiko-bot @ 2026-07-04  6:08 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260704060115.353049-3-dmitry.torokhov@gmail.com>

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

Pre-existing issues:
- [High] Unsafe DMA buffer allocation on the stack for I2C transfers.
--

commit b2ece0d05aab20ebd4014035e04b87c4d9127c9f
Author: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Subject: Input: mms114 - fix Y-resolution configuration

This commit fixes a copy-paste error in mms114_setup_regs() where
props->max_x was being used instead of props->max_y to configure the
lower bits of the Y resolution.

> diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
> index 84afdadb3bccc..27911a9f4e9eb 100644
> --- a/drivers/input/touchscreen/mms114.c
> +++ b/drivers/input/touchscreen/mms114.c
> @@ -408,7 +408,7 @@ static int mms114_setup_regs(struct mms114_data *data)
>  	if (error < 0)
>  		return error;
>  
> -	val = props->max_x & 0xff;
> +	val = props->max_y & 0xff;
>  	error = mms114_write_reg(data, MMS114_Y_RESOLUTION, val);

[Severity: High]
This is a pre-existing issue, but since mms114_write_reg() is called here,
is it safe for the driver to use stack-allocated buffers for I2C transfers?

Looking at mms114_write_reg():

static int mms114_write_reg(struct mms114_data *data, u8 reg, u8 val)
{
        struct i2c_client *client = data->client;
        u8 buf[2];
        ...
        buf[0] = reg;
        buf[1] = val;

        error = i2c_master_send(client, buf, 2);

If the underlying I2C adapter uses DMA for transfers and CONFIG_VMAP_STACK is
enabled, passing a stack-allocated buffer to i2c_master_send() can cause memory
corruption or kernel panics because stack memory is not DMA-safe.

A similar pattern appears in __mms114_read_reg() and mms114_interrupt():

static int __mms114_read_reg(struct mms114_data *data, unsigned int reg, ...)
{
        ...
        u8 buf = reg;
        ...
        xfer[0].buf = &buf;
        ...
        error = i2c_transfer(client->adapter, xfer, 2);

and in mms114_interrupt(), a large array is allocated on the stack and passed
down through __mms114_read_reg():

        struct mms114_touch touch[MMS114_MAX_TOUCH];
        ...
        error = __mms114_read_reg(data, MMS114_INFORMATION,
                                  MMS114_MAX_TOUCH * sizeof(struct mms114_touch),
                                  (u8 *)touch);

Could these stack-allocated buffers lead to instability on DMA-capable I2C
controllers? Should these buffers be moved to the mms114_data struct so they
are dynamically allocated on the heap?

>  	if (error < 0)
>  		return error;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260704060115.353049-1-dmitry.torokhov@gmail.com?part=3

^ permalink raw reply

* Re: [PATCH 14/26] mtd: maps: vmu-flash: remove unused mdev->driver assignment
From: sashiko-bot @ 2026-07-04  6:08 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260703-b4-maple-cleanup-v1-14-41e424964da5@gmail.com>

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

Pre-existing issues:
- [Critical] Dangling pointers for `fileerr_handler` and `can_unload` left on `maple_device` if `probe` fails.
- [Critical] Use-after-free of `card` structure due to dangling `mdev->callback` on probe error path.
- [High] Out-of-bounds read in `vmu_connect` when parsing device `function_data`.
- [High] NULL pointer dereference in `vmu_disconnect` if `vmu_queryblocks` fails.
--

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

mtd: maps: vmu-flash: remove unused mdev->driver assignment

This commit removes the unused assignment to mdev->driver and the now unused
mdrv variable in probe_maple_vmu. The driver field in struct maple_device is
no longer used since earlier cleanups.

> diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c
> index 10244e6731d07..8f7028ac1b56a 100644
> --- a/drivers/mtd/maps/vmu-flash.c
> +++ b/drivers/mtd/maps/vmu-flash.c
> @@ -772,11 +772,9 @@ static void vmu_file_error(struct maple_device *mdev, void *recvbuf)
>  static int probe_maple_vmu(struct device *dev)
>  {
>  	struct maple_device *mdev = to_maple_dev(dev);
> -	struct maple_driver *mdrv = to_maple_driver(dev->driver);
>  
>  	mdev->can_unload = vmu_can_unload;
>  	mdev->fileerr_handler = vmu_file_error;
> -	mdev->driver = mdrv;
>  
>  	return vmu_connect(mdev);

[Severity: Critical]
This is a pre-existing issue, but if vmu_connect() fails below, are these
pointers properly cleared?

If vmu_connect() fails, the probe aborts and the device is left unbound, but
the function pointers to vmu_can_unload() and vmu_file_error() remain
assigned to the persistent maple_device structure. 

If the vmu-flash module is subsequently unloaded, could a later
MAPLE_RESPONSE_FILEERR event cause the maple bus core to dereference the
now-dangling mdev->fileerr_handler pointer?

>  }

While reviewing the context of this patch, I noticed a few other pre-existing
issues in the surrounding code:

> static int vmu_connect(struct maple_device *mdev)
> {
> 	unsigned long test_flash_data, basic_flash_data;
> 	int c, error;
> 	struct memcard *card;
> 	u32 partnum = 0;
> 
> 	test_flash_data = be32_to_cpu(mdev->devinfo.function);
> 	/* Need to count how many bits are set - to find out which
> 	 * function_data element has details of the memory card
> 	 */
> 	c = hweight_long(test_flash_data);
> 
> 	basic_flash_data = be32_to_cpu(mdev->devinfo.function_data[c - 1]);

[Severity: High]
This is a pre-existing issue, but does this array access risk an out-of-bounds
read?

Since test_flash_data is derived directly from the hardware packet, it could
have up to 32 bits set. If a malfunctioning device reports 0 bits or more than
3 bits set, does using c - 1 read past the bounds of the 3-element
function_data array?

[ ... ]

> 	/*
> 	* We want to trap meminfo not get cond
> 	* so set interval to zero, but rely on maple bus
> 	* driver to pass back the results of the meminfo
> 	*/
> 	maple_getcond_callback(mdev, vmu_queryblocks, 0,
> 		MAPLE_FUNC_MEMCARD);

[ ... ]

> 	error = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD,
> 		MAPLE_COMMAND_GETMINFO, 2, &partnum);
> 	if (error) {
> 		dev_err(&mdev->dev, "Could not lock VMU at (%d, %d)"
> 			" error is 0x%X\n", mdev->port, mdev->unit, error);
> 		goto fail_mtd_info;
> 	}
> 	return 0;
> 
> fail_device_busy:
> 	kfree(card->mtd);
> fail_mtd_info:
> 	kfree(card->parts);
> fail_partitions:
> 	kfree(card);
> fail_nomem:
> 	return error;
> }

[Severity: Critical]
This is a pre-existing issue, but if maple_add_packet() fails, is the card
structure freed while the callback is still active?

In vmu_connect(), an asynchronous callback is registered via
maple_getcond_callback(). If a subsequent operation like maple_add_packet()
fails, the error path frees the card structure but does not clear
mdev->callback.

If a delayed or stray MAPLE_RESPONSE_DATATRF packet arrives later, could
maple_dma_handler() invoke the lingering mdev->callback, writing hardware
response data to the already freed card memory?

Regarding vmu_disconnect():

If vmu_queryblocks() fails, it branches to an error path that frees the
priv pointer and sets it to NULL:

> 	for (error = 0; error <= card->partition; error++) {
> 		kfree(((card->mtd)[error]).priv);
> 		((card->mtd)[error]).priv = NULL;
> 	}

Because the initial probe returned success, the device remains bound. When
it is eventually disconnected, vmu_disconnect() executes:

> 	for (x = 0; x < card->partitions; x++) {
> 		mpart = ((card->mtd)[x]).priv;
> 		mpart->mdev = NULL;

[Severity: High]
This is a pre-existing issue, but if vmu_queryblocks() encountered an
asynchronous failure earlier, will vmu_disconnect() blindly dereference a
NULL pointer here?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260703-b4-maple-cleanup-v1-0-41e424964da5@gmail.com?part=14

^ permalink raw reply

* Re: [PATCH 10/26] Input: maplecontrol - remove redundant drvdata resetting
From: sashiko-bot @ 2026-07-04  6:09 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260703-b4-maple-cleanup-v1-10-41e424964da5@gmail.com>

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

Pre-existing issues:
- [Medium] Missing `input_sync()` in the event reporting callback, causing events to not be flushed to userspace.
--

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

Input: maplecontrol - remove redundant drvdata resetting

This patch removes redundant maple_set_drvdata(mdev, NULL) calls from the probe
error paths and device removal functions. The driver core automatically resets
driver data to NULL on probe failures and device removal, making these manual
resets unnecessary.

> diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
> index 6293b6e8148b3..79cec89ad52a9 100644
> --- a/drivers/input/joystick/maplecontrol.c
> +++ b/drivers/input/joystick/maplecontrol.c
> @@ -62,20 +62,19 @@ static void dc_pad_callback(struct mapleq *mq)
>  
>  static int dc_pad_open(struct input_dev *dev)
>  {

[Severity: Medium]
This is a pre-existing issue, but I noticed something while looking at the
code nearby.

In drivers/input/joystick/maplecontrol.c:dc_pad_callback():

	input_report_abs(dev, ABS_RX,     res[14]);
	input_report_abs(dev, ABS_RY,     res[15]);
}

Should this callback include a call to input_sync(dev) before returning?

Without input_sync(), won't the reported events (buttons and axes) be queued
in the input core but not immediately delivered to userspace?

This could lead to delayed or dropped inputs since they would only be delivered
if another event forces a sync.

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260703-b4-maple-cleanup-v1-0-41e424964da5@gmail.com?part=10

^ permalink raw reply

* Re: [PATCH 16/26] sh: maple: remove unused driver field from struct maple_device
From: sashiko-bot @ 2026-07-04  6:09 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260703-b4-maple-cleanup-v1-16-41e424964da5@gmail.com>

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

Pre-existing issues:
- [High] vmu_can_unload() crashes on hot-unplug if the driver fails to probe or is unbound.
--

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

sh: maple: remove unused driver field from struct maple_device

The commit removes the unused driver field from struct maple_device since all 
readers and writers of this field have been eliminated from the maple bus code.

> diff --git a/include/linux/maple.h b/include/linux/maple.h
> index 22f2930251edc..90c26c86e3ede 100644
> --- a/include/linux/maple.h
> +++ b/include/linux/maple.h
> @@ -64,7 +64,6 @@ struct maple_devinfo {
>  };
>  
>  struct maple_device {
> -	struct maple_driver *driver;
>  	struct mapleq *mq;
>  	void (*callback) (struct mapleq * mq);
>  	void (*fileerr_handler)(struct maple_device *mdev, void *recvbuf);

[Severity: High]
This is a pre-existing issue, but while reviewing changes to struct
maple_device, I noticed a potential null pointer dereference in the vmu-flash
driver.

In drivers/mtd/maps/vmu-flash.c:probe_maple_vmu(), the can_unload callback is
set:

probe_maple_vmu() {
        ...
        mdev->can_unload = vmu_can_unload;
        ...
}

If probe fails during device connection or if the driver is unbound via sysfs,
the driver core clears the device's driver data to NULL. However,
mdev->can_unload remains pointing to vmu_can_unload.

If the device is subsequently hot-unplugged, the maple bus core calls
maple_response_none() -> mdev->can_unload(mdev), which dereferences the
driver data without checking if it is NULL:

vmu_can_unload() {
        ...
        card = maple_get_drvdata(mdev);
        for (x = 0; x < card->partitions; x++) {
        ...
}

Could this cause a system crash on hot-unplug? Should mdev->can_unload be
cleared on the probe error path and during unbind?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260703-b4-maple-cleanup-v1-0-41e424964da5@gmail.com?part=16

^ permalink raw reply

* Re: [PATCH 06/26] Input: maplecontrol - simplify maple_device retrieval in open/close
From: sashiko-bot @ 2026-07-04  6:10 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260703-b4-maple-cleanup-v1-6-41e424964da5@gmail.com>

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

New issues:
- [Low] The commit leaves behind an unused `mdev` field in `struct dc_pad` and a corresponding dead store in `probe_maple_controller`, leading to unnecessary code complexity and memory allocation.

Pre-existing issues:
- [High] The event reporting callback `dc_pad_callback` fails to call `input_sync()` after reporting a full frame of input events.
--

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

Input: maplecontrol - simplify maple_device retrieval in open/close

This commit simplifies how the maple_device is retrieved in the open and close
callbacks. It stores the maple_device directly in the input device's drvdata,
removing the need to access it via the platform_data's dc_pad structure.

> diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
> index c66b2614e2982..9d623c9e8f22c 100644
> --- a/drivers/input/joystick/maplecontrol.c
> +++ b/drivers/input/joystick/maplecontrol.c
> @@ -62,19 +62,19 @@ static void dc_pad_callback(struct mapleq *mq)

[Severity: High]
This is a pre-existing issue, but does dc_pad_callback() need a call to
input_sync() after reporting its frame of input events?

The input subsystem requires all logical groups of events to be synchronized.
Without input_sync(), userspace applications may not see the events until a
SYN_REPORT is forced by a buffer overflow or another event.

[ ... ]

> @@ -112,6 +112,7 @@ static int probe_maple_controller(struct device *dev)
>  	pad->mdev = mdev;
>  
>  	maple_set_drvdata(mdev, pad);
> +	input_set_drvdata(idev, mdev);

[Severity: Low]
Does this commit leave the mdev field in struct dc_pad unused?

Now that the input device retrieves mdev from drvdata, the only remaining
used field in struct dc_pad appears to be dev.

Could struct dc_pad be completely eliminated by storing the idev pointer
directly as the Maple device's private data, avoiding the devm_kzalloc()
overhead entirely?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260703-b4-maple-cleanup-v1-0-41e424964da5@gmail.com?part=6

^ permalink raw reply

* Re: [PATCH 03/26] Input: maplecontrol - only enable present axes
From: sashiko-bot @ 2026-07-04  6:10 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260703-b4-maple-cleanup-v1-3-41e424964da5@gmail.com>

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

Pre-existing issues:
- [High] The event reporting callback fails to emit an EV_SYN/SYN_REPORT event, preventing userspace from receiving state updates.
--

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

Input: maplecontrol - only enable present axes

The driver was unconditionally enabling all possible analog axes and hats on
the input device, even if the controller reported it did not have them in
its function data. This patch moves the input_set_abs_params() calls inside
the capability check loop and corrects the D-pad (hat) axis limits.

> diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
> index 6293b6e8148b3..a498fc322c4d5 100644
> --- a/drivers/input/joystick/maplecontrol.c
> +++ b/drivers/input/joystick/maplecontrol.c

[ ... ]

[Severity: High]
This isn't a bug introduced by this patch, but the event reporting callback
fails to emit an EV_SYN/SYN_REPORT event.

Looking at dc_pad_callback() in drivers/input/joystick/maplecontrol.c:

    ...
	input_report_abs(dev, ABS_GAS,    res[10]);
	input_report_abs(dev, ABS_BRAKE,  res[11]);
	input_report_abs(dev, ABS_X,      res[12]);
	input_report_abs(dev, ABS_Y,      res[13]);
	input_report_abs(dev, ABS_RX,     res[14]);
	input_report_abs(dev, ABS_RY,     res[15]);
}

Without calling input_sync(dev) at the end of the callback, won't the evdev
input driver queue these events indefinitely without waking up userspace
readers? Does this prevent userspace from receiving state updates?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260703-b4-maple-cleanup-v1-0-41e424964da5@gmail.com?part=3

^ permalink raw reply

* Re: [PATCH 1/3] Input: mms114 - fix multi-touch slot corruption
From: sashiko-bot @ 2026-07-04  6:11 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260704060115.353049-1-dmitry.torokhov@gmail.com>

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

Pre-existing issues:
- [High] If `mms114_start()` fails during system resume, subsequent device close or suspend causes unbalanced `disable_irq()` and `regulator_disable()` calls, leaving the touchscreen permanently broken.
- [High] The suspend callback releases all touches before disabling the device interrupt, creating a race window where touches can get permanently stuck.
- [High] Stack-allocated buffers are passed directly to I2C transfer functions, which can cause DMA mapping failures or memory corruption.
--

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

Input: mms114 - fix multi-touch slot corruption

This commit fixes a multi-touch slot corruption bug in the mms114 driver.
When the touchscreen controller reports a touch ID of 0, the driver
calculates the slot ID as touch->id - 1, which underflows to UINT_MAX. The
driver fixes this by rejecting touch reports with ID 0.

> diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
> index 006dded17eb80..23e0283bc6b8b 100644
> --- a/drivers/input/touchscreen/mms114.c
> +++ b/drivers/input/touchscreen/mms114.c
> @@ -248,7 +248,7 @@ static void mms114_process_mt(struct mms114_data *data, struct mms114_touch *tou
>  	unsigned int x;
>  	unsigned int y;
>  
> -	if (touch->id > MMS114_MAX_TOUCH) {
> +	if (touch->id == 0 || touch->id > MMS114_MAX_TOUCH) {
>  		dev_err(&client->dev, "Wrong touch id (%d)\n", touch->id);
>  		return;
>  	}

[Severity: High]
This isn't a bug introduced by this patch, but I have a question about the
error handling in mms114_resume().

If mms114_start() fails (e.g. mms114_setup_regs() returns an error) it cleans
up the regulators but doesn't call enable_irq():

static int mms114_start(struct mms114_data *data)
{
...
	error = mms114_setup_regs(data);
	if (error < 0) {
		regulator_disable(data->io_reg);
		regulator_disable(data->core_reg);
		return error;
	}

	enable_irq(client->irq);
	return 0;
}

In mms114_resume(), the error is passed back up but the input device remains
logically open:

static int mms114_resume(struct device *dev)
{
...
	if (input_device_enabled(input_dev)) {
		error = mms114_start(data);
		if (error)
			return error;
	}
...
}

Because the input device is still logically enabled, won't a subsequent
suspend or input_close call mms114_stop(), which unconditionally calls
disable_irq() and regulator_disable()? Does this cause an unbalanced IRQ
disable depth that permanently masks the interrupt?

[Severity: High]
This is a pre-existing issue, but I noticed a potential race condition in
mms114_suspend().

The suspend callback releases all active touch slots before stopping the
device and disabling the interrupt:

static int mms114_suspend(struct device *dev)
{
...
	/* 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_mt_report_pointer_emulation(input_dev, true);
	input_sync(input_dev);

	guard(mutex)(&input_dev->mutex);

	if (input_device_enabled(input_dev))
		mms114_stop(data);
...
}

If a touch interrupt fires between the synthetic slot release and the call to
mms114_stop() (which disables the IRQ), could the physical touches be reported
as active again just as the device is suspended, leaving the touches
permanently stuck on resume?

[Severity: High]
This isn't a bug introduced by this patch, but there seem to be multiple
places where stack-allocated buffers are used for I2C transfers.

For example, in __mms114_read_reg(), a single byte stack variable is passed:

static int __mms114_read_reg(struct mms114_data *data, u8 reg,
			     unsigned int len, void *val)
{
...
	u8 buf = reg;
...
	xfer[0].buf = &buf;
...
	error = i2c_transfer(client->adapter, xfer, 2);
...
}

Similarly in mms114_write_reg():

static int mms114_write_reg(struct mms114_data *data, u8 reg, u8 val)
{
...
	u8 buf[2];

	buf[0] = reg;
	buf[1] = val;

	error = i2c_master_send(client, buf, 2);
...
}

And in mms114_interrupt():

	struct mms114_touch touch[MMS114_MAX_TOUCH];
...
	error = __mms114_read_reg(data, MMS114_INFORMATION, packet_size, touch);
...

Since many I2C controllers use DMA, doesn't passing stack memory to
i2c_transfer() risk DMA mapping failures or memory corruption when
CONFIG_VMAP_STACK is enabled?

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

^ permalink raw reply

* 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


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