* Re: [PATCH v5 4/6] dt-bindings: mfd: motorola-cpcap: document Mapphone and Mot CPCAP
From: sashiko-bot @ 2026-05-11 21:37 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: robh, dmitry.torokhov, linux-input, conor+dt, devicetree, krzk+dt
In-Reply-To: <20260510110804.33045-5-clamor95@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The schema prevents the use of the generic `motorola,cpcap` fallback for the new compatible strings, which will break device probing.
--
commit 43b55cbad252ef116a236dfd195512e35a6f5c82
Author: Svyatoslav Ryhel <clamor95@gmail.com>
dt-bindings: mfd: motorola-cpcap: document Mapphone and Mot CPCAP
Add compatibles for Mapphone and Mot CPCAP subdevice compositions. Both
variations cannot use st,6556002 fallback since they may be based on
different controllers.
> diff --git a/Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml b/Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml
> index 7f257f3a1a5a2..542d149d2b39c 100644
> --- a/Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml
> +++ b/Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml
> @@ -14,9 +14,14 @@ allOf:
>
> properties:
> compatible:
> - items:
> - - const: motorola,cpcap
> - - const: st,6556002
> + oneOf:
> + - enum:
> + - motorola,mapphone-cpcap
> + - motorola,mot-cpcap
Will this prevent the use of motorola,cpcap as a fallback for the new
compatible strings? It looks like this branch of the schema requires devices
to provide only a single compatible string.
Looking at the OMAP4 board code for Mapphone devices, it explicitly matches
against the generic motorola,cpcap string:
arch/arm/mach-omap2/pmic-cpcap.c:cpcap_init() {
...
if (!of_find_compatible_node(NULL, NULL, "motorola,cpcap"))
return -ENODEV;
...
}
By forbidding motorola,cpcap as a fallback in the bindings, will device trees
updated to pass schema validation (by using only the new specific compatibles)
fail to find the node at runtime in the board code?
If the node is not found, does this prevent the initialization of the CPCAP
PMIC voltage regulators on OMAP4 devices, breaking power management and
voltage scaling?
Could the schema permit motorola,cpcap as a fallback for the new compatible
strings, perhaps by using an items list with the new strings as the first
item and motorola,cpcap as the const fallback?
> +
> + - items:
> + - const: motorola,cpcap
> + - const: st,6556002
>
> reg:
> maxItems: 1
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260510110804.33045-1-clamor95@gmail.com?part=4
^ permalink raw reply
* Re: [PATCH 3/4] HID: hid-msi-claw: Add RGB control interface
From: Derek J. Clark @ 2026-05-11 21:55 UTC (permalink / raw)
To: sashiko, sashiko-bot; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260511212230.21800C2BCB0@smtp.kernel.org>
On May 11, 2026 2:22:29 PM PDT, sashiko-bot@kernel.org wrote:
>Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
>- [High] `speed_show()` incorrectly casts the LED class device pointer to a `hid_device`, leading to an out-of-bounds memory read and kernel crash.
>- [High] Deadlock and missing return in `cfg_setup_fn` when handling initialization errors.
>- [High] Sysfs attributes re-arm the cancelled delayed work after device teardown, leading to a Use-After-Free.
>- [High] Racy nullification of `brightness_set` causes a TOCTOU NULL pointer dereference.
>- [Medium] Communication failure in `claw_read_rgb_config` leaves the profile parser in a corrupted state.
>--
>
>commit 9663adbabcba6be0b443e7073133d650a790c871
>Author: Derek J. Clark <derekjohn.clark@gmail.com>
>
>HID: hid-msi-claw: Add RGB control interface
>
>Adds RGB control interface for MSI Claw devices with 9 total zones and
>supports up to 8 sequential frames of RGB zone data.
>
>> diff --git a/drivers/hid/hid-msi-claw.c b/drivers/hid/hid-msi-claw.c
>> index 60694d075d56f..f4fe74a784c29 100644
>> --- a/drivers/hid/hid-msi-claw.c
>> +++ b/drivers/hid/hid-msi-claw.c
>
>[ ... ]
>
>> @@ -743,6 +836,389 @@ static const struct attribute_group claw_gamepad_attr_group = {
>> .is_visible = claw_gamepad_attr_is_visible,
>> };
>>
>> +/* Read RGB config from device */
>> +static int claw_read_rgb_config(struct hid_device *hdev)
>> +{
>> + u8 data[4] = { 0x01, 0x00, 0x00, CLAW_RGB_FRAME_OFFSET };
>> + struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
>> + u16 read_addr = drvdata->rgb_addr;
>> + size_t len = ARRAY_SIZE(data);
>> + int ret, i;
>> +
>> + if (!drvdata->rgb_addr)
>> + return -ENODEV;
>> +
>> + /* Loop through all 8 pages of RGB data */
>> + for (i = 0; i < 8; i++) {
>> + drvdata->profile_pending = CLAW_RGB_PENDING;
>> + data[1] = (read_addr >> 8) & 0xff;
>> + data[2] = read_addr & 0x00ff;
>> + ret = mcu_property_out(hdev, CLAW_COMMAND_TYPE_READ_PROFILE, data, len, 8);
>> + if (ret)
>> + return ret;
>
>If mcu_property_out() fails here, does drvdata->profile_pending remain set
>to CLAW_RGB_PENDING? If a subsequent unrelated profile event or stray ACK
>arrives, could claw_profile_event() incorrectly parse its payload as an RGB
>frame?
>
Hi AI bot,
I am responding for the humans that will be reading this.
Valid. Pending should be reset after errors. TBS, I need to find a way to push pending assignment into the mutex, or there will be issues as found in the other message.
>[ ... ]
>
>> +static ssize_t speed_show(struct device *dev, struct device_attribute *attr,
>> + char *buf)
>> +{
>> + struct hid_device *hdev = to_hid_device(dev);
>> + struct claw_drvdata *drvdata = hid_get_drvdata(hdev);
>
>Since the rgb_attr_group attributes are attached to the LED class device
>rather than the HID device, does to_hid_device(dev) result in an invalid
>pointer dereference here? Other sysfs functions in this patch seem to
>correctly use dev_get_drvdata(dev) to retrieve the led_classdev.
>
Also valid, though it doesn't crash when run it would be more proper to treat the led cdev as the parent.
>
>> @@ -758,6 +1234,13 @@ static void cfg_setup_fn(struct work_struct *work)
>> claw_remove(drvdata->hdev);
>> }
>>
>> + ret = claw_read_rgb_config(drvdata->hdev);
>> + if (ret) {
>> + dev_err(drvdata->led_mc.led_cdev.dev,
>> + "Failed to setup device, can't read RGB config: %d\n", ret);
>> + claw_remove(drvdata->hdev);
>> + }
>
>If claw_remove() is called from within the cfg_setup worker thread, and
>claw_remove() calls cancel_delayed_work_sync(&drvdata->cfg_setup), won't
>this deadlock waiting for itself to complete?
Since it's a void function I can't return an error. I suppose it can just dev_err and return without initializing any sysfs attributes.
>Also, since there is no return statement after claw_remove() is called in
>these error blocks, will this proceed to execute the rest of the function on
>a stopped device?
>
>[ ... ]
>
>> @@ -881,6 +1405,9 @@ static void claw_remove(struct hid_device *hdev)
>>
>> if (drvdata->endpoint == CLAW_XINPUT_CFG_INTF_IN ||
>> drvdata->endpoint == CLAW_DINPUT_CFG_INTF_IN) {
>> + /* Block writes to brightness/multi_intensity during teardown */
>> + drvdata->led_mc.led_cdev.brightness_set = NULL;
>
>Is it safe to dynamically nullify the brightness_set callback here? If a
>concurrent brightness update in the LED core checks the pointer, sees it as
>valid, and then this nullification happens before the actual function call,
>could it result in a NULL pointer dereference?
This was done specifically to address a timing issue with the LED core and userspace writing to brightness during teardown. Without this we will get a null pointer dereference when the brightness function calls mcu_property_out.
>> + cancel_delayed_work_sync(&drvdata->rgb_queue);
>
>Since the LED class device is registered with devres
>(devm_led_classdev_multicolor_register), the sysfs attributes like effect,
>speed, and enabled remain accessible until after claw_remove() completes.
>
>If userspace writes to any of those attributes in this window, could
>mod_delayed_work() re-arm rgb_queue, leading to a use-after-free when
>drvdata is subsequently freed?
>
Swapping this and the sysfs remove after should solve it.
-
>> sysfs_remove_group(&hdev->dev.kobj, &claw_gamepad_attr_group);
>> cancel_delayed_work_sync(&drvdata->cfg_setup);
>> cancel_delayed_work_sync(&drvdata->cfg_resume);
>
^ permalink raw reply
* Re: [PATCH 2/4] HID: hid-msi-claw: Add M-key mapping attributes
From: Derek J. Clark @ 2026-05-11 21:59 UTC (permalink / raw)
To: sashiko, sashiko-bot; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260511205107.C2030C2BCB0@smtp.kernel.org>
On May 11, 2026 1:51:07 PM PDT, sashiko-bot@kernel.org wrote:
>Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>- [High] Data race on `drvdata->profile_pending` and lack of transaction atomicity during concurrent sysfs accesses.
>--
>
>commit b9bc6d29326e3dd3ed065aca7059668a1b674bc8
>Author: Derek J. Clark <derekjohn.clark@gmail.com>
>
>HID: hid-msi-claw: Add M-key mapping attributes
>
>Adds sysfs attributes to remap the M1 and M2 rear buttons to up to 5 events
>(gamepad, keyboard, or mouse) when in macro mode.
>
>> diff --git a/drivers/hid/hid-msi-claw.c b/drivers/hid/hid-msi-claw.c
>> index 7a3cd940ec49e..60694d075d56f 100644
>> --- a/drivers/hid/hid-msi-claw.c
>> +++ b/drivers/hid/hid-msi-claw.c
>[ ... ]
>> +static int claw_buttons_store(struct device *dev, const char *buf, u8 mkey_idx)
>> +{
>[ ... ]
>> +set_buttons:
>> + ret = mcu_property_out(hdev, CLAW_COMMAND_TYPE_WRITE_PROFILE_DATA, data, len, 8);
>> + if (ret < 0)
>> + goto err_free;
>> +
>> + ret = mcu_property_out(hdev, CLAW_COMMAND_TYPE_SYNC_TO_ROM, NULL, 0, 0);
>
>Is it possible for concurrent writers to interleave these commands?
>
>Looking at mcu_property_out(), it takes the cfg_mutex internally, but there
>is no lock held across both calls here. If a second writer executes its
>WRITE_PROFILE_DATA before the first writer executes SYNC_TO_ROM, could the MCU
>be left in an inconsistent state?
>
No, the sync to rom simply writes the state to permanent memory so it remains in the same configuration after a power cycle. The first call writes it to temporary storage.
>[ ... ]
>> +static int claw_buttons_show(struct device *dev, char *buf, enum claw_key_index m_key)
>> +{
>[ ... ]
>> + codes = (m_key == CLAW_KEY_M1) ? drvdata->m1_codes : drvdata->m2_codes;
>> + drvdata->profile_pending = (m_key == CLAW_KEY_M1) ? CLAW_M1_PENDING : CLAW_M2_PENDING;
>> +
>> + ret = mcu_property_out(hdev, CLAW_COMMAND_TYPE_READ_PROFILE, data, len, 8);
>
>Can concurrent reads of button_m1 and button_m2 race and corrupt the
>profile_pending state?
>
>If Thread A and Thread B access the sysfs attributes simultaneously,
>profile_pending is updated locklessly here before mcu_property_out() takes
>the cfg_mutex.
>
>Could Thread B overwrite profile_pending to CLAW_M2_PENDING before Thread A's
>command executes? If so, when the hardware replies to Thread A's M1 command,
>claw_profile_event() might route Thread A's data into Thread B's m2_codes
>buffer and clear the state to CLAW_NO_PENDING.
>
>This would cause Thread B's subsequent reply to be dropped and trigger the
>"Got profile event without changes pending" warning.
>
Possible. I'll look at improving this pattern by managing the pending flag with a mutex.
- Derek
^ permalink raw reply
* [BUG] ALSA: usb-audio: use-after-free in snd_dualsense_ih_match during rapid USB reconnect
From: Sean Brar @ 2026-05-11 21:58 UTC (permalink / raw)
To: linux-input, linux-sound
Cc: roderick.colenbrander, jikos, bentiss, perex, tiwai
A rapid USB disconnect/reconnect cycle on a DualSense controller
(054c:0ce6) triggers a use-after-free in snd_dualsense_ih_match()
(sound/usb/mixer_quirks.c), resulting in a general protection fault
and leaving the USB subsystem in an unrecoverable state requiring a
hard reboot.
Kernel version: 7.0.5-arch1-1 (also reproduced the trigger on
7.0.3-arch1-2; affected code in sound/usb/mixer_quirks.c is
unchanged on current mainline)
Hardware:
- Sony DualSense Wireless Controller (054c:0ce6, bcdDevice=1.00)
- hw_version=0x00000711, fw_version=0x0110002a
- Host: Gigabyte B550 AORUS PRO AC, BIOS F17 03/22/2024
Trigger condition:
When connected to a degraded USB port (intermittent electrical
contact), the DualSense enters a rapid disconnect/reconnect cycle.
snd_usb_audio times out (ETIMEDOUT, -110) querying mixer controls
during probe, each timeout triggers a USB reset, and the device
reconnects every 1–2 seconds. This is not a driver bug, it's the
expected kernel behavior when USB communication is unreliable, but
it creates a race window for the use-after-free described below.
The bug:
In sound/usb/mixer_quirks.c, snd_dualsense_ih_match() is invoked as
an input handler match callback from input_register_device() during
ps_probe() (hid_playstation). At line 575, it obtains a pointer to
the USB device struct:
snd_dev = mei->info.head.mixer->chip->dev;
It then uses this pointer in dev_warn() calls at lines 579 and 585:
dev_warn(&snd_dev->dev, "Failed to get input dev path\n");
dev_warn(&snd_dev->dev, "Failed to get USB dev path\n");
No reference is taken on snd_dev. If the USB device is concurrently
disconnected and freed while snd_dualsense_ih_match() is executing,
snd_dev becomes a dangling pointer. The dev_warn() call dereferences
snd_dev->dev.kobj.name via dev_vprintk_emit() → strnlen(), faulting
on the freed memory.
The OOPS offset (snd_dualsense_ih_match.cold+0xf/0x2b) corresponds
to the first dev_warn() at line 579. The compiler placed both error
branches in a cold section, and the offset is consistent with the
earlier branch.
OOPS:
Oops: general protection fault, probably for non-canonical address
0x441f0ffa1e0ff3: 0000 [#1] SMP NOPTI
CPU: 14 UID: 0 PID: 108 Comm: kworker/14:0 Not tainted 7.0.5-arch1-1
#1 PREEMPT(full)
Hardware name: Gigabyte Technology Co., Ltd. B550 AORUS PRO AC/B550
AORUS PRO AC, BIOS F17 03/22/2024
Workqueue: usb_hub_wq hub_event
RIP: 0010:strnlen+0x29/0x40
RSP: 0018:ffffce3f40537378 EFLAGS: 00010202
RAX: 00441f0ffa1e0ff3 RBX: 00441f0ffa1e0ff3 RCX: 0000000000000000
RDX: 00441f0ffa1e1003 RSI: 0000000000000010 RDI: 00441f0ffa1e0ff3
RBP: ffffce3f40537408 R08: 0000000000000000 R09: ffffce3f40537478
R10: 0000000000000004 R11: ffffffffc20ebe12 R12: ffff8943511c80b0
R13: ffff8943511c80b0 R14: ffff894345daf028 R15: ffffce3f40537418
FS: 0000000000000000(0000) GS:ffff8962144e7000(0000)
knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000055e7f9dc3c18 CR3: 0000000135ffe000 CR4: 0000000000f50ef0
Stack trace:
Call Trace:
<TASK>
dev_vprintk_emit+0x70/0x1b0
dev_printk_emit+0x61/0x7b
__dev_printk+0x2d/0x70
_dev_warn+0x7f/0x99
snd_dualsense_ih_match.cold+0xf/0x2b [snd_usb_audio
a3e71fdbdb8c7ccfdfdb57dadc854b1d1e18445c]
input_attach_handler.isra.0+0x4b/0xa0
input_register_device.cold+0xf8/0x1f0
ps_probe+0xf79/0x10dc [hid_playstation
0cc5feea5231aa914fe418c8a06b14588cd5f064]
hid_device_probe+0x1b8/0x270
hid_add_device+0xcd/0x130
usbhid_probe+0x49b/0x6c0
usb_probe_interface+0xf8/0x2f0
usb_set_configuration+0x738/0x920
usb_generic_driver_probe+0x4a/0x70
usb_probe_device+0x44/0x170
usb_new_device.cold+0x154/0x3fd
hub_event+0x129d/0x1ad0
process_one_work+0x19c/0x3a0
worker_thread+0x1b1/0x310
kthread+0xe1/0x120
ret_from_fork+0x2bc/0x350
ret_from_fork_asm+0x1a/0x30
</TASK>
---[ end trace 0000000000000000 ]---
Analysis:
The race is between two concurrent paths:
1. Probe: hub_event → usb_new_device → ... → ps_probe →
input_register_device → input_attach_handler →
snd_dualsense_ih_match (accesses USB device struct at line 575)
2. Disconnect: hub_event → usb_disconnect → ... → USB device
struct freed
snd_dualsense_ih_match() retrieves snd_dev via the mixer→chip→dev
chain at line 575 without taking a reference. A concurrent disconnect
can free the USB device struct before the subsequent dev_warn() call
dereferences it. The faulting RDI value (0x441f0ffa1e0ff3) is
non-canonical and consistent with SLUB freed-object poisoning,
confirming a use-after-free.
Impact:
After the OOPS, the USB subsystem is left in an unrecoverable state:
all USB ports stop enumerating devices (including ports not involved
in the reconnect cycle), and a clean shutdown hangs in USB driver
teardown. A hard reset is required. The trigger condition (rapid USB
reconnection due to a degraded port) is a normal hardware failure
mode.
Workaround:
# /etc/modprobe.d/dualsense.conf
options snd_usb_audio ignore_ctl_error=1
This suppresses the mixer control timeouts that drive the reconnect
cycle, preventing the race window from opening. DualSense headphone
jack audio controls may not function correctly with this option.
Steps to reproduce:
Disconnect/reconnect loop (the trigger condition):
1. Load hid_playstation and snd_usb_audio (default on standard
desktop kernels)
2. Connect a DualSense (054c:0ce6) via USB to a port with
unreliable electrical contact
3. Observe rapid disconnect/reconnect in dmesg -w, with device
number incrementing each cycle
The OOPS:
The OOPS was observed after the loop ran for several minutes. Exact
timing-dependent reproduction beyond triggering the loop is not
confirmed; this was observed once and not retested to avoid the
unrecoverable USB hang.
Kernel .config (7.0.5-arch1-1):
https://gist.github.com/seanbrar/d97a577efc3f48098d300105c4de398b
dmesg with OOPS (7.0.5-arch1-1):
https://gist.github.com/seanbrar/994ed882ca6f25b93e4763a8906d0fd5
dmesg with reconnect loop (7.0.3-arch1-2):
https://gist.github.com/seanbrar/188a75bf69fffe0d089f7aa82c6aebb6
^ permalink raw reply
* Re: [PATCH v5 5/6] mfd: motorola-cpcap: diverge configuration per-board
From: sashiko-bot @ 2026-05-11 22:08 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: dmitry.torokhov, linux-input, krzk+dt, robh, conor+dt, devicetree
In-Reply-To: <20260510110804.33045-6-clamor95@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Device Tree ABI breakage for existing Mapphone boards and legacy compatibles
- [Low] Compiler warning (-Wpointer-to-int-cast) on 64-bit architectures due to direct pointer-to-enum cast
--
commit 31f4e82a2615f7d51f1707bf1ca43b9d741b3c90
Author: Svyatoslav Ryhel <clamor95@gmail.com>
mfd: motorola-cpcap: diverge configuration per-board
This commit separates the CPCAP subdevice configuration to support
different board-specific settings. It introduces a default composition
and renames the existing one for Mapphone boards.
> diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c
> index d8243b956f875..f5a7fdd89dd5e 100644
> --- a/drivers/mfd/motorola-cpcap.c
> +++ b/drivers/mfd/motorola-cpcap.c
> @@ -195,20 +197,6 @@ static int cpcap_init_irq(struct cpcap_ddata *cpcap)
> return 0;
> }
>
> -static const struct of_device_id cpcap_of_match[] = {
> - { .compatible = "motorola,cpcap", },
> - { .compatible = "st,6556002", },
> - {},
> -};
Will existing device trees relying on the st,6556002 compatible string
fail to probe since it was removed from the match tables?
[ ... ]
> static int cpcap_probe(struct spi_device *spi)
> {
> struct cpcap_ddata *cpcap;
> + const struct mfd_cell *cells;
> + unsigned int num_cells;
> int ret;
>
> cpcap = devm_kzalloc(&spi->dev, sizeof(*cpcap), GFP_KERNEL);
> if (!cpcap)
> return -ENOMEM;
>
> + cpcap->variant = (enum cpcap_variant)spi_get_device_match_data(spi);
Could this direct cast from a pointer to an enum cause a compiler warning
(-Wpointer-to-int-cast) on 64-bit architectures?
spi_get_device_match_data() returns a const void *, which is 64 bits wide on
architectures like arm64, while enum cpcap_variant is typically a 32-bit
integer. Casting through a pointer-sized integer first might prevent this.
[ ... ]
> +static const struct of_device_id cpcap_of_match[] = {
> + {
> + .compatible = "motorola,cpcap",
> + .data = (void *)CPCAP_DEFAULT
> + }, {
Will this mapping break backwards compatibility for existing Mapphone boards?
Existing device trees use compatible = "motorola,cpcap" for the parent MFD
node, but define their child nodes with Mapphone-specific compatibles like
motorola,mapphone-cpcap-adc.
By mapping motorola,cpcap to CPCAP_DEFAULT, the driver now expects child
cells to use motorola,cpcap-adc. This means mfd_add_devices() might fail
to bind child platform devices to their DT nodes since
of_device_is_compatible() won't match.
If this happens, the child platform devices will be created with
pdev->dev.of_node == NULL, completely breaking driver probing for subdevices
on existing boards.
Could motorola,cpcap continue to map to the historical CPCAP_MAPPHONE
configuration to preserve the ABI?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260510110804.33045-1-clamor95@gmail.com?part=5
^ permalink raw reply
* Re: [PATCH 4/4] HID: hid-msi-claw: Add Rumble Intensity Attributes
From: sashiko-bot @ 2026-05-11 22:09 UTC (permalink / raw)
To: Derek J. Clark; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260510043510.442807-5-derekjohn.clark@gmail.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Critical] The underlying `mcu_property_out()` function uses an improperly scoped `guard(mutex)`, breaking all driver synchronization.
- [High] Unprotected modification of `drvdata->profile_pending` causes race conditions during concurrent sysfs reads.
- [High] Torn transactions in sysfs store handlers lead to state mismatch between hardware and software.
- [Medium] Failure to reset `drvdata->profile_pending` on `mcu_property_out()` error paths corrupts state machine.
--
commit 2a92587430af9e91f5af5fbf2205fea99b2d1000
Author: Derek J. Clark <derekjohn.clark@gmail.com>
HID: hid-msi-claw: Add Rumble Intensity Attributes
This commit adds intensity adjustment for the left and right rumble motors
via new sysfs attributes.
> diff --git a/drivers/hid/hid-msi-claw.c b/drivers/hid/hid-msi-claw.c
> index f4fe74a784c29..6d089f49abdb4 100644
> --- a/drivers/hid/hid-msi-claw.c
> +++ b/drivers/hid/hid-msi-claw.c
[ ... ]
> @@ -795,6 +811,116 @@ static ssize_t button_mapping_options_show(struct device *dev,
> }
> static DEVICE_ATTR_RO(button_mapping_options);
>
> +static ssize_t rumble_intensity_left_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
[ ... ]
> + ret = mcu_property_out(hdev, CLAW_COMMAND_TYPE_WRITE_PROFILE_DATA,
> + data, ARRAY_SIZE(data), 8);
> + if (ret)
> + return ret;
> +
> + ret = mcu_property_out(hdev, CLAW_COMMAND_TYPE_SYNC_TO_ROM, NULL, 0, 0);
> + if (ret)
> + return ret;
> +
> + drvdata->rumble_intensity_left = val;
> +
> + return count;
> +}
Could this sequence introduce a regression if interrupted by concurrent sysfs
stores?
Since there doesn't appear to be a lock held across this sequence, concurrent
writes could interleave their WRITE_PROFILE_DATA and SYNC_TO_ROM commands.
This could cause the hardware to synchronize an unintended state or cause the
local driver state to fall out of sync with the actual hardware value.
Also, regarding the underlying mcu_property_out() function: does it use an
improperly scoped guard(mutex)? If the configuration mutex is acquired
strictly inside a limited scope, the lock would be released before
hid_hw_output_report() and wait_for_completion_interruptible_timeout() are
executed. This could leave all concurrent sysfs calls unprotected, causing a
regression with overlapping USB output reports.
> +static ssize_t rumble_intensity_left_show(struct device *dev,
> + struct device_attribute *attr,
> + char *buf)
> +{
[ ... ]
> + drvdata->profile_pending = CLAW_RUMBLE_LEFT_PENDING;
> + ret = mcu_property_out(hdev, CLAW_COMMAND_TYPE_READ_PROFILE, data, ARRAY_SIZE(data), 8);
> + if (ret)
> + return ret;
Is it possible for concurrent sysfs reads to cause a regression here?
Since drvdata->profile_pending is modified without any locking, if two sysfs
attributes are read concurrently, one thread's modification could overwrite
the other's state. When the asynchronous USB response later arrives,
claw_profile_event() might rely on this clobbered value to route the incoming
data, which could result in userspace reading incorrect data.
Additionally, if mcu_property_out() returns an error, the function returns
immediately but leaves drvdata->profile_pending set to the pending state.
Could this stale state cause a regression where a subsequent unrelated
asynchronous profile event is incorrectly intercepted by claw_profile_event()?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260510043510.442807-1-derekjohn.clark@gmail.com?part=4
^ permalink raw reply
* Re: [PATCH] Input: tsc2007 - fix resistance calculation when A/D value is saturated
From: sashiko-bot @ 2026-05-12 0:04 UTC (permalink / raw)
To: Yuki Horii; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260511054003.1205-1-horiiyuk@ishida.co.jp>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Uninitialized stack variable read in the IIO raw read path.
- [High] Returning 0 to invalidate saturated A/D values causes phantom touches with maximum pressure or premature pen-up events.
--
commit 8a6bcc1904d4e8b8d9d219e6c086925c53bfc4cb
Author: Yuki Horii <yuuki198708@gmail.com>
Input: tsc2007 - fix resistance calculation when A/D value is saturated
This patch modifies the touch resistance calculation to return 0 when either
the X or Y A/D value is saturated. This is intended to indicate that the
touch resistance calculation is invalid.
> diff --git a/drivers/input/touchscreen/tsc2007_core.c b/drivers/input/touchscreen/tsc2007_core.c
> index f9b3d2598933c..7d3bc0c396113 100644
> --- a/drivers/input/touchscreen/tsc2007_core.c
> +++ b/drivers/input/touchscreen/tsc2007_core.c
> @@ -69,9 +69,9 @@ u32 tsc2007_calculate_resistance(struct tsc2007 *tsc, struct ts_event *tc)
> {
> u64 rt = 0;
>
> - /* range filtering */
> - if (tc->x == MAX_12BIT)
> - tc->x = 0;
> + /* invalidate touch resistance if X or Y coordinate is saturated */
> + if (tc->x == MAX_12BIT || tc->y == MAX_12BIT)
Does this code read uninitialized stack memory? The IIO path initializes
tc.x, tc.z1, and tc.z2, but it does not initialize tc.y before passing the
struct to tsc2007_calculate_resistance():
drivers/input/touchscreen/tsc2007_iio.c:tsc2007_read_raw() {
...
case 5: {
struct ts_event tc;
tc.x = tsc2007_xfer(tsc, READ_X);
tc.z1 = tsc2007_xfer(tsc, READ_Z1);
tc.z2 = tsc2007_xfer(tsc, READ_Z2);
*val = tsc2007_calculate_resistance(tsc, &tc);
break;
}
...
}
> + return 0;
Is it safe to return 0 to invalidate the sample?
In tsc2007_soft_irq(), if there is no pendown GPIO, !rt evaluates to true
and prematurely breaks the polling loop, causing an early pen-up event.
If there is a pendown GPIO, rt <= ts->max_rt evaluates to true. Then the
driver calculates pressure as ts->max_rt - rt, which maps rt = 0 to the
maximum possible pressure. This results in a valid touch being reported at
the saturated coordinates with maximum pressure, rather than ignoring the
sample.
Should this instead return a value strictly greater than ts->max_rt (such as
U32_MAX) so the debouncing logic safely ignores the invalid sample?
>
> if (likely(tc->x && tc->z1)) {
> /* compute touch resistance using equation #1 */
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260511054003.1205-1-horiiyuk@ishida.co.jp?part=1
^ permalink raw reply
* [PATCH v3 0/6] iio: hid-sensor: standardize scan_type initialization
From: Natália Salvino André @ 2026-05-12 1:16 UTC (permalink / raw)
To: andy, dlechner, jic23, jikos, nuno.sa, srinivas.pandruvada
Cc: Natália Salvino André, linux-iio, linux-input
This series refactors the HID sensor drivers to standardize the
initialization of the iio_chan_spec scan_type structure.
Direct initialization using compound literals was used.
This change improves code readability and ensures that all fields
of the scan_type structure are properly zero-initialized.
Additionally, for the hid-sensor-accel-3d driver, the channel
initialization loop was refactored to iterate directly over the
scan indices, eliminating redundant logic.
Natália Salvino André (6):
iio: accel: HID: hid-sensor-accel-3d: Refactor channel initialization
iio: gyro: HID: hid-sensor-gyro-3d: Refactor channel initialization
iio: light: HID: hid-sensor-als: Refactor channel initialization
iio: light: HID: hid-sensor-prox: Refactor channel initialization
iio: magnetometer: HID: hid-sensor-magn-3d: Refactor channel
initialization
iio: pressure: HID: hid-sensor-press: Refactor channel initialization
drivers/iio/accel/hid-sensor-accel-3d.c | 27 +++++++------------
drivers/iio/gyro/hid-sensor-gyro-3d.c | 24 +++++++----------
drivers/iio/light/hid-sensor-als.c | 18 +++++--------
drivers/iio/light/hid-sensor-prox.c | 19 +++++--------
drivers/iio/magnetometer/hid-sensor-magn-3d.c | 20 +++++---------
drivers/iio/pressure/hid-sensor-press.c | 19 +++++--------
6 files changed, 42 insertions(+), 85 deletions(-)
--
2.51.0
^ permalink raw reply
* [PATCH v3 1/6] iio: accel: HID: hid-sensor-accel-3d: Refactor channel initialization
From: Natália Salvino André @ 2026-05-12 1:16 UTC (permalink / raw)
To: andy, dlechner, jic23, jikos, nuno.sa, srinivas.pandruvada
Cc: Natália Salvino André, Pietro Di Consolo Gregorio,
linux-iio, linux-input
In-Reply-To: <20260512012302.20883-1-natalia.andre@ime.usp.br>
Clean up the channel initialization loop and replace the local
accel_3d_adjust_channel_bit_mask() function with a compound literal
to improve code readability.
Signed-off-by: Natália Salvino André <natalia.andre@ime.usp.br>
Co-developed-by: Pietro Di Consolo Gregorio <pietro.gregorio@usp.br>
Signed-off-by: Pietro Di Consolo Gregorio <pietro.gregorio@usp.br>
---
drivers/iio/accel/hid-sensor-accel-3d.c | 27 +++++++++----------------
1 file changed, 9 insertions(+), 18 deletions(-)
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 2ff591b3458f..99ca67732bbe 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -3,6 +3,7 @@
* HID Sensors Driver
* Copyright (c) 2012, Intel Corporation.
*/
+#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/module.h>
@@ -119,17 +120,6 @@ static const struct iio_chan_spec gravity_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP),
};
-/* Adjust channel real bits based on report descriptor */
-static void accel_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels,
- int channel, int size)
-{
- channels[channel].scan_type.sign = 's';
- /* Real storage bits will change based on the report desc. */
- channels[channel].scan_type.realbits = size * 8;
- /* Maximum size of a sample to capture is u32 */
- channels[channel].scan_type.storagebits = sizeof(u32) * 8;
-}
-
/* Channel read_raw handler */
static int accel_3d_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
@@ -297,19 +287,20 @@ static int accel_3d_parse_report(struct platform_device *pdev,
struct accel_3d_state *st)
{
int ret;
- int i;
- for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) {
+ for (unsigned int ch = CHANNEL_SCAN_INDEX_X; ch <= CHANNEL_SCAN_INDEX_Z; ch++) {
ret = sensor_hub_input_get_attribute_info(hsdev,
HID_INPUT_REPORT,
usage_id,
- HID_USAGE_SENSOR_ACCEL_X_AXIS + i,
- &st->accel[CHANNEL_SCAN_INDEX_X + i]);
+ ch,
+ &st->accel[ch]);
if (ret < 0)
break;
- accel_3d_adjust_channel_bit_mask(channels,
- CHANNEL_SCAN_INDEX_X + i,
- st->accel[CHANNEL_SCAN_INDEX_X + i].size);
+ channels[ch].scan_type = (struct iio_scan_type) {
+ .format = 's',
+ .realbits = BYTES_TO_BITS(st->accel[ch].size),
+ .storagebits = BITS_PER_TYPE(u32),
+ };
}
dev_dbg(&pdev->dev, "accel_3d %x:%x, %x:%x, %x:%x\n",
st->accel[0].index,
--
2.51.0
^ permalink raw reply related
* [PATCH v3 2/6] iio: gyro: HID: hid-sensor-gyro-3d: Refactor channel initialization
From: Natália Salvino André @ 2026-05-12 1:16 UTC (permalink / raw)
To: andy, dlechner, jic23, jikos, nuno.sa, srinivas.pandruvada
Cc: Natália Salvino André, Pietro Di Consolo Gregorio,
linux-iio, linux-input
In-Reply-To: <20260512012302.20883-1-natalia.andre@ime.usp.br>
Replace the local gyro_3d_adjust_channel_bit_mask() function with a
compound literal for scan_type initialization to improve code
readability.
Signed-off-by: Natália Salvino André <natalia.andre@ime.usp.br>
Co-developed-by: Pietro Di Consolo Gregorio <pietro.gregorio@usp.br>
Signed-off-by: Pietro Di Consolo Gregorio <pietro.gregorio@usp.br>
---
drivers/iio/gyro/hid-sensor-gyro-3d.c | 24 +++++++++---------------
1 file changed, 9 insertions(+), 15 deletions(-)
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index c340cc899a7c..4cbe4d93a0a1 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -3,6 +3,7 @@
* HID Sensors Driver
* Copyright (c) 2012, Intel Corporation.
*/
+#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/module.h>
@@ -82,17 +83,6 @@ static const struct iio_chan_spec gyro_3d_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP)
};
-/* Adjust channel real bits based on report descriptor */
-static void gyro_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels,
- int channel, int size)
-{
- channels[channel].scan_type.sign = 's';
- /* Real storage bits will change based on the report desc. */
- channels[channel].scan_type.realbits = size * 8;
- /* Maximum size of a sample to capture is u32 */
- channels[channel].scan_type.storagebits = sizeof(u32) * 8;
-}
-
/* Channel read_raw handler */
static int gyro_3d_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
@@ -251,16 +241,20 @@ static int gyro_3d_parse_report(struct platform_device *pdev,
int i;
for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) {
+ unsigned int ch = CHANNEL_SCAN_INDEX_X + i;
+
ret = sensor_hub_input_get_attribute_info(hsdev,
HID_INPUT_REPORT,
usage_id,
HID_USAGE_SENSOR_ANGL_VELOCITY_X_AXIS + i,
- &st->gyro[CHANNEL_SCAN_INDEX_X + i]);
+ &st->gyro[ch]);
if (ret < 0)
break;
- gyro_3d_adjust_channel_bit_mask(channels,
- CHANNEL_SCAN_INDEX_X + i,
- st->gyro[CHANNEL_SCAN_INDEX_X + i].size);
+ channels[ch].scan_type = (struct iio_scan_type) {
+ .format = 's',
+ .realbits = BYTES_TO_BITS(st->gyro[ch].size),
+ .storagebits = BITS_PER_TYPE(u32),
+ };
}
dev_dbg(&pdev->dev, "gyro_3d %x:%x, %x:%x, %x:%x\n",
st->gyro[0].index,
--
2.51.0
^ permalink raw reply related
* [PATCH v3 3/6] iio: light: HID: hid-sensor-als: Refactor channel initialization
From: Natália Salvino André @ 2026-05-12 1:16 UTC (permalink / raw)
To: andy, dlechner, jic23, jikos, nuno.sa, srinivas.pandruvada
Cc: Natália Salvino André, Pietro Di Consolo Gregorio,
linux-iio, linux-input
In-Reply-To: <20260512012302.20883-1-natalia.andre@ime.usp.br>
Replace the local als_adjust_channel_bit_mask() function with a
compound literal for scan_type initialization to improve code
readability.
Signed-off-by: Natália Salvino André <natalia.andre@ime.usp.br>
Co-developed-by: Pietro Di Consolo Gregorio <pietro.gregorio@usp.br>
Signed-off-by: Pietro Di Consolo Gregorio <pietro.gregorio@usp.br>
---
drivers/iio/light/hid-sensor-als.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index 384572844162..d72e260b8266 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -3,6 +3,7 @@
* HID Sensors Driver
* Copyright (c) 2012, Intel Corporation.
*/
+#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/module.h>
@@ -117,17 +118,6 @@ static const struct iio_chan_spec als_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(CHANNEL_SCAN_INDEX_TIMESTAMP)
};
-/* Adjust channel real bits based on report descriptor */
-static void als_adjust_channel_bit_mask(struct iio_chan_spec *channels,
- int channel, int size)
-{
- channels[channel].scan_type.sign = 's';
- /* Real storage bits will change based on the report desc. */
- channels[channel].scan_type.realbits = size * 8;
- /* Maximum size of a sample to capture is u32 */
- channels[channel].scan_type.storagebits = sizeof(u32) * 8;
-}
-
/* Channel read_raw handler */
static int als_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
@@ -335,7 +325,11 @@ static int als_parse_report(struct platform_device *pdev,
channels[index] = als_channels[i];
st->als_scan_mask[0] |= BIT(i);
- als_adjust_channel_bit_mask(channels, index, st->als[i].size);
+ channels[index].scan_type = (struct iio_scan_type) {
+ .format = 's',
+ .realbits = BYTES_TO_BITS(st->als[i].size),
+ .storagebits = BITS_PER_TYPE(u32),
+ };
++index;
dev_dbg(&pdev->dev, "als %x:%x\n", st->als[i].index,
--
2.51.0
^ permalink raw reply related
* [PATCH v3 4/6] iio: light: HID: hid-sensor-prox: Refactor channel initialization
From: Natália Salvino André @ 2026-05-12 1:16 UTC (permalink / raw)
To: andy, dlechner, jic23, jikos, nuno.sa, srinivas.pandruvada
Cc: Natália Salvino André, Pietro Di Consolo Gregorio,
linux-iio, linux-input
In-Reply-To: <20260512012302.20883-1-natalia.andre@ime.usp.br>
Replace the local prox_adjust_channel_bit_mask() function with a
compound literal for scan_type initialization to improve code
readability.
Signed-off-by: Natália Salvino André <natalia.andre@ime.usp.br>
Co-developed-by: Pietro Di Consolo Gregorio <pietro.gregorio@usp.br>
Signed-off-by: Pietro Di Consolo Gregorio <pietro.gregorio@usp.br>
---
drivers/iio/light/hid-sensor-prox.c | 19 ++++++-------------
1 file changed, 6 insertions(+), 13 deletions(-)
diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
index efa904a70d0e..edc9274a2c07 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -3,6 +3,7 @@
* HID Sensors Driver
* Copyright (c) 2014, Intel Corporation.
*/
+#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/module.h>
@@ -67,17 +68,6 @@ static const struct iio_chan_spec prox_channels[] = {
PROX_CHANNEL(false, 0),
};
-/* Adjust channel real bits based on report descriptor */
-static void prox_adjust_channel_bit_mask(struct iio_chan_spec *channels,
- int channel, int size)
-{
- channels[channel].scan_type.sign = 's';
- /* Real storage bits will change based on the report desc. */
- channels[channel].scan_type.realbits = size * 8;
- /* Maximum size of a sample to capture is u32 */
- channels[channel].scan_type.storagebits = sizeof(u32) * 8;
-}
-
/* Channel read_raw handler */
static int prox_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
@@ -250,8 +240,11 @@ static int prox_parse_report(struct platform_device *pdev,
st->scan_mask[0] |= BIT(index);
channels[index] = prox_channels[i];
channels[index].scan_index = index;
- prox_adjust_channel_bit_mask(channels, index,
- st->prox_attr[index].size);
+ channels[index].scan_type = (struct iio_scan_type) {
+ .format = 's',
+ .realbits = BYTES_TO_BITS(st->prox_attr[index].size),
+ .storagebits = BITS_PER_TYPE(u32),
+ };
dev_dbg(&pdev->dev, "prox %x:%x\n", st->prox_attr[index].index,
st->prox_attr[index].report_id);
st->scale_precision[index] =
--
2.51.0
^ permalink raw reply related
* [PATCH v3 5/6] iio: magnetometer: HID: hid-sensor-magn-3d: Refactor channel initialization
From: Natália Salvino André @ 2026-05-12 1:16 UTC (permalink / raw)
To: andy, dlechner, jic23, jikos, nuno.sa, srinivas.pandruvada
Cc: Natália Salvino André, Pietro Di Consolo Gregorio,
linux-iio, linux-input
In-Reply-To: <20260512012302.20883-1-natalia.andre@ime.usp.br>
Replace the local magn_3d_adjust_channel_bit_mask() function with a
compound literal for scan_type initialization to improve code
readability.
Signed-off-by: Natália Salvino André <natalia.andre@ime.usp.br>
Co-developed-by: Pietro Di Consolo Gregorio <pietro.gregorio@usp.br>
Signed-off-by: Pietro Di Consolo Gregorio <pietro.gregorio@usp.br>
---
drivers/iio/magnetometer/hid-sensor-magn-3d.c | 20 ++++++-------------
1 file changed, 6 insertions(+), 14 deletions(-)
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index c673f9323e47..3b26dc41dd4c 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -3,6 +3,7 @@
* HID Sensors Driver
* Copyright (c) 2012, Intel Corporation.
*/
+#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/module.h>
@@ -132,17 +133,6 @@ static const struct iio_chan_spec magn_3d_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(7)
};
-/* Adjust channel real bits based on report descriptor */
-static void magn_3d_adjust_channel_bit_mask(struct iio_chan_spec *channels,
- int channel, int size)
-{
- channels[channel].scan_type.sign = 's';
- /* Real storage bits will change based on the report desc. */
- channels[channel].scan_type.realbits = size * 8;
- /* Maximum size of a sample to capture is u32 */
- channels[channel].scan_type.storagebits = sizeof(u32) * 8;
-}
-
/* Channel read_raw handler */
static int magn_3d_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
@@ -418,9 +408,11 @@ static int magn_3d_parse_report(struct platform_device *pdev,
if (i != CHANNEL_SCAN_INDEX_TIMESTAMP) {
/* Set magn_val_addr to iio value address */
st->magn_val_addr[i] = &st->iio_vals[*chan_count];
- magn_3d_adjust_channel_bit_mask(_channels,
- *chan_count,
- st->magn[i].size);
+ _channels[*chan_count].scan_type = (struct iio_scan_type) {
+ .format = 's',
+ .realbits = BYTES_TO_BITS(st->magn[i].size),
+ .storagebits = BITS_PER_TYPE(u32),
+ };
}
(*chan_count)++;
}
--
2.51.0
^ permalink raw reply related
* [PATCH v3 6/6] iio: pressure: HID: hid-sensor-press: Refactor channel initialization
From: Natália Salvino André @ 2026-05-12 1:16 UTC (permalink / raw)
To: andy, dlechner, jic23, jikos, nuno.sa, srinivas.pandruvada
Cc: Natália Salvino André, Pietro Di Consolo Gregorio,
linux-iio, linux-input
In-Reply-To: <20260512012302.20883-1-natalia.andre@ime.usp.br>
Replace the local press_adjust_channel_bit_mask() function with a
compound literal for scan_type initialization to improve code
readability.
Signed-off-by: Natália Salvino André <natalia.andre@ime.usp.br>
Co-developed-by: Pietro Di Consolo Gregorio <pietro.gregorio@usp.br>
Signed-off-by: Pietro Di Consolo Gregorio <pietro.gregorio@usp.br>
---
drivers/iio/pressure/hid-sensor-press.c | 19 ++++++-------------
1 file changed, 6 insertions(+), 13 deletions(-)
diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
index 5f1d6abda3e4..a039b99d9851 100644
--- a/drivers/iio/pressure/hid-sensor-press.c
+++ b/drivers/iio/pressure/hid-sensor-press.c
@@ -3,6 +3,7 @@
* HID Sensors Driver
* Copyright (c) 2014, Intel Corporation.
*/
+#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/module.h>
@@ -53,17 +54,6 @@ static const struct iio_chan_spec press_channels[] = {
};
-/* Adjust channel real bits based on report descriptor */
-static void press_adjust_channel_bit_mask(struct iio_chan_spec *channels,
- int channel, int size)
-{
- channels[channel].scan_type.sign = 's';
- /* Real storage bits will change based on the report desc. */
- channels[channel].scan_type.realbits = size * 8;
- /* Maximum size of a sample to capture is u32 */
- channels[channel].scan_type.storagebits = sizeof(u32) * 8;
-}
-
/* Channel read_raw handler */
static int press_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
@@ -225,8 +215,11 @@ static int press_parse_report(struct platform_device *pdev,
&st->press_attr);
if (ret < 0)
return ret;
- press_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_PRESSURE,
- st->press_attr.size);
+ channels[CHANNEL_SCAN_INDEX_PRESSURE].scan_type = (struct iio_scan_type) {
+ .format = 's',
+ .realbits = BYTES_TO_BITS(st->press_attr.size),
+ .storagebits = BITS_PER_TYPE(u32),
+ };
dev_dbg(&pdev->dev, "press %x:%x\n", st->press_attr.index,
st->press_attr.report_id);
--
2.51.0
^ permalink raw reply related
* [PATCH] HID: quirks: Add ALWAYS_POLL quirk for SIGMACHIP USB mouse
From: hlleng @ 2026-05-12 1:57 UTC (permalink / raw)
To: jikos, bentiss; +Cc: linux-input, linux-kernel, hlleng, stable
The SIGMACHIP USB mouse with VID/PID 1c4f:0034 can disconnect and
re-enumerate repeatedly after it has been enumerated if its interrupt
endpoint is not continuously polled.
This was observed with the device reporting itself as "SIGMACHIP Usb
Mouse". Keeping the input event device open avoids the disconnects.
Add HID_QUIRK_ALWAYS_POLL for this device so the HID core keeps polling
it even when there is no userspace input consumer.
Cc: stable@vger.kernel.org
Signed-off-by: hlleng <a909204013@gmail.com>
---
drivers/hid/hid-ids.h | 1 +
drivers/hid/hid-quirks.c | 1 +
2 files changed, 2 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 0cf637423..c07e90dbd 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -1280,6 +1280,7 @@
#define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f
#define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002
+#define USB_DEVICE_ID_SIGMA_MICRO_USB_MOUSE 0x0034
#define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD2 0x0059
#define USB_VENDOR_ID_SIGMATEL 0x066F
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 9e88c9d6c..800b8f76d 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -187,6 +187,7 @@ static const struct hid_device_id hid_quirks[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS },
{ HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD), HID_QUIRK_NO_INIT_REPORTS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_USB_MOUSE), HID_QUIRK_ALWAYS_POLL },
{ HID_USB_DEVICE(USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH), HID_QUIRK_NOGET },
{ HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH), HID_QUIRK_NOGET },
--
2.54.0
^ permalink raw reply related
* Re: [PATCH] Input: tsc2007 - fix resistance calculation when A/D value is saturated
From: 堀井裕樹 @ 2026-05-12 3:23 UTC (permalink / raw)
To: sashiko; +Cc: dmitry.torokhov, linux-input, andreas
In-Reply-To: <20260512000455.44AB2C2BCB0@smtp.kernel.org>
Thank you for AI review
> Does this code read uninitialized stack memory? The IIO path initializes
> tc.x, tc.z1, and tc.z2, but it does not initialize tc.y before passing the
> struct to tsc2007_calculate_resistance():
I knew this code existed, but I didn't realize it hadn't been initialized.
I'll fix it.
> Is it safe to return 0 to invalidate the sample?
>
> In tsc2007_soft_irq(), if there is no pendown GPIO, !rt evaluates to true
> and prematurely breaks the polling loop, causing an early pen-up event.
I'll fix it.
In the original code, I had set touch input to be disabled when the
value was 0, but after submitting the patch,
I realized that setting the resistance to infinity—rather than
disabling it at 0—would allow the interrupt handling to continue.
^ permalink raw reply
* Re: [PATCH] HID: lenovo: Fix buffer over-read in X12 Tab raw_event handler
From: sashiko-bot @ 2026-05-12 4:49 UTC (permalink / raw)
To: Kean; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260511132854.1351379-1-rh_king@163.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Unaligned memory access via direct pointer cast in raw event handler.
- [High] Missing input capability registration causes hotkey events to be silently dropped.
--
commit a1525e53f7f5fe161ed804808d59755ff69c771f
Author: Kean <rh_king@163.com>
HID: lenovo: Fix buffer over-read in X12 Tab raw_event handler
In lenovo_raw_event(), the X12 Tab keyboard handler reads a 4-byte
little-endian value via *(__le32 *)data but only guards the access
with a size >= 3 check. If a 3-byte report with ID 0x03 is received,
the code reads one byte beyond the end of the buffer.
Change the size check to >= 4 to match the actual access width.
> diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
> index a6b73e03c16b3..4686ecb6cfa8e 100644
> --- a/drivers/hid/hid-lenovo.c
> +++ b/drivers/hid/hid-lenovo.c
> @@ -793,7 +793,7 @@ static int lenovo_raw_event(struct hid_device *hdev,
> */
> if (unlikely((hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB
> || hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB2)
> - && size >= 3 && report->id == 0x03))
> + && size >= 4 && report->id == 0x03))
> return lenovo_raw_event_TP_X12_tab(hdev, le32_to_cpu(*(__le32 *)data));
This isn't a regression from this patch, but could this direct pointer cast
lead to unaligned memory access exceptions?
The data pointer provided by the HID core can have arbitrary alignment
depending on the transport layer. For instance, if injected via uhid using
UHID_INPUT2, the payload data starts at an offset of 6 bytes from the start
of the uhid_event struct, which is 2-byte aligned but not 4-byte aligned.
On architectures that do not natively support unaligned memory access,
dereferencing an unaligned pointer triggers an unaligned access exception.
Would it be safer to use get_unaligned_le32(data) to safely extract the
value?
Also, another issue not introduced by this patch: do the hotkey events
processed by lenovo_raw_event_TP_X12_tab() get silently dropped by the input
core?
The lenovo_raw_event_TP_X12_tab() handler reports events for keys like
KEY_RFKILL, KEY_PERFORMANCE, and KEY_BOOKMARKS:
drivers/hid/hid-lenovo.c:lenovo_raw_event_TP_X12_tab() {
...
case TP_X12_RAW_HOTKEY_FN_F8:
if (hdev->product == USB_DEVICE_ID_LENOVO_X12_TAB) {
report_key_event(input, KEY_RFKILL);
return 1;
}
report_key_event(input, KEY_PERFORMANCE);
return 1;
...
}
However, if these key capabilities are not registered in the input_dev's
keybit array during device initialization, the kernel's input core checks
is_event_supported(code, dev->keybit, KEY_MAX) and drops the events when
report_key_event() is called.
Are these custom hotkey capabilities properly registered during device setup
to prevent them from being filtered out?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260511132854.1351379-1-rh_king@163.com?part=1
^ permalink raw reply
* Re: [PATCH v1 5/8] hid: Pen battery quirk for Surface Pro 12in
From: sashiko-bot @ 2026-05-12 6:07 UTC (permalink / raw)
To: Harrison Vanderbyl; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <2702fbde567457ea0835ba12cc29421590e688aa.1778498477.git.harrison.vanderbyl@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Macro value alignment uses spaces instead of a tab.
--
commit c48c3082a15452ea3cc6ed81c88834aa52ab9d60
Author: Harrison Vanderbyl <harrison.vanderbyl@gmail.com>
hid: Pen battery quirk for Surface Pro 12in
This commit adds a quirk to ignore the battery on the Surface Pro 12in
pen, which uses Bluetooth for battery reporting instead of I2C. This
prevents a phantom battery or device hang.
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -459,6 +459,7 @@
> #define USB_DEVICE_ID_HP_X2 0x074d
> #define USB_DEVICE_ID_HP_X2_10_COVER 0x0755
> #define I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM 0x2F81
> +#define I2C_DEVICE_ID_SURFACE_PRO_12IN 0x4376
This isn't a bug, but it looks like spaces were used here instead of a tab
to align the macro value.
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1778498477.git.harrison.vanderbyl@gmail.com?part=5
^ permalink raw reply
* Re: [PATCH] ipv6: addrconf: skip autoconf on unregistering devices
From: Xu Rao @ 2026-05-12 9:24 UTC (permalink / raw)
To: jikos, bentiss; +Cc: linux-input, linux-kernel, raoxu
Hi Eric,
Thanks for the review.
> 1) I presume this targets the net tree, rather than net-next?
Yes, this is intended for the net tree. I will keep the subject as
"[PATCH net v2]".
> 2) Please add a Fixes: tag
I looked for a Fixes target, but I could not identify a single commit
which introduced this exact bug with enough confidence. The path which
can create an IPv6 link-local address from NETDEV_UP/NETDEV_CHANGE is
very old, while the failure depends on an unregister-time race between
rtnetlink flag changes, addrconf autoconfiguration, and netdev teardown.
Because this looks like a long-standing lifecycle gap exposed by this
race rather than a clear regression from one commit, I did not want to
add a misleading Fixes tag. If you prefer a historical Fixes tag for
netdev requirements, I can add the closest addrconf change you think is
appropriate in v2.
> 3) Why READ_ONCE() are needed there?
I used READ_ONCE() in v1 because dev->reg_state is written with
WRITE_ONCE() in the unregister path and netdev_reg_state() also reads it
with READ_ONCE(). However, addrconf_notify() is called from the
netdevice notifier path and does not need lockless access semantics for
this check. I will switch this to a plain dev->reg_state load in v2.
> 4) Make sure in V2 to CC netdev@ mailing list
> 5) Please wait ~24 hours before sending a V2.
I will also make sure to CC netdev@vger.kernel.org on v2 and will wait
about 24 hours before sending it, as requested.
Thanks,
Xu Rao
^ permalink raw reply
* Re: [PATCH v3 0/4] HID: Proper fix for OOM in hid-core
From: Lee Jones @ 2026-05-12 10:17 UTC (permalink / raw)
To: Benjamin Tissoires
Cc: Jiri Kosina, Filipe Laíns, Bastien Nocera, Ping Cheng,
Jason Gerecke, Viresh Kumar, Johan Hovold, Alex Elder,
Greg Kroah-Hartman, Icenowy Zheng, linux-input, linux-kernel,
greybus-dev, linux-staging, linux-usb, stable
In-Reply-To: <20260506091606.GB305027@google.com>
On Wed, 06 May 2026, Lee Jones wrote:
> On Mon, 04 May 2026, Benjamin Tissoires wrote:
>
> > Commit 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing
> > bogus memset()") enforced the provided data to be at least the size of
> > the declared buffer in the report descriptor to prevent a buffer
> > overflow.
> >
> > We only had corner cases of malicious devices exposing the OOM because
> > in most cases, the buffer provided by the transport layer needs to be
> > allocated at probe time and is large enough to handle all the possible
> > reports.
> >
> > However, the patch from above, which enforces the spec a little bit more
> > introduced both regressions for devices not following the spec (not
> > necesserally malicious), but also a stream of errors for those devices.
> >
> > Let's revert to the old behavior by giving more information to HID core
> > to be able to decide whether it can or not memset the rest of the buffer
> > to 0 and continue the processing.
> >
> > Note that the first commit makes an API change, but the callers are
> > relatively limited, so it should be fine on its own. The second patch
> > can't really make the same kind of API change because we have too many
> > callers in various subsystems. We can switch them one by one to the safe
> > approach when needed.
> >
> > The last 2 patches are small cleanups I initially put together with the
> > 2 first patches, but they can be applied on their own and don't need to
> > be pulled in stable like the first 2.
> >
> > Cheers,
> > Benjamin
> >
> > Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
> > ---
> > Changes in v3:
> > - fixed ghib -> ghid in greybus
> > - fixed i386 size_t debug size reported by kernel-bot
> > - Link to v2: https://lore.kernel.org/r/20260416-wip-fix-core-v2-0-be92570e5627@kernel.org
> >
> > Changes in v2:
> > - added a small blurb explaining the difference between the safe and the
> > non safe version of hid_safe_input_report
> > - Link to v1: https://lore.kernel.org/r/20260415-wip-fix-core-v1-0-ed3c4c823175@kernel.org
> >
> > ---
> > Benjamin Tissoires (4):
> > HID: pass the buffer size to hid_report_raw_event
> > HID: core: introduce hid_safe_input_report()
> > HID: multitouch: use __free(kfree) to clean up temporary buffers
> > HID: wacom: use __free(kfree) to clean up temporary buffers
> >
> > drivers/hid/bpf/hid_bpf_dispatch.c | 6 ++--
> > drivers/hid/hid-core.c | 67 ++++++++++++++++++++++++++++++--------
> > drivers/hid/hid-gfrm.c | 4 +--
> > drivers/hid/hid-logitech-hidpp.c | 2 +-
> > drivers/hid/hid-multitouch.c | 18 ++++------
> > drivers/hid/hid-primax.c | 2 +-
> > drivers/hid/hid-vivaldi-common.c | 2 +-
> > drivers/hid/i2c-hid/i2c-hid-core.c | 7 ++--
> > drivers/hid/usbhid/hid-core.c | 11 ++++---
> > drivers/hid/wacom_sys.c | 46 +++++++++-----------------
> > drivers/staging/greybus/hid.c | 2 +-
> > include/linux/hid.h | 6 ++--
> > include/linux/hid_bpf.h | 14 +++++---
> > 13 files changed, 109 insertions(+), 78 deletions(-)
>
> What's the plan for this set Benjamin? -rcs or -next?
Are there any updates on this set please?
FYI, this set is still important to us.
Ideally, if all is well, it would go into the -rcs for v7.1.
--
Lee Jones
^ permalink raw reply
* [PATCH v5 0/2] input: misc: add support for Imagis ISA1200 haptic motor driver
From: Svyatoslav Ryhel @ 2026-05-12 10:24 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Linus Walleij, Svyatoslav Ryhel
Cc: linux-input, devicetree, linux-kernel
The ISA1200 is a haptic feedback unit from Imagis Technology using two
motors for haptic feedback in mobile phones. Used in many mobile devices
c. 2012 including Samsung Galxy S Advance GT-I9070 (Janice), Samsung Beam
GT-I8350 (Gavini), LG Optimus 4X P880 and LG Optimus Vu P895.
The exact datasheet for the ISA1200 is not available; all data was modeled
based on available downstream kernel sources for various devices and
fragments of information scattered across the internet.
---
Changes in v5:
- added supplies to private structure
- clk_on dropped
- ret > err
- added active flag to track status
- all hardware manipulations consolidated in start/stop
- dropped mutex from work
- dropped active check from isa1200_vibrator_close it was
moved to stop directly
- dropped hw maniplations from probe
- bustype set to BUS_I2C
- adjusted error strings
- fixed cancel_work_sync in isa1200_suspend
Changes in v4:
- added INPUT_FF_MEMLESS option selection
- fixed missing clock status set
- guard start/stop calls in isa1200_play_work with lock
- clamp ldo voltages to allowed range
- fixed imagis,pll-div parsing
- dropped Tested-by from schema adding commit
Changes in v3:
- added clock state tracking
- dropped level check in vibrator close
- added clkdiv clamping
- added comments regarding registers 5 and 6
Changes in v2:
- imagis,clk-div switched to accept actual divider value
- dropped DT header
- adjusted imagis,period-ns range
- initiated hctrl0 and hctrl1 values in isa1200_start
- fixed situation when PWM might return -EPROBE_DEFER to be
treated properly
- added chech a clock or PWM is available
- fixed regulator voltages check being off by 10
- added chech if state.period is not zero
- added action call to disable clock and gpios on error
- used managed version of work init
- added work cancel on suspend
- PW calls are done under mutex lock
---
Linus Walleij (1):
Input: isa1200 - new driver for Imagis ISA1200
Svyatoslav Ryhel (1):
dt-bindings: input: Document Imagis ISA1200 haptic motor driver
.../bindings/input/imagis,isa1200.yaml | 140 +++++
drivers/input/misc/Kconfig | 12 +
drivers/input/misc/Makefile | 1 +
drivers/input/misc/isa1200.c | 524 ++++++++++++++++++
4 files changed, 677 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/imagis,isa1200.yaml
create mode 100644 drivers/input/misc/isa1200.c
--
2.51.0
^ permalink raw reply
* [PATCH v5 1/2] dt-bindings: input: Document Imagis ISA1200 haptic motor driver
From: Svyatoslav Ryhel @ 2026-05-12 10:24 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Linus Walleij, Svyatoslav Ryhel
Cc: linux-input, devicetree, linux-kernel
In-Reply-To: <20260512102445.55372-1-clamor95@gmail.com>
Document the Imagis ISA1200 haptic motor driver, used primarily in mobile
handheld devices and capable of supporting up to two motors.
The exact datasheet for the ISA1200 is not available; all data was modeled
based on available downstream kernel sources for various devices and
fragments of information scattered across the internet.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
.../bindings/input/imagis,isa1200.yaml | 140 ++++++++++++++++++
1 file changed, 140 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/imagis,isa1200.yaml
diff --git a/Documentation/devicetree/bindings/input/imagis,isa1200.yaml b/Documentation/devicetree/bindings/input/imagis,isa1200.yaml
new file mode 100644
index 000000000000..bbe6f99d39c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/imagis,isa1200.yaml
@@ -0,0 +1,140 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/imagis,isa1200.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Imagis ISA1200 haptic motor driver
+
+maintainers:
+ - Svyatoslav Ryhel <clamor95@gmail.com>
+ - Linus Walleij <linusw@kernel.org>
+
+description:
+ The ISA1200 is a high-performance enhanced haptic motor driver designed
+ for mobile hand-held devices. It supports various voltages for both ERM
+ (Eccentric Rotating Mass) and LRA (Linear Resonant Actuator) type
+ actuators. Thanks to an embedded LDO, battery power can be used directly
+ in handheld applications.
+
+properties:
+ compatible:
+ const: imagis,isa1200
+
+ reg:
+ maxItems: 1
+
+ control-gpios:
+ description:
+ One or two GPIOs flagged as active high linked to HEN and LEN pins
+ maxItems: 2
+
+ clocks:
+ maxItems: 1
+
+ pwms:
+ maxItems: 1
+
+ vdd-supply:
+ description:
+ Regulator for 2.4V - 5.5V power supply
+
+ vddp-supply:
+ description:
+ Regulator for 2.4V - 3.6V IO power supply
+
+ imagis,clk-div:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Divider for the external input clock/PWM
+ enum: [128, 256, 512, 1024]
+ default: 128
+
+ imagis,pll-div:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Divider for the internal PLL clock
+ minimum: 1
+ maximum: 15
+ default: 1
+
+ imagis,mode:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ Defines the motor type isa1200 drives
+ 0 - LRA (Linear Resonant Actuator)
+ 1 - ERM (Eccentric Rotating Mass)
+ enum: [0, 1]
+ default: 0
+
+ imagis,period-ns:
+ description:
+ Period of the internal PWM channel in nanoseconds.
+ minimum: 10000
+ maximum: 30000
+
+ imagis,duty-cycle-ns:
+ description:
+ Duty cycle of the external/internal PWM channel in nanoseconds,
+ defaults to 50% of the channel's period
+
+ ldo:
+ $ref: /schemas/regulator/regulator.yaml#
+ type: object
+ description:
+ Embedded LDO regulator with voltage range 2.3V - 3.8V
+ unevaluatedProperties: false
+
+ required:
+ - regulator-min-microvolt
+ - regulator-max-microvolt
+
+required:
+ - compatible
+ - reg
+ - ldo
+
+anyOf:
+ - required:
+ - clocks
+ - imagis,period-ns
+ - required:
+ - pwms
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ haptic-engine@49 {
+ compatible = "imagis,isa1200";
+ reg = <0x49>;
+
+ clocks = <&isa1200_refclk>;
+
+ control-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>,
+ <&gpio 23 GPIO_ACTIVE_HIGH>;
+
+ vdd-supply = <&vdd_3v3_vbat>;
+ vddp-supply = <&vdd_2v8_vvib>;
+
+ imagis,clk-div = <256>;
+ imagis,pll-div = <2>;
+
+ imagis,mode = <0>; /* LRA_MODE */
+
+ imagis,period-ns = <13400>;
+ imagis,duty-cycle-ns = <100>;
+
+ ldo {
+ regulator-name = "vdd_vib";
+ regulator-min-microvolt = <2300000>;
+ regulator-max-microvolt = <2300000>;
+ };
+ };
+ };
--
2.51.0
^ permalink raw reply related
* [PATCH v5 2/2] Input: isa1200 - new driver for Imagis ISA1200
From: Svyatoslav Ryhel @ 2026-05-12 10:24 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Linus Walleij, Svyatoslav Ryhel
Cc: linux-input, devicetree, linux-kernel
In-Reply-To: <20260512102445.55372-1-clamor95@gmail.com>
From: Linus Walleij <linusw@kernel.org>
The ISA1200 is a haptic feedback unit from Imagis Technology using two
motors for haptic feedback in mobile phones. Used in many mobile devices
c. 2012 including Samsung Galxy S Advance GT-I9070 (Janice), Samsung Beam
GT-I8350 (Gavini), LG Optimus 4X P880 and LG Optimus Vu P895.
The exact datasheet for the ISA1200 is not available; all data was modeled
based on available downstream kernel sources for various devices and
fragments of information scattered across the internet.
Tested-by: Linus Walleij <linusw@kernel.org> # GT-I9070 Janice
Signed-off-by: Linus Walleij <linusw@kernel.org>
Co-developed-by: Svyatoslav Ryhel <clamor95@gmail.com>
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/input/misc/Kconfig | 12 +
drivers/input/misc/Makefile | 1 +
drivers/input/misc/isa1200.c | 524 +++++++++++++++++++++++++++++++++++
3 files changed, 537 insertions(+)
create mode 100644 drivers/input/misc/isa1200.c
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 94a753fcb64f..52f192104ee2 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -852,6 +852,18 @@ config INPUT_IQS7222
To compile this driver as a module, choose M here: the
module will be called iqs7222.
+config INPUT_ISA1200_HAPTIC
+ tristate "Imagis ISA1200 haptic feedback unit"
+ depends on I2C
+ select INPUT_FF_MEMLESS
+ select REGMAP_I2C
+ help
+ Say Y to enable support for the Imagis ISA1200 haptic
+ feedback unit.
+
+ To compile this driver as a module, choose M here: the
+ module will be called isa1200.
+
config INPUT_CMA3000
tristate "VTI CMA3000 Tri-axis accelerometer"
help
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 415fc4e2918b..d62bf2e9d85f 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o
obj-$(CONFIG_INPUT_IQS269A) += iqs269a.o
obj-$(CONFIG_INPUT_IQS626A) += iqs626a.o
obj-$(CONFIG_INPUT_IQS7222) += iqs7222.o
+obj-$(CONFIG_INPUT_ISA1200_HAPTIC) += isa1200.o
obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
diff --git a/drivers/input/misc/isa1200.c b/drivers/input/misc/isa1200.c
new file mode 100644
index 000000000000..ff82252a08e1
--- /dev/null
+++ b/drivers/input/misc/isa1200.c
@@ -0,0 +1,524 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/array_size.h>
+#include <linux/bitmap.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/devm-helpers.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/units.h>
+
+/*
+ * System control (LDO regulator)
+ *
+ * LDO voltage to register mapping is linear, but it is split in two parts:
+ * 2.3V - 3.0V map to 0x08 - 0x0f; 3.1V - 3.8V map to 0x00 - 0x7
+ */
+
+#define ISA1200_SCTRL 0x00
+#define ISA1200_LDO_VOLTAGE_BASE 0x08
+#define ISA1200_LDO_VOLTAGE_STEP 100000
+#define ISA1200_LDO_VOLTAGE_2V3 23
+#define ISA1200_LDO_VOLTAGE_3V1 31
+#define ISA1200_LDO_VOLTAGE_MIN 2300000
+#define ISA1200_LDO_VOLTAGE_MAX 3800000
+
+/*
+ * The output frequency is calculated with this formula:
+ *
+ * base clock frequency
+ * fout = -----------------------------------------
+ * (128 - PWM_FREQ) * 2 * PLLDIV * PWM_PERIOD
+ *
+ * The base clock frequency is the clock frequency provided on the
+ * clock input to the chip, divided by the value in HCTRL0
+ *
+ * PWM_FREQ is configured in register HCTRL4, it is common to set this
+ * to 0 to get only two variables to calculate.
+ *
+ * PLLDIV is configured in register HCTRL3 (bits 7..4, so 0..15)
+ * PWM_PERIOD is configured in register HCTRL6
+ * Further the duty cycle can be configured in HCTRL5
+ */
+
+/*
+ * HCTRL0 configures clock or PWM input and selects the divider for
+ * the clock input.
+ */
+#define ISA1200_HCTRL0 0x30
+#define ISA1200_HCTRL0_HAP_ENABLE BIT(7)
+#define ISA1200_HCTRL0_PWM_GEN_MODE BIT(4)
+#define ISA1200_HCTRL0_PWM_INPUT_MODE BIT(3)
+#define ISA1200_HCTRL0_CLKDIV_128 128
+
+/*
+ * HCTRL1 configures the motor type and clock sourse
+ */
+#define ISA1200_HCTRL1 0x31
+#define ISA1200_HCTRL1_EXT_CLOCK BIT(7)
+#define ISA1200_HCTRL1_DAC_INVERT BIT(6)
+#define ISA1200_HCTRL1_MODE(n) (((n) & 1) << 5)
+
+/* HCTRL2 controls software reset of the chip */
+#define ISA1200_HCTRL2 0x32
+#define ISA1200_HCTRL2_SW_RESET BIT(0)
+
+/*
+ * HCTRL3 controls the PLL divisor
+ *
+ * Bits [0,1] are always set to 1 (we don't know what they are
+ * used for) and bit 4 and upward control the PLL divisor.
+ */
+#define ISA1200_HCTRL3 0x33
+#define ISA1200_HCTRL3_DEFAULT 0x03
+#define ISA1200_HCTRL3_PLLDIV(n) (((n) & 0xf) << 4)
+
+/* HCTRL4 controls the PWM frequency of external channel */
+#define ISA1200_HCTRL4 0x34
+
+/* HCTRL5 controls the PWM high duty cycle of internal channel */
+#define ISA1200_HCTRL5 0x35
+
+/* HCTRL6 controls the PWM period of internal channel */
+#define ISA1200_HCTRL6 0x36
+#define ISA1200_HCTRL6_PERIOD_SCALE 100
+
+/* The use for these registers is unknown but they exist */
+#define ISA1200_HCTRL7 0x37
+#define ISA1200_HCTRL8 0x38
+#define ISA1200_HCTRL9 0x39
+#define ISA1200_HCTRLA 0x3a
+#define ISA1200_HCTRLB 0x3b
+#define ISA1200_HCTRLC 0x3c
+#define ISA1200_HCTRLD 0x3d
+
+#define ISA1200_EN_PINS_MAX 2
+
+static const struct regulator_bulk_data isa1200_supplies[] = {
+ { .supply = "vdd" }, { .supply = "vddp" },
+};
+
+struct isa1200_config {
+ u32 ldo_voltage;
+ u32 mode;
+ u32 clkdiv;
+ u32 plldiv;
+ u32 freq;
+ u32 period;
+ u32 duty;
+};
+
+struct isa1200 {
+ struct input_dev *input;
+ struct regmap *map;
+
+ struct clk *clk;
+ struct pwm_device *pwm;
+ struct gpio_descs *enable_gpios;
+ struct regulator_bulk_data *supplies;
+
+ struct work_struct play_work;
+ struct isa1200_config config;
+
+ bool active;
+ int level;
+};
+
+static const struct regmap_config isa1200_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = ISA1200_HCTRLD,
+};
+
+static void isa1200_start(struct isa1200 *isa)
+{
+ struct isa1200_config *config = &isa->config;
+ struct device *dev = &isa->input->dev;
+ struct pwm_state state;
+ u8 hctrl0 = 0, hctrl1 = 0;
+ DECLARE_BITMAP(values, ISA1200_EN_PINS_MAX);
+ int err;
+
+ if (!isa->active) {
+ err = regulator_bulk_enable(ARRAY_SIZE(isa1200_supplies),
+ isa->supplies);
+ if (err) {
+ dev_err(dev, "failed to enable supplies (%d)\n", err);
+ return;
+ }
+
+ err = clk_prepare_enable(isa->clk);
+ if (err) {
+ dev_err(dev, "failed to enable clock (%d)\n", err);
+ regulator_bulk_disable(ARRAY_SIZE(isa1200_supplies),
+ isa->supplies);
+ return;
+ }
+
+ bitmap_fill(values, ISA1200_EN_PINS_MAX);
+ gpiod_multi_set_value_cansleep(isa->enable_gpios, values);
+
+ usleep_range(200, 300);
+ }
+
+ regmap_write(isa->map, ISA1200_SCTRL, config->ldo_voltage);
+
+ if (isa->clk) {
+ hctrl0 = ISA1200_HCTRL0_PWM_GEN_MODE;
+ hctrl1 = ISA1200_HCTRL1_EXT_CLOCK;
+ }
+
+ if (isa->pwm) {
+ hctrl0 = ISA1200_HCTRL0_PWM_INPUT_MODE;
+ hctrl1 = 0;
+ }
+
+ hctrl0 |= __ffs(config->clkdiv / ISA1200_HCTRL0_CLKDIV_128);
+ hctrl1 |= ISA1200_HCTRL1_DAC_INVERT;
+ hctrl1 |= ISA1200_HCTRL1_MODE(config->mode);
+
+ regmap_write(isa->map, ISA1200_HCTRL0, hctrl0);
+ regmap_write(isa->map, ISA1200_HCTRL1, hctrl1);
+
+ /* Make sure to de-assert software reset */
+ regmap_write(isa->map, ISA1200_HCTRL2, 0x00);
+
+ /* PLL divisor */
+ regmap_write(isa->map, ISA1200_HCTRL3,
+ ISA1200_HCTRL3_PLLDIV(config->plldiv) |
+ ISA1200_HCTRL3_DEFAULT);
+
+ /* Frequency */
+ regmap_write(isa->map, ISA1200_HCTRL4, config->freq);
+ /* Duty cycle */
+ regmap_write(isa->map, ISA1200_HCTRL5, config->period >> 1);
+ /* Period */
+ regmap_write(isa->map, ISA1200_HCTRL6, config->period);
+
+ hctrl0 |= ISA1200_HCTRL0_HAP_ENABLE;
+ regmap_write(isa->map, ISA1200_HCTRL0, hctrl0);
+
+ if (isa->clk)
+ regmap_write(isa->map, ISA1200_HCTRL5, config->duty);
+
+ if (isa->pwm) {
+ pwm_get_state(isa->pwm, &state);
+ state.duty_cycle = config->duty;
+ state.enabled = true;
+ pwm_apply_might_sleep(isa->pwm, &state);
+ }
+
+ isa->active = true;
+}
+
+static void isa1200_stop(struct isa1200 *isa)
+{
+ struct pwm_state state;
+ DECLARE_BITMAP(values, ISA1200_EN_PINS_MAX);
+
+ if (!isa->active)
+ return;
+
+ if (isa->pwm) {
+ pwm_get_state(isa->pwm, &state);
+ state.duty_cycle = 0;
+ state.enabled = false;
+ pwm_apply_might_sleep(isa->pwm, &state);
+ }
+
+ regmap_write(isa->map, ISA1200_HCTRL0, 0x00);
+
+ bitmap_zero(values, ISA1200_EN_PINS_MAX);
+ gpiod_multi_set_value_cansleep(isa->enable_gpios, values);
+
+ clk_disable_unprepare(isa->clk);
+ regulator_bulk_disable(ARRAY_SIZE(isa1200_supplies),
+ isa->supplies);
+
+ isa->active = false;
+ isa->level = 0;
+}
+
+static void isa1200_play_work(struct work_struct *work)
+{
+ struct isa1200 *isa = container_of(work, struct isa1200, play_work);
+
+ if (isa->level)
+ isa1200_start(isa);
+ else
+ isa1200_stop(isa);
+}
+
+static int isa1200_vibrator_play_effect(struct input_dev *input, void *data,
+ struct ff_effect *effect)
+{
+ struct isa1200 *isa = input_get_drvdata(input);
+ int level;
+
+ /*
+ * TODO: we currently only support rumble.
+ * The ISA1200 can control two motors and some devices
+ * also have two motors mounted.
+ */
+ level = effect->u.rumble.strong_magnitude;
+ if (!level)
+ level = effect->u.rumble.weak_magnitude;
+
+ dev_dbg(&input->dev, "FF effect type %d level %d\n",
+ effect->type, level);
+
+ if (isa->level != level) {
+ isa->level = level;
+ schedule_work(&isa->play_work);
+ }
+
+ return 0;
+}
+
+static void isa1200_vibrator_close(struct input_dev *input)
+{
+ struct isa1200 *isa = input_get_drvdata(input);
+
+ cancel_work_sync(&isa->play_work);
+ isa1200_stop(isa);
+}
+
+static int isa1200_of_probe(struct i2c_client *client)
+{
+ struct isa1200 *isa = i2c_get_clientdata(client);
+ struct isa1200_config *config = &isa->config;
+ struct device *dev = &client->dev;
+ struct fwnode_handle *ldo_node;
+ int err;
+
+ isa->clk = devm_clk_get_optional(dev, NULL);
+ if (IS_ERR(isa->clk))
+ return dev_err_probe(dev, PTR_ERR(isa->clk),
+ "failed to get clock\n");
+
+ isa->pwm = devm_pwm_get(dev, NULL);
+ if (IS_ERR(isa->pwm)) {
+ err = PTR_ERR(isa->pwm);
+ if (err == -ENODEV || err == -EINVAL)
+ isa->pwm = NULL;
+ else
+ return dev_err_probe(dev, err, "getting PWM\n");
+ }
+
+ if (!isa->clk && !isa->pwm)
+ return dev_err_probe(dev, -EINVAL,
+ "clock or PWM are required, none were provided\n");
+
+ err = devm_regulator_bulk_get_const(dev, ARRAY_SIZE(isa1200_supplies),
+ isa1200_supplies, &isa->supplies);
+ if (err)
+ return dev_err_probe(dev, err, "failed to get supplies\n");
+
+ isa->enable_gpios = devm_gpiod_get_array_optional(dev, "control",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(isa->enable_gpios))
+ return dev_err_probe(dev, PTR_ERR(isa->enable_gpios),
+ "failed to get enable gpios\n");
+
+ ldo_node = device_get_named_child_node(dev, "ldo");
+ if (!ldo_node)
+ return dev_err_probe(dev, -ENODEV,
+ "failed to get embedded LDO node\n");
+
+ err = fwnode_property_read_u32(ldo_node, "regulator-min-microvolt",
+ &config->ldo_voltage);
+ fwnode_handle_put(ldo_node);
+ if (err)
+ return dev_err_probe(dev, err,
+ "failed to get ldo voltage\n");
+
+ config->ldo_voltage = clamp(config->ldo_voltage,
+ ISA1200_LDO_VOLTAGE_MIN,
+ ISA1200_LDO_VOLTAGE_MAX);
+
+ config->ldo_voltage /= ISA1200_LDO_VOLTAGE_STEP;
+ if (config->ldo_voltage < ISA1200_LDO_VOLTAGE_3V1)
+ config->ldo_voltage = config->ldo_voltage -
+ ISA1200_LDO_VOLTAGE_2V3 +
+ ISA1200_LDO_VOLTAGE_BASE;
+ else
+ config->ldo_voltage -= ISA1200_LDO_VOLTAGE_3V1;
+
+ config->mode = 0; /* LRA_MODE */
+ device_property_read_u32(dev, "imagis,mode", &config->mode);
+
+ config->clkdiv = ISA1200_HCTRL0_CLKDIV_128;
+ device_property_read_u32(dev, "imagis,clk-div", &config->clkdiv);
+ if (!config->clkdiv)
+ return dev_err_probe(dev, -EINVAL, "clk-div cannot be zero\n");
+
+ config->clkdiv = clamp(config->clkdiv, ISA1200_HCTRL0_CLKDIV_128,
+ ISA1200_HCTRL0_CLKDIV_128 << 3);
+
+ err = device_property_read_u32(dev, "imagis,pll-div", &config->plldiv);
+ if (err || !config->plldiv)
+ config->plldiv = 1;
+
+ config->period = 0;
+ config->freq = 0;
+ config->duty = 0;
+
+ if (isa->clk) {
+ err = device_property_read_u32(dev, "imagis,period-ns",
+ &config->period);
+ if (err)
+ return dev_err_probe(dev, err,
+ "failed to get period\n");
+
+ /*
+ * TODO: The scale value is arbitrary, but it fits observations
+ * quite well, and the exact conversion method is unknown.
+ * The period property value returned above is the HCTRL6
+ * register value set by the vendor code, multiplied by 100.
+ */
+ config->period /= ISA1200_HCTRL6_PERIOD_SCALE;
+ config->duty = config->period >> 1;
+ }
+
+ if (isa->pwm) {
+ struct pwm_state state;
+
+ pwm_init_state(isa->pwm, &state);
+
+ if (!state.period)
+ return dev_err_probe(dev, -EINVAL,
+ "PWM period cannot be zero\n");
+
+ config->freq = div64_u64(NANO, state.period * config->clkdiv);
+ config->duty = state.period >> 1;
+
+ err = pwm_apply_might_sleep(isa->pwm, &state);
+ if (err)
+ return dev_err_probe(dev, err,
+ "failed to apply initial PWM state\n");
+ }
+
+ /*
+ * TODO: If device is using a clock, this property should return the
+ * value written to the HCTRL5 register by downstrem code. It likely
+ * needs to be converted into a meaningful duty cycle value, though
+ * unfortunately the exact conversion mechanism is unknown. If the
+ * device uses PWM, this property will return the correct duty cycle
+ * in nanoseconds.
+ */
+ device_property_read_u32(dev, "imagis,duty-cycle-ns", &config->duty);
+
+ return 0;
+}
+
+static int isa1200_probe(struct i2c_client *client)
+{
+ struct isa1200 *isa;
+ struct device *dev = &client->dev;
+ int err;
+
+ isa = devm_kzalloc(dev, sizeof(*isa), GFP_KERNEL);
+ if (!isa)
+ return -ENOMEM;
+
+ isa->input = devm_input_allocate_device(dev);
+ if (!isa->input)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, isa);
+
+ err = isa1200_of_probe(client);
+ if (err)
+ return err;
+
+ isa->map = devm_regmap_init_i2c(client, &isa1200_regmap_config);
+ if (IS_ERR(isa->map))
+ return dev_err_probe(dev, PTR_ERR(isa->map),
+ "failed to initialize register map\n");
+
+ INIT_WORK(&isa->play_work, isa1200_play_work);
+
+ isa->input->name = "isa1200-haptic";
+ isa->input->id.bustype = BUS_I2C;
+ isa->input->close = isa1200_vibrator_close;
+
+ isa->active = false;
+
+ input_set_drvdata(isa->input, isa);
+
+ /* TODO: this hardware can likely support more than rumble */
+ input_set_capability(isa->input, EV_FF, FF_RUMBLE);
+
+ err = input_ff_create_memless(isa->input, NULL,
+ isa1200_vibrator_play_effect);
+ if (err)
+ return dev_err_probe(dev, err, "failed to create FF dev\n");
+
+ err = input_register_device(isa->input);
+ if (err)
+ return dev_err_probe(dev, err, "failed to register input dev\n");
+
+ return 0;
+}
+
+static int isa1200_suspend(struct device *dev)
+{
+ struct isa1200 *isa = dev_get_drvdata(dev);
+
+ guard(mutex)(&isa->input->mutex);
+
+ if (input_device_enabled(isa->input)) {
+ cancel_work_sync(&isa->play_work);
+ if (isa->level)
+ isa1200_stop(isa);
+ }
+
+ return 0;
+}
+
+static int isa1200_resume(struct device *dev)
+{
+ struct isa1200 *isa = dev_get_drvdata(dev);
+
+ guard(mutex)(&isa->input->mutex);
+
+ if (input_device_enabled(isa->input))
+ if (isa->level)
+ isa1200_start(isa);
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(isa1200_pm_ops, isa1200_suspend, isa1200_resume);
+
+static const struct of_device_id isa1200_of_match[] = {
+ { .compatible = "imagis,isa1200" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, isa1200_of_match);
+
+static struct i2c_driver isa1200_i2c_driver = {
+ .driver = {
+ .name = "isa1200",
+ .of_match_table = isa1200_of_match,
+ .pm = pm_sleep_ptr(&isa1200_pm_ops),
+ },
+ .probe = isa1200_probe,
+};
+module_i2c_driver(isa1200_i2c_driver);
+
+MODULE_AUTHOR("Linus Walleij <linusw@kernel.org>");
+MODULE_AUTHOR("Svyatoslav Ryhel <clamor95@gmail.com>");
+MODULE_DESCRIPTION("Imagis ISA1200 haptic feedback unit");
+MODULE_LICENSE("GPL");
--
2.51.0
^ permalink raw reply related
* Re: [PATCH v3 1/9] iio: hid-sensors: drop redundant iio_dev argument
From: srinivas pandruvada @ 2026-05-12 12:37 UTC (permalink / raw)
To: Sanjay Chitroda, jikos, jic23
Cc: dlechner, nuno.sa, andy, sakari.ailus, linux-input, linux-iio,
linux-kernel
In-Reply-To: <20260509101040.791404-2-sanjayembedded@gmail.com>
On Sat, 2026-05-09 at 15:40 +0530, Sanjay Chitroda wrote:
> From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
>
> hid_sensor_remove_trigger() uses struct hid_sensor_common to release
> resources acquired during trigger setup.
>
> Earlier implementations required struct iio_dev to clean up buffers,
> but with the current code this argument is no longer used and is
> redundant.
>
> Adapt to hid_sensor_remove_trigger() API change across all HID IIO
> drivers to match updated prototype.
>
> Removing it simplifies the API and is a preparatory step toward
> converting the trigger handling to a devm-based API.
>
> Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> ---
> drivers/iio/accel/hid-sensor-accel-3d.c | 4 ++--
> drivers/iio/common/hid-sensors/hid-sensor-trigger.c | 3 +--
> drivers/iio/common/hid-sensors/hid-sensor-trigger.h | 3 +--
> drivers/iio/gyro/hid-sensor-gyro-3d.c | 4 ++--
> drivers/iio/humidity/hid-sensor-humidity.c | 4 ++--
> drivers/iio/light/hid-sensor-als.c | 4 ++--
> drivers/iio/light/hid-sensor-prox.c | 4 ++--
> drivers/iio/magnetometer/hid-sensor-magn-3d.c | 4 ++--
> drivers/iio/orientation/hid-sensor-incl-3d.c | 4 ++--
> drivers/iio/orientation/hid-sensor-rotation.c | 4 ++--
> drivers/iio/position/hid-sensor-custom-intel-hinge.c | 4 ++--
> drivers/iio/pressure/hid-sensor-press.c | 4 ++--
> drivers/iio/temperature/hid-sensor-temperature.c | 4 ++--
> 13 files changed, 24 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c
> b/drivers/iio/accel/hid-sensor-accel-3d.c
> index 2ff591b3458f..a63dae90dadc 100644
> --- a/drivers/iio/accel/hid-sensor-accel-3d.c
> +++ b/drivers/iio/accel/hid-sensor-accel-3d.c
> @@ -416,7 +416,7 @@ static int hid_accel_3d_probe(struct
> platform_device *pdev)
> error_iio_unreg:
> iio_device_unregister(indio_dev);
> error_remove_trigger:
> - hid_sensor_remove_trigger(indio_dev, &accel_state-
> >common_attributes);
> + hid_sensor_remove_trigger(&accel_state->common_attributes);
> return ret;
> }
>
> @@ -429,7 +429,7 @@ static void hid_accel_3d_remove(struct
> platform_device *pdev)
>
> sensor_hub_remove_callback(hsdev, hsdev->usage);
> iio_device_unregister(indio_dev);
> - hid_sensor_remove_trigger(indio_dev, &accel_state-
> >common_attributes);
> + hid_sensor_remove_trigger(&accel_state->common_attributes);
> }
>
> static const struct platform_device_id hid_accel_3d_ids[] = {
> diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
> b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
> index 417c4ab8c1b2..28d050b45c74 100644
> --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
> +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
> @@ -218,8 +218,7 @@ static const struct iio_buffer_setup_ops
> hid_sensor_buffer_ops = {
> .predisable = buffer_predisable,
> };
>
> -void hid_sensor_remove_trigger(struct iio_dev *indio_dev,
> - struct hid_sensor_common *attrb)
> +void hid_sensor_remove_trigger(struct hid_sensor_common *attrb)
> {
> if (atomic_read(&attrb->runtime_pm_enable))
> pm_runtime_disable(&attrb->pdev->dev);
> diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
> b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
> index f94fca4f1edf..afec46ecbe71 100644
> --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
> +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
> @@ -16,8 +16,7 @@ extern const struct dev_pm_ops hid_sensor_pm_ops;
>
> int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char
> *name,
> struct hid_sensor_common *attrb);
> -void hid_sensor_remove_trigger(struct iio_dev *indio_dev,
> - struct hid_sensor_common *attrb);
> +void hid_sensor_remove_trigger(struct hid_sensor_common *attrb);
> int hid_sensor_power_state(struct hid_sensor_common *st, bool
> state);
>
> #endif
> diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c
> b/drivers/iio/gyro/hid-sensor-gyro-3d.c
> index c340cc899a7c..fe663b19e902 100644
> --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
> +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
> @@ -354,7 +354,7 @@ static int hid_gyro_3d_probe(struct
> platform_device *pdev)
> error_iio_unreg:
> iio_device_unregister(indio_dev);
> error_remove_trigger:
> - hid_sensor_remove_trigger(indio_dev, &gyro_state-
> >common_attributes);
> + hid_sensor_remove_trigger(&gyro_state->common_attributes);
> return ret;
> }
>
> @@ -367,7 +367,7 @@ static void hid_gyro_3d_remove(struct
> platform_device *pdev)
>
> sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);
> iio_device_unregister(indio_dev);
> - hid_sensor_remove_trigger(indio_dev, &gyro_state-
> >common_attributes);
> + hid_sensor_remove_trigger(&gyro_state->common_attributes);
> }
>
> static const struct platform_device_id hid_gyro_3d_ids[] = {
> diff --git a/drivers/iio/humidity/hid-sensor-humidity.c
> b/drivers/iio/humidity/hid-sensor-humidity.c
> index be2338d5f407..e580a2af9562 100644
> --- a/drivers/iio/humidity/hid-sensor-humidity.c
> +++ b/drivers/iio/humidity/hid-sensor-humidity.c
> @@ -255,7 +255,7 @@ static int hid_humidity_probe(struct
> platform_device *pdev)
> error_remove_callback:
> sensor_hub_remove_callback(hsdev,
> HID_USAGE_SENSOR_HUMIDITY);
> error_remove_trigger:
> - hid_sensor_remove_trigger(indio_dev, &humid_st-
> >common_attributes);
> + hid_sensor_remove_trigger(&humid_st->common_attributes);
> return ret;
> }
>
> @@ -268,7 +268,7 @@ static void hid_humidity_remove(struct
> platform_device *pdev)
>
> iio_device_unregister(indio_dev);
> sensor_hub_remove_callback(hsdev,
> HID_USAGE_SENSOR_HUMIDITY);
> - hid_sensor_remove_trigger(indio_dev, &humid_st-
> >common_attributes);
> + hid_sensor_remove_trigger(&humid_st->common_attributes);
> }
>
> static const struct platform_device_id hid_humidity_ids[] = {
> diff --git a/drivers/iio/light/hid-sensor-als.c
> b/drivers/iio/light/hid-sensor-als.c
> index 384572844162..9b57cdced18a 100644
> --- a/drivers/iio/light/hid-sensor-als.c
> +++ b/drivers/iio/light/hid-sensor-als.c
> @@ -432,7 +432,7 @@ static int hid_als_probe(struct platform_device
> *pdev)
> error_iio_unreg:
> iio_device_unregister(indio_dev);
> error_remove_trigger:
> - hid_sensor_remove_trigger(indio_dev, &als_state-
> >common_attributes);
> + hid_sensor_remove_trigger(&als_state->common_attributes);
> return ret;
> }
>
> @@ -445,7 +445,7 @@ static void hid_als_remove(struct platform_device
> *pdev)
>
> sensor_hub_remove_callback(hsdev, hsdev->usage);
> iio_device_unregister(indio_dev);
> - hid_sensor_remove_trigger(indio_dev, &als_state-
> >common_attributes);
> + hid_sensor_remove_trigger(&als_state->common_attributes);
> }
>
> static const struct platform_device_id hid_als_ids[] = {
> diff --git a/drivers/iio/light/hid-sensor-prox.c
> b/drivers/iio/light/hid-sensor-prox.c
> index efa904a70d0e..473c45626487 100644
> --- a/drivers/iio/light/hid-sensor-prox.c
> +++ b/drivers/iio/light/hid-sensor-prox.c
> @@ -340,7 +340,7 @@ static int hid_prox_probe(struct platform_device
> *pdev)
> error_iio_unreg:
> iio_device_unregister(indio_dev);
> error_remove_trigger:
> - hid_sensor_remove_trigger(indio_dev, &prox_state-
> >common_attributes);
> + hid_sensor_remove_trigger(&prox_state->common_attributes);
> return ret;
> }
>
> @@ -353,7 +353,7 @@ static void hid_prox_remove(struct
> platform_device *pdev)
>
> sensor_hub_remove_callback(hsdev, hsdev->usage);
> iio_device_unregister(indio_dev);
> - hid_sensor_remove_trigger(indio_dev, &prox_state-
> >common_attributes);
> + hid_sensor_remove_trigger(&prox_state->common_attributes);
> }
>
> static const struct platform_device_id hid_prox_ids[] = {
> diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> index b01dd53eb100..8be3dfe4dd58 100644
> --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
> @@ -542,7 +542,7 @@ static int hid_magn_3d_probe(struct
> platform_device *pdev)
> error_iio_unreg:
> iio_device_unregister(indio_dev);
> error_remove_trigger:
> - hid_sensor_remove_trigger(indio_dev, &magn_state-
> >magn_flux_attributes);
> + hid_sensor_remove_trigger(&magn_state-
> >magn_flux_attributes);
> return ret;
> }
>
> @@ -555,7 +555,7 @@ static void hid_magn_3d_remove(struct
> platform_device *pdev)
>
> sensor_hub_remove_callback(hsdev,
> HID_USAGE_SENSOR_COMPASS_3D);
> iio_device_unregister(indio_dev);
> - hid_sensor_remove_trigger(indio_dev, &magn_state-
> >magn_flux_attributes);
> + hid_sensor_remove_trigger(&magn_state-
> >magn_flux_attributes);
> }
>
> static const struct platform_device_id hid_magn_3d_ids[] = {
> diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c
> b/drivers/iio/orientation/hid-sensor-incl-3d.c
> index 4e23a598a3fb..56fd9c53dfc2 100644
> --- a/drivers/iio/orientation/hid-sensor-incl-3d.c
> +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
> @@ -378,7 +378,7 @@ static int hid_incl_3d_probe(struct
> platform_device *pdev)
> error_iio_unreg:
> iio_device_unregister(indio_dev);
> error_remove_trigger:
> - hid_sensor_remove_trigger(indio_dev, &incl_state-
> >common_attributes);
> + hid_sensor_remove_trigger(&incl_state->common_attributes);
> return ret;
> }
>
> @@ -391,7 +391,7 @@ static void hid_incl_3d_remove(struct
> platform_device *pdev)
>
> sensor_hub_remove_callback(hsdev,
> HID_USAGE_SENSOR_INCLINOMETER_3D);
> iio_device_unregister(indio_dev);
> - hid_sensor_remove_trigger(indio_dev, &incl_state-
> >common_attributes);
> + hid_sensor_remove_trigger(&incl_state->common_attributes);
> }
>
> static const struct platform_device_id hid_incl_3d_ids[] = {
> diff --git a/drivers/iio/orientation/hid-sensor-rotation.c
> b/drivers/iio/orientation/hid-sensor-rotation.c
> index 4a11e4555099..56fdb3412fe3 100644
> --- a/drivers/iio/orientation/hid-sensor-rotation.c
> +++ b/drivers/iio/orientation/hid-sensor-rotation.c
> @@ -353,7 +353,7 @@ static int hid_dev_rot_probe(struct
> platform_device *pdev)
> error_iio_unreg:
> iio_device_unregister(indio_dev);
> error_remove_trigger:
> - hid_sensor_remove_trigger(indio_dev, &rot_state-
> >common_attributes);
> + hid_sensor_remove_trigger(&rot_state->common_attributes);
> return ret;
> }
>
> @@ -366,7 +366,7 @@ static void hid_dev_rot_remove(struct
> platform_device *pdev)
>
> sensor_hub_remove_callback(hsdev, hsdev->usage);
> iio_device_unregister(indio_dev);
> - hid_sensor_remove_trigger(indio_dev, &rot_state-
> >common_attributes);
> + hid_sensor_remove_trigger(&rot_state->common_attributes);
> }
>
> static const struct platform_device_id hid_dev_rot_ids[] = {
> diff --git a/drivers/iio/position/hid-sensor-custom-intel-hinge.c
> b/drivers/iio/position/hid-sensor-custom-intel-hinge.c
> index a26d391661fd..5288b63f4e21 100644
> --- a/drivers/iio/position/hid-sensor-custom-intel-hinge.c
> +++ b/drivers/iio/position/hid-sensor-custom-intel-hinge.c
> @@ -337,7 +337,7 @@ static int hid_hinge_probe(struct platform_device
> *pdev)
> error_remove_callback:
> sensor_hub_remove_callback(hsdev, hsdev->usage);
> error_remove_trigger:
> - hid_sensor_remove_trigger(indio_dev, &st-
> >common_attributes);
> + hid_sensor_remove_trigger(&st->common_attributes);
> return ret;
> }
>
> @@ -350,7 +350,7 @@ static void hid_hinge_remove(struct
> platform_device *pdev)
>
> iio_device_unregister(indio_dev);
> sensor_hub_remove_callback(hsdev, hsdev->usage);
> - hid_sensor_remove_trigger(indio_dev, &st-
> >common_attributes);
> + hid_sensor_remove_trigger(&st->common_attributes);
> }
>
> static const struct platform_device_id hid_hinge_ids[] = {
> diff --git a/drivers/iio/pressure/hid-sensor-press.c
> b/drivers/iio/pressure/hid-sensor-press.c
> index 5f1d6abda3e4..2bf5d055e175 100644
> --- a/drivers/iio/pressure/hid-sensor-press.c
> +++ b/drivers/iio/pressure/hid-sensor-press.c
> @@ -319,7 +319,7 @@ static int hid_press_probe(struct platform_device
> *pdev)
> error_iio_unreg:
> iio_device_unregister(indio_dev);
> error_remove_trigger:
> - hid_sensor_remove_trigger(indio_dev, &press_state-
> >common_attributes);
> + hid_sensor_remove_trigger(&press_state->common_attributes);
> return ret;
> }
>
> @@ -332,7 +332,7 @@ static void hid_press_remove(struct
> platform_device *pdev)
>
> sensor_hub_remove_callback(hsdev,
> HID_USAGE_SENSOR_PRESSURE);
> iio_device_unregister(indio_dev);
> - hid_sensor_remove_trigger(indio_dev, &press_state-
> >common_attributes);
> + hid_sensor_remove_trigger(&press_state->common_attributes);
> }
>
> static const struct platform_device_id hid_press_ids[] = {
> diff --git a/drivers/iio/temperature/hid-sensor-temperature.c
> b/drivers/iio/temperature/hid-sensor-temperature.c
> index 9f628a8e5cfb..60d4fcc8043b 100644
> --- a/drivers/iio/temperature/hid-sensor-temperature.c
> +++ b/drivers/iio/temperature/hid-sensor-temperature.c
> @@ -253,7 +253,7 @@ static int hid_temperature_probe(struct
> platform_device *pdev)
> error_remove_callback:
> sensor_hub_remove_callback(hsdev,
> HID_USAGE_SENSOR_TEMPERATURE);
> error_remove_trigger:
> - hid_sensor_remove_trigger(indio_dev, &temp_st-
> >common_attributes);
> + hid_sensor_remove_trigger(&temp_st->common_attributes);
> return ret;
> }
>
> @@ -265,7 +265,7 @@ static void hid_temperature_remove(struct
> platform_device *pdev)
> struct temperature_state *temp_st = iio_priv(indio_dev);
>
> sensor_hub_remove_callback(hsdev,
> HID_USAGE_SENSOR_TEMPERATURE);
> - hid_sensor_remove_trigger(indio_dev, &temp_st-
> >common_attributes);
> + hid_sensor_remove_trigger(&temp_st->common_attributes);
> }
>
> static const struct platform_device_id hid_temperature_ids[] = {
^ permalink raw reply
* Re: [PATCH v3 2/9] iio: hid-sensors: cleanup codestyle warning
From: srinivas pandruvada @ 2026-05-12 12:39 UTC (permalink / raw)
To: Sanjay Chitroda, jikos, jic23
Cc: dlechner, nuno.sa, andy, sakari.ailus, linux-input, linux-iio,
linux-kernel
In-Reply-To: <20260509101040.791404-3-sanjayembedded@gmail.com>
On Sat, 2026-05-09 at 15:40 +0530, Sanjay Chitroda wrote:
> From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
>
> Reported by checkpatch:
> FILE: drivers/iio/common/hid-sensors/hid-sensor-trigger.c
>
> WARNING: Missing a blank line after declarations
>
> Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
> ---
> drivers/iio/common/hid-sensors/hid-sensor-trigger.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
> b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
> index 28d050b45c74..98fadc61a68a 100644
> --- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
> +++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
> @@ -313,7 +313,9 @@ static int __maybe_unused
> hid_sensor_resume(struct device *dev)
> {
> struct iio_dev *indio_dev = dev_get_drvdata(dev);
> struct hid_sensor_common *attrb =
> iio_device_get_drvdata(indio_dev);
> +
> schedule_work(&attrb->work);
> +
> return 0;
> }
>
> @@ -321,6 +323,7 @@ static int __maybe_unused
> hid_sensor_runtime_resume(struct device *dev)
> {
> struct iio_dev *indio_dev = dev_get_drvdata(dev);
> struct hid_sensor_common *attrb =
> iio_device_get_drvdata(indio_dev);
> +
> return _hid_sensor_power_state(attrb, true);
> }
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox