Linux Input/HID development
 help / color / mirror / Atom feed
* Re: [PATCH v4 2/2] Input: isa1200 - new driver for Imagis ISA1200
From: Dmitry Torokhov @ 2026-05-08 13:57 UTC (permalink / raw)
  To: Svyatoslav Ryhel
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Linus Walleij,
	linux-input, devicetree, linux-kernel
In-Reply-To: <CAPVz0n1wYMsLLzbQ=4HLT1+Cx8GoxY+n9Q0cJ=dYv9bF=piOVg@mail.gmail.com>

On Fri, May 08, 2026 at 02:13:43PM +0300, Svyatoslav Ryhel wrote:
> чт, 7 трав. 2026 р. о 22:26 Dmitry Torokhov <dmitry.torokhov@gmail.com> пише:
> >
> > Hi Svyatoslav,
> >
> > On Thu, May 07, 2026 at 04:39:48PM +0300, Svyatoslav Ryhel wrote:

...

> > > +}
> > > +
> > > +static int isa1200_suspend(struct device *dev)
> > > +{
> > > +     struct isa1200 *isa = dev_get_drvdata(dev);
> > > +
> > > +     cancel_work_sync(&isa->play_work);
> >
> > Move it under input_device_enabled().
> >
> > > +
> > > +     guard(mutex)(&isa->input->mutex);
> > > +
> 
> Should I remove mutex locking from both PM functions?

No, you should remove it from isa1200_play_work().

Thanks.

-- 
Dmitry

^ permalink raw reply

* [dtor-input:next] BUILD SUCCESS 7b9b6b34a6474e6f0e4e7c48e33e824131ed46d5
From: kernel test robot @ 2026-05-08 14:22 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
branch HEAD: 7b9b6b34a6474e6f0e4e7c48e33e824131ed46d5  Input: tsc2007 - reduce I2C transactions for Z2 read

elapsed time: 776m

configs tested: 211
configs skipped: 7

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-15.2.0
alpha                            allyesconfig    gcc-15.2.0
alpha                               defconfig    gcc-15.2.0
arc                              allmodconfig    clang-16
arc                               allnoconfig    gcc-15.2.0
arc                              allyesconfig    gcc-15.2.0
arc                                 defconfig    gcc-15.2.0
arc                     haps_hs_smp_defconfig    gcc-15.2.0
arc                 nsimosci_hs_smp_defconfig    gcc-15.2.0
arc                            randconfig-001    gcc-8.5.0
arc                   randconfig-001-20260508    gcc-12.5.0
arc                   randconfig-001-20260508    gcc-8.5.0
arc                            randconfig-002    gcc-8.5.0
arc                   randconfig-002-20260508    gcc-12.5.0
arc                   randconfig-002-20260508    gcc-8.5.0
arm                               allnoconfig    gcc-15.2.0
arm                              allyesconfig    clang-16
arm                                 defconfig    gcc-15.2.0
arm                           h3600_defconfig    gcc-15.2.0
arm                        neponset_defconfig    gcc-15.2.0
arm                            randconfig-001    gcc-8.5.0
arm                   randconfig-001-20260508    gcc-12.5.0
arm                   randconfig-001-20260508    gcc-8.5.0
arm                            randconfig-002    gcc-8.5.0
arm                   randconfig-002-20260508    gcc-12.5.0
arm                   randconfig-002-20260508    gcc-8.5.0
arm                            randconfig-003    gcc-8.5.0
arm                   randconfig-003-20260508    gcc-12.5.0
arm                   randconfig-003-20260508    gcc-8.5.0
arm                            randconfig-004    gcc-8.5.0
arm                   randconfig-004-20260508    gcc-12.5.0
arm                   randconfig-004-20260508    gcc-8.5.0
arm64                            allmodconfig    clang-19
arm64                             allnoconfig    gcc-15.2.0
arm64                               defconfig    gcc-15.2.0
arm64                 randconfig-001-20260508    gcc-14.3.0
arm64                 randconfig-002-20260508    gcc-14.3.0
arm64                 randconfig-003-20260508    gcc-14.3.0
arm64                 randconfig-004-20260508    gcc-14.3.0
csky                             allmodconfig    gcc-15.2.0
csky                              allnoconfig    gcc-15.2.0
csky                                defconfig    gcc-15.2.0
csky                  randconfig-001-20260508    gcc-14.3.0
csky                  randconfig-002-20260508    gcc-14.3.0
hexagon                          allmodconfig    clang-17
hexagon                          allmodconfig    gcc-15.2.0
hexagon                           allnoconfig    gcc-15.2.0
hexagon                             defconfig    gcc-15.2.0
hexagon               randconfig-001-20260508    clang-23
hexagon               randconfig-002-20260508    clang-23
i386                             allmodconfig    clang-20
i386                             allmodconfig    gcc-14
i386                              allnoconfig    gcc-15.2.0
i386                             allyesconfig    clang-20
i386                             allyesconfig    gcc-14
i386                 buildonly-randconfig-001    gcc-14
i386        buildonly-randconfig-001-20260508    gcc-14
i386                 buildonly-randconfig-002    gcc-14
i386        buildonly-randconfig-002-20260508    gcc-14
i386                 buildonly-randconfig-003    gcc-14
i386        buildonly-randconfig-003-20260508    gcc-14
i386                 buildonly-randconfig-004    gcc-14
i386        buildonly-randconfig-004-20260508    gcc-14
i386                 buildonly-randconfig-005    gcc-14
i386        buildonly-randconfig-005-20260508    gcc-14
i386                 buildonly-randconfig-006    gcc-14
i386        buildonly-randconfig-006-20260508    gcc-14
i386                                defconfig    gcc-15.2.0
i386                  randconfig-001-20260508    gcc-14
i386                  randconfig-002-20260508    gcc-14
i386                  randconfig-003-20260508    gcc-14
i386                  randconfig-004-20260508    gcc-14
i386                  randconfig-005-20260508    gcc-14
i386                  randconfig-006-20260508    gcc-14
i386                  randconfig-007-20260508    gcc-14
i386                  randconfig-011-20260508    gcc-13
i386                  randconfig-012-20260508    gcc-13
i386                  randconfig-013-20260508    gcc-13
i386                  randconfig-014-20260508    gcc-13
i386                  randconfig-015-20260508    gcc-13
i386                  randconfig-016-20260508    gcc-13
i386                  randconfig-017-20260508    gcc-13
loongarch                        allmodconfig    clang-19
loongarch                         allnoconfig    gcc-15.2.0
loongarch                           defconfig    clang-19
loongarch             randconfig-001-20260508    clang-23
loongarch             randconfig-002-20260508    clang-23
m68k                             allmodconfig    gcc-15.2.0
m68k                              allnoconfig    gcc-15.2.0
m68k                             allyesconfig    clang-16
m68k                                defconfig    clang-19
microblaze                        allnoconfig    gcc-15.2.0
microblaze                       allyesconfig    gcc-15.2.0
microblaze                          defconfig    clang-19
mips                             allmodconfig    gcc-15.2.0
mips                              allnoconfig    gcc-15.2.0
mips                             allyesconfig    gcc-15.2.0
mips                      loongson3_defconfig    gcc-15.2.0
mips                        omega2p_defconfig    clang-23
mips                         rt305x_defconfig    clang-23
nios2                            allmodconfig    clang-23
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    clang-23
nios2                               defconfig    clang-19
nios2                 randconfig-001-20260508    clang-23
nios2                 randconfig-002-20260508    clang-23
openrisc                         allmodconfig    clang-23
openrisc                         allmodconfig    gcc-15.2.0
openrisc                          allnoconfig    clang-23
openrisc                            defconfig    gcc-15.2.0
parisc                           allmodconfig    gcc-15.2.0
parisc                            allnoconfig    clang-23
parisc                           allyesconfig    clang-19
parisc                           allyesconfig    gcc-15.2.0
parisc                              defconfig    gcc-15.2.0
parisc                randconfig-001-20260508    gcc-9.5.0
parisc                randconfig-002-20260508    gcc-9.5.0
parisc64                            defconfig    clang-19
powerpc                          allmodconfig    gcc-15.2.0
powerpc                           allnoconfig    clang-23
powerpc                       holly_defconfig    clang-23
powerpc               randconfig-001-20260508    gcc-9.5.0
powerpc               randconfig-002-20260508    gcc-9.5.0
powerpc                     tqm8555_defconfig    gcc-15.2.0
powerpc64             randconfig-001-20260508    gcc-9.5.0
powerpc64             randconfig-002-20260508    gcc-9.5.0
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                            allyesconfig    clang-16
riscv                               defconfig    gcc-15.2.0
riscv                 randconfig-001-20260508    clang-23
riscv                 randconfig-002-20260508    clang-23
s390                             allmodconfig    clang-18
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-15.2.0
s390                                defconfig    gcc-15.2.0
s390                  randconfig-001-20260508    clang-23
s390                  randconfig-002-20260508    clang-23
sh                               allmodconfig    gcc-15.2.0
sh                                allnoconfig    clang-23
sh                               allyesconfig    clang-19
sh                               allyesconfig    gcc-15.2.0
sh                                  defconfig    gcc-14
sh                          polaris_defconfig    gcc-15.2.0
sh                    randconfig-001-20260508    clang-23
sh                    randconfig-002-20260508    clang-23
sparc                             allnoconfig    clang-23
sparc                               defconfig    gcc-15.2.0
sparc                 randconfig-001-20260508    gcc-12
sparc                 randconfig-002-20260508    gcc-12
sparc64                          allmodconfig    clang-23
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20260508    gcc-12
sparc64               randconfig-002-20260508    gcc-12
um                               allmodconfig    clang-19
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-14
um                               allyesconfig    gcc-15.2.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                    randconfig-001-20260508    gcc-12
um                    randconfig-002-20260508    gcc-12
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-20
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-20
x86_64               buildonly-randconfig-001    gcc-14
x86_64      buildonly-randconfig-001-20260508    gcc-14
x86_64               buildonly-randconfig-002    gcc-14
x86_64      buildonly-randconfig-002-20260508    gcc-14
x86_64               buildonly-randconfig-003    gcc-14
x86_64      buildonly-randconfig-003-20260508    gcc-14
x86_64               buildonly-randconfig-004    gcc-14
x86_64      buildonly-randconfig-004-20260508    gcc-14
x86_64               buildonly-randconfig-005    gcc-14
x86_64      buildonly-randconfig-005-20260508    gcc-14
x86_64               buildonly-randconfig-006    gcc-14
x86_64      buildonly-randconfig-006-20260508    gcc-14
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-20
x86_64                randconfig-001-20260508    clang-20
x86_64                randconfig-002-20260508    clang-20
x86_64                randconfig-003-20260508    clang-20
x86_64                randconfig-004-20260508    clang-20
x86_64                randconfig-005-20260508    clang-20
x86_64                randconfig-006-20260508    clang-20
x86_64                randconfig-011-20260508    gcc-14
x86_64                randconfig-012-20260508    gcc-14
x86_64                randconfig-013-20260508    gcc-14
x86_64                randconfig-014-20260508    gcc-14
x86_64                randconfig-015-20260508    gcc-14
x86_64                randconfig-016-20260508    gcc-14
x86_64                randconfig-071-20260508    gcc-14
x86_64                randconfig-072-20260508    gcc-14
x86_64                randconfig-073-20260508    gcc-14
x86_64                randconfig-074-20260508    gcc-14
x86_64                randconfig-075-20260508    gcc-14
x86_64                randconfig-076-20260508    gcc-14
x86_64                               rhel-9.4    clang-20
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-20
x86_64                    rhel-9.4-kselftests    clang-20
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-20
xtensa                            allnoconfig    clang-23
xtensa                           allyesconfig    clang-23
xtensa                           allyesconfig    gcc-15.2.0
xtensa                randconfig-001-20260508    gcc-12
xtensa                randconfig-002-20260508    gcc-12

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* [PATCH RESEND 2] HID: Add force feedback support for Speedlink Cougar Vibration Flightstick
From: Harald Judt @ 2026-05-08 17:54 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires; +Cc: linux-input

Hi,

I have implemented force feedback/rumble support for the Speedlink
Cougar Vibration Flightstick joystick. While I am not quite sure about
the correctness of my approach regarding the strong and weak motors, it
seems to work as expected; I ran the fftest samples and also tested it
successfully with SuperTuxKart.

Here is the code, hopefully I have set up thunderbird mail correctly to
not mangle the patch...


From 48d8512fbe49ae7b940dc5869fe50aa905d3d5fb Mon Sep 17 00:00:00 2001
From: Harald Judt <h.judt@gmx.at>
Date: Sun, 18 Jan 2026 02:47:20 +0100
Subject: [PATCH] HID: Add force feedback support for Gembird based joystick

This commit adds force feedback support for a Gembird based joystick, namely
the SpeedLink Cougar Vibration Flightstick (SL-6630), which sports vibration
motors for rumble effects. Though it is not easy to determine, it seems to have
one motor in the base and the other in the stick, both are of equal
strength. The implementation tries to take this into account for realising weak
and strong rumble effects and has been tested using fftest and SuperTuxKart.

Signed-off-by: Harald Judt <h.judt@gmx.at>
---
 drivers/hid/Kconfig           |   8 ++
 drivers/hid/Makefile          |   1 +
 drivers/hid/hid-gembird-joy.c | 178 ++++++++++++++++++++++++++++++++++
 drivers/hid/hid-ids.h         |   3 +
 drivers/hid/hid-quirks.c      |   3 +
 5 files changed, 193 insertions(+)
 create mode 100644 drivers/hid/hid-gembird-joy.c

diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 04420a713be0..b4e2c8f67728 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -406,6 +406,14 @@ config HID_GEMBIRD
 	help
 	Support for Gembird JPD-DualForce 2.
 
+config HID_GEMBIRD_JOY_FF
+	tristate "Gembird Joysticks force feedback support"
+	depends on USB_HID
+	select INPUT_FF_MEMLESS
+	help
+	Force feedback support for Gembird (Vendor ID 0x12bd) based devices:
+	  - Speed Link Cougar Vibration Flightstick (SL-6630)
+
 config HID_GFRM
 	tristate "Google Fiber TV Box remote control support"
 	help
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 361a7daedeb8..593a429661ed 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_HID_EVISION)	+= hid-evision.o
 obj-$(CONFIG_HID_EZKEY)		+= hid-ezkey.o
 obj-$(CONFIG_HID_FT260)		+= hid-ft260.o
 obj-$(CONFIG_HID_GEMBIRD)	+= hid-gembird.o
