Linux Input/HID development
 help / color / mirror / Atom feed
* [hid:for-7.1/lenovo 10/16] drivers/hid/hid-lenovo-go-s.c:164:73: sparse: sparse: Using plain integer as NULL pointer
From: kernel test robot @ 2026-03-07 20:40 UTC (permalink / raw)
  To: Derek J. Clark
  Cc: oe-kbuild-all, linux-input, Jiri Kosina, Mark Pearson,
	Mario Limonciello

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-7.1/lenovo
head:   d2c424e80caf8237bda4c94bc2e25398967243f9
commit: 4325fdab5dbbfd467df6797e018c9dd0e5c3ae75 [10/16] HID: hid-lenovo-go-s: Add Lenovo Legion Go S Series HID Driver
config: arc-randconfig-r113-20260307 (https://download.01.org/0day-ci/archive/20260308/202603080451.lcXQ6ejg-lkp@intel.com/config)
compiler: arc-linux-gcc (GCC) 13.4.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260308/202603080451.lcXQ6ejg-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603080451.lcXQ6ejg-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/hid/hid-lenovo-go-s.c:164:73: sparse: sparse: Using plain integer as NULL pointer

vim +164 drivers/hid/hid-lenovo-go-s.c

   159	
   160	static void cfg_setup(struct work_struct *work)
   161	{
   162		int ret;
   163	
 > 164		ret = mcu_property_out(drvdata.hdev, GET_VERSION, FEATURE_NONE, 0, 0);
   165		if (ret) {
   166			dev_err(&drvdata.hdev->dev, "Failed to retrieve MCU Version: %i\n", ret);
   167			return;
   168		}
   169	}
   170	

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

^ permalink raw reply

* Re: [PATCH v2] usbhid: tolerate intermittent errors
From: Alan Stern @ 2026-03-07 22:52 UTC (permalink / raw)
  To: Liam Mitchell
  Cc: Jiri Kosina, Benjamin Tissoires, Oliver Neukum, linux-usb,
	linux-input, linux-kernel
In-Reply-To: <20260307-usbhid-eproto-v2-1-e5a8abce4652@gmail.com>

On Sat, Mar 07, 2026 at 07:57:09PM +0100, Liam Mitchell wrote:
> Modifies usbhid error handling to tolerate intermittent protocol
> errors, avoiding URB resubmission delay and device reset.
> 
> ---
> Protocol errors like EPROTO can occur randomly, sometimes frequently and are often not fixed by a device reset.
> 
> The current error handling will only resubmit the URB after at least 13ms delay and may reset the USB device if another error occurs 1-1.5s later, regardless of error type or count.
> 
> These delays and device resets increase the chance that input events will be missed and that users see symptoms like missed or sticky keyboard keys.
> 
> This patch allows one protocol error per 500ms to be tolerated and have the URB re-submitted immediately.
> 
> 500ms was chosen to be well above the error rate of a malfunctioning
> device but low enough to be useful for users with devices noisier than
> mine.
> 
> Signed-off-by: Liam Mitchell <mitchell.liam@gmail.com>
> Link: https://lore.kernel.org/linux-input/CAOQ1CL6Q+4GNy=kgisLzs0UBXFT3b02PG8t-0rPuW-Wf6NhQ6g@mail.gmail.com/
> ---

Liam, take a look at

	https://bugzilla.kernel.org/show_bug.cgi?id=221184

On Roman's system, these protocol errors occur fairly regularly, 
apparently caused by high system load.

Do you think a better approach might be to reduce the 13-ms delay to 
just 1 or 2 ms, and perform a reset only there has been no successful 
communication for about one second?  This might perhaps be _too_ lenient 
sometimes, but I don't think such situations will arise in practice.

The reason for having at least a small delay is to avoid getting into a 
tight resubmit/error loop in cases where the device has been unplugged.

Alan Stern

^ permalink raw reply

* [hid:for-7.1/lenovo 12/16] drivers/hid/hid-lenovo-go-s.c:583:21: sparse: sparse: symbol 'gamepad_poll_rate' was not declared. Should it be static?
From: kernel test robot @ 2026-03-07 23:36 UTC (permalink / raw)
  To: Derek J. Clark; +Cc: oe-kbuild-all, linux-input, Jiri Kosina, Mark Pearson

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-7.1/lenovo
head:   d2c424e80caf8237bda4c94bc2e25398967243f9
commit: 14651777fd67507d19574cd7e7835c16e6174853 [12/16] HID: hid-lenovo-go-s: Add Feature Status Attributes
config: arc-randconfig-r113-20260307 (https://download.01.org/0day-ci/archive/20260308/202603080756.jqm0j0md-lkp@intel.com/config)
compiler: arc-linux-gcc (GCC) 13.4.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260308/202603080756.jqm0j0md-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603080756.jqm0j0md-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
   drivers/hid/hid-lenovo-go-s.c:406:72: sparse: sparse: Using plain integer as NULL pointer
>> drivers/hid/hid-lenovo-go-s.c:583:21: sparse: sparse: symbol 'gamepad_poll_rate' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go-s.c:609:21: sparse: sparse: symbol 'imu_sensor_enabled' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go-s.c:645:21: sparse: sparse: symbol 'mouse_wheel_step' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:690:72: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:697:73: sparse: sparse: Using plain integer as NULL pointer
>> drivers/hid/hid-lenovo-go-s.c:407:21: sparse: sparse: unsigned value that used to be signed checked against zero?
   drivers/hid/hid-lenovo-go-s.c:406:33: sparse: signed value source

vim +/gamepad_poll_rate +583 drivers/hid/hid-lenovo-go-s.c

   398	
   399	static ssize_t gamepad_property_show(struct device *dev,
   400					     struct device_attribute *attr, char *buf,
   401					     enum feature_status_index index)
   402	{
   403		size_t count = 0;
   404		u8 i;
   405	
   406		count = mcu_property_out(drvdata.hdev, GET_GAMEPAD_CFG, index, 0, 0);
 > 407		if (count < 0)
   408			return count;
   409	
   410		switch (index) {
   411		case FEATURE_GAMEPAD_MODE:
   412			i = drvdata.gp_mode;
   413			if (i >= ARRAY_SIZE(gamepad_mode_text))
   414				return -EINVAL;
   415			count = sysfs_emit(buf, "%s\n", gamepad_mode_text[i]);
   416			break;
   417		case FEATURE_AUTO_SLEEP_TIME:
   418			count = sysfs_emit(buf, "%u\n", drvdata.gp_auto_sleep_time);
   419			break;
   420		case FEATURE_IMU_ENABLE:
   421			i = drvdata.imu_sensor_en;
   422			if (i >= ARRAY_SIZE(feature_enabled_text))
   423				return -EINVAL;
   424			count = sysfs_emit(buf, "%s\n", feature_enabled_text[i]);
   425			break;
   426		case FEATURE_IMU_BYPASS:
   427			i = drvdata.imu_bypass_en;
   428			if (i >= ARRAY_SIZE(feature_enabled_text))
   429				return -EINVAL;
   430			count = sysfs_emit(buf, "%s\n", feature_enabled_text[i]);
   431			break;
   432		case FEATURE_RGB_ENABLE:
   433			i = drvdata.rgb_en;
   434			if (i >= ARRAY_SIZE(feature_enabled_text))
   435				return -EINVAL;
   436			count = sysfs_emit(buf, "%s\n", feature_enabled_text[i]);
   437			break;
   438		case FEATURE_TOUCHPAD_ENABLE:
   439			i = drvdata.tp_en;
   440			if (i >= ARRAY_SIZE(feature_enabled_text))
   441				return -EINVAL;
   442			count = sysfs_emit(buf, "%s\n", feature_enabled_text[i]);
   443			break;
   444		case FEATURE_OS_MODE:
   445			i = drvdata.os_mode;
   446			if (i >= ARRAY_SIZE(os_type_text))
   447				return -EINVAL;
   448			count = sysfs_emit(buf, "%s\n", os_type_text[i]);
   449			break;
   450		case FEATURE_POLL_RATE:
   451			i = drvdata.gp_poll_rate;
   452			if (i >= ARRAY_SIZE(poll_rate_text))
   453				return -EINVAL;
   454			count = sysfs_emit(buf, "%s\n", poll_rate_text[i]);
   455			break;
   456		case FEATURE_DPAD_MODE:
   457			i = drvdata.gp_dpad_mode;
   458			if (i >= ARRAY_SIZE(dpad_mode_text))
   459				return -EINVAL;
   460			count = sysfs_emit(buf, "%s\n", dpad_mode_text[i]);
   461			break;
   462		case FEATURE_MOUSE_WHEEL_STEP:
   463			i = drvdata.mouse_step;
   464			if (i < 1 || i > 127)
   465				return -EINVAL;
   466			count = sysfs_emit(buf, "%u\n", i);
   467			break;
   468		default:
   469			return -EINVAL;
   470		}
   471	
   472		return count;
   473	}
   474	
   475	static ssize_t gamepad_property_options(struct device *dev,
   476						struct device_attribute *attr,
   477						char *buf,
   478						enum feature_status_index index)
   479	{
   480		size_t count = 0;
   481		unsigned int i;
   482	
   483		switch (index) {
   484		case FEATURE_GAMEPAD_MODE:
   485			for (i = 0; i < ARRAY_SIZE(gamepad_mode_text); i++) {
   486				count += sysfs_emit_at(buf, count, "%s ",
   487						       gamepad_mode_text[i]);
   488			}
   489			break;
   490		case FEATURE_AUTO_SLEEP_TIME:
   491			return sysfs_emit(buf, "0-255\n");
   492		case FEATURE_IMU_ENABLE:
   493			for (i = 0; i < ARRAY_SIZE(feature_enabled_text); i++) {
   494				count += sysfs_emit_at(buf, count, "%s ",
   495						       feature_enabled_text[i]);
   496			}
   497			break;
   498		case FEATURE_IMU_BYPASS:
   499		case FEATURE_RGB_ENABLE:
   500		case FEATURE_TOUCHPAD_ENABLE:
   501			for (i = 0; i < ARRAY_SIZE(feature_enabled_text); i++) {
   502				count += sysfs_emit_at(buf, count, "%s ",
   503						       feature_enabled_text[i]);
   504			}
   505			break;
   506		case FEATURE_OS_MODE:
   507			for (i = 0; i < ARRAY_SIZE(os_type_text); i++) {
   508				count += sysfs_emit_at(buf, count, "%s ",
   509						       os_type_text[i]);
   510			}
   511			break;
   512		case FEATURE_POLL_RATE:
   513			for (i = 0; i < ARRAY_SIZE(poll_rate_text); i++) {
   514				count += sysfs_emit_at(buf, count, "%s ",
   515						       poll_rate_text[i]);
   516			}
   517			break;
   518		case FEATURE_DPAD_MODE:
   519			for (i = 0; i < ARRAY_SIZE(dpad_mode_text); i++) {
   520				count += sysfs_emit_at(buf, count, "%s ",
   521						       dpad_mode_text[i]);
   522			}
   523			break;
   524		case FEATURE_MOUSE_WHEEL_STEP:
   525			return sysfs_emit(buf, "1-127\n");
   526		default:
   527			return count;
   528		}
   529	
   530		if (count)
   531			buf[count - 1] = '\n';
   532	
   533		return count;
   534	}
   535	
   536	static ssize_t mcu_id_show(struct device *dev, struct device_attribute *attr,
   537				   char *buf)
   538	{
   539		return sysfs_emit(buf, "%*phN\n", 12, &drvdata.mcu_id);
   540	}
   541	
   542	#define LEGOS_DEVICE_ATTR_RW(_name, _attrname, _rtype, _group)                 \
   543		static ssize_t _name##_store(struct device *dev,                       \
   544					     struct device_attribute *attr,            \
   545					     const char *buf, size_t count)            \
   546		{                                                                      \
   547			return _group##_property_store(dev, attr, buf, count,          \
   548						       _name.index);                   \
   549		}                                                                      \
   550		static ssize_t _name##_show(struct device *dev,                        \
   551					    struct device_attribute *attr, char *buf)  \
   552		{                                                                      \
   553			return _group##_property_show(dev, attr, buf, _name.index);    \
   554		}                                                                      \
   555		static ssize_t _name##_##_rtype##_show(                                \
   556			struct device *dev, struct device_attribute *attr, char *buf)  \
   557		{                                                                      \
   558			return _group##_property_options(dev, attr, buf, _name.index); \
   559		}                                                                      \
   560		static DEVICE_ATTR_RW_NAMED(_name, _attrname)
   561	
   562	#define LEGOS_DEVICE_ATTR_RO(_name, _attrname, _group)                        \
   563		static ssize_t _name##_show(struct device *dev,                       \
   564					    struct device_attribute *attr, char *buf) \
   565		{                                                                     \
   566			return _group##_property_show(dev, attr, buf, _name.index);   \
   567		}                                                                     \
   568		static DEVICE_ATTR_RO_NAMED(_name, _attrname)
   569	
   570	/* Gamepad */
   571	struct gos_cfg_attr auto_sleep_time = { FEATURE_AUTO_SLEEP_TIME };
   572	LEGOS_DEVICE_ATTR_RW(auto_sleep_time, "auto_sleep_time", range, gamepad);
   573	static DEVICE_ATTR_RO(auto_sleep_time_range);
   574	
   575	struct gos_cfg_attr dpad_mode = { FEATURE_DPAD_MODE };
   576	LEGOS_DEVICE_ATTR_RW(dpad_mode, "dpad_mode", index, gamepad);
   577	static DEVICE_ATTR_RO(dpad_mode_index);
   578	
   579	struct gos_cfg_attr gamepad_mode = { FEATURE_GAMEPAD_MODE };
   580	LEGOS_DEVICE_ATTR_RW(gamepad_mode, "mode", index, gamepad);
   581	static DEVICE_ATTR_RO_NAMED(gamepad_mode_index, "mode_index");
   582	
 > 583	struct gos_cfg_attr gamepad_poll_rate = { FEATURE_POLL_RATE };
   584	LEGOS_DEVICE_ATTR_RW(gamepad_poll_rate, "poll_rate", index, gamepad);
   585	static DEVICE_ATTR_RO_NAMED(gamepad_poll_rate_index, "poll_rate_index");
   586	
   587	static struct attribute *legos_gamepad_attrs[] = {
   588		&dev_attr_auto_sleep_time.attr,
   589		&dev_attr_auto_sleep_time_range.attr,
   590		&dev_attr_dpad_mode.attr,
   591		&dev_attr_dpad_mode_index.attr,
   592		&dev_attr_gamepad_mode.attr,
   593		&dev_attr_gamepad_mode_index.attr,
   594		&dev_attr_gamepad_poll_rate.attr,
   595		&dev_attr_gamepad_poll_rate_index.attr,
   596		NULL,
   597	};
   598	
   599	static const struct attribute_group gamepad_attr_group = {
   600		.name = "gamepad",
   601		.attrs = legos_gamepad_attrs,
   602	};
   603	
   604	/* IMU */
   605	struct gos_cfg_attr imu_bypass_enabled = { FEATURE_IMU_BYPASS };
   606	LEGOS_DEVICE_ATTR_RW(imu_bypass_enabled, "bypass_enabled", index, gamepad);
   607	static DEVICE_ATTR_RO_NAMED(imu_bypass_enabled_index, "bypass_enabled_index");
   608	
 > 609	struct gos_cfg_attr imu_sensor_enabled = { FEATURE_IMU_ENABLE };
   610	LEGOS_DEVICE_ATTR_RW(imu_sensor_enabled, "sensor_enabled", index, gamepad);
   611	static DEVICE_ATTR_RO_NAMED(imu_sensor_enabled_index, "sensor_enabled_index");
   612	
   613	static struct attribute *legos_imu_attrs[] = {
   614		&dev_attr_imu_bypass_enabled.attr,
   615		&dev_attr_imu_bypass_enabled_index.attr,
   616		&dev_attr_imu_sensor_enabled.attr,
   617		&dev_attr_imu_sensor_enabled_index.attr,
   618		NULL,
   619	};
   620	
   621	static const struct attribute_group imu_attr_group = {
   622		.name = "imu",
   623		.attrs = legos_imu_attrs,
   624	};
   625	
   626	/* MCU */
   627	static DEVICE_ATTR_RO(mcu_id);
   628	
   629	struct gos_cfg_attr os_mode = { FEATURE_OS_MODE };
   630	LEGOS_DEVICE_ATTR_RW(os_mode, "os_mode", index, gamepad);
   631	static DEVICE_ATTR_RO(os_mode_index);
   632	
   633	static struct attribute *legos_mcu_attrs[] = {
   634		&dev_attr_mcu_id.attr,
   635		&dev_attr_os_mode.attr,
   636		&dev_attr_os_mode_index.attr,
   637		NULL,
   638	};
   639	
   640	static const struct attribute_group mcu_attr_group = {
   641		.attrs = legos_mcu_attrs,
   642	};
   643	
   644	/* Mouse */
 > 645	struct gos_cfg_attr mouse_wheel_step = { FEATURE_MOUSE_WHEEL_STEP };
   646	LEGOS_DEVICE_ATTR_RW(mouse_wheel_step, "step", range, gamepad);
   647	static DEVICE_ATTR_RO_NAMED(mouse_wheel_step_range, "step_range");
   648	

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

^ permalink raw reply

* Re: [PATCH v2 1/2] iio: add IIO_DECLARE_QUATERNION() macro
From: David Lechner @ 2026-03-08  0:35 UTC (permalink / raw)
  To: Francesco Lavra
  Cc: linux-iio, linux-kernel, Jonathan Cameron, linux-input,
	Jonathan Cameron, Nuno Sá, Andy Shevchenko, Jiri Kosina,
	Srinivas Pandruvada
In-Reply-To: <20260228-iio-fix-repeat-alignment-v2-1-d58bfaa2920d@baylibre.com>

On 2/28/26 2:02 PM, David Lechner wrote:
> Add a new IIO_DECLARE_QUATERNION() macro that is used to declare the
> field in an IIO buffer struct that contains a quaternion vector.
> 
> Quaternions are currently the only IIO data type that uses the .repeat
> feature of struct iio_scan_type. This has an implicit rule that the
> element in the buffer must be aligned to the entire size of the repeated
> element. This macro will make that requirement explicit. Since this is
> the only user, we just call the macro IIO_DECLARE_QUATERNION() instead
> of something more generic.
> 
> Signed-off-by: David Lechner <dlechner@baylibre.com>
> ---
>  include/linux/iio/iio.h | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
> index a9ecff191bd9..2c91b7659ce9 100644
> --- a/include/linux/iio/iio.h
> +++ b/include/linux/iio/iio.h
> @@ -931,6 +931,18 @@ static inline void *iio_device_get_drvdata(const struct iio_dev *indio_dev)
>  #define IIO_DECLARE_DMA_BUFFER_WITH_TS(type, name, count) \
>  	__IIO_DECLARE_BUFFER_WITH_TS(type, name, count) __aligned(IIO_DMA_MINALIGN)
>  
> +/**
> + * IIO_DECLARE_QUATERNION() - Declare a quaternion element
> + * @type: element type of the individual vectors
> + * @name: identifier name
> + *
> + * Quaternions are a vector composed of 4 elements (W, X, Y, Z). Use this macro
> + * to declare a quaternion element in a struct to ensure proper alignment in
> + * an IIO buffer.
> + */
> +#define IIO_DECLARE_QUATERNION(type, name) \
> +	type name[4] __aligned(sizeof(type) * 4)
> +
>  struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv);
>  
>  /* The information at the returned address is guaranteed to be cacheline aligned */
> 

Hi Francesco,

I should have cc'ed you on this one. We'll want to add another macro
like this for IIO_DECLARE_QUATERNION_AXIS(), I imagine. (This has been
applied to the fixes-togreg branch since it is a dependency to a fix.)

What to do on that for the alignment though is an open question since
we've never had a repeat of 3 before. The question is if it is OK to
have an alignment that isn't a power of two bytes. For your case, since
the data is 3 x 16-bit, it would be 3 * 2 = 6 bytes.


^ permalink raw reply

* [PATCH v2 0/5] iio: buffer: fix timestamp alignment (in rare case)
From: David Lechner @ 2026-03-08  1:44 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, Nuno Sá,
	Andy Shevchenko, Lars Möllendorf, Lars-Peter Clausen,
	Greg Kroah-Hartman
  Cc: Jonathan Cameron, Lixu Zhang, Francesco Lavra, linux-input,
	linux-iio, linux-kernel, David Lechner

In [1], it was pointed out that the iio_push_to_buffers_with_timestamp()
function is not putting the timestamp at the correct offset in the scan
buffer in rare cases where the largest scan element size is larger than
sizeof(int64_t).

[1]: https://lore.kernel.org/linux-iio/20260215162351.79f40b32@jic23-huawei/

This only affected one driver, namely hid-sensor-rotation since it is
the only driver that meets the condition. To fix things up, first we
fix the hid-sensor-rotation driver in a way that preserves compatibility
with the broken timestamp alignment. Then we are free to fix the core
IIO code without affecting any users.

The first patch depends on [2] which is now in iio/fixes-togreg. It
should be OK to apply the first patch there and let the rest of the
patches go through iio/togreg (the later patches are just preventing
future bugs).

[2]: https://lore.kernel.org/linux-iio/20260228-iio-fix-repeat-alignment-v2-0-d58bfaa2920d@baylibre.com/

Signed-off-by: David Lechner <dlechner@baylibre.com>
---
Changes in v2:
- Don't say "HACK" in comments.
- Cache timestamp offset instead of largest scan element size.
- New patch to ensure size/alignment is always power of 2 bytes.
- Link to v1: https://lore.kernel.org/r/20260301-iio-fix-timestamp-alignment-v1-0-1a54980bfb90@baylibre.com

---
David Lechner (5):
      iio: orientation: hid-sensor-rotation: add timestamp hack to not break userspace
      iio: buffer: check return value of iio_compute_scan_bytes()
      iio: buffer: cache timestamp offset in scan buffer
      iio: buffer: ensure repeat alignment is a power of two
      iio: buffer: fix timestamp alignment when quaternion in scan

 drivers/iio/industrialio-buffer.c             | 46 ++++++++++++++++++++-------
 drivers/iio/orientation/hid-sensor-rotation.c | 22 +++++++++++--
 include/linux/iio/buffer.h                    | 12 +++++--
 include/linux/iio/iio.h                       |  3 ++
 4 files changed, 66 insertions(+), 17 deletions(-)
---
base-commit: 6f25a6105c41a7d6b12986dbe80ded396a5667f8
change-id: 20260228-iio-fix-timestamp-alignment-89ade1af458b
prerequisite-message-id: <20260228-iio-fix-repeat-alignment-v2-0-d58bfaa2920d@baylibre.com>
prerequisite-patch-id: e155a526d57c5759a2fcfbfca7f544cb419addfd
prerequisite-patch-id: 6c69eaad0dd2ae69bd2745e7d387f739fc1a9ba0

Best regards,
--  
David Lechner <dlechner@baylibre.com>


^ permalink raw reply

* [PATCH v2 1/5] iio: orientation: hid-sensor-rotation: add timestamp hack to not break userspace
From: David Lechner @ 2026-03-08  1:44 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, Nuno Sá,
	Andy Shevchenko, Lars Möllendorf, Lars-Peter Clausen,
	Greg Kroah-Hartman
  Cc: Jonathan Cameron, Lixu Zhang, Francesco Lavra, linux-input,
	linux-iio, linux-kernel, David Lechner
In-Reply-To: <20260307-iio-fix-timestamp-alignment-v2-0-d1d48fbadbbf@baylibre.com>

Add a hack to push two timestamps in the hid-sensor-rotation scan data
to avoid breaking userspace applications that depend on the timestamp
being at the incorrect location in the scan data due to unintentional
misalignment in older kernels.

When this driver was written, the timestamp was in the correct location
because of the way iio_compute_scan_bytes() was implemented at the time.
(Samples were 24 bytes each.) Then commit 883f61653069 ("iio: buffer:
align the size of scan bytes to size of the largest element") changed
the computed scan_bytes to be a different size (32 bytes), which caused
iio_push_to_buffers_with_timestamp() to place the timestamp at an
incorrect offset.

There have been long periods of time (6 years each) where the timestamp
was in either location, so to not break either case, we open-code the
timestamps to be pushed to both locations in the scan data.

Reported-by: Jonathan Cameron <jic23@kernel.org>
Closes: https://lore.kernel.org/linux-iio/20260215162351.79f40b32@jic23-huawei/
Fixes: 883f61653069 ("iio: buffer: align the size of scan bytes to size of the largest element")
Signed-off-by: David Lechner <dlechner@baylibre.com>
---

v2 changes:
- Rebased on fix that also touches the scan struct.
- Improved comments.

I found that I could emulate this thanks to /dev/uhid. And thanks to AI
code generators, I was able to reasonably quickly make a script that
worked for emulating "HID-SENSOR-20008a". See v1 message for test script
source code.

[v1]: https://lore.kernel.org/linux-iio/20260301-iio-fix-timestamp-alignment-v1-1-1a54980bfb90@baylibre.com/

I set up the buffer like this:

cd /sys/bus/iio/devices/iio:device1/buffer0
echo 1 > in_rot_quaternion_en
echo 1 > in_timestamp_en
echo 1 > enable

Before this series is applied, we can see that the timestamp (group of 8
ending in "98 18") is at offset of 24 in the 32-byte data.

hd /dev/iio\:device1

00000000  6a 18 00 00 ac f3 ff ff  83 2d 00 00 02 d3 ff ff  |j........-......|
00000010  00 00 00 00 00 00 00 00  5a 17 a0 2a 73 cb 98 18  |........Z..*s...|

00000020  ad 17 00 00 6a f4 ff ff  35 2b 00 00 ca d0 ff ff  |....j...5+......|
00000030  00 00 00 00 00 00 00 00  2a a6 bb 30 73 cb 98 18  |........*..0s...|

00000040  92 1e 00 00 50 ec ff ff  ea c1 ff ff 78 f0 ff ff  |....P.......x...|
00000050  00 00 00 00 00 00 00 00  8f 3b a7 39 77 cb 98 18  |.........;.9w...|

After the first patch, we can see that the timestamp is now repeated at
both the correct and previous incorrect offsets (24 and 32). (Normally,
the last 8 bytes would be all 00 for padding.)

00000000  dd e0 ff ff 0e e0 ff ff  75 07 00 00 90 3f 00 00  |........u....?..|
00000010  f4 38 82 d0 3a cc 98 18  f4 38 82 d0 3a cc 98 18  |.8..:....8..:...|

00000020  a0 e0 ff ff 1d e0 ff ff  a0 0a 00 00 1c 3f 00 00  |.............?..|
00000030  3a 29 9f d6 3a cc 98 18  3a 29 9f d6 3a cc 98 18  |:)..:...:)..:...|

00000040  a9 e1 ff ff 1e 14 00 00  6c c1 ff ff 98 f2 ff ff  |........l.......|
00000050  39 21 77 11 55 cc 98 18  39 21 77 11 55 cc 98 18  |9!w.U...9!w.U...|
---
 drivers/iio/orientation/hid-sensor-rotation.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c
index 6806481873be..5a5e6e4fbe34 100644
--- a/drivers/iio/orientation/hid-sensor-rotation.c
+++ b/drivers/iio/orientation/hid-sensor-rotation.c
@@ -20,7 +20,12 @@ struct dev_rot_state {
 	struct hid_sensor_hub_attribute_info quaternion;
 	struct {
 		IIO_DECLARE_QUATERNION(s32, sampled_vals);
-		aligned_s64 timestamp;
+		/*
+		 * ABI regression avoidance: There are two copies of the same
+		 * timestamp in case of userspace depending on broken alignment
+		 * from older kernels.
+		 */
+		aligned_s64 timestamp[2];
 	} scan;
 	int scale_pre_decml;
 	int scale_post_decml;
@@ -154,8 +159,19 @@ static int dev_rot_proc_event(struct hid_sensor_hub_device *hsdev,
 		if (!rot_state->timestamp)
 			rot_state->timestamp = iio_get_time_ns(indio_dev);
 
-		iio_push_to_buffers_with_timestamp(indio_dev, &rot_state->scan,
-						   rot_state->timestamp);
+		/*
+		 * ABI regression avoidance: IIO previously had an incorrect
+		 * implementation of iio_push_to_buffers_with_timestamp() that
+		 * put the timestamp in the last 8 bytes of the buffer, which
+		 * was incorrect according to the IIO ABI. To avoid breaking
+		 * userspace that may be depending on this broken behavior, we
+		 * put the timestamp in both the correct place [0] and the old
+		 * incorrect place [1].
+		 */
+		rot_state->scan.timestamp[0] = rot_state->timestamp;
+		rot_state->scan.timestamp[1] = rot_state->timestamp;
+
+		iio_push_to_buffers(indio_dev, &rot_state->scan);
 
 		rot_state->timestamp = 0;
 	}

-- 
2.43.0


^ permalink raw reply related

* [PATCH v2 2/5] iio: buffer: check return value of iio_compute_scan_bytes()
From: David Lechner @ 2026-03-08  1:44 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, Nuno Sá,
	Andy Shevchenko, Lars Möllendorf, Lars-Peter Clausen,
	Greg Kroah-Hartman
  Cc: Jonathan Cameron, Lixu Zhang, Francesco Lavra, linux-input,
	linux-iio, linux-kernel, David Lechner
In-Reply-To: <20260307-iio-fix-timestamp-alignment-v2-0-d1d48fbadbbf@baylibre.com>

Check return value of iio_compute_scan_bytes() as it can return an
error.

The result is moved to an output parameter while we are touching this
as we will need to add a second output parameter in a later change.

The return type of iio_buffer_update_bytes_per_datum() also had to be
changed to propagate the error.

Signed-off-by: David Lechner <dlechner@baylibre.com>
---
 drivers/iio/industrialio-buffer.c | 36 +++++++++++++++++++++++++-----------
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index f15a180dc49e..4e413b4bb073 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -762,7 +762,8 @@ static int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev)
 }
 
 static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
-				  const unsigned long *mask, bool timestamp)
+				  const unsigned long *mask, bool timestamp,
+				  unsigned int *scan_bytes)
 {
 	unsigned int bytes = 0;
 	int length, i, largest = 0;
@@ -788,8 +789,9 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
 		largest = max(largest, length);
 	}
 
-	bytes = ALIGN(bytes, largest);
-	return bytes;
+	*scan_bytes = ALIGN(bytes, largest);
+
+	return 0;
 }
 
 static void iio_buffer_activate(struct iio_dev *indio_dev,
@@ -834,18 +836,23 @@ static int iio_buffer_disable(struct iio_buffer *buffer,
 	return buffer->access->disable(buffer, indio_dev);
 }
 
-static void iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
-					      struct iio_buffer *buffer)
+static int iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
+					     struct iio_buffer *buffer)
 {
 	unsigned int bytes;
+	int ret;
 
 	if (!buffer->access->set_bytes_per_datum)
-		return;
+		return 0;
 
-	bytes = iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
-				       buffer->scan_timestamp);
+	ret = iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
+				     buffer->scan_timestamp, &bytes);
+	if (ret)
+		return ret;
 
 	buffer->access->set_bytes_per_datum(buffer, bytes);
+
+	return 0;
 }
 
 static int iio_buffer_request_update(struct iio_dev *indio_dev,
@@ -853,7 +860,10 @@ static int iio_buffer_request_update(struct iio_dev *indio_dev,
 {
 	int ret;
 
-	iio_buffer_update_bytes_per_datum(indio_dev, buffer);
+	ret = iio_buffer_update_bytes_per_datum(indio_dev, buffer);
+	if (ret)
+		return ret;
+
 	if (buffer->access->request_update) {
 		ret = buffer->access->request_update(buffer);
 		if (ret) {
@@ -896,6 +906,7 @@ static int iio_verify_update(struct iio_dev *indio_dev,
 	struct iio_buffer *buffer;
 	bool scan_timestamp;
 	unsigned int modes;
+	int ret;
 
 	if (insert_buffer &&
 	    bitmap_empty(insert_buffer->scan_mask, masklength)) {
@@ -983,8 +994,11 @@ static int iio_verify_update(struct iio_dev *indio_dev,
 		scan_mask = compound_mask;
 	}
 
-	config->scan_bytes = iio_compute_scan_bytes(indio_dev,
-						    scan_mask, scan_timestamp);
+	ret = iio_compute_scan_bytes(indio_dev, scan_mask, scan_timestamp,
+				     &config->scan_bytes);
+	if (ret)
+		return ret;
+
 	config->scan_mask = scan_mask;
 	config->scan_timestamp = scan_timestamp;
 

-- 
2.43.0


^ permalink raw reply related

* [PATCH v2 3/5] iio: buffer: cache timestamp offset in scan buffer
From: David Lechner @ 2026-03-08  1:44 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, Nuno Sá,
	Andy Shevchenko, Lars Möllendorf, Lars-Peter Clausen,
	Greg Kroah-Hartman
  Cc: Jonathan Cameron, Lixu Zhang, Francesco Lavra, linux-input,
	linux-iio, linux-kernel, David Lechner
In-Reply-To: <20260307-iio-fix-timestamp-alignment-v2-0-d1d48fbadbbf@baylibre.com>

Cache the offset (in bytes) for the timestamp element in a scan buffer.
This will be used later to ensure proper alignment of the timestamp
element in the scan buffer.

The new field could not be placed in struct iio_dev_opaque because we
will need to access it in a static inline function later, so we make it
__private instead. It is only intended to be used by core IIO code.

Signed-off-by: David Lechner <dlechner@baylibre.com>
---

v2 changes:
* Cache the timestamp offset instead of the largest scan element size.
---
 drivers/iio/industrialio-buffer.c | 14 +++++++++++---
 include/linux/iio/iio.h           |  3 +++
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 4e413b4bb073..ecfe0c9740e2 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -763,7 +763,8 @@ static int iio_storage_bytes_for_timestamp(struct iio_dev *indio_dev)
 
 static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
 				  const unsigned long *mask, bool timestamp,
-				  unsigned int *scan_bytes)
+				  unsigned int *scan_bytes,
+				  unsigned int *timestamp_offset)
 {
 	unsigned int bytes = 0;
 	int length, i, largest = 0;
@@ -785,6 +786,10 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
 			return length;
 
 		bytes = ALIGN(bytes, length);
+
+		if (timestamp_offset)
+			*timestamp_offset = bytes;
+
 		bytes += length;
 		largest = max(largest, length);
 	}
@@ -846,7 +851,7 @@ static int iio_buffer_update_bytes_per_datum(struct iio_dev *indio_dev,
 		return 0;
 
 	ret = iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
-				     buffer->scan_timestamp, &bytes);
+				     buffer->scan_timestamp, &bytes, NULL);
 	if (ret)
 		return ret;
 
@@ -890,6 +895,7 @@ struct iio_device_config {
 	unsigned int watermark;
 	const unsigned long *scan_mask;
 	unsigned int scan_bytes;
+	unsigned int scan_timestamp_offset;
 	bool scan_timestamp;
 };
 
@@ -995,7 +1001,8 @@ static int iio_verify_update(struct iio_dev *indio_dev,
 	}
 
 	ret = iio_compute_scan_bytes(indio_dev, scan_mask, scan_timestamp,
-				     &config->scan_bytes);
+				     &config->scan_bytes,
+				     &config->scan_timestamp_offset);
 	if (ret)
 		return ret;
 
@@ -1153,6 +1160,7 @@ static int iio_enable_buffers(struct iio_dev *indio_dev,
 	indio_dev->active_scan_mask = config->scan_mask;
 	ACCESS_PRIVATE(indio_dev, scan_timestamp) = config->scan_timestamp;
 	indio_dev->scan_bytes = config->scan_bytes;
+	ACCESS_PRIVATE(indio_dev, scan_timestamp_offset) = config->scan_timestamp_offset;
 	iio_dev_opaque->currentmode = config->mode;
 
 	iio_update_demux(indio_dev);
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index 2c91b7659ce9..ecbaeecbe0ac 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -584,6 +584,8 @@ struct iio_buffer_setup_ops {
  *			and owner
  * @buffer:		[DRIVER] any buffer present
  * @scan_bytes:		[INTERN] num bytes captured to be fed to buffer demux
+ * @scan_timestamp_offset: [INTERN] cache of the offset (in bytes) for the
+ *			   timestamp in the scan buffer
  * @available_scan_masks: [DRIVER] optional array of allowed bitmasks. Sort the
  *			   array in order of preference, the most preferred
  *			   masks first.
@@ -610,6 +612,7 @@ struct iio_dev {
 
 	struct iio_buffer		*buffer;
 	int				scan_bytes;
+	unsigned int			__private scan_timestamp_offset;
 
 	const unsigned long		*available_scan_masks;
 	unsigned int			__private masklength;

-- 
2.43.0


^ permalink raw reply related

* [PATCH v2 4/5] iio: buffer: ensure repeat alignment is a power of two
From: David Lechner @ 2026-03-08  1:44 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, Nuno Sá,
	Andy Shevchenko, Lars Möllendorf, Lars-Peter Clausen,
	Greg Kroah-Hartman
  Cc: Jonathan Cameron, Lixu Zhang, Francesco Lavra, linux-input,
	linux-iio, linux-kernel, David Lechner
In-Reply-To: <20260307-iio-fix-timestamp-alignment-v2-0-d1d48fbadbbf@baylibre.com>

Use roundup_pow_of_two() in the calculation of iio_storage_bytes_for_si()
when scan_type->repeat > 1 to ensure that the size is a power of two.
storagebits is always going to be a power of two bytes, so we only need
to apply this to the repeat factor. The storage size is also used for
alignment, and we want to ensure that all alignments are a power of two.

The only repeat in use in the kernel currently is for quaternions, which
have a repeat of 4, so this does not change the result for existing
users.

Signed-off-by: David Lechner <dlechner@baylibre.com>
---

v2 changes: new patch

In v1, Nuno made the point that if the size isn't a power of two, then
the alignment won't be a power of two either. And this could cause
unexpected problems regarding alignment in general.

This will affect the work Francesco is doing with IIO_MOD_QUATERNION_AXIS
which will have a repeat of 3, so this is a good time to think about this.
---
 drivers/iio/industrialio-buffer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index ecfe0c9740e2..c38da24561c0 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -748,7 +748,7 @@ static int iio_storage_bytes_for_si(struct iio_dev *indio_dev,
 	bytes = scan_type->storagebits / 8;
 
 	if (scan_type->repeat > 1)
-		bytes *= scan_type->repeat;
+		bytes *= roundup_pow_of_two(scan_type->repeat);
 
 	return bytes;
 }

-- 
2.43.0


^ permalink raw reply related

* [PATCH v2 5/5] iio: buffer: fix timestamp alignment when quaternion in scan
From: David Lechner @ 2026-03-08  1:44 UTC (permalink / raw)
  To: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, Nuno Sá,
	Andy Shevchenko, Lars Möllendorf, Lars-Peter Clausen,
	Greg Kroah-Hartman
  Cc: Jonathan Cameron, Lixu Zhang, Francesco Lavra, linux-input,
	linux-iio, linux-kernel, David Lechner
In-Reply-To: <20260307-iio-fix-timestamp-alignment-v2-0-d1d48fbadbbf@baylibre.com>

Fix timestamp alignment when a scan buffer contains an element larger
than sizeof(int64_t). Currently s32 quaternions are the only such
element, and the one driver that has this (hid-sensor-rotation) has a
workaround in place already so this change does not affect it.

Previously, we assumed that the timestamp would always be 8-byte aligned
relative to the end of the scan buffer, but in the case of a scan buffer
a 16-byte quaternion vector, scan_bytes == 32, but the timestamp needs
to be placed at offset 16, not 24.

ts_offset is now a value in bytes so we have to change how the array
access is done.

Signed-off-by: David Lechner <dlechner@baylibre.com>
---

v2 changes:
* Use cached timestamp offset instead of largest scan element size.
* Mention change of ts_offset semantics in commit message.

To test this, I used hid-sensor-rotation minus the first patch in the
series so that we can see that the timestamp actually moved to the
correct location.

Before this patch, the timestamp (8 bytes ending with "98 18") is in the
wrong location.

00000000  6a 18 00 00 ac f3 ff ff  83 2d 00 00 02 d3 ff ff  |j........-......|
00000010  00 00 00 00 00 00 00 00  5a 17 a0 2a 73 cb 98 18  |........Z..*s...|

00000020  ad 17 00 00 6a f4 ff ff  35 2b 00 00 ca d0 ff ff  |....j...5+......|
00000030  00 00 00 00 00 00 00 00  2a a6 bb 30 73 cb 98 18  |........*..0s...|

00000040  92 1e 00 00 50 ec ff ff  ea c1 ff ff 78 f0 ff ff  |....P.......x...|
00000050  00 00 00 00 00 00 00 00  8f 3b a7 39 77 cb 98 18  |.........;.9w...|

After this patch, timestamp is now in the correct location.

00000000  55 0f 00 00 dd 1f 00 00  af 0b 00 00 ec 3e 00 00  |U............>..|
00000010  c7 17 68 42 6d d0 98 18  00 00 00 00 00 00 00 00  |..hBm...........|

00000020  57 0e 00 00 c8 1f 00 00  d1 0e 00 00 42 3e 00 00  |W...........B>..|
00000030  56 a2 87 48 6d d0 98 18  00 00 00 00 00 00 00 00  |V..Hm...........|

00000040  a3 e2 ff ff d3 1b 00 00  0b c9 ff ff cc 20 00 00  |............. ..|
00000050  27 59 4d b3 72 d0 98 18  00 00 00 00 00 00 00 00  |'YM.r...........|

I also tested this with a different driver not affected by this bug to
make sure that the timestamp is still in the correct location for all
other drivers.
---
 include/linux/iio/buffer.h | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/include/linux/iio/buffer.h b/include/linux/iio/buffer.h
index d37f82678f71..8fd0d57d238f 100644
--- a/include/linux/iio/buffer.h
+++ b/include/linux/iio/buffer.h
@@ -34,8 +34,16 @@ static inline int iio_push_to_buffers_with_timestamp(struct iio_dev *indio_dev,
 	void *data, int64_t timestamp)
 {
 	if (ACCESS_PRIVATE(indio_dev, scan_timestamp)) {
-		size_t ts_offset = indio_dev->scan_bytes / sizeof(int64_t) - 1;
-		((int64_t *)data)[ts_offset] = timestamp;
+		size_t ts_offset = ACCESS_PRIVATE(indio_dev, scan_timestamp_offset);
+
+		/*
+		 * The size of indio_dev->scan_bytes is always aligned to the
+		 * largest scan element's alignment (see iio_compute_scan_bytes()).
+		 * So there may be padding after the timestamp. ts_offset contains
+		 * the offset in bytes that was already computed for correctly
+		 * aligning the timestamp.
+		 */
+		*(int64_t *)(data + ts_offset) = timestamp;
 	}
 
 	return iio_push_to_buffers(indio_dev, data);

-- 
2.43.0


^ permalink raw reply related

* [hid:for-7.1/lenovo 13/16] drivers/hid/hid-lenovo-go-s.c:795:21: sparse: sparse: symbol 'touchpad_linux_mode' was not declared. Should it be static?
From: kernel test robot @ 2026-03-08  2:37 UTC (permalink / raw)
  To: Derek J. Clark; +Cc: oe-kbuild-all, linux-input, Jiri Kosina, Mark Pearson

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-7.1/lenovo
head:   d2c424e80caf8237bda4c94bc2e25398967243f9
commit: f3ac4e11aaf3cd334d7f2cb205851bd157a2535f [13/16] HID: hid-lenovo-go-s: Add Touchpad Mode Attributes
config: arc-randconfig-r113-20260307 (https://download.01.org/0day-ci/archive/20260308/202603081041.UgxXYvsF-lkp@intel.com/config)
compiler: arc-linux-gcc (GCC) 13.4.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260308/202603081041.UgxXYvsF-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603081041.UgxXYvsF-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
   drivers/hid/hid-lenovo-go-s.c:447:72: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:619:67: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:713:21: sparse: sparse: symbol 'gamepad_poll_rate' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:739:21: sparse: sparse: symbol 'imu_sensor_enabled' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:775:21: sparse: sparse: symbol 'mouse_wheel_step' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go-s.c:795:21: sparse: sparse: symbol 'touchpad_linux_mode' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go-s.c:799:21: sparse: sparse: symbol 'touchpad_windows_mode' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:832:72: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:839:73: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:448:21: sparse: sparse: unsigned value that used to be signed checked against zero?
   drivers/hid/hid-lenovo-go-s.c:447:33: sparse: signed value source

vim +/touchpad_linux_mode +795 drivers/hid/hid-lenovo-go-s.c

   794	
 > 795	struct gos_cfg_attr touchpad_linux_mode = { CFG_LINUX_MODE };
   796	LEGOS_DEVICE_ATTR_RW(touchpad_linux_mode, "linux_mode", index, touchpad);
   797	static DEVICE_ATTR_RO_NAMED(touchpad_linux_mode_index, "linux_mode_index");
   798	
 > 799	struct gos_cfg_attr touchpad_windows_mode = { CFG_WINDOWS_MODE };
   800	LEGOS_DEVICE_ATTR_RW(touchpad_windows_mode, "windows_mode", index, touchpad);
   801	static DEVICE_ATTR_RO_NAMED(touchpad_windows_mode_index, "windows_mode_index");
   802	

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

^ permalink raw reply

* [hid:for-7.1/lenovo 14/16] drivers/hid/hid-lenovo-go-s.c:1204:18: sparse: sparse: symbol 'gos_rgb_subled_info' was not declared. Should it be static?
From: kernel test robot @ 2026-03-08  5:36 UTC (permalink / raw)
  To: Derek J. Clark; +Cc: oe-kbuild-all, linux-input, Jiri Kosina, Mark Pearson

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-7.1/lenovo
head:   d2c424e80caf8237bda4c94bc2e25398967243f9
commit: 550752e2c153663c3a374b048535654073007c90 [14/16] HID: hid-lenovo-go-s: Add RGB LED control interface
config: arc-randconfig-r113-20260307 (https://download.01.org/0day-ci/archive/20260308/202603081333.9m9vOhOR-lkp@intel.com/config)
compiler: arc-linux-gcc (GCC) 13.4.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260308/202603081333.9m9vOhOR-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603081333.9m9vOhOR-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
   drivers/hid/hid-lenovo-go-s.c:522:72: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:694:67: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:765:63: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:909:71: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:964:74: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:1058:21: sparse: sparse: symbol 'gamepad_poll_rate' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:1084:21: sparse: sparse: symbol 'imu_sensor_enabled' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:1120:21: sparse: sparse: symbol 'mouse_wheel_step' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:1140:21: sparse: sparse: symbol 'touchpad_linux_mode' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:1144:21: sparse: sparse: symbol 'touchpad_windows_mode' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go-s.c:1204:18: sparse: sparse: symbol 'gos_rgb_subled_info' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go-s.c:1225:24: sparse: sparse: symbol 'gos_cdev_rgb' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:1241:72: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:1248:73: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:523:21: sparse: sparse: unsigned value that used to be signed checked against zero?
   drivers/hid/hid-lenovo-go-s.c:522:33: sparse: signed value source

vim +/gos_rgb_subled_info +1204 drivers/hid/hid-lenovo-go-s.c

  1203	
> 1204	struct mc_subled gos_rgb_subled_info[] = {
  1205		{
  1206			.color_index = LED_COLOR_ID_RED,
  1207			.brightness = 0x50,
  1208			.intensity = 0x24,
  1209			.channel = 0x1,
  1210		},
  1211		{
  1212			.color_index = LED_COLOR_ID_GREEN,
  1213			.brightness = 0x50,
  1214			.intensity = 0x22,
  1215			.channel = 0x2,
  1216		},
  1217		{
  1218			.color_index = LED_COLOR_ID_BLUE,
  1219			.brightness = 0x50,
  1220			.intensity = 0x99,
  1221			.channel = 0x3,
  1222		},
  1223	};
  1224	
> 1225	struct led_classdev_mc gos_cdev_rgb = {
  1226		.led_cdev = {
  1227			.name = "go_s:rgb:joystick_rings",
  1228			.brightness = 0x50,
  1229			.max_brightness = 0x64,
  1230			.brightness_set = hid_gos_brightness_set,
  1231		},
  1232		.num_colors = ARRAY_SIZE(gos_rgb_subled_info),
  1233		.subled_info = gos_rgb_subled_info,
  1234	};
  1235	

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

^ permalink raw reply

* Re: [PATCH] HID: logitech-hidpp: Add support for HID++ Multi-Platform feature (0x4531)
From: dev exalt @ 2026-03-08  8:08 UTC (permalink / raw)
  To: jikos, bentiss
  Cc: lains, hadess, linux-input, linux-kernel, sari.kreitem, hbarnor
In-Reply-To: <CAJaUH_8A70=_Cb8yCWqJxbjpW-BnK958fExnC1kSgyhVaydbUw@mail.gmail.com>

Dear maintainers,


We would like to kindly follow up on this patch sent on Dec 15, 2025,
as we haven't received feedback yet.

Patch link:
https://lore.kernel.org/linux-input/20251215125319.33261-1-exalt.dev.team@gmail.com/T/#u

We understand maintainers are busy, so just sending a gentle reminder
in case this slipped.

Thank you for your time and review.


Best regards,

Baraa Atta (Dev Exalt) <exalt.dev.team@gmail.com>


On Sun, Mar 8, 2026 at 10:01 AM dev exalt <exalt.dev.team@gmail.com> wrote:
>
> Dear maintainers,
>
>
> We would like to kindly follow up on this patch sent on Dec 15, 2025, as we haven't received feedback yet.
>
> Patch link:
> https://lore.kernel.org/linux-input/20251215125319.33261-1-exalt.dev.team@gmail.com/T/#u
>
> We understand maintainers are busy, so just sending a gentle reminder in case this slipped.
>
> Thank you for your time and review.
>
>
> Best regards,
>
> Baraa Atta (Dev Exalt) <exalt.dev.team@gmail.com>
>
>
> On Mon, Dec 15, 2025 at 2:53 PM DevExalt <exalt.dev.team@gmail.com> wrote:
>>
>> From: "Baraa Atta (Dev Exalt)" <exalt.dev.team@gmail.com>
>>
>> Add support in the Logitech HID++ driver for the HID++ Multi-Platform
>> feature (0x4531), which enables HID++ devices to adjust their behavior
>> based on the host operating system (Linux, ChromeOS, Android).
>>
>> This patch:
>>  * Adds device IDs for MX Keys S (046d:b378) and Casa Keys (046d:b371).
>>  * Introduces the module parameter "hidpp_platform" to allow selecting a
>>    target platform.
>>  * Detects whether a device implements feature 0x4531.
>>  * Validates that the requested platform is supported by the device.
>>  * Applies the platform index when valid, otherwise leaves the device
>>    unchanged.
>>  * Keeps default behavior when "hidpp_platform" is unset or invalid.
>>
>> Supported values for hidpp_platform:
>>    Android, Linux, Chrome
>>
>> TEST=Pair MX Keys S and Casa Keys over Bluetooth and verify:
>>      * Feature 0x4531 is detected.
>>      * Valid platform values are accepted and applied.
>>      * Invalid platform values result in no update.
>>      * Devices without 0x4531 retain default behavior.
>>      * Platform-specific key behavior is observed once applied.
>>
>> Signed-off-by: Baraa Atta (Dev Exalt) <exalt.dev.team@gmail.com>
>> ---
>>  drivers/hid/hid-ids.h            |   2 +
>>  drivers/hid/hid-logitech-hidpp.c | 280 +++++++++++++++++++++++++++++++
>>  drivers/hid/hid-quirks.c         |   2 +
>>  3 files changed, 284 insertions(+)
>>
>> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
>> index d31711f1aaec..12de1194d7fa 100644
>> --- a/drivers/hid/hid-ids.h
>> +++ b/drivers/hid/hid-ids.h
>> @@ -866,6 +866,8 @@
>>  #define USB_DEVICE_ID_LOGITECH_T651    0xb00c
>>  #define USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD 0xb309
>>  #define USB_DEVICE_ID_LOGITECH_CASA_TOUCHPAD   0xbb00
>> +#define USB_DEVICE_ID_LOGITECH_CASA_KEYS_KEYBOARD      0xb371
>> +#define USB_DEVICE_ID_LOGITECH_MX_KEYS_S_KEYBOARD      0xb378
>>  #define USB_DEVICE_ID_LOGITECH_C007    0xc007
>>  #define USB_DEVICE_ID_LOGITECH_C077    0xc077
>>  #define USB_DEVICE_ID_LOGITECH_RECEIVER        0xc101
>> diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
>> index d5011a5d0890..e94daed31981 100644
>> --- a/drivers/hid/hid-logitech-hidpp.c
>> +++ b/drivers/hid/hid-logitech-hidpp.c
>> @@ -4373,6 +4373,280 @@ static bool hidpp_application_equals(struct hid_device *hdev,
>>         return report && report->application == application;
>>  }
>>
>> +/* -------------------------------------------------------------------------- */
>> +/* 0x4531: Multi-Platform Support                                             */
>> +/* -------------------------------------------------------------------------- */
>> +
>> +/*
>> + * Some Logitech devices expose the HID++ feature 0x4531 (Multi-Platform) allowing
>> + * the host to specify which operating system platform to use on the device. Changing device's
>> + * platform may alter the behavior of the device to match the specified platform.
>> + */
>> +
>> +static char *hidpp_platform;
>> +module_param(hidpp_platform, charp, 0644);
>> +MODULE_PARM_DESC(hidpp_platform, "Select host platform type for Logitech HID++ Multi-Platform feature "
>> +                "0x4531, valid values: (linux|chrome|android).  If unset, no "
>> +                "change is applied.");
>> +
>> +#define HIDPP_MULTIPLATFORM_FEAT_ID                    0x4531
>> +#define HIDPP_MULTIPLATFORM_GET_FEATURE_INFO           0x0F
>> +#define HIDPP_MULTIPLATFORM_GET_PLATFORM_DESCRIPTOR    0x1F
>> +#define HIDPP_MULTIPLATFORM_SET_CURRENT_PLATFORM       0x3F
>> +
>> +#define HIDPP_MULTIPLATFORM_PLATFORM_MASK_LINUX                BIT(10)
>> +#define HIDPP_MULTIPLATFORM_PLATFORM_MASK_CHROME       BIT(11)
>> +#define HIDPP_MULTIPLATFORM_PLATFORM_MASK_ANDROID      BIT(12)
>> +
>> +struct hidpp_platform_desc {
>> +       u8 plat_idx;
>> +       u8 desc_idx;
>> +       u16 plat_mask;
>> +};
>> +
>> +/**
>> + * hidpp_multiplatform_mask_from_str() - Convert platform name to an HID++ platform mask
>> + * @pname: Platform name string
>> + *
>> + * Converts a platform name string to its corresponding HID++ platform mask based on
>> + * the Multi-Platform feature specification.
>> + *
>> + * Return: Platform mask corresponding to @pname on success,
>> + * or 0 if @pname is NULL or unsupported.
>> + */
>> +static u16 hidpp_multiplatform_mask_from_str(const char *pname)
>> +{
>> +       if (!pname)
>> +               return 0;
>> +
>> +       if (!strcasecmp(pname, "linux"))
>> +               return HIDPP_MULTIPLATFORM_PLATFORM_MASK_LINUX;
>> +       if (!strcasecmp(pname, "chrome"))
>> +               return HIDPP_MULTIPLATFORM_PLATFORM_MASK_CHROME;
>> +       if (!strcasecmp(pname, "android"))
>> +               return HIDPP_MULTIPLATFORM_PLATFORM_MASK_ANDROID;
>> +
>> +       return 0;
>> +}
>> +
>> +/**
>> + * hidpp_multiplatform_get_num_pdesc() - Retrieve number of platform descriptors
>> + * @hidpp: Pointer to the hidpp_device instance
>> + * @feat_index: Feature index of the Multi-Platform feature
>> + * @num_desc: Pointer to store the number of platform descriptors
>> + *
>> + * Retrieves the number of platform descriptors supported by the device through
>> + * the Multi-Platform feature and stores it in @num_desc.
>> + *
>> + * Return: 0 on success, or non-zero on failure.
>> + */
>> +static int hidpp_multiplatform_get_num_pdesc(struct hidpp_device *hidpp,
>> +                                            u8 feat_index, u8 *num_desc)
>> +{
>> +       int ret;
>> +       struct hidpp_report response;
>> +       struct hid_device *hdev = hidpp->hid_dev;
>> +
>> +       ret = hidpp_send_fap_command_sync(hidpp, feat_index,
>> +                                         HIDPP_MULTIPLATFORM_GET_FEATURE_INFO,
>> +                                         NULL, 0, &response);
>> +       if (ret) {
>> +               hid_warn(hdev, "Multiplatform: GET_FEATURE_INFO failed (err=%d)", ret);
>> +               return ret;
>> +       }
>> +
>> +       *num_desc = response.fap.params[3];
>> +       hid_dbg(hdev, "Multiplatform: Device supports %d platform descriptors", *num_desc);
>> +
>> +       return 0;
>> +}
>> +
>> +/**
>> + * hidpp_multiplatform_get_platform_desc() - Retrieve a platform descriptor entry
>> + * @hidpp: Pointer to the hidpp_device instance
>> + * @feat_index: Feature index of the Multi-Platform feature
>> + * @platform_idx: Index of the platform descriptor to retrieve
>> + * @pdesc: Pointer to store the retrieved platform descriptor
>> + *
>> + * Retrieves a single platform descriptor identified by @platform_idx from the
>> + * device and stores the parsed descriptor fields in @pdesc.
>> + *
>> + * Return: 0 on success, or non-zero on failure.
>> + */
>> +static int hidpp_multiplatform_get_platform_desc(struct hidpp_device *hidpp, u8 feat_index,
>> +                                                u8 platform_idx, struct hidpp_platform_desc *pdesc)
>> +{
>> +       int ret;
>> +       struct hidpp_report response;
>> +       u8 params[1] = { platform_idx };
>> +       struct hid_device *hdev = hidpp->hid_dev;
>> +
>> +       ret = hidpp_send_fap_command_sync(hidpp, feat_index,
>> +                                         HIDPP_MULTIPLATFORM_GET_PLATFORM_DESCRIPTOR,
>> +                                         params, sizeof(params), &response);
>> +
>> +       if (ret) {
>> +               hid_warn(hdev,
>> +                        "Multiplatform: GET_PLATFORM_DESCRIPTOR failed for index %d (err=%d)",
>> +                        platform_idx, ret);
>> +               return ret;
>> +       }
>> +
>> +       pdesc->plat_idx = response.fap.params[0];
>> +       pdesc->desc_idx = response.fap.params[1];
>> +       pdesc->plat_mask = get_unaligned_be16(&response.fap.params[2]);
>> +
>> +       hid_dbg(hdev,
>> +               "Multiplatform: descriptor %d: plat_idx=%d, desc_idx=%d, plat_mask=0x%04x",
>> +               platform_idx, pdesc->plat_idx, pdesc->desc_idx, pdesc->plat_mask);
>> +
>> +       return 0;
>> +}
>> +
>> +/**
>> + * hidpp_multiplatform_get_platform_index() - Find platform index for a mask
>> + * @hidpp: Pointer to the hidpp_device instance
>> + * @feat_index: Feature index of the Multi-Platform feature
>> + * @plat_mask: Platform mask to search for
>> + * @plat_index: Pointer to store the matched platform index
>> + *
>> + * Iterates through all platform descriptors exposed by the device via the
>> + * Multi-Platform feature, retrieving each descriptor and comparing its
>> + * platform mask to @plat_mask. A descriptor matches if its mask overlaps with
>> + * the requested @plat_mask (i.e. (pdesc.plat_mask & plat_mask) is non-zero).
>> + *
>> + * When a matching descriptor is found, its platform index (plat_idx) is
>> + * written to @plat_index and the function returns success.
>> + *
>> + * If no descriptor matches, -ENOENT is returned.
>> + *
>> + * Return: 0 on success; -ENOENT if no matching descriptor exists;
>> + *         or non-zero on failure.
>> + */
>> +static int hidpp_multiplatform_get_platform_index(struct hidpp_device *hidpp,
>> +                                                 u8 feat_index, u16 plat_mask,
>> +                                                 u8 *plat_index)
>> +{
>> +       int i;
>> +       int ret;
>> +       u8 num_desc;
>> +       struct hidpp_platform_desc pdesc;
>> +       struct hid_device *hdev = hidpp->hid_dev;
>> +
>> +       ret = hidpp_multiplatform_get_num_pdesc(hidpp, feat_index, &num_desc);
>> +       if (ret)
>> +               return ret;
>> +
>> +       for (i = 0; i < num_desc; i++) {
>> +               ret = hidpp_multiplatform_get_platform_desc(hidpp, feat_index, i, &pdesc);
>> +               if (ret)
>> +                       return ret;
>> +
>> +               if (pdesc.plat_mask & plat_mask) {
>> +                       *plat_index = pdesc.plat_idx;
>> +                       hid_dbg(hdev,
>> +                               "Multiplatform: Selected platform index %d for platform '%s'",
>> +                               *plat_index, hidpp_platform);
>> +                       return 0;
>> +               }
>> +       }
>> +
>> +       hid_dbg(hdev,
>> +               "Multiplatform: No matching platform descriptor found for platform '%s'",
>> +               hidpp_platform);
>> +       return -ENOENT;
>> +}
>> +
>> +/**
>> + * hidpp_multiplatform_update_device_platform() - Update the device platform
>> + * @hidpp: Pointer to the hidpp_device instance
>> + * @feat_index: Feature index of the Multi-Platform feature
>> + * @plat_index: Platform index to set on the device
>> + *
>> + * Sends the HID++ Multi-Platform 'SET_CURRENT_PLATFORM' command to the device to
>> + * update its platform index to @plat_index.
>> + *
>> + * Return: 0 on success, or non-zero on failure.
>> + */
>> +static int hidpp_multiplatform_update_device_platform(struct hidpp_device *hidpp,
>> +                                                     u8 feat_index, u8 plat_index)
>> +{
>> +       int ret;
>> +       struct hidpp_report response;
>> +       /* Byte 0 (hostIndex): 0xFF selects the current host. */
>> +       u8 params[2] = { 0xFF, plat_index };
>> +
>> +       ret = hidpp_send_fap_command_sync(hidpp, feat_index,
>> +                                         HIDPP_MULTIPLATFORM_SET_CURRENT_PLATFORM,
>> +                                         params, sizeof(params), &response);
>> +
>> +       if (ret)
>> +               hid_warn(hidpp->hid_dev,
>> +                        "Multiplatform: SET_CURRENT_PLATFORM failed for index %d (err=%d)",
>> +                        plat_index, ret);
>> +
>> +       return ret;
>> +}
>> +
>> +/**
>> + * hidpp_multiplatform_init() - Apply the HID++ Multi-Platform (0x4531) feature
>> + * @hidpp: Pointer to the hidpp_device instance
>> + *
>> + * Initializes the Multi-Platform feature by selecting the device platform
>> + * corresponding to the module parameter @hidpp_platform, if provided.
>> + *
>> + * The function performs the following steps:
>> + *   1. Convert the @hidpp_platform string into a platform mask.
>> + *   2. Check whether the device supports the Multi-Platform feature (0x4531).
>> + *   3. Look up the device's platform index whose mask matches the host
>> + *      platform mask.
>> + *   4. Apply that platform index to the device via 'SET_CURRENT_PLATFORM'.
>> + *
>> + * If the module parameter is unset or invalid, or the device does not support
>> + * the feature, or no matching platform descriptor is found, the function exits
>> + * silently without modifying the device state.
>> + *
>> + * On success, the device's platform configuration is updated.
>> + */
>> +static void hidpp_multiplatform_init(struct hidpp_device *hidpp)
>> +{
>> +       int ret;
>> +       u8 feat_index;
>> +       u8 plat_index;
>> +       u16 host_plat_mask;
>> +       struct hid_device *hdev = hidpp->hid_dev;
>> +
>> +       if (!hidpp_platform)
>> +               return;
>> +
>> +       host_plat_mask = hidpp_multiplatform_mask_from_str(hidpp_platform);
>> +       if (!host_plat_mask) {
>> +               hid_warn(hdev,
>> +                        "Multiplatform: Invalid or unsupported platform name '%s'",
>> +                        hidpp_platform);
>> +               return;
>> +       }
>> +
>> +       ret = hidpp_root_get_feature(hidpp, HIDPP_MULTIPLATFORM_FEAT_ID, &feat_index);
>> +       if (ret) {
>> +               hid_warn(hdev,
>> +                        "Multiplatform: Failed to get the HID++ multiplatform feature 0x4531");
>> +               return;
>> +       }
>> +
>> +       ret = hidpp_multiplatform_get_platform_index(hidpp, feat_index, host_plat_mask,
>> +                                                    &plat_index);
>> +       if (ret)
>> +               return;
>> +
>> +       ret = hidpp_multiplatform_update_device_platform(hidpp, feat_index, plat_index);
>> +       if (ret)
>> +               return;
>> +
>> +       hid_info(hdev,
>> +                "Multiplatform: Device platform successfully set to '%s'", hidpp_platform);
>> +}
>> +
>>  static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
>>  {
>>         struct hidpp_device *hidpp;
>> @@ -4467,6 +4741,8 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
>>         if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
>>                 connect_mask &= ~HID_CONNECT_HIDINPUT;
>>
>> +       hidpp_multiplatform_init(hidpp);
>> +
>>         /* Now export the actual inputs and hidraw nodes to the world */
>>         hid_device_io_stop(hdev);
>>         ret = hid_connect(hdev, connect_mask);
>> @@ -4664,6 +4940,10 @@ static const struct hid_device_id hidpp_devices[] = {
>>           HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb034) },
>>         { /* MX Anywhere 3SB mouse over Bluetooth */
>>           HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb038) },
>> +       { /* Casa Keys keyboard over Bluetooth */
>> +         HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CASA_KEYS_KEYBOARD) },
>> +       { /* MX Keys S keyboard over Bluetooth */
>> +         HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MX_KEYS_S_KEYBOARD) },
>>         {}
>>  };
>>
>> diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
>> index c89a015686c0..99ca04b61bda 100644
>> --- a/drivers/hid/hid-quirks.c
>> +++ b/drivers/hid/hid-quirks.c
>> @@ -520,6 +520,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
>>  #endif
>>  #if IS_ENABLED(CONFIG_HID_LOGITECH_HIDPP)
>>         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL) },
>> +       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CASA_KEYS_KEYBOARD) },
>> +       { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MX_KEYS_S_KEYBOARD) },
>>  #endif
>>  #if IS_ENABLED(CONFIG_HID_MAGICMOUSE)
>>         { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGICMOUSE) },
>> --
>> 2.34.1
>>

^ permalink raw reply

* [hid:for-7.1/lenovo 15/16] drivers/hid/hid-lenovo-go-s.c:1175:21: sparse: sparse: symbol 'imu_manufacturer' was not declared. Should it be static?
From: kernel test robot @ 2026-03-08  8:56 UTC (permalink / raw)
  To: Derek J. Clark; +Cc: oe-kbuild-all, linux-input, Jiri Kosina, Mark Pearson

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-7.1/lenovo
head:   d2c424e80caf8237bda4c94bc2e25398967243f9
commit: 041eadd5f2d207dd1d286747d137a7d896dd7d5c [15/16] HID: hid-lenovo-go-s: Add IMU and Touchpad RO Attributes
config: arc-randconfig-r113-20260307 (https://download.01.org/0day-ci/archive/20260308/202603081611.J61k8tIx-lkp@intel.com/config)
compiler: arc-linux-gcc (GCC) 13.4.0
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260308/202603081611.J61k8tIx-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603081611.J61k8tIx-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
   drivers/hid/hid-lenovo-go-s.c:582:72: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:754:67: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:856:63: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:1000:71: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:1055:74: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:1149:21: sparse: sparse: symbol 'gamepad_poll_rate' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go-s.c:1175:21: sparse: sparse: symbol 'imu_manufacturer' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:1178:21: sparse: sparse: symbol 'imu_sensor_enabled' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:1215:21: sparse: sparse: symbol 'mouse_wheel_step' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:1235:21: sparse: sparse: symbol 'touchpad_linux_mode' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go-s.c:1239:21: sparse: sparse: symbol 'touchpad_manufacturer' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go-s.c:1242:21: sparse: sparse: symbol 'touchpad_version' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:1245:21: sparse: sparse: symbol 'touchpad_windows_mode' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:1307:18: sparse: sparse: symbol 'gos_rgb_subled_info' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:1328:24: sparse: sparse: symbol 'gos_cdev_rgb' was not declared. Should it be static?
   drivers/hid/hid-lenovo-go-s.c:1344:72: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:1351:73: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:1357:72: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:1364:72: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:1371:73: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go-s.c:583:21: sparse: sparse: unsigned value that used to be signed checked against zero?
   drivers/hid/hid-lenovo-go-s.c:582:33: sparse: signed value source

vim +/imu_manufacturer +1175 drivers/hid/hid-lenovo-go-s.c

  1174	
> 1175	struct gos_cfg_attr imu_manufacturer = { TEST_IMU_MFR };
  1176	LEGOS_DEVICE_ATTR_RO(imu_manufacturer, "manufacturer", test);
  1177	
  1178	struct gos_cfg_attr imu_sensor_enabled = { FEATURE_IMU_ENABLE };
  1179	LEGOS_DEVICE_ATTR_RW(imu_sensor_enabled, "sensor_enabled", index, gamepad);
  1180	static DEVICE_ATTR_RO_NAMED(imu_sensor_enabled_index, "sensor_enabled_index");
  1181	
  1182	static struct attribute *legos_imu_attrs[] = {
  1183		&dev_attr_imu_bypass_enabled.attr,
  1184		&dev_attr_imu_bypass_enabled_index.attr,
  1185		&dev_attr_imu_manufacturer.attr,
  1186		&dev_attr_imu_sensor_enabled.attr,
  1187		&dev_attr_imu_sensor_enabled_index.attr,
  1188		NULL,
  1189	};
  1190	
  1191	static const struct attribute_group imu_attr_group = {
  1192		.name = "imu",
  1193		.attrs = legos_imu_attrs,
  1194	};
  1195	
  1196	/* MCU */
  1197	static DEVICE_ATTR_RO(mcu_id);
  1198	
  1199	struct gos_cfg_attr os_mode = { FEATURE_OS_MODE };
  1200	LEGOS_DEVICE_ATTR_RW(os_mode, "os_mode", index, gamepad);
  1201	static DEVICE_ATTR_RO(os_mode_index);
  1202	
  1203	static struct attribute *legos_mcu_attrs[] = {
  1204		&dev_attr_mcu_id.attr,
  1205		&dev_attr_os_mode.attr,
  1206		&dev_attr_os_mode_index.attr,
  1207		NULL,
  1208	};
  1209	
  1210	static const struct attribute_group mcu_attr_group = {
  1211		.attrs = legos_mcu_attrs,
  1212	};
  1213	
  1214	/* Mouse */
  1215	struct gos_cfg_attr mouse_wheel_step = { FEATURE_MOUSE_WHEEL_STEP };
  1216	LEGOS_DEVICE_ATTR_RW(mouse_wheel_step, "step", range, gamepad);
  1217	static DEVICE_ATTR_RO_NAMED(mouse_wheel_step_range, "step_range");
  1218	
  1219	static struct attribute *legos_mouse_attrs[] = {
  1220		&dev_attr_mouse_wheel_step.attr,
  1221		&dev_attr_mouse_wheel_step_range.attr,
  1222		NULL,
  1223	};
  1224	
  1225	static const struct attribute_group mouse_attr_group = {
  1226		.name = "mouse",
  1227		.attrs = legos_mouse_attrs,
  1228	};
  1229	
  1230	/* Touchpad */
  1231	struct gos_cfg_attr touchpad_enabled = { FEATURE_TOUCHPAD_ENABLE };
  1232	LEGOS_DEVICE_ATTR_RW(touchpad_enabled, "enabled", index, gamepad);
  1233	static DEVICE_ATTR_RO_NAMED(touchpad_enabled_index, "enabled_index");
  1234	
  1235	struct gos_cfg_attr touchpad_linux_mode = { CFG_LINUX_MODE };
  1236	LEGOS_DEVICE_ATTR_RW(touchpad_linux_mode, "linux_mode", index, touchpad);
  1237	static DEVICE_ATTR_RO_NAMED(touchpad_linux_mode_index, "linux_mode_index");
  1238	
> 1239	struct gos_cfg_attr touchpad_manufacturer = { TEST_TP_MFR };
  1240	LEGOS_DEVICE_ATTR_RO(touchpad_manufacturer, "manufacturer", test);
  1241	
> 1242	struct gos_cfg_attr touchpad_version = { TEST_TP_VER };
  1243	LEGOS_DEVICE_ATTR_RO(touchpad_version, "version", test);
  1244	

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

^ permalink raw reply

* Re: [PATCH v4 1/2] dt-bindings: Input: Add Wacom W9000-series penabled touchscreens
From: Krzysztof Kozlowski @ 2026-03-08  9:15 UTC (permalink / raw)
  To: Hendrik Noack
  Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Ferass El Hafidi, linux-input, devicetree, linux-kernel
In-Reply-To: <20260307181557.66927-2-hendrik-noack@gmx.de>

On Sat, Mar 07, 2026 at 07:15:32PM +0100, Hendrik Noack wrote:
> Add bindings for Wacom W9002 and two Wacom W9007 variants which can be
> found in tablets.
> 
> Co-developed-by: Ferass El Hafidi <funderscore@postmarketos.org>
> Signed-off-by: Ferass El Hafidi <funderscore@postmarketos.org>
> Signed-off-by: Hendrik Noack <hendrik-noack@gmx.de>
> ---

You received review and instruction what to do. Did you read it?

Your way of organizing your work makes it difficult for us. Look, try
yourself:

b4 diff '20260307181557.66927-2-hendrik-noack@gmx.de'
Checking for older revisions
Grabbing search results from lore.kernel.org
  Added from v3: 2 patches
---
Analyzing 16 messages in the thread
Preparing fake-am for v3: dt-bindings: Input: Add Wacom W9000-series penabled touchscreens
ERROR: v3 series incomplete; unable to create a fake-am range
---
Could not create fake-am range for lower series v3


Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH v2] usbhid: tolerate intermittent errors
From: Liam Mitchell @ 2026-03-08 13:48 UTC (permalink / raw)
  To: Alan Stern
  Cc: Jiri Kosina, Benjamin Tissoires, Oliver Neukum, linux-usb,
	linux-input, linux-kernel