+obj-$(CONFIG_HID_GEMBIRD_JOY_FF)	+= hid-gembird-joy.o
 obj-$(CONFIG_HID_GFRM)		+= hid-gfrm.o
 obj-$(CONFIG_HID_GLORIOUS)  += hid-glorious.o
 obj-$(CONFIG_HID_VIVALDI_COMMON) += hid-vivaldi-common.o
diff --git a/drivers/hid/hid-gembird-joy.c b/drivers/hid/hid-gembird-joy.c
new file mode 100644
index 000000000000..5a5afa02f840
--- /dev/null
+++ b/drivers/hid/hid-gembird-joy.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *  HID driver for Gembird based Joysticks
+ *
+ *  Currently supported devices:
+ *    - 12bd:a02f Speed Link Cougar Vibration Flightstick (SL-6630)
+ *
+ *  Copyright (c) 2026 Harald Judt <h.judt@gmx.at>
+ */
+
+
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+
+#include "hid-ids.h"
+
+
+struct gembird_joy_device {
+	struct hid_report *report;
+};
+
+static int hid_gembird_joy_play(struct input_dev *dev, void *data,
+				struct ff_effect *effect)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct gembird_joy_device *joy = data;
+	int strong, weak;
+
+	strong = effect->u.rumble.strong_magnitude;
+	weak = effect->u.rumble.weak_magnitude;
+
+	hid_dbg(hid, "called with 0x%04x 0x%04x\n", strong, weak);
+
+	/* Likely there are two motors, one in the base and the other in an upper
+	 * part of the stick, yet they are not different in strength, and honestly
+	 * it is hard to determine which motor is active or correlates to value 0
+	 * or 1 of the report field. However, the third value does not have any
+	 * function, thus it will always be set to 0.
+	 *
+	 * The windows drivers want to make believe the first value in the report
+	 * field should be influenced by horizontal axis movement, and the second
+	 * by vertical axis movement, but this might just be some arbitrary gimmick
+	 * of the configuration dialog, which describes the motors as left and
+	 * right.
+	 *
+	 * Ranges are the same for both motors, weak and strong (0 to 31), so scale
+	 * down the magnitudes accordingly...
+	 */
+	strong = (strong / 0xff) * 0x1f / 0xff;
+	weak = (weak / 0xff) * 0x1f / 0xff;
+
+	/* ... and to support the notions of strong vs weak rumble effects,
+	 * increase the magnitude for the strong rumble effect if it is below the
+	 * half of the maximum value, as the strong motor has the same strength as
+	 * the weak one. Likewise, decrease the magnitude for the weak effect.
+	 */
+	if (strong < 0x10 && !weak)         /* fftest effect 4 strong rumble */
+		strong *= 2;
+	else if (!strong && weak >= 0x10)   /* fftest effect 5 weak rumble */
+		weak /= 2;
+
+	/* Use unmodified values if both magnitudes have been set. */
+	joy->report->field[0]->value[0] = strong;
+	joy->report->field[0]->value[1] = weak;
+	joy->report->field[0]->value[2] = 0;
+
+	hid_dbg(hid, "running with 0x%02x, 0x%02x\n", strong, weak);
+	hid_hw_request(hid, joy->report, HID_REQ_SET_REPORT);
+
+	return 0;
+}
+
+static int gembird_joy_init(struct hid_device *hid)
+{
+	struct gembird_joy_device *joy;
+	struct hid_report *report;
+	struct hid_input *hidinput;
+	struct list_head *report_list =
+			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct list_head *report_ptr = report_list;
+	struct input_dev *dev;
+	int error;
+
+	if (list_empty(&hid->inputs)) {
+		hid_err(hid, "no inputs found\n");
+		return -ENODEV;
+	}
+	hidinput = list_first_entry(&hid->inputs, struct hid_input, list);
+	dev = hidinput->input;
+
+	if (list_empty(report_list)) {
+		hid_err(hid, "no output reports found\n");
+		return -ENODEV;
+	}
+
+	list_for_each_entry(hidinput, &hid->inputs, list) {
+		report_ptr = report_ptr->next;
+
+		if (report_ptr == report_list) {
+			hid_err(hid, "required output report is missing\n");
+			return -ENODEV;
+		}
+
+		report = list_entry(report_ptr, struct hid_report, list);
+		if (report->maxfield < 1) {
+			hid_err(hid, "no fields in the report\n");
+			return -ENODEV;
+		}
+
+		if (report->field[0]->report_count < 3) {
+			hid_err(hid, "not enough values in the field\n");
+			return -ENODEV;
+		}
+
+		joy = kzalloc(sizeof(struct gembird_joy_device), GFP_KERNEL);
+		if (!joy)
+			return -ENOMEM;
+
+		dev = hidinput->input;
+
+		set_bit(FF_RUMBLE, dev->ffbit);
+
+		error = input_ff_create_memless(dev, joy, hid_gembird_joy_play);
+		if (error) {
+			kfree(joy);
+			return error;
+		}
+
+		joy->report = report;
+		joy->report->field[0]->value[0] = 0x00;
+		joy->report->field[0]->value[1] = 0x00;
+		joy->report->field[0]->value[2] = 0x00;
+		hid_hw_request(hid, joy->report, HID_REQ_SET_REPORT);
+	}
+
+	hid_info(hid, "Force Feedback for Gembird Joystick devices by Harald Judt <h.judt@gmx.at>\n");
+
+	return 0;
+}
+
+static int gembird_joy_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "parse failed\n");
+		return ret;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+	if (ret) {
+		hid_err(hdev, "hw start failed\n");
+		return ret;
+	}
+
+	gembird_joy_init(hdev);
+
+	return 0;
+}
+
+static const struct hid_device_id gembird_joy_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GEMBIRD_JOY, USB_DEVICE_ID_GEMBIRD_JOY_SL_6630) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, gembird_joy_devices);
+
+static struct hid_driver gembird_joy_driver = {
+	.name = "gembird_joy",
+	.id_table = gembird_joy_devices,
+	.probe = gembird_joy_probe,
+};
+module_hid_driver(gembird_joy_driver);
+
+MODULE_AUTHOR("Harald Judt <h.judt@gmx.at>");
+MODULE_DESCRIPTION("Force feedback support for HID Gembird joysticks");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index c4589075a5ed..1bdd9b879152 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -528,6 +528,9 @@
 #define USB_VENDOR_ID_GEMBIRD			0x11ff
 #define USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2	0x3331
 
+#define USB_VENDOR_ID_GEMBIRD_JOY		0x12bd
+#define USB_DEVICE_ID_GEMBIRD_JOY_SL_6630	0xa02f
+
 #define USB_VENDOR_ID_GENERAL_TOUCH	0x0dfc
 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS 0x0003
 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS 0x0100
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 6a8a7ca3d804..835070491da7 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -444,6 +444,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
 #if IS_ENABLED(CONFIG_HID_GEMBIRD)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GEMBIRD, USB_DEVICE_ID_GEMBIRD_JPD_DUALFORCE2) },
 #endif
+#if IS_ENABLED(CONFIG_HID_GEMBIRD_JOY_FF)
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GEMBIRD_JOY, USB_DEVICE_ID_GEMBIRD_JOY_SL_6630) },
+#endif
 #if IS_ENABLED(CONFIG_HID_GFRM)
 	{ HID_BLUETOOTH_DEVICE(0x58, 0x2000) },
 	{ HID_BLUETOOTH_DEVICE(0x471, 0x2210) },
-- 
2.52.0



-- 
`Experience is the best teacher.'

PGP Key ID: 4FFFAB21B8580ABD
Fingerprint: E073 6DD8 FF40 9CF2 0665 11D4 4FFF AB21 B858 0ABD

^ permalink raw reply related

* Re: [PATCH RFC 1/4] regulator: add devm_fwnode family of functions
From: sashiko-bot @ 2026-05-08 21:08 UTC (permalink / raw)
  To: Griffin Kroah-Hartman
  Cc: robh, devicetree, dmitry.torokhov, krzk+dt, conor+dt, linux-input
In-Reply-To: <20260508-gpiokeys-vdd-supply-v1-1-0bb32e8e6428@fairphone.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The fallback stubs for `devm_fwnode_regulator_get` and its variants incorrectly return `NULL` instead of `ERR_PTR(-ENODEV)` when `CONFIG_OF` is disabled but `CONFIG_REGULATOR` is enabled, leading to a guaranteed kernel panic on non-OF systems.
--

commit f8899ceec7e07e935c3ae44032450cd2b8f68352
Author: Griffin Kroah-Hartman <griffin.kroah@fairphone.com>

regulator: add devm_fwnode family of functions

Add devm_fwnode_regulator_get and variants.

These function wrappers allow regulators to be accessed from the fwnode
struct without any casts.

> diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
> --- a/include/linux/regulator/consumer.h
> +++ b/include/linux/regulator/consumer.h
[ ... ]
> +static inline struct regulator *__must_check
> +devm_fwnode_regulator_get(struct device *dev, struct fwnode_handle *fwnode,
> +	const char *id)
> +{
> +	return NULL;
> +}

Will returning NULL here instead of ERR_PTR(-ENODEV) cause a panic on non-OF
systems?

If CONFIG_REGULATOR is enabled but CONFIG_OF is disabled, a driver calling
this will get NULL. Since drivers typically check the return value with
IS_ERR(), IS_ERR(NULL) evaluates to false. The driver would assume it
successfully acquired a valid regulator.

Later, when the driver calls regulator_enable(), it will pass this NULL
pointer. Since CONFIG_REGULATOR is enabled, regulator_enable() is not stubbed
out and will unconditionally dereference the pointer, leading to a NULL
pointer dereference.

Should these stubs return ERR_PTR(-ENODEV) instead to safely signal the
absence of a regulator and match the expected regulator API semantics?

> +
> +static inline struct regulator *__must_check
> +devm_fwnode_regulator_get_exclusive(struct device *dev, struct fwnode_handle *fwnode,
> +	const char *id)
> +{
> +	return NULL;
> +}
> +
> +static inline struct regulator *__must_check
> +devm_fwnode_regulator_get_optional(struct device *dev, struct fwnode_handle *fwnode,
> +	const char *id)
> +{
> +	return NULL;
> +}

Does returning NULL for the optional and exclusive variants violate the
regulator API semantics which require returning ERR_PTR(-ENODEV) to safely
signal the absence of a regulator?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260508-gpiokeys-vdd-supply-v1-0-0bb32e8e6428@fairphone.com?part=1

^ permalink raw reply

* [dtor-input:for-linus] BUILD SUCCESS 74d695fd6f9d70df849c555f358ddfd26e2d85bf
From: kernel test robot @ 2026-05-08 21:22 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git for-linus
branch HEAD: 74d695fd6f9d70df849c555f358ddfd26e2d85bf  Input: fm801-gp - simplify initialisation of pci_device_id array

elapsed time: 1197m

configs tested: 334
configs skipped: 9

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-15.2.0
alpha                            allyesconfig    gcc-15.2.0
alpha                               defconfig    gcc-15.2.0
arc                              allmodconfig    clang-16
arc                               allnoconfig    gcc-15.2.0
arc                              allyesconfig    clang-19
arc                              allyesconfig    clang-23
arc                              allyesconfig    gcc-15.2.0
arc                                 defconfig    gcc-15.2.0
arc                     haps_hs_smp_defconfig    gcc-15.2.0
arc                 nsimosci_hs_smp_defconfig    gcc-15.2.0
arc                            randconfig-001    gcc-8.5.0
arc                   randconfig-001-20260508    gcc-12.5.0
arc                   randconfig-001-20260508    gcc-8.5.0
arc                   randconfig-001-20260509    gcc-9.5.0
arc                            randconfig-002    gcc-8.5.0
arc                   randconfig-002-20260508    gcc-12.5.0
arc                   randconfig-002-20260508    gcc-8.5.0
arc                   randconfig-002-20260509    gcc-9.5.0
arm                               allnoconfig    clang-23
arm                               allnoconfig    gcc-15.2.0
arm                              allyesconfig    clang-16
arm                                 defconfig    gcc-15.2.0
arm                           h3600_defconfig    gcc-15.2.0
arm                        neponset_defconfig    gcc-15.2.0
arm                            randconfig-001    gcc-8.5.0
arm                   randconfig-001-20260508    gcc-12.5.0
arm                   randconfig-001-20260508    gcc-8.5.0
arm                   randconfig-001-20260509    gcc-9.5.0
arm                            randconfig-002    gcc-8.5.0
arm                   randconfig-002-20260508    gcc-12.5.0
arm                   randconfig-002-20260508    gcc-8.5.0
arm                   randconfig-002-20260509    gcc-9.5.0
arm                            randconfig-003    gcc-8.5.0
arm                   randconfig-003-20260508    gcc-12.5.0
arm                   randconfig-003-20260508    gcc-8.5.0
arm                   randconfig-003-20260509    gcc-9.5.0
arm                            randconfig-004    gcc-8.5.0
arm                   randconfig-004-20260508    gcc-12.5.0
arm                   randconfig-004-20260508    gcc-8.5.0
arm                   randconfig-004-20260509    gcc-9.5.0
arm64                            allmodconfig    clang-19
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-15.2.0
arm64                               defconfig    gcc-15.2.0
arm64                 randconfig-001-20260508    gcc-14.3.0
arm64                 randconfig-001-20260509    gcc-10.5.0
arm64                 randconfig-002-20260508    gcc-14.3.0
arm64                 randconfig-002-20260509    gcc-10.5.0
arm64                 randconfig-003-20260508    gcc-14.3.0
arm64                 randconfig-003-20260509    gcc-10.5.0
arm64                 randconfig-004-20260508    gcc-14.3.0
arm64                 randconfig-004-20260509    gcc-10.5.0
csky                             allmodconfig    gcc-15.2.0
csky                              allnoconfig    gcc-15.2.0
csky                                defconfig    gcc-15.2.0
csky                  randconfig-001-20260508    gcc-14.3.0
csky                  randconfig-001-20260509    gcc-10.5.0
csky                  randconfig-002-20260508    gcc-14.3.0
csky                  randconfig-002-20260509    gcc-10.5.0
hexagon                          allmodconfig    clang-17
hexagon                          allmodconfig    gcc-15.2.0
hexagon                           allnoconfig    clang-23
hexagon                           allnoconfig    gcc-15.2.0
hexagon                             defconfig    gcc-15.2.0
hexagon                        randconfig-001    gcc-11.5.0
hexagon               randconfig-001-20260508    clang-23
hexagon               randconfig-001-20260508    gcc-11.5.0
hexagon               randconfig-001-20260509    clang-17
hexagon                        randconfig-002    gcc-11.5.0
hexagon               randconfig-002-20260508    clang-23
hexagon               randconfig-002-20260508    gcc-11.5.0
hexagon               randconfig-002-20260509    clang-17
i386                             allmodconfig    clang-20
i386                              allnoconfig    gcc-14
i386                              allnoconfig    gcc-15.2.0
i386                             allyesconfig    clang-20
i386                 buildonly-randconfig-001    gcc-14
i386        buildonly-randconfig-001-20260508    gcc-14
i386        buildonly-randconfig-001-20260509    gcc-14
i386                 buildonly-randconfig-002    gcc-14
i386        buildonly-randconfig-002-20260508    gcc-14
i386        buildonly-randconfig-002-20260509    gcc-14
i386                 buildonly-randconfig-003    gcc-14
i386        buildonly-randconfig-003-20260508    gcc-14
i386        buildonly-randconfig-003-20260509    gcc-14
i386                 buildonly-randconfig-004    gcc-14
i386        buildonly-randconfig-004-20260508    gcc-14
i386        buildonly-randconfig-004-20260509    gcc-14
i386                 buildonly-randconfig-005    gcc-14
i386        buildonly-randconfig-005-20260508    gcc-14
i386        buildonly-randconfig-005-20260509    gcc-14
i386                 buildonly-randconfig-006    gcc-14
i386        buildonly-randconfig-006-20260508    gcc-14
i386        buildonly-randconfig-006-20260509    gcc-14
i386                                defconfig    gcc-15.2.0
i386                           randconfig-001    gcc-14
i386                  randconfig-001-20260508    gcc-14
i386                  randconfig-001-20260509    clang-20
i386                           randconfig-002    gcc-14
i386                  randconfig-002-20260508    gcc-14
i386                  randconfig-002-20260509    clang-20
i386                           randconfig-003    gcc-14
i386                  randconfig-003-20260508    gcc-14
i386                  randconfig-003-20260509    clang-20
i386                           randconfig-004    gcc-14
i386                  randconfig-004-20260508    gcc-14
i386                  randconfig-004-20260509    clang-20
i386                           randconfig-005    gcc-14
i386                  randconfig-005-20260508    gcc-14
i386                  randconfig-005-20260509    clang-20
i386                           randconfig-006    gcc-14
i386                  randconfig-006-20260508    gcc-14
i386                  randconfig-006-20260509    clang-20
i386                           randconfig-007    gcc-14
i386                  randconfig-007-20260508    gcc-14
i386                  randconfig-007-20260509    clang-20
i386                  randconfig-011-20260508    gcc-13
i386                  randconfig-012-20260508    gcc-13
i386                  randconfig-013-20260508    gcc-13
i386                  randconfig-014-20260508    gcc-13
i386                  randconfig-015-20260508    gcc-13
i386                  randconfig-016-20260508    gcc-13
i386                  randconfig-017-20260508    gcc-13
loongarch                        allmodconfig    clang-19
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    clang-23
loongarch                         allnoconfig    gcc-15.2.0
loongarch                           defconfig    clang-19
loongarch                      randconfig-001    gcc-11.5.0
loongarch             randconfig-001-20260508    clang-23
loongarch             randconfig-001-20260508    gcc-11.5.0
loongarch             randconfig-001-20260509    clang-17
loongarch                      randconfig-002    gcc-11.5.0
loongarch             randconfig-002-20260508    clang-23
loongarch             randconfig-002-20260508    gcc-11.5.0
loongarch             randconfig-002-20260509    clang-17
m68k                             allmodconfig    gcc-15.2.0
m68k                              allnoconfig    gcc-15.2.0
m68k                             allyesconfig    clang-16
m68k                                defconfig    clang-19
microblaze                        allnoconfig    gcc-15.2.0
microblaze                       allyesconfig    gcc-15.2.0
microblaze                          defconfig    clang-19
mips                             allmodconfig    gcc-15.2.0
mips                              allnoconfig    gcc-15.2.0
mips                             allyesconfig    gcc-15.2.0
mips                      loongson3_defconfig    gcc-15.2.0
mips                        omega2p_defconfig    clang-23
mips                         rt305x_defconfig    clang-23
nios2                            allmodconfig    clang-23
nios2                             allnoconfig    clang-23
nios2                             allnoconfig    gcc-11.5.0
nios2                               defconfig    clang-19
nios2                          randconfig-001    gcc-11.5.0
nios2                 randconfig-001-20260508    clang-23
nios2                 randconfig-001-20260508    gcc-11.5.0
nios2                 randconfig-001-20260509    clang-17
nios2                          randconfig-002    gcc-11.5.0
nios2                 randconfig-002-20260508    clang-23
nios2                 randconfig-002-20260508    gcc-11.5.0
nios2                 randconfig-002-20260509    clang-17
openrisc                         allmodconfig    clang-23
openrisc                          allnoconfig    clang-23
openrisc                          allnoconfig    gcc-15.2.0
openrisc                            defconfig    gcc-15.2.0
openrisc                 simple_smp_defconfig    gcc-15.2.0
parisc                           allmodconfig    gcc-15.2.0
parisc                            allnoconfig    clang-23
parisc                            allnoconfig    gcc-15.2.0
parisc                           allyesconfig    clang-19
parisc                           allyesconfig    gcc-15.2.0
parisc                              defconfig    gcc-15.2.0
parisc                         randconfig-001    gcc-9.5.0
parisc                randconfig-001-20260508    gcc-9.5.0
parisc                randconfig-001-20260509    gcc-11.5.0
parisc                         randconfig-002    gcc-9.5.0
parisc                randconfig-002-20260508    gcc-9.5.0
parisc                randconfig-002-20260509    gcc-11.5.0
parisc64                            defconfig    clang-19
powerpc                          allmodconfig    gcc-15.2.0
powerpc                           allnoconfig    clang-23
powerpc                           allnoconfig    gcc-15.2.0
powerpc                       holly_defconfig    clang-23
powerpc                        randconfig-001    gcc-9.5.0
powerpc               randconfig-001-20260508    gcc-9.5.0
powerpc               randconfig-001-20260509    gcc-11.5.0
powerpc                        randconfig-002    gcc-9.5.0
powerpc               randconfig-002-20260508    gcc-9.5.0
powerpc               randconfig-002-20260509    gcc-11.5.0
powerpc                     tqm8555_defconfig    gcc-15.2.0
powerpc64                      randconfig-001    gcc-9.5.0
powerpc64             randconfig-001-20260508    gcc-9.5.0
powerpc64             randconfig-001-20260509    gcc-11.5.0
powerpc64                      randconfig-002    gcc-9.5.0
powerpc64             randconfig-002-20260508    gcc-9.5.0
powerpc64             randconfig-002-20260509    gcc-11.5.0
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                             allnoconfig    gcc-15.2.0
riscv                            allyesconfig    clang-16
riscv                               defconfig    gcc-15.2.0
riscv                 randconfig-001-20260508    clang-23
riscv                 randconfig-001-20260509    clang-23
riscv                 randconfig-002-20260508    clang-23
riscv                 randconfig-002-20260509    clang-23
s390                             allmodconfig    clang-18
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-15.2.0
s390                                defconfig    gcc-15.2.0
s390                  randconfig-001-20260508    clang-23
s390                  randconfig-001-20260509    clang-23
s390                  randconfig-002-20260508    clang-23
s390                  randconfig-002-20260509    clang-23
sh                               allmodconfig    gcc-15.2.0
sh                                allnoconfig    clang-23
sh                                allnoconfig    gcc-15.2.0
sh                               allyesconfig    clang-19
sh                               allyesconfig    gcc-15.2.0
sh                        apsh4ad0a_defconfig    gcc-15.2.0
sh                                  defconfig    gcc-14
sh                     magicpanelr2_defconfig    gcc-15.2.0
sh                          polaris_defconfig    gcc-15.2.0
sh                    randconfig-001-20260508    clang-23
sh                    randconfig-001-20260509    clang-23
sh                    randconfig-002-20260508    clang-23
sh                    randconfig-002-20260509    clang-23
sparc                             allnoconfig    clang-23
sparc                             allnoconfig    gcc-15.2.0
sparc                               defconfig    gcc-15.2.0
sparc                          randconfig-001    gcc-12
sparc                 randconfig-001-20260508    gcc-12
sparc                 randconfig-001-20260509    clang-23
sparc                          randconfig-002    gcc-12
sparc                 randconfig-002-20260508    gcc-12
sparc                 randconfig-002-20260509    clang-23
sparc64                          allmodconfig    clang-23
sparc64                             defconfig    gcc-14
sparc64                        randconfig-001    gcc-12
sparc64               randconfig-001-20260508    gcc-12
sparc64               randconfig-001-20260509    clang-23
sparc64                        randconfig-002    gcc-12
sparc64               randconfig-002-20260508    gcc-12
sparc64               randconfig-002-20260509    clang-23
um                               allmodconfig    clang-19
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-14
um                               allyesconfig    gcc-15.2.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                             randconfig-001    gcc-12
um                    randconfig-001-20260508    gcc-12
um                    randconfig-001-20260509    clang-23
um                             randconfig-002    gcc-12
um                    randconfig-002-20260508    gcc-12
um                    randconfig-002-20260509    clang-23
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-20
x86_64                            allnoconfig    clang-20
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-20
x86_64               buildonly-randconfig-001    gcc-14
x86_64      buildonly-randconfig-001-20260508    gcc-14
x86_64               buildonly-randconfig-002    gcc-14
x86_64      buildonly-randconfig-002-20260508    gcc-14
x86_64               buildonly-randconfig-003    gcc-14
x86_64      buildonly-randconfig-003-20260508    gcc-14
x86_64               buildonly-randconfig-004    gcc-14
x86_64      buildonly-randconfig-004-20260508    gcc-14
x86_64               buildonly-randconfig-005    gcc-14
x86_64      buildonly-randconfig-005-20260508    gcc-14
x86_64               buildonly-randconfig-006    gcc-14
x86_64      buildonly-randconfig-006-20260508    gcc-14
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-20
x86_64                         randconfig-001    clang-20
x86_64                randconfig-001-20260508    clang-20
x86_64                         randconfig-002    clang-20
x86_64                randconfig-002-20260508    clang-20
x86_64                         randconfig-003    clang-20
x86_64                randconfig-003-20260508    clang-20
x86_64                         randconfig-004    clang-20
x86_64                randconfig-004-20260508    clang-20
x86_64                         randconfig-005    clang-20
x86_64                randconfig-005-20260508    clang-20
x86_64                         randconfig-006    clang-20
x86_64                randconfig-006-20260508    clang-20
x86_64                         randconfig-011    gcc-14
x86_64                randconfig-011-20260508    gcc-14
x86_64                         randconfig-012    gcc-14
x86_64                randconfig-012-20260508    gcc-14
x86_64                         randconfig-013    gcc-14
x86_64                randconfig-013-20260508    gcc-14
x86_64                         randconfig-014    gcc-14
x86_64                randconfig-014-20260508    gcc-14
x86_64                         randconfig-015    gcc-14
x86_64                randconfig-015-20260508    gcc-14
x86_64                         randconfig-016    gcc-14
x86_64                randconfig-016-20260508    gcc-14
x86_64                         randconfig-071    gcc-14
x86_64                randconfig-071-20260508    gcc-14
x86_64                randconfig-071-20260509    clang-20
x86_64                         randconfig-072    gcc-14
x86_64                randconfig-072-20260508    gcc-14
x86_64                randconfig-072-20260509    clang-20
x86_64                         randconfig-073    gcc-14
x86_64                randconfig-073-20260508    gcc-14
x86_64                randconfig-073-20260509    clang-20
x86_64                         randconfig-074    gcc-14
x86_64                randconfig-074-20260508    gcc-14
x86_64                randconfig-074-20260509    clang-20
x86_64                         randconfig-075    gcc-14
x86_64                randconfig-075-20260508    gcc-14
x86_64                randconfig-075-20260509    clang-20
x86_64                         randconfig-076    gcc-14
x86_64                randconfig-076-20260508    gcc-14
x86_64                randconfig-076-20260509    clang-20
x86_64                               rhel-9.4    clang-20
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-20
x86_64                    rhel-9.4-kselftests    clang-20
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-20
xtensa                            allnoconfig    clang-23
xtensa                            allnoconfig    gcc-15.2.0
xtensa                           allyesconfig    clang-23
xtensa                         randconfig-001    gcc-12
xtensa                randconfig-001-20260508    gcc-12
xtensa                randconfig-001-20260509    clang-23
xtensa                         randconfig-002    gcc-12
xtensa                randconfig-002-20260508    gcc-12
xtensa                randconfig-002-20260509    clang-23

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH RFC 3/4] Input: gpio-keys - add regulator to gpio_keys
From: sashiko-bot @ 2026-05-08 21:36 UTC (permalink / raw)
  To: Griffin Kroah-Hartman
  Cc: linux-input, robh, krzk+dt, dmitry.torokhov, conor+dt, devicetree
In-Reply-To: <20260508-gpiokeys-vdd-supply-v1-3-0bb32e8e6428@fairphone.com>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Tying the regulator's power state to the input device's open()/close() lifecycle leaves interrupts active while the hardware is unpowered, causing an interrupt storm.
- [Medium] System wakeup functionality is broken because regulators are disabled if the input device is closed.
- [Medium] Unsafe hardware access during system resume causes spurious key events.
- [Medium] Missing pdata->disable() in the gpio_keys_open() error path leads to a resource leak.
- [Low] Incorrect teardown order in gpio_keys_close() violates LIFO symmetry.
--

commit d47e6012a488ac21d0005ba6dd4aa95a285831d3
Author: Griffin Kroah-Hartman <griffin.kroah@fairphone.com>

Input: gpio-keys - add regulator to gpio_keys

This commit allows gpio-keys to have a vdd power supply managed through
regulators.

> diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
> index e196174856796..2199ce7455cfc 100644
> --- a/drivers/input/keyboard/gpio_keys.c
> +++ b/drivers/input/keyboard/gpio_keys.c

[ ... ]

> @@ -729,6 +730,7 @@ static int gpio_keys_open(struct input_dev *input)
>  	struct gpio_keys_drvdata *ddata = input_get_drvdata(input);
>  	const struct gpio_keys_platform_data *pdata = ddata->pdata;
>  	int error;
> +	int i;
>  
>  	if (pdata->enable) {
>  		error = pdata->enable(input->dev.parent);
> @@ -736,19 +738,48 @@ static int gpio_keys_open(struct input_dev *input)
>  			return error;
>  	}
>  
> +	for (i = 0; i < pdata->nbuttons; i++) {
> +		const struct gpio_keys_button *button = &pdata->buttons[i];
> +
> +		if (!button->regulator)
> +			continue;
> +		error = regulator_enable(button->regulator);
> +		if (error)
> +			goto reg_err;
> +	}

Because interrupts are requested unconditionally in gpio_keys_probe() and
remain unmasked, tying the regulator power state to the input device's
open()/close() lifecycle leaves the physical button unpowered when the device
is closed. Could this allow the GPIO pin to float and trigger an interrupt
storm?

Also, if the input device is closed before suspend, the regulator remains
disabled. Does this prevent an unpowered physical button from generating the
electrical signal required to trigger a wakeup interrupt?

Additionally, gpio_keys_resume() unconditionally calls
gpio_keys_report_state(), which reads the current state of all GPIOs. If the
device is closed, the regulators are powered off. Can reading unpowered GPIOs
return floating states that inject spurious phantom key press events on every
resume?

> +
>  	/* Report current state of buttons that are connected to GPIOs */
>  	gpio_keys_report_state(ddata);
>  
>  	return 0;
> +
> +reg_err:
> +	for (--i; i >= 0; i--) {
> +		const struct gpio_keys_button *button = &pdata->buttons[i];
> +
> +		if (!button->regulator)
> +			continue;
> +		regulator_disable(button->regulator);
> +	}
> +	return error;

If regulator_enable() fails and we jump to reg_err, we return the error but
fail to call pdata->disable(). Does this leave the platform state permanently
active and leak resources since pdata->enable() was called earlier?

>  }
>  
>  static void gpio_keys_close(struct input_dev *input)
>  {
>  	struct gpio_keys_drvdata *ddata = input_get_drvdata(input);
>  	const struct gpio_keys_platform_data *pdata = ddata->pdata;
> +	int i;
>  
>  	if (pdata->disable)
>  		pdata->disable(input->dev.parent);
> +
> +	for (i = 0; i < pdata->nbuttons; i++) {
> +		const struct gpio_keys_button *button = &pdata->buttons[i];
> +
> +		if (!button->regulator)
> +			continue;
> +		regulator_disable(button->regulator);
> +	}
>  }

Is the teardown order correct here? In gpio_keys_open(), pdata->enable() is
called before the regulators are enabled. Should gpio_keys_close() reverse
this sequence by disabling the regulators before calling pdata->disable() to
maintain LIFO symmetry?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260508-gpiokeys-vdd-supply-v1-0-0bb32e8e6428@fairphone.com?part=3

^ permalink raw reply

* Re: [PATCH RFC 4/4] arm64: dts: qcom: milos-fairphone-fp6: add supply for Hall Effect sensor
From: sashiko-bot @ 2026-05-08 21:56 UTC (permalink / raw)
  To: Griffin Kroah-Hartman
  Cc: robh, conor+dt, linux-input, krzk+dt, devicetree, dmitry.torokhov
In-Reply-To: <20260508-gpiokeys-vdd-supply-v1-4-0bb32e8e6428@fairphone.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Removing `regulator-always-on` from the Hall sensor's supply causes interrupt storms, spurious events, and broken system wakeup when the input device is closed.
--

commit 35bf0d08eef4da2139153f5425e351a93d9d591d
Author: Griffin Kroah-Hartman <griffin.kroah@fairphone.com>

arm64: dts: qcom: milos-fairphone-fp6: add supply for Hall Effect sensor

This commit adds a vdd-supply property to the Hall Effect sensor and removes
the regulator-always-on property from vreg_l10b, relying on the gpio-keys
driver to manage power.

> diff --git a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
> index c1899db46e714..ae6900c3f75c6 100644
> --- a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
> +++ b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
> @@ -32,13 +32,13 @@ gpio-keys {
>  		pinctrl-0 = <&volume_up_default>, <&hall_sensor_default>;
>  		pinctrl-names = "default";
>  
> -		/* Powered by the always-on vreg_l10b */
>  		event-hall-sensor {
>  			label = "Hall Effect Sensor";
>  			gpios = <&tlmm 70 GPIO_ACTIVE_LOW>;
>  			linux,input-type = <EV_SW>;
>  			linux,code = <SW_LID>;
>  			linux,can-disable;
> +			vdd-supply = <&vreg_l10b>;

When the device is opened, the driver reads the GPIO state immediately after
enabling the regulator. Without a startup-delay-us property on the regulator
to allow the voltage to stabilize, could this read an uninitialized state and
generate spurious lid events?

>  			wakeup-source;
>  		};
>  
[ ... ]
> @@ -326,8 +326,6 @@ vreg_l10b: ldo10 {
>  			regulator-min-microvolt = <1800000>;
>  			regulator-max-microvolt = <1800000>;
>  			regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
> -			/* Hall sensor VDD */
> -			regulator-always-on;
>  		};

Could removing this property cause an interrupt storm?

The gpio-keys driver requests and unmasks the GPIO interrupt during probe, but
only enables the vdd-supply regulator when the input device is explicitly
opened by userspace.

If the device is closed, the regulator is disabled. Cutting power to the Hall
sensor while its edge-triggered interrupt remains active might cause the GPIO
line to float. A floating line can pick up electrical noise and trigger a
continuous interrupt storm.

Additionally, does this break the system's ability to wake up?

If the system suspends while the device is closed, the sensor remains
unpowered. Even though the wake IRQ is armed due to the wakeup-source
property, an unpowered sensor wouldn't be able to detect lid events to wake
the system.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260508-gpiokeys-vdd-supply-v1-0-0bb32e8e6428@fairphone.com?part=4

^ permalink raw reply

* Re: [PATCH RESEND 2] HID: Add force feedback support for Speedlink Cougar Vibration Flightstick
From: sashiko-bot @ 2026-05-08 22:51 UTC (permalink / raw)
  To: Harald Judt; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <b3bfa73b-0547-45f9-b6ae-f28815e6c632@gmx.at>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Race condition in force feedback initialization leading to a NULL pointer dereference.
- [High] Ignoring the return value of `gembird_joy_init()` causes a NULL pointer dereference when user-space interacts with the event device after an initialization failure.
- [High] Non-monotonic magnitude scaling logic severely breaks force feedback functionality.
- [Medium] Memory leak of the `gembird_joy_device` state structure upon device disconnect.
--

commit f9141496ab06cd22000d2487bbb234d7e91931b5
Author: Harald Judt <h.judt@gmx.at>

HID: Add force feedback support for Gembird based joystick

This commit adds force feedback (rumble) support for the SpeedLink Cougar
Vibration Flightstick (SL-6630) joystick, which uses a Gembird controller.

> diff --git a/drivers/hid/hid-gembird-joy.c b/drivers/hid/hid-gembird-joy.c
> new file mode 100644
> index 0000000000000..5a5afa02f8407
> --- /dev/null
> +++ b/drivers/hid/hid-gembird-joy.c

[ ... ]

> +static int hid_gembird_joy_play(struct input_dev *dev, void *data,
> +				struct ff_effect *effect)
> +{
> +	struct hid_device *hid = input_get_drvdata(dev);
> +	struct gembird_joy_device *joy = data;
> +	int strong, weak;
> +
> +	strong = effect->u.rumble.strong_magnitude;
> +	weak = effect->u.rumble.weak_magnitude;

[ ... ]

> +	strong = (strong / 0xff) * 0x1f / 0xff;
> +	weak = (weak / 0xff) * 0x1f / 0xff;
> +
> +	/* ... and to support the notions of strong vs weak rumble effects,
> +	 * increase the magnitude for the strong rumble effect if it is below the
> +	 * half of the maximum value, as the strong motor has the same strength as
> +	 * the weak one. Likewise, decrease the magnitude for the weak effect.
> +	 */
> +	if (strong < 0x10 && !weak)         /* fftest effect 4 strong rumble */
> +		strong *= 2;
> +	else if (!strong && weak >= 0x10)   /* fftest effect 5 weak rumble */
> +		weak /= 2;

Will this cause issues with non-monotonic force feedback behavior and
unintended truncation?

Since the math uses integer division, any input value below 255 for strong
or weak will evaluate to zero during the first division by 0xff.

Additionally, could the conditional scaling cause abrupt changes in rumble
strength? For instance, if a game requests a strong magnitude that scales
down to 15, it gets doubled to 30 because of the strong < 0x10 check.
However, a slightly stronger requested magnitude that scales to 16 will
remain 16, meaning an increase in requested strength results in a drop in
physical rumble.

[ ... ]

> +static int gembird_joy_init(struct hid_device *hid)
> +{

[ ... ]

> +		joy = kzalloc(sizeof(struct gembird_joy_device), GFP_KERNEL);
> +		if (!joy)
> +			return -ENOMEM;

Does this memory leak when the device is disconnected or the driver is
unbound? The allocation doesn't use devm_kzalloc, and there isn't a
remove callback to free it. The input_ff_create_memless teardown
handles its own structures but not the user-provided private data.

> +
> +		dev = hidinput->input;
> +
> +		set_bit(FF_RUMBLE, dev->ffbit);
> +
> +		error = input_ff_create_memless(dev, joy, hid_gembird_joy_play);
> +		if (error) {
> +			kfree(joy);
> +			return error;
> +		}
> +
> +		joy->report = report;

Is there a window here where an ioctl could trigger a NULL pointer
dereference?

The device was already started earlier in gembird_joy_probe via
hid_hw_start, so userspace can issue an EVIOCSFF ioctl as soon as
input_ff_create_memless succeeds. If the ioctl triggers
hid_gembird_joy_play before joy->report is assigned on the next line,
the callback will try to access joy->report->field and dereference NULL.

[ ... ]

> +static int gembird_joy_probe(struct hid_device *hdev, const struct hid_device_id *id)
> +{
> +	int ret;
> +
> +	ret = hid_parse(hdev);
> +	if (ret) {
> +		hid_err(hdev, "parse failed\n");
> +		return ret;
> +	}
> +
> +	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
> +	if (ret) {
> +		hid_err(hdev, "hw start failed\n");
> +		return ret;
> +	}
> +
> +	gembird_joy_init(hdev);
> +
> +	return 0;
> +}

What happens if gembird_joy_init fails?

If input_ff_create_memless returns an error, gembird_joy_init
propagates it, but the return value is ignored here and probe succeeds.

Because set_bit(FF_RUMBLE, dev->ffbit) was already called, the device
remains registered and advertises rumble support. If userspace then issues
an EVIOCSFF ioctl, the kernel will allow it, which could lead to a panic
when it tries to dereference the missing force feedback structures.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/b3bfa73b-0547-45f9-b6ae-f28815e6c632@gmx.at?part=1

^ permalink raw reply

* Re: [PATCH RESEND 2] HID: Add force feedback support for Speedlink Cougar Vibration Flightstick
From: Dmitry Torokhov @ 2026-05-08 23:14 UTC (permalink / raw)
  To: sashiko; +Cc: Harald Judt, linux-input
In-Reply-To: <20260508225130.C6D33C2BCB0@smtp.kernel.org>

On Fri, May 08, 2026 at 10:51:30PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
> - [High] Race condition in force feedback initialization leading to a NULL pointer dereference.
> - [High] Ignoring the return value of `gembird_joy_init()` causes a NULL pointer dereference when user-space interacts with the event device after an initialization failure.
> - [High] Non-monotonic magnitude scaling logic severely breaks force feedback functionality.
> - [Medium] Memory leak of the `gembird_joy_device` state structure upon device disconnect.
> --
> 
> commit f9141496ab06cd22000d2487bbb234d7e91931b5
> Author: Harald Judt <h.judt@gmx.at>
> 
> HID: Add force feedback support for Gembird based joystick
> 
> This commit adds force feedback (rumble) support for the SpeedLink Cougar
> Vibration Flightstick (SL-6630) joystick, which uses a Gembird controller.
> 
> > diff --git a/drivers/hid/hid-gembird-joy.c b/drivers/hid/hid-gembird-joy.c
> > new file mode 100644
> > index 0000000000000..5a5afa02f8407
> > --- /dev/null
> > +++ b/drivers/hid/hid-gembird-joy.c
> 
> [ ... ]
> 
> > +static int hid_gembird_joy_play(struct input_dev *dev, void *data,
> > +				struct ff_effect *effect)
> > +{
> > +	struct hid_device *hid = input_get_drvdata(dev);
> > +	struct gembird_joy_device *joy = data;
> > +	int strong, weak;
> > +
> > +	strong = effect->u.rumble.strong_magnitude;
> > +	weak = effect->u.rumble.weak_magnitude;
> 
> [ ... ]
> 
> > +	strong = (strong / 0xff) * 0x1f / 0xff;
> > +	weak = (weak / 0xff) * 0x1f / 0xff;
> > +
> > +	/* ... and to support the notions of strong vs weak rumble effects,
> > +	 * increase the magnitude for the strong rumble effect if it is below the
> > +	 * half of the maximum value, as the strong motor has the same strength as
> > +	 * the weak one. Likewise, decrease the magnitude for the weak effect.
> > +	 */
> > +	if (strong < 0x10 && !weak)         /* fftest effect 4 strong rumble */
> > +		strong *= 2;
> > +	else if (!strong && weak >= 0x10)   /* fftest effect 5 weak rumble */
> > +		weak /= 2;
> 
> Will this cause issues with non-monotonic force feedback behavior and
> unintended truncation?
> 
> Since the math uses integer division, any input value below 255 for strong
> or weak will evaluate to zero during the first division by 0xff.
> 
> Additionally, could the conditional scaling cause abrupt changes in rumble
> strength? For instance, if a game requests a strong magnitude that scales
> down to 15, it gets doubled to 30 because of the strong < 0x10 check.
> However, a slightly stronger requested magnitude that scales to 16 will
> remain 16, meaning an increase in requested strength results in a drop in
> physical rumble.
> 
> [ ... ]
> 
> > +static int gembird_joy_init(struct hid_device *hid)
> > +{
> 
> [ ... ]
> 
> > +		joy = kzalloc(sizeof(struct gembird_joy_device), GFP_KERNEL);
> > +		if (!joy)
> > +			return -ENOMEM;
> 
> Does this memory leak when the device is disconnected or the driver is
> unbound? The allocation doesn't use devm_kzalloc, and there isn't a
> remove callback to free it. The input_ff_create_memless teardown
> handles its own structures but not the user-provided private data.

Sashiko is wrong here.

> 
> > +
> > +		dev = hidinput->input;
> > +
> > +		set_bit(FF_RUMBLE, dev->ffbit);
> > +
> > +		error = input_ff_create_memless(dev, joy, hid_gembird_joy_play);
> > +		if (error) {
> > +			kfree(joy);
> > +			return error;
> > +		}
> > +
> > +		joy->report = report;
> 
> Is there a window here where an ioctl could trigger a NULL pointer
> dereference?
> 
> The device was already started earlier in gembird_joy_probe via
> hid_hw_start, so userspace can issue an EVIOCSFF ioctl as soon as
> input_ff_create_memless succeeds. If the ioctl triggers
> hid_gembird_joy_play before joy->report is assigned on the next line,
> the callback will try to access joy->report->field and dereference NULL.

Sashiko is wrong here as well. The device is not accessible from
userspace until it is registered.

> 
> [ ... ]
> 
> > +static int gembird_joy_probe(struct hid_device *hdev, const struct hid_device_id *id)
> > +{
> > +	int ret;
> > +
> > +	ret = hid_parse(hdev);
> > +	if (ret) {
> > +		hid_err(hdev, "parse failed\n");
> > +		return ret;
> > +	}
> > +
> > +	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
> > +	if (ret) {
> > +		hid_err(hdev, "hw start failed\n");
> > +		return ret;
> > +	}
> > +
> > +	gembird_joy_init(hdev);
> > +
> > +	return 0;
> > +}
> 
> What happens if gembird_joy_init fails?
> 
> If input_ff_create_memless returns an error, gembird_joy_init
> propagates it, but the return value is ignored here and probe succeeds.
> 
> Because set_bit(FF_RUMBLE, dev->ffbit) was already called, the device
> remains registered and advertises rumble support. If userspace then issues
> an EVIOCSFF ioctl, the kernel will allow it, which could lead to a panic
> when it tries to dereference the missing force feedback structures.
> 

Need to have error handling.

Thanks.

-- 
Dmitry

^ permalink raw reply

* [PATCH] Input: analog: replace deprecated simple_strtoul() with kstrtouint()
From: Akash Sukhavasi @ 2026-05-09  2:40 UTC (permalink / raw)
  To: dmitry.torokhov; +Cc: linux-input, linux-kernel, Akash Sukhavasi

The simple_strtoul() function is deprecated because it ignores
trailing garbage characters, which can mask typos in input.

Replace it with kstrtouint() in analog_parse_options() to enforce
strict input parsing.

Note that this introduces a minor, intended behavior change: while
the old code would silently parse a malformed string like "12abc"
as 12, the new code will reject it entirely and fall back to the
unconfigured state (0xff). This strict parsing is the preferred
modern behavior for kernel parameters.

Signed-off-by: Akash Sukhavasi <akash.sukhavasi@gmail.com>
---
 drivers/input/joystick/analog.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index b6f7bce1c..07ad360f8 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -653,7 +653,7 @@ static struct analog_types analog_types[] = {
 static void analog_parse_options(void)
 {
 	int i, j;
-	char *end;
+	unsigned int parsed_val;
 
 	for (i = 0; i < js_nargs; i++) {
 
@@ -664,8 +664,10 @@ static void analog_parse_options(void)
 			}
 		if (analog_types[j].name) continue;
 
-		analog_options[i] = simple_strtoul(js[i], &end, 0);
-		if (end != js[i]) continue;
+		if (kstrtouint(js[i], 0, &parsed_val) == 0) {
+			analog_options[i] = parsed_val;
+			continue;
+		}
 
 		analog_options[i] = 0xff;
 		if (!strlen(js[i])) continue;
-- 
2.54.0


^ permalink raw reply related

* [PATCH] HID: i2c-hid: add reset quirk for BLTP7853 touchpad
From: Xu Rao @ 2026-05-09  8:21 UTC (permalink / raw)
  To: jikos, bentiss; +Cc: linux-input, linux-kernel, raoxu

The BLTP7853 I2C HID touchpad may fail to probe after reboot or
reprobe because reset completion is not signalled to the host. The
driver then waits for the reset-complete interrupt until it times out
and the device probe fails:

  i2c_hid i2c-BLTP7853:00: failed to reset device.
  i2c_hid i2c-BLTP7853:00: can't add hid device: -61
  i2c_hid: probe of i2c-BLTP7853:00 failed with error -61

Add I2C_HID_QUIRK_NO_IRQ_AFTER_RESET for the device so i2c-hid does
not wait for a reset interrupt that may never arrive.

Signed-off-by: Xu Rao <raoxu@uniontech.com>
---
 drivers/hid/hid-ids.h              | 3 +++
 drivers/hid/i2c-hid/i2c-hid-core.c | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 0cf63742315b..dcb0b34cd069 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -277,6 +277,9 @@
 #define USB_VENDOR_ID_BIGBEN	0x146b
 #define USB_DEVICE_ID_BIGBEN_PS3OFMINIPAD	0x0902

+#define I2C_VENDOR_ID_BLTP		0x36b6
+#define I2C_PRODUCT_ID_BLTP7853		0xc001
+
 #define USB_VENDOR_ID_BTC		0x046e
 #define USB_DEVICE_ID_BTC_EMPREX_REMOTE	0x5578
 #define USB_DEVICE_ID_BTC_EMPREX_REMOTE_2	0x5577
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index 5a183af3d5c6..baff2728603e 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -149,6 +149,8 @@ static const struct i2c_hid_quirks {
 		 I2C_HID_QUIRK_BOGUS_IRQ },
 	{ I2C_VENDOR_ID_GOODIX, I2C_DEVICE_ID_GOODIX_0D42,
 		 I2C_HID_QUIRK_DELAY_WAKEUP_AFTER_RESUME },
+	{ I2C_VENDOR_ID_BLTP, I2C_PRODUCT_ID_BLTP7853,
+		I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
 	{ 0, 0 }
 };

--
2.50.1



^ permalink raw reply related

* [PATCH] HID: mcp2221: fix OOB write in mcp2221_raw_event()
From: Florian Pradines @ 2026-05-09  9:45 UTC (permalink / raw)
  To: gupt21, jikos, bentiss; +Cc: linux-i2c, linux-input, Florian Pradines

mcp2221_raw_event() copies device-supplied data into mcp->rxbuf at
offset rxbuf_idx without checking that the copy fits within the
destination buffer. A device responding with up to 60 bytes to a
small I2C/SMBus read can overflow the buffer.

Add a rxbuf_size field to struct mcp2221, set it alongside rxbuf in
mcp_i2c_smbus_read(), and check rxbuf_idx + data[3] <= rxbuf_size
before the memcpy.

Signed-off-by: Florian Pradines <florian.pradines@gmail.com>
---
 drivers/hid/hid-mcp2221.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c
index be80970ab48e..e4ddd8e9293b 100644
--- a/drivers/hid/hid-mcp2221.c
+++ b/drivers/hid/hid-mcp2221.c
@@ -128,6 +128,7 @@ struct mcp2221 {
 	u8 *rxbuf;
 	u8 txbuf[64];
 	int rxbuf_idx;
+	int rxbuf_size;
 	int status;
 	u8 cur_i2c_clk_div;
 	struct gpio_chip *gc;
@@ -330,12 +331,14 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp,
 		mcp->txbuf[3] = (u8)(msg->addr << 1);
 		total_len = msg->len;
 		mcp->rxbuf = msg->buf;
+		mcp->rxbuf_size = msg->len;
 	} else {
 		mcp->txbuf[1] = smbus_len;
 		mcp->txbuf[2] = 0;
 		mcp->txbuf[3] = (u8)(smbus_addr << 1);
 		total_len = smbus_len;
 		mcp->rxbuf = smbus_buf;
+		mcp->rxbuf_size = smbus_len;
 	}
 
 	ret = mcp_send_data_req_status(mcp, mcp->txbuf, 4);
@@ -919,6 +922,10 @@ static int mcp2221_raw_event(struct hid_device *hdev,
 					mcp->status = -EINVAL;
 					break;
 				}
+				if (mcp->rxbuf_idx + data[3] > mcp->rxbuf_size) {
+					mcp->status = -EINVAL;
+					break;
+				}
 				buf = mcp->rxbuf;
 				memcpy(&buf[mcp->rxbuf_idx], &data[4], data[3]);
 				mcp->rxbuf_idx = mcp->rxbuf_idx + data[3];
-- 
2.47.3


^ permalink raw reply related

* Re: [PATCH] Input: analog: replace deprecated simple_strtoul() with kstrtouint()
From: David Laight @ 2026-05-09  9:55 UTC (permalink / raw)
  To: Akash Sukhavasi; +Cc: dmitry.torokhov, linux-input, linux-kernel
In-Reply-To: <20260509024048.46132-1-akash.sukhavasi@gmail.com>

On Fri,  8 May 2026 21:40:48 -0500
Akash Sukhavasi <akash.sukhavasi@gmail.com> wrote:

> The simple_strtoul() function is deprecated because it ignores
> trailing garbage characters, which can mask typos in input.
> 
> Replace it with kstrtouint() in analog_parse_options() to enforce
> strict input parsing.
> 
> Note that this introduces a minor, intended behavior change: while
> the old code would silently parse a malformed string like "12abc"
> as 12, the new code will reject it entirely and fall back to the
> unconfigured state (0xff). This strict parsing is the preferred
> modern behavior for kernel parameters.

However that might break existing systems.
So I'm not at all sure it should be done.

	David

> 
> Signed-off-by: Akash Sukhavasi <akash.sukhavasi@gmail.com>
> ---
>  drivers/input/joystick/analog.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
> index b6f7bce1c..07ad360f8 100644
> --- a/drivers/input/joystick/analog.c
> +++ b/drivers/input/joystick/analog.c
> @@ -653,7 +653,7 @@ static struct analog_types analog_types[] = {
>  static void analog_parse_options(void)
>  {
>  	int i, j;
> -	char *end;
> +	unsigned int parsed_val;
>  
>  	for (i = 0; i < js_nargs; i++) {
>  
> @@ -664,8 +664,10 @@ static void analog_parse_options(void)
>  			}
>  		if (analog_types[j].name) continue;
>  
> -		analog_options[i] = simple_strtoul(js[i], &end, 0);
> -		if (end != js[i]) continue;
> +		if (kstrtouint(js[i], 0, &parsed_val) == 0) {
> +			analog_options[i] = parsed_val;
> +			continue;
> +		}
>  
>  		analog_options[i] = 0xff;
>  		if (!strlen(js[i])) continue;


^ permalink raw reply

* [PATCH v3 0/9] iio: introduce devm_ API for hid sensro setup and cleanup
From: Sanjay Chitroda @ 2026-05-09 10:10 UTC (permalink / raw)
  To: jikos, jic23, srinivas.pandruvada
  Cc: dlechner, nuno.sa, andy, sanjayembeddedse, sakari.ailus,
	linux-input, linux-iio, linux-kernel

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

Key highlights:
- Prepare change as pre-requisite for devm conversion for HID IIO
  drivers by removing redundant argument
- Add devm API to setup trigger and clenaup resource using
  devm_add_action_or_reset()
- few cleanup and prepratory changes before updating driver for devm_
- few sample driver update using devm conversion to auto release resource

changes in v3:
- Added cleanup and prepratory changes before adding devm_ API
  conversion based on self review: 0002, 0004, 0006, 0007 and 0008
- Address andy's review comment on commit message and coding style
- v2 series -> https://lore.kernel.org/all/20260429175918.2541914-1-sanjayembedded@gmail.com/
changes in v2:
- Following input from Jonathan and Andy, squash initial patch v1
  series in single change as individual change should not break anything
- Add devm API support and two driver using the same
- v1 series -> https://lore.kernel.org/all/20260428071613.1134053-1-sanjayembedded@gmail.com/

Testing:
  - Compiled with W=1
  - Build-tested on QEMU x86_64

Based on further feedback and reviews, I would extend this series to convert all HID IIO driver to use devm_* API.

Thanks,
Sanjay Chitroda


Sanjay Chitroda (9):
  iio: hid-sensors: drop redundant iio_dev argument
  iio: hid-sensors: cleanup codestyle warning
  iio: hid-sensors: introduce device managed API
  iio: gyro: hid-sensor-gyro-3d: cleanup codestyle warning
  iio: gyro: hid-sensor-gyro-3d: drop hid_sensor_remove_trigger() using
    devm API
  iio: humidity: hid-sensor-humidity: cleanup codestyle check
  iio: humidity: hid-sensor-humidity: use common device for devres
  iio: humidity: hid-sensor-humidity: use local struct device
  iio: humidity: hid-sensor-humidity: drop hid_sensor_remove_trigger()
    using devm API

 drivers/iio/accel/hid-sensor-accel-3d.c       |  4 +-
 .../common/hid-sensors/hid-sensor-trigger.c   | 24 +++++++-
 .../common/hid-sensors/hid-sensor-trigger.h   |  5 +-
 drivers/iio/gyro/hid-sensor-gyro-3d.c         | 16 ++---
 drivers/iio/humidity/hid-sensor-humidity.c    | 61 +++++++++----------
 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 +-
 .../position/hid-sensor-custom-intel-hinge.c  |  4 +-
 drivers/iio/pressure/hid-sensor-press.c       |  4 +-
 .../iio/temperature/hid-sensor-temperature.c  |  4 +-
 13 files changed, 78 insertions(+), 64 deletions(-)


base-commit: 39b80c5c9830d12d2d6531059001301c4265322a
-- 
2.34.1


^ permalink raw reply

* [PATCH v3 1/9] iio: hid-sensors: drop redundant iio_dev argument
From: Sanjay Chitroda @ 2026-05-09 10:10 UTC (permalink / raw)
  To: jikos, jic23, srinivas.pandruvada
  Cc: dlechner, nuno.sa, andy, sanjayembeddedse, sakari.ailus,
	linux-input, linux-iio, linux-kernel
In-Reply-To: <20260509101040.791404-1-sanjayembedded@gmail.com>

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>
---
 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[] = {
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 2/9] iio: hid-sensors: cleanup codestyle warning
From: Sanjay Chitroda @ 2026-05-09 10:10 UTC (permalink / raw)
  To: jikos, jic23, srinivas.pandruvada
  Cc: dlechner, nuno.sa, andy, sanjayembeddedse, sakari.ailus,
	linux-input, linux-iio, linux-kernel
In-Reply-To: <20260509101040.791404-1-sanjayembedded@gmail.com>

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>
---
 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);
 }
 
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 3/9] iio: hid-sensors: introduce device managed API
From: Sanjay Chitroda @ 2026-05-09 10:10 UTC (permalink / raw)
  To: jikos, jic23, srinivas.pandruvada
  Cc: dlechner, nuno.sa, andy, sanjayembeddedse, sakari.ailus,
	linux-input, linux-iio, linux-kernel
In-Reply-To: <20260509101040.791404-1-sanjayembedded@gmail.com>

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

hid_sensor_setup_trigger() is common API used for the HID IIO drivers,
prepare devm API devm_hid_sensor_setup_trigger() to acquire resource
during setup and release using device managed framework during drivers
fail, unbind or remove path.

Register action with devm_add_action_or_reset() to release resource with
devres framework.

Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
Changes in v3:
- Remove cast and update function based on review comment from Andy
- v2 link -> https://lore.kernel.org/all/20260429175918.2541914-3-sanjayembedded@gmail.com/
---
 .../common/hid-sensors/hid-sensor-trigger.c    | 18 ++++++++++++++++++
 .../common/hid-sensors/hid-sensor-trigger.h    |  2 ++
 2 files changed, 20 insertions(+)

diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index 98fadc61a68a..fb6a4587ae03 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -301,6 +301,24 @@ int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
 }
 EXPORT_SYMBOL_NS(hid_sensor_setup_trigger, "IIO_HID");
 
+static void hid_sensor_remove_trigger_action(void *attrb)
+{
+	hid_sensor_remove_trigger(attrb);
+}
+
+int devm_hid_sensor_setup_trigger(struct device *dev, struct iio_dev *indio_dev,
+				  const char *name, struct hid_sensor_common *attrb)
+{
+	int ret;
+
+	ret = hid_sensor_setup_trigger(indio_dev, name, attrb);
+	if (ret)
+		return ret;
+
+	return devm_add_action_or_reset(dev, hid_sensor_remove_trigger_action, attrb);
+}
+EXPORT_SYMBOL_NS(devm_hid_sensor_setup_trigger, "IIO_HID");
+
 static int __maybe_unused hid_sensor_suspend(struct device *dev)
 {
 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
index afec46ecbe71..6fd7c39a240d 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
@@ -17,6 +17,8 @@ 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 hid_sensor_common *attrb);
+int devm_hid_sensor_setup_trigger(struct device *dev, struct iio_dev *indio_dev,
+				  const char *name, struct hid_sensor_common *attrb);
 int hid_sensor_power_state(struct hid_sensor_common *st, bool state);
 
 #endif
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 4/9] iio: gyro: hid-sensor-gyro-3d: cleanup codestyle warning
From: Sanjay Chitroda @ 2026-05-09 10:10 UTC (permalink / raw)
  To: jikos, jic23, srinivas.pandruvada
  Cc: dlechner, nuno.sa, andy, sanjayembeddedse, sakari.ailus,
	linux-input, linux-iio, linux-kernel
In-Reply-To: <20260509101040.791404-1-sanjayembedded@gmail.com>

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

Reported by checkpatch:
FILE: drivers/iio/gyro/hid-sensor-gyro-3d.c

WARNING: Prefer 'unsigned int' to bare use of 'unsigned'
+                               unsigned usage_id,

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

diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index fe663b19e902..87537f9c58fb 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -187,7 +187,7 @@ static const struct iio_info gyro_3d_info = {
 
 /* Callback handler to send event after all samples are received and captured */
 static int gyro_3d_proc_event(struct hid_sensor_hub_device *hsdev,
-				unsigned usage_id,
+				unsigned int usage_id,
 				void *priv)
 {
 	struct iio_dev *indio_dev = platform_get_drvdata(priv);
@@ -209,7 +209,7 @@ static int gyro_3d_proc_event(struct hid_sensor_hub_device *hsdev,
 
 /* Capture samples in local storage */
 static int gyro_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
-				unsigned usage_id,
+				unsigned int usage_id,
 				size_t raw_len, char *raw_data,
 				void *priv)
 {
@@ -244,7 +244,7 @@ static int gyro_3d_capture_sample(struct hid_sensor_hub_device *hsdev,
 static int gyro_3d_parse_report(struct platform_device *pdev,
 				struct hid_sensor_hub_device *hsdev,
 				struct iio_chan_spec *channels,
-				unsigned usage_id,
+				unsigned int usage_id,
 				struct gyro_3d_state *st)
 {
 	int ret;
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 5/9] iio: gyro: hid-sensor-gyro-3d: drop hid_sensor_remove_trigger() using devm API
From: Sanjay Chitroda @ 2026-05-09 10:10 UTC (permalink / raw)
  To: jikos, jic23, srinivas.pandruvada
  Cc: dlechner, nuno.sa, andy, sanjayembeddedse, sakari.ailus,
	linux-input, linux-iio, linux-kernel
In-Reply-To: <20260509101040.791404-1-sanjayembedded@gmail.com>

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

Use devm_hid_sensor_setup_trigger() to automatically release resource
during fail, unbind or removal of driver using devres framework.

This simplify the setup, remove goto, avoid manual resource cleanup in
teardown path.

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

diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index 87537f9c58fb..72e7db8ce3b2 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -326,8 +326,8 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
 
 	atomic_set(&gyro_state->common_attributes.data_ready, 0);
 
-	ret = hid_sensor_setup_trigger(indio_dev, name,
-					&gyro_state->common_attributes);
+	ret = devm_hid_sensor_setup_trigger(&pdev->dev, indio_dev, name,
+					    &gyro_state->common_attributes);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "trigger setup failed\n");
 		return ret;
@@ -336,7 +336,7 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
 	ret = iio_device_register(indio_dev);
 	if (ret) {
 		dev_err(&pdev->dev, "device register failed\n");
-		goto error_remove_trigger;
+		return ret;
 	}
 
 	gyro_state->callbacks.send_event = gyro_3d_proc_event;
@@ -353,8 +353,6 @@ 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(&gyro_state->common_attributes);
 	return ret;
 }
 
@@ -363,11 +361,9 @@ static void hid_gyro_3d_remove(struct platform_device *pdev)
 {
 	struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
-	struct gyro_3d_state *gyro_state = iio_priv(indio_dev);
 
 	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);
 	iio_device_unregister(indio_dev);
-	hid_sensor_remove_trigger(&gyro_state->common_attributes);
 }
 
 static const struct platform_device_id hid_gyro_3d_ids[] = {
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 6/9] iio: humidity: hid-sensor-humidity: cleanup codestyle check
From: Sanjay Chitroda @ 2026-05-09 10:10 UTC (permalink / raw)
  To: jikos, jic23, srinivas.pandruvada
  Cc: dlechner, nuno.sa, andy, sanjayembeddedse, sakari.ailus,
	linux-input, linux-iio, linux-kernel
In-Reply-To: <20260509101040.791404-1-sanjayembedded@gmail.com>

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

Reported by checkpatch:
FILE: drivers/iio/humidity/hid-sensor-humidity.c

CHECK: Alignment should match open parenthesis

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

diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
index e580a2af9562..968dd8d4bb35 100644
--- a/drivers/iio/humidity/hid-sensor-humidity.c
+++ b/drivers/iio/humidity/hid-sensor-humidity.c
@@ -45,7 +45,7 @@ static const struct iio_chan_spec humidity_channels[] = {
 
 /* Adjust channel real bits based on report descriptor */
 static void humidity_adjust_channel_bit_mask(struct iio_chan_spec *channels,
-					int channel, int size)
+					     int channel, int size)
 {
 	channels[channel].scan_type.sign = 's';
 	/* Real storage bits will change based on the report desc. */
@@ -55,8 +55,8 @@ static void humidity_adjust_channel_bit_mask(struct iio_chan_spec *channels,
 }
 
 static int humidity_read_raw(struct iio_dev *indio_dev,
-				struct iio_chan_spec const *chan,
-				int *val, int *val2, long mask)
+			     struct iio_chan_spec const *chan,
+			     int *val, int *val2, long mask)
 {
 	struct hid_humidity_state *humid_st = iio_priv(indio_dev);
 
@@ -101,8 +101,8 @@ static int humidity_read_raw(struct iio_dev *indio_dev,
 }
 
 static int humidity_write_raw(struct iio_dev *indio_dev,
-				struct iio_chan_spec const *chan,
-				int val, int val2, long mask)
+			      struct iio_chan_spec const *chan,
+			      int val, int val2, long mask)
 {
 	struct hid_humidity_state *humid_st = iio_priv(indio_dev);
 
@@ -127,7 +127,7 @@ static const struct iio_info humidity_info = {
 
 /* Callback handler to send event after all samples are received and captured */
 static int humidity_proc_event(struct hid_sensor_hub_device *hsdev,
-				unsigned int usage_id, void *pdev)
+			       unsigned int usage_id, void *pdev)
 {
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct hid_humidity_state *humid_st = iio_priv(indio_dev);
@@ -141,8 +141,8 @@ static int humidity_proc_event(struct hid_sensor_hub_device *hsdev,
 
 /* Capture samples in local storage */
 static int humidity_capture_sample(struct hid_sensor_hub_device *hsdev,
-				unsigned int usage_id, size_t raw_len,
-				char *raw_data, void *pdev)
+				   unsigned int usage_id, size_t raw_len,
+				   char *raw_data, void *pdev)
 {
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct hid_humidity_state *humid_st = iio_priv(indio_dev);
@@ -159,17 +159,17 @@ static int humidity_capture_sample(struct hid_sensor_hub_device *hsdev,
 
 /* Parse report which is specific to an usage id */
 static int humidity_parse_report(struct platform_device *pdev,
-				struct hid_sensor_hub_device *hsdev,
-				struct iio_chan_spec *channels,
-				unsigned int usage_id,
-				struct hid_humidity_state *st)
+				 struct hid_sensor_hub_device *hsdev,
+				 struct iio_chan_spec *channels,
+				 unsigned int usage_id,
+				 struct hid_humidity_state *st)
 {
 	int ret;
 
 	ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT,
-					usage_id,
-					HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,
-					&st->humidity_attr);
+						  usage_id,
+						  HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,
+						  &st->humidity_attr);
 	if (ret < 0)
 		return ret;
 
@@ -208,20 +208,20 @@ static int hid_humidity_probe(struct platform_device *pdev)
 	humid_st->common_attributes.pdev = pdev;
 
 	ret = hid_sensor_parse_common_attributes(hsdev,
-					HID_USAGE_SENSOR_HUMIDITY,
-					&humid_st->common_attributes,
-					humidity_sensitivity_addresses,
-					ARRAY_SIZE(humidity_sensitivity_addresses));
+						 HID_USAGE_SENSOR_HUMIDITY,
+						 &humid_st->common_attributes,
+						 humidity_sensitivity_addresses,
+						 ARRAY_SIZE(humidity_sensitivity_addresses));
 	if (ret)
 		return ret;
 
 	humid_chans = devm_kmemdup(&indio_dev->dev, humidity_channels,
-					sizeof(humidity_channels), GFP_KERNEL);
+				   sizeof(humidity_channels), GFP_KERNEL);
 	if (!humid_chans)
 		return -ENOMEM;
 
 	ret = humidity_parse_report(pdev, hsdev, humid_chans,
-				HID_USAGE_SENSOR_HUMIDITY, humid_st);
+				    HID_USAGE_SENSOR_HUMIDITY, humid_st);
 	if (ret)
 		return ret;
 
@@ -234,7 +234,7 @@ static int hid_humidity_probe(struct platform_device *pdev)
 	atomic_set(&humid_st->common_attributes.data_ready, 0);
 
 	ret = hid_sensor_setup_trigger(indio_dev, name,
-				&humid_st->common_attributes);
+				       &humid_st->common_attributes);
 	if (ret)
 		return ret;
 
@@ -242,7 +242,7 @@ static int hid_humidity_probe(struct platform_device *pdev)
 
 	humidity_callbacks.pdev = pdev;
 	ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY,
-					&humidity_callbacks);
+					   &humidity_callbacks);
 	if (ret)
 		goto error_remove_trigger;
 
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 7/9] iio: humidity: hid-sensor-humidity: use common device for devres
From: Sanjay Chitroda @ 2026-05-09 10:10 UTC (permalink / raw)
  To: jikos, jic23, srinivas.pandruvada
  Cc: dlechner, nuno.sa, andy, sanjayembeddedse, sakari.ailus,
	linux-input, linux-iio, linux-kernel
In-Reply-To: <20260509101040.791404-1-sanjayembedded@gmail.com>

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

kmemdup() is used for memory that is logically tied to the HID
platform device, even though the driver binds into the IIO framework.

Using &indio_dev->dev for devres allocations works functionally, but it
results in two separate devres ownership trees—one for the HID
platform device (pdev) and another for the IIO device (indio_dev).

The devres framework is intended to have a single, well-defined parent
device. Since the memory originates from HID sensor probing and is not
IIO-specific, &pdev->dev is the correct and logical owner.

Switch to using the platform device for devm_kmemdup() so that all
resources are released deterministically and consistently.

Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
 drivers/iio/humidity/hid-sensor-humidity.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
index 968dd8d4bb35..18d4e376376d 100644
--- a/drivers/iio/humidity/hid-sensor-humidity.c
+++ b/drivers/iio/humidity/hid-sensor-humidity.c
@@ -215,7 +215,7 @@ static int hid_humidity_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	humid_chans = devm_kmemdup(&indio_dev->dev, humidity_channels,
+	humid_chans = devm_kmemdup(&pdev->dev, humidity_channels,
 				   sizeof(humidity_channels), GFP_KERNEL);
 	if (!humid_chans)
 		return -ENOMEM;
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 8/9] iio: humidity: hid-sensor-humidity: use local struct device
From: Sanjay Chitroda @ 2026-05-09 10:10 UTC (permalink / raw)
  To: jikos, jic23, srinivas.pandruvada
  Cc: dlechner, nuno.sa, andy, sanjayembeddedse, sakari.ailus,
	linux-input, linux-iio, linux-kernel
In-Reply-To: <20260509101040.791404-1-sanjayembedded@gmail.com>

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

Introduce a local struct device pointer derived from &pdev->dev.
This avoids repeated &pdev->dev usage and improves readability.

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

diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
index 18d4e376376d..d310ec43a118 100644
--- a/drivers/iio/humidity/hid-sensor-humidity.c
+++ b/drivers/iio/humidity/hid-sensor-humidity.c
@@ -196,10 +196,11 @@ static int hid_humidity_probe(struct platform_device *pdev)
 	struct iio_dev *indio_dev;
 	struct hid_humidity_state *humid_st;
 	struct iio_chan_spec *humid_chans;
-	struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
+	struct device *dev = &pdev->dev;
+	struct hid_sensor_hub_device *hsdev = dev_get_platdata(dev);
 	int ret;
 
-	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*humid_st));
+	indio_dev = devm_iio_device_alloc(dev, sizeof(*humid_st));
 	if (!indio_dev)
 		return -ENOMEM;
 
@@ -215,7 +216,7 @@ static int hid_humidity_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	humid_chans = devm_kmemdup(&pdev->dev, humidity_channels,
+	humid_chans = devm_kmemdup(dev, humidity_channels,
 				   sizeof(humidity_channels), GFP_KERNEL);
 	if (!humid_chans)
 		return -ENOMEM;
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3 9/9] iio: humidity: hid-sensor-humidity: drop hid_sensor_remove_trigger() using devm API
From: Sanjay Chitroda @ 2026-05-09 10:10 UTC (permalink / raw)
  To: jikos, jic23, srinivas.pandruvada
  Cc: dlechner, nuno.sa, andy, sanjayembeddedse, sakari.ailus,
	linux-input, linux-iio, linux-kernel
In-Reply-To: <20260509101040.791404-1-sanjayembedded@gmail.com>

From: Sanjay Chitroda <sanjayembeddedse@gmail.com>

Use devm_hid_sensor_setup_trigger() to automatically release resources
during failure, unbind or removal of driver using devres framework.

This is done in a way to simplify the setup, remove goto and avoid manual
resource cleanup in teardown path.

Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
changes in v3:
- Update commit message based on review comment from Andy
- Based on discussion using parent device of HID platform driver used
  with devres framework for this driver
- v2 link -> https://lore.kernel.org/all/20260429175918.2541914-5-sanjayembedded@gmail.com/
---
 drivers/iio/humidity/hid-sensor-humidity.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
index d310ec43a118..4d4282e4b6e4 100644
--- a/drivers/iio/humidity/hid-sensor-humidity.c
+++ b/drivers/iio/humidity/hid-sensor-humidity.c
@@ -234,8 +234,8 @@ static int hid_humidity_probe(struct platform_device *pdev)
 
 	atomic_set(&humid_st->common_attributes.data_ready, 0);
 
-	ret = hid_sensor_setup_trigger(indio_dev, name,
-				       &humid_st->common_attributes);
+	ret = devm_hid_sensor_setup_trigger(dev, indio_dev, name,
+					    &humid_st->common_attributes);
 	if (ret)
 		return ret;
 
@@ -245,7 +245,7 @@ static int hid_humidity_probe(struct platform_device *pdev)
 	ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY,
 					   &humidity_callbacks);
 	if (ret)
-		goto error_remove_trigger;
+		return ret;
 
 	ret = iio_device_register(indio_dev);
 	if (ret)
@@ -255,8 +255,6 @@ 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(&humid_st->common_attributes);
 	return ret;
 }
 
@@ -265,11 +263,9 @@ static void hid_humidity_remove(struct platform_device *pdev)
 {
 	struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
-	struct hid_humidity_state *humid_st = iio_priv(indio_dev);
 
 	iio_device_unregister(indio_dev);
 	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY);
-	hid_sensor_remove_trigger(&humid_st->common_attributes);
 }
 
 static const struct platform_device_id hid_humidity_ids[] = {
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH] HID: mcp2221: fix OOB write in mcp2221_raw_event()
From: sashiko-bot @ 2026-05-09 10:36 UTC (permalink / raw)
  To: Florian Pradines; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260509094517.2691246-1-florian.pradines@gmail.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Critical] The patch adds a size bound but leaves a dangling pointer in `mcp->rxbuf` when a read times out, resulting in a Use-After-Free.
- [High] Unsynchronized updates to `mcp->rxbuf` and `mcp->rxbuf_size` allow an attacker to bypass the new bounds check completely, causing an Out-Of-Bounds (OOB) write.
- [High] The patch fails to prevent stack buffer overflows for `I2C_SMBUS_BLOCK_DATA` reads because it bases `mcp->rxbuf_size` on uninitialized stack memory.
- [High] The raw event handler blindly accesses payload data without validating against the actual received HID report size, leading to out-of-bounds kernel heap reads.
--

commit 2cea5cadcf6c54079354cc3c519d5621e3b06d74
Author: Florian Pradines <florian.pradines@gmail.com>

HID: mcp2221: fix OOB write in mcp2221_raw_event()

This commit attempts to fix an out-of-bounds write in mcp2221_raw_event()
by adding a rxbuf_size field. It sets this field alongside rxbuf in
mcp_i2c_smbus_read() and validates the incoming data length against it
before copying.

> diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c
> index be80970ab48e2..e4ddd8e9293b6 100644
> --- a/drivers/hid/hid-mcp2221.c
> +++ b/drivers/hid/hid-mcp2221.c
[ ... ]
> @@ -330,12 +331,14 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp,
>  		mcp->txbuf[3] = (u8)(msg->addr << 1);
>  		total_len = msg->len;
>  		mcp->rxbuf = msg->buf;
> +		mcp->rxbuf_size = msg->len;
>  	} else {
>  		mcp->txbuf[1] = smbus_len;
>  		mcp->txbuf[2] = 0;
>  		mcp->txbuf[3] = (u8)(smbus_addr << 1);
>  		total_len = smbus_len;
>  		mcp->rxbuf = smbus_buf;
> +		mcp->rxbuf_size = smbus_len;

Does this code fail to prevent stack buffer overflows for
I2C_SMBUS_BLOCK_DATA reads?

In i2c_smbus_read_block_data(), the i2c_smbus_data union is allocated
on the stack but its first byte (data.block[0]) is not initialized before
the read. In mcp_smbus_xfer(), the driver uses data->block[0] + 1 to
determine the read length, which is then assigned here to mcp->rxbuf_size.

If this uninitialized stack memory contains a large value (e.g., 255), the
new bounds check will pass for large responses, and memcpy can write past
the 34-byte data->block array, overflowing the stack.

Also, are these updates to mcp->rxbuf and mcp->rxbuf_size safe from
concurrent access?

These are updated non-atomically in process context, while
mcp2221_raw_event() runs asynchronously.

If a previous read timed out leaving rxbuf_idx = 0 and rxbuf_size = 60,
could a late 60-byte response arrive just after mcp->rxbuf is assigned a new
2-byte buffer but before mcp->rxbuf_size is updated to 2?

This would cause the event handler to read the old rxbuf_size (60), pass the
check, and copy 60 bytes into the 2-byte buffer, bypassing the protection.

>  	}
>  
>  	ret = mcp_send_data_req_status(mcp, mcp->txbuf, 4);

If mcp_send_data_req_status() times out, it returns -ETIMEDOUT without
setting mcp->rxbuf to NULL.

If the caller then frees or pops the buffer, and a delayed or malicious
MCP2221_I2C_GET_DATA report is processed by mcp2221_raw_event(), could this
result in a use-after-free?

Since rxbuf is not NULL and rxbuf_idx < rxbuf_size, the new check passes,
and memcpy would write data directly into the freed memory.

[ ... ]
> @@ -919,6 +922,10 @@ static int mcp2221_raw_event(struct hid_device *hdev,
>  					mcp->status = -EINVAL;
>  					break;
>  				}
> +				if (mcp->rxbuf_idx + data[3] > mcp->rxbuf_size) {
> +					mcp->status = -EINVAL;
> +					break;
> +				}
>  				buf = mcp->rxbuf;
>  				memcpy(&buf[mcp->rxbuf_idx], &data[4], data[3]);

This isn't a regression from this patch, but does the raw event handler
blindly access payload data without validating against the actual received
HID report size?

The mcp2221_raw_event() function receives a size parameter representing the
length of the HID report but ignores it.

If a malicious USB device presents a HID report descriptor with a small
maximum report size (e.g., 4 bytes), the HID core will allocate a 4-byte
buffer.

If the device then sends data[3] = 60, this memcpy will read 60 bytes past
the end of the 4-byte kernel heap buffer, potentially leaking adjacent
kernel memory to user-space.

>  				mcp->rxbuf_idx = mcp->rxbuf_idx + data[3];

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260509094517.2691246-1-florian.pradines@gmail.com?part=1

^ permalink raw reply

* Re: [PATCH v3 1/9] iio: hid-sensors: drop redundant iio_dev argument
From: sashiko-bot @ 2026-05-09 10:42 UTC (permalink / raw)
  To: Sanjay Chitroda; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260509101040.791404-2-sanjayembedded@gmail.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] This problem wasn't introduced by this patch, but the removal sequence across HID IIO drivers cancels asynchronous suspend requests, leaving the hardware powered on, which violates PM subsystem guidelines.
- [High] This problem wasn't introduced by this patch, but in `hid-sensor-temperature.c`, the trigger is manually unregistered and freed in the `remove` callback while the IIO device is still active and registered, creating a use-after-free vulnerability.
--

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

iio: hid-sensors: drop redundant iio_dev argument

This commit removes the unused iio_dev argument from
hid_sensor_remove_trigger() across all HID IIO drivers, adapting the
function prototype to simplify the API for a future devm-based conversion.

> diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
> index 2ff591b3458f7..a63dae90dadc5 100644
> --- a/drivers/iio/accel/hid-sensor-accel-3d.c
> +++ b/drivers/iio/accel/hid-sensor-accel-3d.c
[ ... ]
> @@ -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);
>  }

This problem wasn't introduced by this patch, but could this removal sequence
leave the hardware powered on?

Looking at the removal path across these drivers, iio_device_unregister()
disables the IIO buffers, which eventually calls hid_sensor_power_state()
and queues an asynchronous suspend via pm_runtime_put_autosuspend().

Immediately afterward, hid_sensor_remove_trigger() calls
pm_runtime_disable(). Does calling pm_runtime_disable() immediately after an
async put cancel the pending suspend work, leaving the physical device active
while marking it suspended in the PM core?

[ ... ]
> diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
> index 9f628a8e5cfbe..60d4fcc8043b6 100644
> --- a/drivers/iio/temperature/hid-sensor-temperature.c
> +++ b/drivers/iio/temperature/hid-sensor-temperature.c
[ ... ]
> @@ -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);
>  }

This problem also wasn't introduced by this patch, but is there a
use-after-free risk in this specific driver's removal sequence?

The temperature driver uses devm_iio_device_register() to register the IIO
device, which means the device unregistration is deferred until the devres
cleanup phase after hid_temperature_remove() returns.

However, hid_sensor_remove_trigger() is called manually here and it calls
iio_trigger_free(). Since the IIO device remains fully registered and exposed
to user-space until devres runs, could concurrent sysfs access or buffer
operations dereference the freed trigger pointer?

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

^ permalink raw reply


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