In-Reply-To: <6cbc6c70-8252-43d0-8701-e1613ddc769f@rowland.harvard.edu>

On Sat, 7 Mar 2026 at 23:53, Alan Stern <stern@rowland.harvard.edu> wrote:
>
> On Sat, Mar 07, 2026 at 07:57:09PM +0100, Liam Mitchell wrote:
> > Modifies usbhid error handling to tolerate intermittent protocol
> > errors, avoiding URB resubmission delay and device reset.
> >
> > ---
> > Protocol errors like EPROTO can occur randomly, sometimes frequently and are often not fixed by a device reset.
> >
> > The current error handling will only resubmit the URB after at least 13ms delay and may reset the USB device if another error occurs 1-1.5s later, regardless of error type or count.
> >
> > These delays and device resets increase the chance that input events will be missed and that users see symptoms like missed or sticky keyboard keys.
> >
> > This patch allows one protocol error per 500ms to be tolerated and have the URB re-submitted immediately.
> >
> > 500ms was chosen to be well above the error rate of a malfunctioning
> > device but low enough to be useful for users with devices noisier than
> > mine.
> >
> > Signed-off-by: Liam Mitchell <mitchell.liam@gmail.com>
> > Link: https://lore.kernel.org/linux-input/CAOQ1CL6Q+4GNy=kgisLzs0UBXFT3b02PG8t-0rPuW-Wf6NhQ6g@mail.gmail.com/
> > ---
>
> Liam, take a look at
>
>         https://bugzilla.kernel.org/show_bug.cgi?id=221184
>
> On Roman's system, these protocol errors occur fairly regularly,
> apparently caused by high system load.

Thanks Alan, I commented there.

> Do you think a better approach might be to reduce the 13-ms delay to
> just 1 or 2 ms, and perform a reset only there has been no successful
> communication for about one second?  This might perhaps be _too_ lenient
> sometimes, but I don't think such situations will arise in practice.

I would prefer to have at least the first error resubmit immediately.
I want to reduce device downtime and missed events. From that
perspective, I want to assume the error is intermittent unless we see
evidence otherwise.

The current reset logic "reset only if there has been no successful
communication for one second" is problematic because there is no sign
of successful communication if the user isn't pressing keys or moving
the mouse. Two EPROTO errors 1.4 seconds apart will trigger device
reset and 100-200ms of downtime when ideally URBs would be immediately
resubmitted with only a few ms of downtime.

Can we infer from not receiving errors that we have successful
communication? That might change the equation. If we don't receive
errors for say 10x the polling interval, can we assume it is working?

Ideally the reset is only triggered when we are very sure the device
is not working and needs it.

> The reason for having at least a small delay is to avoid getting into a
> tight resubmit/error loop in cases where the device has been unplugged.
>
> Alan Stern

This patch would only allow one immediate resubmission per window
(500ms). How costly is a URB submission? I was assuming they are
relatively cheap and even one per 100ms wouldn't cause problems.

Liam

^ permalink raw reply

* Re: [PATCH v2] usbhid: tolerate intermittent errors
From: Alan Stern @ 2026-03-08 15:19 UTC (permalink / raw)
  To: Liam Mitchell
  Cc: Jiri Kosina, Benjamin Tissoires, Oliver Neukum, linux-usb,
	linux-input, linux-kernel
In-Reply-To: <CAOQ1CL6GcPUDw+wriKtqq05ywkuhjyi-ujp7WwFpSWgY1fV1zg@mail.gmail.com>

On Sun, Mar 08, 2026 at 02:48:42PM +0100, Liam Mitchell wrote:
> On Sat, 7 Mar 2026 at 23:53, Alan Stern <stern@rowland.harvard.edu> wrote:
> > Do you think a better approach might be to reduce the 13-ms delay to
> > just 1 or 2 ms, and perform a reset only there has been no successful
> > communication for about one second?  This might perhaps be _too_ lenient
> > sometimes, but I don't think such situations will arise in practice.
> 
> I would prefer to have at least the first error resubmit immediately.
> I want to reduce device downtime and missed events. From that
> perspective, I want to assume the error is intermittent unless we see
> evidence otherwise.

Okay; a single immediate resubmission won't cause any problems.

> The current reset logic "reset only if there has been no successful
> communication for one second" is problematic because there is no sign
> of successful communication if the user isn't pressing keys or moving
> the mouse. Two EPROTO errors 1.4 seconds apart will trigger device
> reset and 100-200ms of downtime when ideally URBs would be immediately
> resubmitted with only a few ms of downtime.
> 
> Can we infer from not receiving errors that we have successful
> communication? That might change the equation. If we don't receive
> errors for say 10x the polling interval, can we assume it is working?

Pretty much, yes.  If the communication is not working at all (for 
example, if the device was unplugged) then an interrupt URB will fail 
within three polling intervals.  10 intervals seems like a reasonable 
limit.

> Ideally the reset is only triggered when we are very sure the device
> is not working and needs it.

Agreed.  I don't know how frequently the bad states that HID devices get 
into can be fixed by a reset, but I suspect it's not very frequent at 
all.

> > The reason for having at least a small delay is to avoid getting into a
> > tight resubmit/error loop in cases where the device has been unplugged.
> >
> > Alan Stern
> 
> This patch would only allow one immediate resubmission per window
> (500ms). How costly is a URB submission? I was assuming they are
> relatively cheap and even one per 100ms wouldn't cause problems.

This problem mainly shows up in syzbot testing.  Submission isn't all 
that expensive, but in the virtual environment used by syzbot, failure 
occurs during or shortly after submission.  If resubmission is then 
immediate after failure, the whole thing becomes an unending tight loop 
executing mostly in atomic context, which ties up a CPU long enough to 
trigger a warning about a possible kernel hang.

Alan Stern

^ permalink raw reply

* [hid:for-7.1/lenovo 2/16] drivers/hid/hid-lenovo-go.c:484:20: sparse: sparse: symbol 'version_product_mcu' was not declared. Should it be static?
From: kernel test robot @ 2026-03-08 16:01 UTC (permalink / raw)
  To: Derek J. Clark; +Cc: oe-kbuild-all, linux-input, Jiri Kosina, Mark Pearson

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git for-7.1/lenovo
head:   d2c424e80caf8237bda4c94bc2e25398967243f9
commit: 3bb54f568ecc35be7675eef5303a47e14aba54bc [2/16] HID: hid-lenovo-go: Add Lenovo Legion Go Series HID Driver
config: loongarch-randconfig-r131-20260308 (https://download.01.org/0day-ci/archive/20260308/202603082311.tPfUsIMR-lkp@intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
sparse: v0.6.5-rc1
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260308/202603082311.tPfUsIMR-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603082311.tPfUsIMR-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/hid/hid-lenovo-go.c:484:20: sparse: sparse: symbol 'version_product_mcu' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:487:20: sparse: sparse: symbol 'version_protocol_mcu' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:490:20: sparse: sparse: symbol 'version_firmware_mcu' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:493:20: sparse: sparse: symbol 'version_hardware_mcu' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:496:20: sparse: sparse: symbol 'version_gen_mcu' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:513:20: sparse: sparse: symbol 'version_product_tx_dongle' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:516:20: sparse: sparse: symbol 'version_protocol_tx_dongle' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:519:20: sparse: sparse: symbol 'version_firmware_tx_dongle' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:522:20: sparse: sparse: symbol 'version_hardware_tx_dongle' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:525:20: sparse: sparse: symbol 'version_gen_tx_dongle' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:543:20: sparse: sparse: symbol 'version_product_left' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:546:20: sparse: sparse: symbol 'version_protocol_left' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:549:20: sparse: sparse: symbol 'version_firmware_left' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:552:20: sparse: sparse: symbol 'version_hardware_left' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:555:20: sparse: sparse: symbol 'version_gen_left' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:573:20: sparse: sparse: symbol 'version_product_right' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:576:20: sparse: sparse: symbol 'version_protocol_right' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:579:20: sparse: sparse: symbol 'version_firmware_right' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:582:20: sparse: sparse: symbol 'version_hardware_right' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:585:20: sparse: sparse: symbol 'version_gen_right' was not declared. Should it be static?
>> drivers/hid/hid-lenovo-go.c:624:58: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:632:59: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:640:59: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:648:59: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:656:62: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:665:60: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:673:61: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:681:61: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:689:61: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:697:64: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:706:66: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:714:67: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:722:67: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:730:67: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:738:70: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:747:67: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:755:68: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:763:68: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:771:68: sparse: sparse: Using plain integer as NULL pointer
   drivers/hid/hid-lenovo-go.c:779:71: sparse: sparse: Using plain integer as NULL pointer

vim +/version_product_mcu +484 drivers/hid/hid-lenovo-go.c

   444	
   445	#define LEGO_DEVICE_ATTR_RW(_name, _attrname, _dtype, _rtype, _group)         \
   446		static ssize_t _name##_store(struct device *dev,                      \
   447					     struct device_attribute *attr,           \
   448					     const char *buf, size_t count)           \
   449		{                                                                     \
   450			return _group##_store(dev, attr, buf, count, _name.index,     \
   451					      _dtype);                                \
   452		}                                                                     \
   453		static ssize_t _name##_show(struct device *dev,                       \
   454					    struct device_attribute *attr, char *buf) \
   455		{                                                                     \
   456			return _group##_show(dev, attr, buf, _name.index, _dtype);    \
   457		}                                                                     \
   458		static ssize_t _name##_##_rtype##_show(                               \
   459			struct device *dev, struct device_attribute *attr, char *buf) \
   460		{                                                                     \
   461			return _group##_options(dev, attr, buf, _name.index);         \
   462		}                                                                     \
   463		static DEVICE_ATTR_RW_NAMED(_name, _attrname)
   464	
   465	#define LEGO_DEVICE_ATTR_WO(_name, _attrname, _dtype, _group)             \
   466		static ssize_t _name##_store(struct device *dev,                  \
   467					     struct device_attribute *attr,       \
   468					     const char *buf, size_t count)       \
   469		{                                                                 \
   470			return _group##_store(dev, attr, buf, count, _name.index, \
   471					      _dtype);                            \
   472		}                                                                 \
   473		static DEVICE_ATTR_WO_NAMED(_name, _attrname)
   474	
   475	#define LEGO_DEVICE_ATTR_RO(_name, _attrname, _dtype, _group)                 \
   476		static ssize_t _name##_show(struct device *dev,                       \
   477					    struct device_attribute *attr, char *buf) \
   478		{                                                                     \
   479			return _group##_show(dev, attr, buf, _name.index, _dtype);    \
   480		}                                                                     \
   481		static DEVICE_ATTR_RO_NAMED(_name, _attrname)
   482	
   483	/* Gamepad - MCU */
 > 484	struct go_cfg_attr version_product_mcu = { PRODUCT_VERSION };
   485	LEGO_DEVICE_ATTR_RO(version_product_mcu, "product_version", USB_MCU, version);
   486	
 > 487	struct go_cfg_attr version_protocol_mcu = { PROTOCOL_VERSION };
   488	LEGO_DEVICE_ATTR_RO(version_protocol_mcu, "protocol_version", USB_MCU, version);
   489	
 > 490	struct go_cfg_attr version_firmware_mcu = { FIRMWARE_VERSION };
   491	LEGO_DEVICE_ATTR_RO(version_firmware_mcu, "firmware_version", USB_MCU, version);
   492	
 > 493	struct go_cfg_attr version_hardware_mcu = { HARDWARE_VERSION };
   494	LEGO_DEVICE_ATTR_RO(version_hardware_mcu, "hardware_version", USB_MCU, version);
   495	
 > 496	struct go_cfg_attr version_gen_mcu = { HARDWARE_GENERATION };
   497	LEGO_DEVICE_ATTR_RO(version_gen_mcu, "hardware_generation", USB_MCU, version);
   498	
   499	static struct attribute *mcu_attrs[] = {
   500		&dev_attr_version_firmware_mcu.attr,
   501		&dev_attr_version_gen_mcu.attr,
   502		&dev_attr_version_hardware_mcu.attr,
   503		&dev_attr_version_product_mcu.attr,
   504		&dev_attr_version_protocol_mcu.attr,
   505		NULL,
   506	};
   507	
   508	static const struct attribute_group mcu_attr_group = {
   509		.attrs = mcu_attrs,
   510	};
   511	
   512	/* Gamepad - TX Dongle */
 > 513	struct go_cfg_attr version_product_tx_dongle = { PRODUCT_VERSION };
   514	LEGO_DEVICE_ATTR_RO(version_product_tx_dongle, "product_version", TX_DONGLE, version);
   515	
 > 516	struct go_cfg_attr version_protocol_tx_dongle = { PROTOCOL_VERSION };
   517	LEGO_DEVICE_ATTR_RO(version_protocol_tx_dongle, "protocol_version", TX_DONGLE, version);
   518	
 > 519	struct go_cfg_attr version_firmware_tx_dongle = { FIRMWARE_VERSION };
   520	LEGO_DEVICE_ATTR_RO(version_firmware_tx_dongle, "firmware_version", TX_DONGLE, version);
   521	
 > 522	struct go_cfg_attr version_hardware_tx_dongle = { HARDWARE_VERSION };
   523	LEGO_DEVICE_ATTR_RO(version_hardware_tx_dongle, "hardware_version", TX_DONGLE, version);
   524	
 > 525	struct go_cfg_attr version_gen_tx_dongle = { HARDWARE_GENERATION };
   526	LEGO_DEVICE_ATTR_RO(version_gen_tx_dongle, "hardware_generation", TX_DONGLE, version);
   527	
   528	static struct attribute *tx_dongle_attrs[] = {
   529		&dev_attr_version_hardware_tx_dongle.attr,
   530		&dev_attr_version_firmware_tx_dongle.attr,
   531		&dev_attr_version_gen_tx_dongle.attr,
   532		&dev_attr_version_product_tx_dongle.attr,
   533		&dev_attr_version_protocol_tx_dongle.attr,
   534		NULL,
   535	};
   536	
   537	static const struct attribute_group tx_dongle_attr_group = {
   538		.name = "tx_dongle",
   539		.attrs = tx_dongle_attrs,
   540	};
   541	
   542	/* Gamepad - Left */
 > 543	struct go_cfg_attr version_product_left = { PRODUCT_VERSION };
   544	LEGO_DEVICE_ATTR_RO(version_product_left, "product_version", LEFT_CONTROLLER, version);
   545	
 > 546	struct go_cfg_attr version_protocol_left = { PROTOCOL_VERSION };
   547	LEGO_DEVICE_ATTR_RO(version_protocol_left, "protocol_version", LEFT_CONTROLLER, version);
   548	
 > 549	struct go_cfg_attr version_firmware_left = { FIRMWARE_VERSION };
   550	LEGO_DEVICE_ATTR_RO(version_firmware_left, "firmware_version", LEFT_CONTROLLER, version);
   551	
 > 552	struct go_cfg_attr version_hardware_left = { HARDWARE_VERSION };
   553	LEGO_DEVICE_ATTR_RO(version_hardware_left, "hardware_version", LEFT_CONTROLLER, version);
   554	
 > 555	struct go_cfg_attr version_gen_left = { HARDWARE_GENERATION };
   556	LEGO_DEVICE_ATTR_RO(version_gen_left, "hardware_generation", LEFT_CONTROLLER, version);
   557	
   558	static struct attribute *left_gamepad_attrs[] = {
   559		&dev_attr_version_hardware_left.attr,
   560		&dev_attr_version_firmware_left.attr,
   561		&dev_attr_version_gen_left.attr,
   562		&dev_attr_version_product_left.attr,
   563		&dev_attr_version_protocol_left.attr,
   564		NULL,
   565	};
   566	
   567	static const struct attribute_group left_gamepad_attr_group = {
   568		.name = "left_handle",
   569		.attrs = left_gamepad_attrs,
   570	};
   571	
   572	/* Gamepad - Right */
 > 573	struct go_cfg_attr version_product_right = { PRODUCT_VERSION };
   574	LEGO_DEVICE_ATTR_RO(version_product_right, "product_version", RIGHT_CONTROLLER, version);
   575	
 > 576	struct go_cfg_attr version_protocol_right = { PROTOCOL_VERSION };
   577	LEGO_DEVICE_ATTR_RO(version_protocol_right, "protocol_version", RIGHT_CONTROLLER, version);
   578	
 > 579	struct go_cfg_attr version_firmware_right = { FIRMWARE_VERSION };
   580	LEGO_DEVICE_ATTR_RO(version_firmware_right, "firmware_version", RIGHT_CONTROLLER, version);
   581	
 > 582	struct go_cfg_attr version_hardware_right = { HARDWARE_VERSION };
   583	LEGO_DEVICE_ATTR_RO(version_hardware_right, "hardware_version", RIGHT_CONTROLLER, version);
   584	
 > 585	struct go_cfg_attr version_gen_right = { HARDWARE_GENERATION };
   586	LEGO_DEVICE_ATTR_RO(version_gen_right, "hardware_generation", RIGHT_CONTROLLER, version);
   587	
   588	static struct attribute *right_gamepad_attrs[] = {
   589		&dev_attr_version_hardware_right.attr,
   590		&dev_attr_version_firmware_right.attr,
   591		&dev_attr_version_gen_right.attr,
   592		&dev_attr_version_product_right.attr,
   593		&dev_attr_version_protocol_right.attr,
   594		NULL,
   595	};
   596	
   597	static const struct attribute_group right_gamepad_attr_group = {
   598		.name = "right_handle",
   599		.attrs = right_gamepad_attrs,
   600	};
   601	
   602	/* Touchpad */
   603	static struct attribute *touchpad_attrs[] = {
   604		NULL,
   605	};
   606	
   607	static const struct attribute_group touchpad_attr_group = {
   608		.name = "touchpad",
   609		.attrs = touchpad_attrs,
   610	};
   611	
   612	static const struct attribute_group *top_level_attr_groups[] = {
   613		&mcu_attr_group,	  &tx_dongle_attr_group,
   614		&left_gamepad_attr_group, &right_gamepad_attr_group,
   615		&touchpad_attr_group,	  NULL,
   616	};
   617	
   618	static void cfg_setup(struct work_struct *work)
   619	{
   620		int ret;
   621	
   622		/* MCU Version Attrs */
   623		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
 > 624				       PRODUCT_VERSION, USB_MCU, 0, 0);
   625		if (ret < 0) {
   626			dev_err(&drvdata.hdev->dev,
   627				"Failed to retrieve USB_MCU Product Version: %i\n", ret);
   628			return;
   629		}
   630	
   631		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   632				       PROTOCOL_VERSION, USB_MCU, 0, 0);
   633		if (ret < 0) {
   634			dev_err(&drvdata.hdev->dev,
   635				"Failed to retrieve USB_MCU Protocol Version: %i\n", ret);
   636			return;
   637		}
   638	
   639		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   640				       FIRMWARE_VERSION, USB_MCU, 0, 0);
   641		if (ret < 0) {
   642			dev_err(&drvdata.hdev->dev,
   643				"Failed to retrieve USB_MCU Firmware Version: %i\n", ret);
   644			return;
   645		}
   646	
   647		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   648				       HARDWARE_VERSION, USB_MCU, 0, 0);
   649		if (ret < 0) {
   650			dev_err(&drvdata.hdev->dev,
   651				"Failed to retrieve USB_MCU Hardware Version: %i\n", ret);
   652			return;
   653		}
   654	
   655		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   656				       HARDWARE_GENERATION, USB_MCU, 0, 0);
   657		if (ret < 0) {
   658			dev_err(&drvdata.hdev->dev,
   659				"Failed to retrieve USB_MCU Hardware Generation: %i\n", ret);
   660			return;
   661		}
   662	
   663		/* TX Dongle Version Attrs */
   664		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   665				       PRODUCT_VERSION, TX_DONGLE, 0, 0);
   666		if (ret < 0) {
   667			dev_err(&drvdata.hdev->dev,
   668				"Failed to retrieve TX_DONGLE Product Version: %i\n", ret);
   669			return;
   670		}
   671	
   672		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   673				       PROTOCOL_VERSION, TX_DONGLE, 0, 0);
   674		if (ret < 0) {
   675			dev_err(&drvdata.hdev->dev,
   676				"Failed to retrieve TX_DONGLE Protocol Version: %i\n", ret);
   677			return;
   678		}
   679	
   680		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   681				       FIRMWARE_VERSION, TX_DONGLE, 0, 0);
   682		if (ret < 0) {
   683			dev_err(&drvdata.hdev->dev,
   684				"Failed to retrieve TX_DONGLE Firmware Version: %i\n", ret);
   685			return;
   686		}
   687	
   688		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   689				       HARDWARE_VERSION, TX_DONGLE, 0, 0);
   690		if (ret < 0) {
   691			dev_err(&drvdata.hdev->dev,
   692				"Failed to retrieve TX_DONGLE Hardware Version: %i\n", ret);
   693			return;
   694		}
   695	
   696		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   697				       HARDWARE_GENERATION, TX_DONGLE, 0, 0);
   698		if (ret < 0) {
   699			dev_err(&drvdata.hdev->dev,
   700				"Failed to retrieve TX_DONGLE Hardware Generation: %i\n", ret);
   701			return;
   702		}
   703	
   704		/* Left Handle Version Attrs */
   705		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   706				       PRODUCT_VERSION, LEFT_CONTROLLER, 0, 0);
   707		if (ret < 0) {
   708			dev_err(&drvdata.hdev->dev,
   709				"Failed to retrieve LEFT_CONTROLLER Product Version: %i\n", ret);
   710			return;
   711		}
   712	
   713		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   714				       PROTOCOL_VERSION, LEFT_CONTROLLER, 0, 0);
   715		if (ret < 0) {
   716			dev_err(&drvdata.hdev->dev,
   717				"Failed to retrieve LEFT_CONTROLLER Protocol Version: %i\n", ret);
   718			return;
   719		}
   720	
   721		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   722				       FIRMWARE_VERSION, LEFT_CONTROLLER, 0, 0);
   723		if (ret < 0) {
   724			dev_err(&drvdata.hdev->dev,
   725				"Failed to retrieve LEFT_CONTROLLER Firmware Version: %i\n", ret);
   726			return;
   727		}
   728	
   729		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   730				       HARDWARE_VERSION, LEFT_CONTROLLER, 0, 0);
   731		if (ret < 0) {
   732			dev_err(&drvdata.hdev->dev,
   733				"Failed to retrieve LEFT_CONTROLLER Hardware Version: %i\n", ret);
   734			return;
   735		}
   736	
   737		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   738				       HARDWARE_GENERATION, LEFT_CONTROLLER, 0, 0);
   739		if (ret < 0) {
   740			dev_err(&drvdata.hdev->dev,
   741				"Failed to retrieve LEFT_CONTROLLER Hardware Generation: %i\n", ret);
   742			return;
   743		}
   744	
   745		/* Right Handle Version Attrs */
   746		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   747				       PRODUCT_VERSION, RIGHT_CONTROLLER, 0, 0);
   748		if (ret < 0) {
   749			dev_err(&drvdata.hdev->dev,
   750				"Failed to retrieve RIGHT_CONTROLLER Product Version: %i\n", ret);
   751			return;
   752		}
   753	
   754		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   755				       PROTOCOL_VERSION, RIGHT_CONTROLLER, 0, 0);
   756		if (ret < 0) {
   757			dev_err(&drvdata.hdev->dev,
   758				"Failed to retrieve RIGHT_CONTROLLER Protocol Version: %i\n", ret);
   759			return;
   760		}
   761	
   762		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   763				       FIRMWARE_VERSION, RIGHT_CONTROLLER, 0, 0);
   764		if (ret < 0) {
   765			dev_err(&drvdata.hdev->dev,
   766				"Failed to retrieve RIGHT_CONTROLLER Firmware Version: %i\n", ret);
   767			return;
   768		}
   769	
   770		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   771				       HARDWARE_VERSION, RIGHT_CONTROLLER, 0, 0);
   772		if (ret < 0) {
   773			dev_err(&drvdata.hdev->dev,
   774				"Failed to retrieve RIGHT_CONTROLLER Hardware Version: %i\n", ret);
   775			return;
   776		}
   777	
   778		ret = mcu_property_out(drvdata.hdev, MCU_CONFIG_DATA, GET_VERSION_DATA,
   779				       HARDWARE_GENERATION, RIGHT_CONTROLLER, 0, 0);
   780		if (ret < 0) {
   781			dev_err(&drvdata.hdev->dev,
   782				"Failed to retrieve RIGHT_CONTROLLER Hardware Generation: %i\n", ret);
   783			return;
   784		}
   785	}
   786	

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

^ permalink raw reply

* [PATCH v4 0/2] Input: st1232 - add system wakeup support
From: phucduc.bui @ 2026-03-09  0:03 UTC (permalink / raw)
  To: krzk+dt, geert+renesas
  Cc: krzk, krzysztof.kozlowski, conor+dt, devicetree, dmitry.torokhov,
	hechtb, javier.carrasco, jeff, phucduc.bui, linux-input,
	linux-kernel, linux-renesas-soc, magnus.damm, robh, wsa+renesas

From: bui duc phuc <phucduc.bui@gmail.com>

This patch series adds support for using the Sitronix ST1232
touchscreen as a wakeup source on the Armadillo800EVA board.

Patch 1 documents the generic wakeup-source property in the
Devicetree binding for the ST1232 touchscreen controller.

Patch 2 enables the wakeup-source property in the ST1232
touchscreen node for the Armadillo800EVA board, allowing touch
events to wake the system from suspend.

Verified functionality

* The "power/wakeup" sysfs attribute is present for the device.
* The system resumes correctly from 'mem' and 'freeze' states when the
  touchscreen is touched.

Additional test information

Demo video showing wakeup from suspend:
https://youtu.be/POJhbguiA7A

Kernel config and boot logs:
https://gist.github.com/BuiDucPhuc/ac7d5d732658ca293af4323ad04accca

Changes in v4:
*Drop patch 3 as the I2C core already performs the initialization, 
 registration, and management of the wakeup interrupt, making the 
 implementation in the driver redundant.
 The original intention of patch 3 was to expose active_count, 
 event_count, and wakeup_count to user space. However, this is not 
 necessary since the R8A7740 SoC has some specific characteristics 
 in its wakeup interrupt handling.
 Moreover, modifying this driver could potentially affect other SoCs 
 sharing the same driver, so the patch is removed.
*Going back to v1 design.
*Update the cover letter

Changes in v3:
* Patch 3: Removed debug dev_info() log messages for a cleaner
  production-ready implementation.
* No changes to Patch 1 and Patch 2.
* Link : 
  https://lore.kernel.org/all/20260306111912.58388-1-phucduc.bui@gmail.com/
  

Changes in v2
* Drop description for wakeup-source property as suggested by
  Krzysztof Kozlowski.
* Updated commit messages for clarity.
* Added driver-side wakeup handling in st1232.c.
* Link : 
  https://lore.kernel.org/all/20260306104025.43970-1-phucduc.bui@gmail.com/

v1 
 *Link: 
  https://lore.kernel.org/all/20260305113512.227269-1-phucduc.bui@gmail.com/

This series depends on the following patch which has been
submitted but not yet merged:

drm: shmobile: Fix blank screen after resume when LCDC is stopped
Link: https://lore.kernel.org/all/20260226054035.30330-1-phucduc.bui@gmail.com/



bui duc phuc (2):
  dt-bindings: input: touchscreen: sitronix,st1232: Add wakeup-source
  arm: dts: renesas: r8a7740-armadillo800eva: Add wakeup-source to
    st1232

 .../bindings/input/touchscreen/sitronix,st1232.yaml           | 4 ++++
 arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts         | 1 +
 2 files changed, 5 insertions(+)

-- 
2.43.0


^ permalink raw reply

* [PATCH v4 1/2] dt-bindings: input: touchscreen: sitronix,st1232: Add wakeup-source
From: phucduc.bui @ 2026-03-09  0:03 UTC (permalink / raw)
  To: krzk+dt, geert+renesas
  Cc: krzk, krzysztof.kozlowski, conor+dt, devicetree, dmitry.torokhov,
	hechtb, javier.carrasco, jeff, phucduc.bui, linux-input,
	linux-kernel, linux-renesas-soc, magnus.damm, robh, wsa+renesas
In-Reply-To: <20260309000319.74880-1-phucduc.bui@gmail.com>

From: bui duc phuc <phucduc.bui@gmail.com>

Document the 'wakeup-source' property for Sitronix ST1232 touchscreen
controllers to allow the device to wake the system from suspend.

Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
---
 .../bindings/input/touchscreen/sitronix,st1232.yaml           | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/input/touchscreen/sitronix,st1232.yaml b/Documentation/devicetree/bindings/input/touchscreen/sitronix,st1232.yaml
index 978afaa4fcef..fe1fa217d842 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/sitronix,st1232.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/sitronix,st1232.yaml
@@ -32,6 +32,9 @@ properties:
     description: A phandle to the reset GPIO
     maxItems: 1
 
+  wakeup-source:
+    type: boolean
+
 required:
   - compatible
   - reg
@@ -51,6 +54,7 @@ examples:
                     reg = <0x55>;
                     interrupts = <2 0>;
                     gpios = <&gpio1 166 0>;
+                    wakeup-source;
 
                     touch-overlay {
                             segment-0 {
-- 
2.43.0


^ permalink raw reply related

* [PATCH v4 2/2] arm: dts: renesas: r8a7740-armadillo800eva: Add wakeup-source to st1232
From: phucduc.bui @ 2026-03-09  0:03 UTC (permalink / raw)
  To: krzk+dt, geert+renesas
  Cc: krzk, krzysztof.kozlowski, conor+dt, devicetree, dmitry.torokhov,
	hechtb, javier.carrasco, jeff, phucduc.bui, linux-input,
	linux-kernel, linux-renesas-soc, magnus.damm, robh, wsa+renesas
In-Reply-To: <20260309000319.74880-1-phucduc.bui@gmail.com>

From: bui duc phuc <phucduc.bui@gmail.com>

Add the wakeup-source property to the ST1232 touchscreen node
in the device tree so that the touchscreen interrupt can wake
the system from suspend when the panel is touched.

Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
---
 arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts b/arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts
index 04d24b6d8056..d47a6cc3e756 100644
--- a/arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts
+++ b/arch/arm/boot/dts/renesas/r8a7740-armadillo800eva.dts
@@ -228,6 +228,7 @@ touchscreen@55 {
 		pinctrl-0 = <&st1232_pins>;
 		pinctrl-names = "default";
 		gpios = <&pfc 166 GPIO_ACTIVE_LOW>;
+		wakeup-source;
 	};
 };
 
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH 09/12] dt-bindings: input: Document hid-over-spi DT schema
From: Dmitry Torokhov @ 2026-03-09  5:44 UTC (permalink / raw)
  To: Val Packett
  Cc: Jingyuan Liang, Jiri Kosina, Benjamin Tissoires, Jonathan Corbet,
	Mark Brown, Steven Rostedt, Masami Hiramatsu, Mathieu Desnoyers,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-input,
	linux-doc, linux-kernel, linux-spi, linux-trace-kernel,
	devicetree, hbarnor, Dmitry Antipov, Jarrett Schultz
In-Reply-To: <1cc6de61-8b56-492e-ab78-e3aa448f58ad@packett.cool>

On Sat, Mar 07, 2026 at 04:25:44AM -0300, Val Packett wrote:
> 
> On 3/3/26 3:13 AM, Jingyuan Liang wrote:
> > Documentation describes the required and optional properties for
> > implementing Device Tree for a Microsoft G6 Touch Digitizer that
> > supports HID over SPI Protocol 1.0 specification.
> > […]
> > +properties:
> > +  compatible:
> > +    oneOf:
> > +      - items:
> > +          - enum:
> > +              - microsoft,g6-touch-digitizer
> > +          - const: hid-over-spi
> > +      - description: Just "hid-over-spi" alone is allowed, but not recommended.
> > […]
> > +required:
> > +  - compatible
> > +  - interrupts
> > +  - reset-gpios
> 
> Why is reset required? Is it so implausible on some device implementing the
> spec there wouldn't be a reset gpio?

No, because it is mandated by the spec:

"HID SPI peripheral must provide a dedicated reset line, driven by the
HOST, which, when toggled (pulled LOW for at least 10ms, normally HIGH),
will have the effect of resetting the device. If a HID SPI peripheral is
enumerated via ACPI, the device ASL configuration must expose an ACPI
FLDR (_RST) method to control this line."

The spec also states that the host must initiate reset during
initialization of the device.

> 
> > +  - vdd-supply
> Linux makes up a dummy regulator if DT doesn't provide one, so can
> regulators even be required?

There is still a supply line to the chip even if it is not exposed to
the OS control. So as far as chip is concerned the supply is required.

Thanks.

-- 
Dmitry

^ permalink raw reply

* [PATCH] Input: mpr121: Drop redundant wakeup handling
From: phucduc.bui @ 2026-03-09  7:14 UTC (permalink / raw)
  To: dmitry.torokhov; +Cc: phucduc.bui, linux-input, linux-kernel

From: bui duc phuc <phucduc.bui@gmail.com>

The driver currently calls device_init_wakeup() and manually toggles
IRQ wake in suspend and resume paths. This is unnecessary since the
I2C core already handles wakeup configuration when the device is
described in Device Tree with the "wakeup-source" property.

Note: Compile-tested only, not verified on hardware.

Signed-off-by: bui duc phuc <phucduc.bui@gmail.com>
---
 drivers/input/keyboard/mpr121_touchkey.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
index bd1a944ded46..47edc161ec77 100644
--- a/drivers/input/keyboard/mpr121_touchkey.c
+++ b/drivers/input/keyboard/mpr121_touchkey.c
@@ -295,8 +295,6 @@ static int mpr_touchkey_probe(struct i2c_client *client)
 		return error;
 
 	i2c_set_clientdata(client, mpr121);
-	device_init_wakeup(dev,
-			device_property_read_bool(dev, "wakeup-source"));
 
 	return 0;
 }
@@ -305,9 +303,6 @@ static int mpr_suspend(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 
-	if (device_may_wakeup(&client->dev))
-		enable_irq_wake(client->irq);
-
 	i2c_smbus_write_byte_data(client, ELECTRODE_CONF_ADDR, 0x00);
 
 	return 0;
@@ -318,9 +313,6 @@ static int mpr_resume(struct device *dev)
 	struct i2c_client *client = to_i2c_client(dev);
 	struct mpr121_touchkey *mpr121 = i2c_get_clientdata(client);
 
-	if (device_may_wakeup(&client->dev))
-		disable_irq_wake(client->irq);
-
 	i2c_smbus_write_byte_data(client, ELECTRODE_CONF_ADDR,
 				  mpr121->keycount);
 
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH v7 1/3] input: trackpoint - Enable doubletap by default on capable devices
From: Ilpo Järvinen @ 2026-03-09  8:01 UTC (permalink / raw)
  To: Vishnu Sankar
  Cc: Mark Pearson, dmitry.torokhov, hmh, Hans de Goede, corbet,
	derekjohn.clark, linux-input, LKML, ibm-acpi-devel, linux-doc,
	platform-driver-x86, vsankar
In-Reply-To: <20260209063355.491189-2-vishnuocv@gmail.com>

On Mon, 9 Feb 2026, Vishnu Sankar wrote:

> Enable doubletap functionality by default on TrackPoint devices that
> support it. The feature is detected using firmware ID pattern matching
> (PNP: LEN03xxx) with a deny list of incompatible devices.
> 
> This provides immediate doubletap functionality without requiring
> userspace configuration. The hardware is enabled during device
> detection, while event filtering continues to be handled by the
> thinkpad_acpi driver as before.
> 
> Signed-off-by: Vishnu Sankar <vishnuocv@gmail.com>
> Suggested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
> Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
> Changes in v7:
> - Removed unwanted comments
> - Removed psmouse_info ()
> 
> Changes in v6:
> - No Changes
> 
> Changes in v5:
> - Renamed function to trackpoint_is_dt_capable()
> - Simplified string comparison without sscanf()
> - Removed wrapper function as suggested
> - Fixed missing period in comment
> 
> Changes in v4:
> - Simplified approach: removed all sysfs attributes and user interface
> - Enable doubletap by default during device detection
> - Removed global variables and complex attribute infrastructure
> - Uses minimal firmware ID detection with deny list
> - Follows KISS principle as suggested by reviewers
> 
> Changes in v3:
> - No changes
> 
> Changes in v2:
> - Improve commit messages
> - Sysfs attributes moved to trackpoint.c
> - Removed unnecessary comments
> - Removed unnecessary debug messages
> - Using strstarts() instead of strcmp()
> - is_trackpoint_dt_capable() modified
> - Removed _BIT suffix and used BIT() define
> - Reverse the trackpoint_doubletap_status() logic to return error first
> - Removed export functions as a result of the design change
> - Changed trackpoint_dev->psmouse to parent_psmouse
> - The path of trackpoint.h is not changed
> ---
>  drivers/input/mouse/trackpoint.c | 45 ++++++++++++++++++++++++++++++++
>  drivers/input/mouse/trackpoint.h |  5 ++++
>  2 files changed, 50 insertions(+)
> 
> diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
> index 5f6643b69a2c..e12d76350252 100644
> --- a/drivers/input/mouse/trackpoint.c
> +++ b/drivers/input/mouse/trackpoint.c
> @@ -393,6 +393,45 @@ static int trackpoint_reconnect(struct psmouse *psmouse)
>  	return 0;
>  }
>  
> +/* List of known incapable device PNP IDs */
> +static const char * const dt_incompatible_devices[] = {
> +	"LEN0304",
> +	"LEN0306",
> +	"LEN0317",
> +	"LEN031A",
> +	"LEN031B",
> +	"LEN031C",
> +	"LEN031D",
> +};
> +
> +/*
> + * Checks if it's a doubletap capable device.
> + * The PNP ID format is "PNP: LEN030d PNP0f13".
> + */
> +static bool trackpoint_is_dt_capable(const char *pnp_id)
> +{
> +	size_t i;
> +
> +	if (!pnp_id)
> +		return false;
> +
> +	/* Must start with "PNP: LEN03" */
> +	if (!strstarts(pnp_id, "PNP: LEN03"))

Missing include.

> +		return false;
> +
> +	/* Ensure enough length before comparing */
> +	if (strlen(pnp_id) < 12)
> +		return false;
> +
> +	/* Check deny-list */
> +	for (i = 0; i < ARRAY_SIZE(dt_incompatible_devices); i++) {

Missing include for ARRAY_SIZE().

> +		if (!strncmp(pnp_id + 5,
> +			     dt_incompatible_devices[i], 7))

Fits to one line.

> +			return false;
> +	}
> +	return true;
> +}
> +
>  int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
>  {
>  	struct ps2dev *ps2dev = &psmouse->ps2dev;
> @@ -470,6 +509,12 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
>  		     psmouse->vendor, firmware_id,
>  		     (button_info & 0xf0) >> 4, button_info & 0x0f);
>  
> +	if (trackpoint_is_dt_capable(ps2dev->serio->firmware_id)) {
> +		error = trackpoint_write(ps2dev, TP_DOUBLETAP, TP_DOUBLETAP_ENABLE);
> +		if (error)
> +			psmouse_warn(psmouse, "Failed to enable doubletap: %d\n", error);
> +	}
> +
>  	return 0;
>  }
>  
> diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h
> index eb5412904fe0..3e03cdb39449 100644
> --- a/drivers/input/mouse/trackpoint.h
> +++ b/drivers/input/mouse/trackpoint.h
> @@ -69,6 +69,8 @@
>  					/* (how hard it is to drag */
>  					/* with Z-axis pressed) */
>  
> +#define TP_DOUBLETAP		0x58	/* TrackPoint doubletap register */
> +
>  #define TP_MINDRAG		0x59	/* Minimum amount of force needed */
>  					/* to trigger dragging */
>  
> @@ -110,6 +112,9 @@
>  					   external device will be forced to 1 */
>  #define TP_MASK_EXT_TAG			0x04
>  
> +/* Doubletap register values */
> +#define TP_DOUBLETAP_ENABLE	0xFF	/* Enable value */
> +#define TP_DOUBLETAP_DISABLE	0xFE	/* Disable value */
>  
>  /* Power on Self Test Results */
>  #define TP_POR_SUCCESS		0x3B
> 

-- 
 i.


^ permalink raw reply

* Re: [PATCH v7 3/3] Documentation: thinkpad-acpi - Document doubletap_enable attribute
From: Ilpo Järvinen @ 2026-03-09  8:03 UTC (permalink / raw)
  To: Vishnu Sankar
  Cc: Mark Pearson, dmitry.torokhov, hmh, Hans de Goede, corbet,
	derekjohn.clark, linux-input, LKML, ibm-acpi-devel, linux-doc,
	platform-driver-x86, vsankar
In-Reply-To: <20260209063355.491189-4-vishnuocv@gmail.com>

On Mon, 9 Feb 2026, Vishnu Sankar wrote:

> Document the doubletap_enable sysfs attribute for ThinkPad ACPI driver.
> 
> Signed-off-by: Vishnu Sankar <vishnuocv@gmail.com>
> ---

> +        * 1 - doubletap events are processed (default)
> +	* 0 - doubletap events are filtered out (ignored)

There's something odd in space vs tab here.

-- 
 i.


^ 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