Linux Input/HID development
 help / color / mirror / Atom feed
* Re: [PATCH v2 3/3] arm64: dts: qcom: sdm845-oneplus: add tri-state-key
From: Caleb Connolly @ 2023-02-19 15:30 UTC (permalink / raw)
  To: Gergo Koteles, Pavel Machek
  Cc: Dmitry Torokhov, Andy Gross, Bjorn Andersson, Konrad Dybcio,
	Rob Herring, Krzysztof Kozlowski, Jiri Kosina, Benjamin Tissoires,
	linux-input, linux-kernel, linux-arm-msm, devicetree
In-Reply-To: <007239f0-1b13-77b9-0d9c-d68747e20331@irl.hu>



On 16/02/2023 03:32, Gergo Koteles wrote:
> Hi,
>
>>
>>
>> On 11/02/2023 16:40, Pavel Machek wrote:
>>> Hi!
>>>
>>>> +++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
>>>> @@ -52,6 +52,43 @@ key-vol-up {
>>>>   		};
>>>>   	};
>>>>
>>>> +	tri-state-key {
>>>> +		compatible = "gpio-keys";
>>>> +		label = "Tri-state key";
>>>> +		pinctrl-names = "default";
>>>> +		pinctrl-0 = <&tri_state_key_default>;
>>>> +		state-top {
>>>> +			label = "Tri-state key top";
>>>
>>> "top/middle" is not too useful. Do we need the label at all? If so,
>>> should it say "loud/vibrations only/mute"?
>>
>> "mute", "vibrate" and "ring" sound good to me.
>>
>
> OnePlus uses the silent/vibrate/ring, iPhone the silent/ring names.
> Maybe silent/vibrate/ring are more familiar.
>
> Adding labels can document these modes here.
> Should we also document these in input-event-codes.h?

Maybe it would be best to define macros for these rather than leave them
as magic numbers
> #define ABS_SND_PROFILE		0x22 /* 0 = silent; 1 = vibrate; 2 = ring */

#define ABS_SND_PROFILE_SILENT	0
#define ABS_SND_PROFILE_VIBRATE	1
#define ABS_SND_PROFILE_RING	2

>
>
> Thanks,
> Gergo
>
>> Although it would be nice if users can easily map the physical key
>> position to the action when viewing the input device or remapping the
>> key in userspace.
>>
>> Do you have any ideas or recommendations on how to do this?
>>>
>>> BR,
>>> 								Pavel
>>
>> --
>> Kind Regards,
>> Caleb
>>
>

--
Kind Regards,
Caleb


^ permalink raw reply

* Re: [PATCH v1 01/17] thermal/core: Add a thermal zone 'devdata' accessor
From: Niklas Söderlund @ 2023-02-19 15:07 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: rafael, linux-pm, linux-kernel, Zhang Rui, Len Brown,
	Damien Le Moal, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, Jean Delvare, Guenter Roeck,
	Jonathan Cameron, Lars-Peter Clausen, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Dmitry Torokhov, Raju Rangoju,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Ido Schimmel, Petr Machata, Gregory Greenman, Kalle Valo,
	Sebastian Reichel, Liam Girdwood, Mark Brown, Miquel Raynal,
	Amit Kucheria, Florian Fainelli,
	Broadcom internal kernel review list, Ray Jui, Scott Branden,
	Markus Mayer, Support Opensource, Andy Gross, Bjorn Andersson,
	Konrad Dybcio, Thara Gopinath, Heiko Stuebner,
	Bartlomiej Zolnierkiewicz, Krzysztof Kozlowski, Alim Akhtar,
	Orson Zhai, Baolin Wang, Chunyan Zhang, Vasily Khoruzhick,
	Yangtao Li, Thierry Reding, Jonathan Hunter, Talel Shenhar,
	Eduardo Valentin, Keerthy, Kunihiko Hayashi, Masami Hiramatsu,
	Matthias Brugger, AngeloGioacchino Del Regno, Stefan Wahren,
	Neil Armstrong, ye xingchen, Zheng Yongjun, Tim Zimmermann,
	Yang Li, Srinivas Pandruvada, Ricardo Neri, Jiang Jian,
	Daniel Golle, Balsam CHIHI, Randy Dunlap, Mikko Perttunen,
	open list:ACPI THERMAL DRIVER,
	open list:LIBATA SUBSYSTEM (Serial and Parallel ATA drivers),
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	open list:HARDWARE MONITORING,
	open list:IIO SUBSYSTEM AND DRIVERS,
	open list:ARM/Allwinner sunXi SoC support,
	open list:INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN)...,
	open list:CXGB4 ETHERNET DRIVER (CXGB4),
	open list:INTEL WIRELESS WIFI LINK (iwlwifi),
	moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE,
	open list:ARM/QUALCOMM SUPPORT,
	open list:RENESAS R-CAR THERMAL DRIVERS,
	open list:ARM/Rockchip SoC support,
	open list:SAMSUNG THERMAL DRIVER,
	open list:TEGRA ARCHITECTURE SUPPORT,
	open list:TI BANDGAP AND THERMAL DRIVER,
	moderated list:ARM/Mediatek SoC support
In-Reply-To: <20230219143657.241542-2-daniel.lezcano@linaro.org>

Hi Daniel,

Thanks for your work.

On 2023-02-19 15:36:41 +0100, Daniel Lezcano wrote:
> The thermal zone device structure is exposed to the different drivers
> and obviously they access the internals while that should be
> restricted to the core thermal code.
> 
> In order to self-encapsulate the thermal core code, we need to prevent
> the drivers accessing directly the thermal zone structure and provide
> accessor functions to deal with.
> 
> Provide an accessor to the 'devdata' structure and make use of it in
> the different drivers.
> 
> No functional changes intended.
> 
> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> ---

...

>  drivers/thermal/rcar_gen3_thermal.c              |  4 ++--
>  drivers/thermal/rcar_thermal.c                   |  3 +--

For R-Car,

Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>

...


> diff --git a/include/linux/thermal.h b/include/linux/thermal.h
> index 2bb4bf33f4f3..724b95662da9 100644
> --- a/include/linux/thermal.h
> +++ b/include/linux/thermal.h
> @@ -365,6 +365,8 @@ thermal_zone_device_register_with_trips(const char *, struct thermal_trip *, int
>  					void *, struct thermal_zone_device_ops *,
>  					struct thermal_zone_params *, int, int);
>  
> +void *thermal_zone_device_get_data(struct thermal_zone_device *tzd);
> +

bikeshedding:

Would it make sens to name this thermal_zone_device_get_priv_data(), 
thermal_zone_device_get_priv() or something like that? To make it more 
explicitly when reading the driver code this fetches the drivers private 
data, and not some data belonging to the zone itself.

>  int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
>  				     struct thermal_cooling_device *,

-- 
Kind Regards,
Niklas Söderlund

^ permalink raw reply

* Re: [PATCH v1 01/17] thermal/core: Add a thermal zone 'devdata' accessor
From: Guenter Roeck @ 2023-02-19 14:56 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: rafael, linux-pm, linux-kernel, Zhang Rui, Len Brown,
	Damien Le Moal, Shawn Guo, Sascha Hauer, Pengutronix Kernel Team,
	Fabio Estevam, NXP Linux Team, Jean Delvare, Jonathan Cameron,
	Lars-Peter Clausen, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Dmitry Torokhov, Raju Rangoju, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Ido Schimmel, Petr Machata,
	Gregory Greenman, Kalle Valo, Sebastian Reichel, Liam Girdwood,
	Mark Brown, Miquel Raynal, Amit Kucheria, Florian Fainelli,
	Broadcom internal kernel review list, Ray Jui, Scott Branden,
	Markus Mayer, Support Opensource, Andy Gross, Bjorn Andersson,
	Konrad Dybcio, Thara Gopinath, Niklas Söderlund,
	Heiko Stuebner, Bartlomiej Zolnierkiewicz, Krzysztof Kozlowski,
	Alim Akhtar, Orson Zhai, Baolin Wang, Chunyan Zhang,
	Vasily Khoruzhick, Yangtao Li, Thierry Reding, Jonathan Hunter,
	Talel Shenhar, Eduardo Valentin, Keerthy, Kunihiko Hayashi,
	Masami Hiramatsu, Matthias Brugger, AngeloGioacchino Del Regno,
	Stefan Wahren, Neil Armstrong, ye xingchen, Zheng Yongjun,
	Tim Zimmermann, Yang Li, Srinivas Pandruvada, Ricardo Neri,
	Jiang Jian, Daniel Golle, Balsam CHIHI, Randy Dunlap,
	Mikko Perttunen, open list:ACPI THERMAL DRIVER,
	open list:LIBATA SUBSYSTEM (Serial and Parallel ATA drivers),
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	open list:HARDWARE MONITORING,
	open list:IIO SUBSYSTEM AND DRIVERS,
	open list:ARM/Allwinner sunXi SoC support,
	open list:INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN)...,
	open list:CXGB4 ETHERNET DRIVER (CXGB4),
	open list:INTEL WIRELESS WIFI LINK (iwlwifi),
	moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE,
	open list:ARM/QUALCOMM SUPPORT,
	open list:RENESAS R-CAR THERMAL DRIVERS,
	open list:ARM/Rockchip SoC support,
	open list:SAMSUNG THERMAL DRIVER,
	open list:TEGRA ARCHITECTURE SUPPORT,
	open list:TI BANDGAP AND THERMAL DRIVER,
	moderated list:ARM/Mediatek SoC support
In-Reply-To: <20230219143657.241542-2-daniel.lezcano@linaro.org>

On Sun, Feb 19, 2023 at 03:36:41PM +0100, Daniel Lezcano wrote:
> The thermal zone device structure is exposed to the different drivers
> and obviously they access the internals while that should be
> restricted to the core thermal code.
> 
> In order to self-encapsulate the thermal core code, we need to prevent
> the drivers accessing directly the thermal zone structure and provide
> accessor functions to deal with.
> 
> Provide an accessor to the 'devdata' structure and make use of it in
> the different drivers.
> 
> No functional changes intended.
> 
> Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
> ---
...
>  drivers/hwmon/hwmon.c                            |  4 ++--
>  drivers/hwmon/pmbus/pmbus_core.c                 |  2 +-
>  drivers/hwmon/scmi-hwmon.c                       |  2 +-
>  drivers/hwmon/scpi-hwmon.c                       |  2 +-

For hwmon:

Acked-by: Guenter Roeck <linux@roeck-us.net>

Guenter

^ permalink raw reply

* [PATCH v1 01/17] thermal/core: Add a thermal zone 'devdata' accessor
From: Daniel Lezcano @ 2023-02-19 14:36 UTC (permalink / raw)
  To: rafael, daniel.lezcano
  Cc: linux-pm, linux-kernel, Zhang Rui, Len Brown, Damien Le Moal,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Jean Delvare, Guenter Roeck, Jonathan Cameron,
	Lars-Peter Clausen, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Dmitry Torokhov, Raju Rangoju, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Ido Schimmel, Petr Machata,
	Gregory Greenman, Kalle Valo, Sebastian Reichel, Liam Girdwood,
	Mark Brown, Miquel Raynal, Amit Kucheria, Florian Fainelli,
	Broadcom internal kernel review list, Ray Jui, Scott Branden,
	Markus Mayer, Support Opensource, Andy Gross, Bjorn Andersson,
	Konrad Dybcio, Thara Gopinath, Niklas Söderlund,
	Heiko Stuebner, Bartlomiej Zolnierkiewicz, Krzysztof Kozlowski,
	Alim Akhtar, Orson Zhai, Baolin Wang, Chunyan Zhang,
	Vasily Khoruzhick, Yangtao Li, Thierry Reding, Jonathan Hunter,
	Talel Shenhar, Eduardo Valentin, Keerthy, Kunihiko Hayashi,
	Masami Hiramatsu, Matthias Brugger, AngeloGioacchino Del Regno,
	Stefan Wahren, Neil Armstrong, ye xingchen, Zheng Yongjun,
	Tim Zimmermann, Yang Li, Srinivas Pandruvada, Ricardo Neri,
	Jiang Jian, Daniel Golle, Balsam CHIHI, Randy Dunlap,
	Mikko Perttunen, open list:ACPI THERMAL DRIVER,
	open list:LIBATA SUBSYSTEM (Serial and Parallel ATA drivers),
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	open list:HARDWARE MONITORING,
	open list:IIO SUBSYSTEM AND DRIVERS,
	open list:ARM/Allwinner sunXi SoC support,
	open list:INPUT (KEYBOARD, MOUSE, JOYSTICK , TOUCHSCREEN)...,
	open list:CXGB4 ETHERNET DRIVER (CXGB4),
	open list:INTEL WIRELESS WIFI LINK (iwlwifi),
	moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE,
	open list:ARM/QUALCOMM SUPPORT,
	open list:RENESAS R-CAR THERMAL DRIVERS,
	open list:ARM/Rockchip SoC support,
	open list:SAMSUNG THERMAL DRIVER,
	open list:TEGRA ARCHITECTURE SUPPORT,
	open list:TI BANDGAP AND THERMAL DRIVER,
	moderated list:ARM/Mediatek SoC support
In-Reply-To: <20230219143657.241542-1-daniel.lezcano@linaro.org>

The thermal zone device structure is exposed to the different drivers
and obviously they access the internals while that should be
restricted to the core thermal code.

In order to self-encapsulate the thermal core code, we need to prevent
the drivers accessing directly the thermal zone structure and provide
accessor functions to deal with.

Provide an accessor to the 'devdata' structure and make use of it in
the different drivers.

No functional changes intended.

Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
 drivers/acpi/thermal.c                           | 16 ++++++++--------
 drivers/ata/ahci_imx.c                           |  2 +-
 drivers/hwmon/hwmon.c                            |  4 ++--
 drivers/hwmon/pmbus/pmbus_core.c                 |  2 +-
 drivers/hwmon/scmi-hwmon.c                       |  2 +-
 drivers/hwmon/scpi-hwmon.c                       |  2 +-
 drivers/iio/adc/sun4i-gpadc-iio.c                |  2 +-
 drivers/input/touchscreen/sun4i-ts.c             |  2 +-
 .../net/ethernet/chelsio/cxgb4/cxgb4_thermal.c   |  2 +-
 .../net/ethernet/mellanox/mlxsw/core_thermal.c   | 14 +++++++-------
 drivers/net/wireless/intel/iwlwifi/mvm/tt.c      |  4 ++--
 drivers/power/supply/power_supply_core.c         |  2 +-
 drivers/regulator/max8973-regulator.c            |  2 +-
 drivers/thermal/armada_thermal.c                 |  4 ++--
 drivers/thermal/broadcom/bcm2711_thermal.c       |  2 +-
 drivers/thermal/broadcom/bcm2835_thermal.c       |  2 +-
 drivers/thermal/broadcom/brcmstb_thermal.c       |  4 ++--
 drivers/thermal/broadcom/ns-thermal.c            |  2 +-
 drivers/thermal/broadcom/sr-thermal.c            |  2 +-
 drivers/thermal/da9062-thermal.c                 |  2 +-
 drivers/thermal/dove_thermal.c                   |  2 +-
 drivers/thermal/hisi_thermal.c                   |  2 +-
 drivers/thermal/imx8mm_thermal.c                 |  2 +-
 drivers/thermal/imx_sc_thermal.c                 |  2 +-
 drivers/thermal/imx_thermal.c                    |  6 +++---
 drivers/thermal/intel/intel_pch_thermal.c        |  2 +-
 drivers/thermal/intel/intel_soc_dts_iosf.c       | 13 +++++--------
 drivers/thermal/intel/x86_pkg_temp_thermal.c     |  4 ++--
 drivers/thermal/k3_bandgap.c                     |  2 +-
 drivers/thermal/k3_j72xx_bandgap.c               |  2 +-
 drivers/thermal/kirkwood_thermal.c               |  2 +-
 drivers/thermal/max77620_thermal.c               |  2 +-
 drivers/thermal/mediatek/auxadc_thermal.c        |  2 +-
 drivers/thermal/mediatek/lvts_thermal.c          |  4 ++--
 drivers/thermal/qcom/qcom-spmi-adc-tm5.c         |  4 ++--
 drivers/thermal/qcom/qcom-spmi-temp-alarm.c      |  4 ++--
 drivers/thermal/qoriq_thermal.c                  |  2 +-
 drivers/thermal/rcar_gen3_thermal.c              |  4 ++--
 drivers/thermal/rcar_thermal.c                   |  3 +--
 drivers/thermal/rockchip_thermal.c               |  4 ++--
 drivers/thermal/rzg2l_thermal.c                  |  2 +-
 drivers/thermal/samsung/exynos_tmu.c             |  4 ++--
 drivers/thermal/spear_thermal.c                  |  8 ++++----
 drivers/thermal/sprd_thermal.c                   |  2 +-
 drivers/thermal/sun8i_thermal.c                  |  2 +-
 drivers/thermal/tegra/tegra-bpmp-thermal.c       |  6 ++++--
 drivers/thermal/tegra/tegra30-tsensor.c          |  4 ++--
 drivers/thermal/thermal-generic-adc.c            |  2 +-
 drivers/thermal/thermal_core.c                   |  6 ++++++
 drivers/thermal/thermal_mmio.c                   |  2 +-
 .../thermal/ti-soc-thermal/ti-thermal-common.c   |  4 ++--
 drivers/thermal/uniphier_thermal.c               |  2 +-
 include/linux/thermal.h                          |  2 ++
 53 files changed, 97 insertions(+), 91 deletions(-)

diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 0b4b844f9d4c..69d0da6456d5 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -498,7 +498,7 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
 
 static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
 {
-	struct acpi_thermal *tz = thermal->devdata;
+	struct acpi_thermal *tz = thermal_zone_device_get_data(thermal);
 	int result;
 
 	if (!tz)
@@ -516,7 +516,7 @@ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
 static int thermal_get_trip_type(struct thermal_zone_device *thermal,
 				 int trip, enum thermal_trip_type *type)
 {
-	struct acpi_thermal *tz = thermal->devdata;
+	struct acpi_thermal *tz = thermal_zone_device_get_data(thermal);
 	int i;
 
 	if (!tz || trip < 0)
@@ -560,7 +560,7 @@ static int thermal_get_trip_type(struct thermal_zone_device *thermal,
 static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
 				 int trip, int *temp)
 {
-	struct acpi_thermal *tz = thermal->devdata;
+	struct acpi_thermal *tz = thermal_zone_device_get_data(thermal);
 	int i;
 
 	if (!tz || trip < 0)
@@ -613,7 +613,7 @@ static int thermal_get_trip_temp(struct thermal_zone_device *thermal,
 static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
 				int *temperature)
 {
-	struct acpi_thermal *tz = thermal->devdata;
+	struct acpi_thermal *tz = thermal_zone_device_get_data(thermal);
 
 	if (tz->trips.critical.flags.valid) {
 		*temperature = deci_kelvin_to_millicelsius_with_offset(
@@ -628,7 +628,7 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
 static int thermal_get_trend(struct thermal_zone_device *thermal,
 			     int trip, enum thermal_trend *trend)
 {
-	struct acpi_thermal *tz = thermal->devdata;
+	struct acpi_thermal *tz = thermal_zone_device_get_data(thermal);
 	enum thermal_trip_type type;
 	int i;
 
@@ -670,7 +670,7 @@ static int thermal_get_trend(struct thermal_zone_device *thermal,
 
 static void acpi_thermal_zone_device_hot(struct thermal_zone_device *thermal)
 {
-	struct acpi_thermal *tz = thermal->devdata;
+	struct acpi_thermal *tz = thermal_zone_device_get_data(thermal);
 
 	acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
 					dev_name(&tz->device->dev),
@@ -679,7 +679,7 @@ static void acpi_thermal_zone_device_hot(struct thermal_zone_device *thermal)
 
 static void acpi_thermal_zone_device_critical(struct thermal_zone_device *thermal)
 {
-	struct acpi_thermal *tz = thermal->devdata;
+	struct acpi_thermal *tz = thermal_zone_device_get_data(thermal);
 
 	acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
 					dev_name(&tz->device->dev),
@@ -693,7 +693,7 @@ static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
 					  bool bind)
 {
 	struct acpi_device *device = cdev->devdata;
-	struct acpi_thermal *tz = thermal->devdata;
+	struct acpi_thermal *tz = thermal_zone_device_get_data(thermal);
 	struct acpi_device *dev;
 	acpi_handle handle;
 	int i;
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index a950767f7948..0ef928528aec 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -418,7 +418,7 @@ static int __sata_ahci_read_temperature(void *dev, int *temp)
 
 static int sata_ahci_read_temperature(struct thermal_zone_device *tz, int *temp)
 {
-	return __sata_ahci_read_temperature(tz->devdata, temp);
+	return __sata_ahci_read_temperature(thermal_zone_device_get_data(tz), temp);
 }
 
 static ssize_t sata_ahci_show_temp(struct device *dev,
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 33edb5c02f7d..b33477d04c2b 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -154,7 +154,7 @@ static DEFINE_IDA(hwmon_ida);
 #ifdef CONFIG_THERMAL_OF
 static int hwmon_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct hwmon_thermal_data *tdata = tz->devdata;
+	struct hwmon_thermal_data *tdata = thermal_zone_device_get_data(tz);
 	struct hwmon_device *hwdev = to_hwmon_device(tdata->dev);
 	int ret;
 	long t;
@@ -171,7 +171,7 @@ static int hwmon_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 
 static int hwmon_thermal_set_trips(struct thermal_zone_device *tz, int low, int high)
 {
-	struct hwmon_thermal_data *tdata = tz->devdata;
+	struct hwmon_thermal_data *tdata = thermal_zone_device_get_data(tz);
 	struct hwmon_device *hwdev = to_hwmon_device(tdata->dev);
 	const struct hwmon_chip_info *chip = hwdev->chip;
 	const struct hwmon_channel_info **info = chip->info;
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 95e95783972a..159a88af6277 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -1272,7 +1272,7 @@ struct pmbus_thermal_data {
 
 static int pmbus_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct pmbus_thermal_data *tdata = tz->devdata;
+	struct pmbus_thermal_data *tdata = thermal_zone_device_get_data(tz);
 	struct pmbus_sensor *sensor = tdata->sensor;
 	struct pmbus_data *pmbus_data = tdata->pmbus_data;
 	struct i2c_client *client = to_i2c_client(pmbus_data->dev);
diff --git a/drivers/hwmon/scmi-hwmon.c b/drivers/hwmon/scmi-hwmon.c
index e192f0c67146..7951b6026f48 100644
--- a/drivers/hwmon/scmi-hwmon.c
+++ b/drivers/hwmon/scmi-hwmon.c
@@ -141,7 +141,7 @@ static int scmi_hwmon_thermal_get_temp(struct thermal_zone_device *tz,
 {
 	int ret;
 	long value;
-	struct scmi_thermal_sensor *th_sensor = tz->devdata;
+	struct scmi_thermal_sensor *th_sensor = thermal_zone_device_get_data(tz);
 
 	ret = scmi_hwmon_read_scaled_value(th_sensor->ph, th_sensor->info,
 					   &value);
diff --git a/drivers/hwmon/scpi-hwmon.c b/drivers/hwmon/scpi-hwmon.c
index 4d75385f7d5e..efe0ddbc5293 100644
--- a/drivers/hwmon/scpi-hwmon.c
+++ b/drivers/hwmon/scpi-hwmon.c
@@ -64,7 +64,7 @@ static void scpi_scale_reading(u64 *value, struct sensor_data *sensor)
 
 static int scpi_read_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct scpi_thermal_zone *zone = tz->devdata;
+	struct scpi_thermal_zone *zone = thermal_zone_device_get_data(tz);
 	struct scpi_sensors *scpi_sensors = zone->scpi_sensors;
 	struct scpi_ops *scpi_ops = scpi_sensors->scpi_ops;
 	struct sensor_data *sensor = &scpi_sensors->data[zone->sensor_id];
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index a6ade70dedf8..e24ac3ee8a35 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -414,7 +414,7 @@ static int sun4i_gpadc_runtime_resume(struct device *dev)
 
 static int sun4i_gpadc_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct sun4i_gpadc_iio *info = tz->devdata;
+	struct sun4i_gpadc_iio *info = thermal_zone_device_get_data(tz);
 	int val, scale, offset;
 
 	if (sun4i_gpadc_temp_read(info->indio_dev, &val))
diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c
index 73eb8f80be6e..5e5434ffe397 100644
--- a/drivers/input/touchscreen/sun4i-ts.c
+++ b/drivers/input/touchscreen/sun4i-ts.c
@@ -194,7 +194,7 @@ static int sun4i_get_temp(const struct sun4i_ts_data *ts, int *temp)
 
 static int sun4i_get_tz_temp(struct thermal_zone_device *tz, int *temp)
 {
-	return sun4i_get_temp(tz->devdata, temp);
+	return sun4i_get_temp(thermal_zone_device_get_data(tz), temp);
 }
 
 static const struct thermal_zone_device_ops sun4i_ts_tz_ops = {
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c
index 95e1b415ba13..8b0d318feef4 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_thermal.c
@@ -12,7 +12,7 @@
 static int cxgb4_thermal_get_temp(struct thermal_zone_device *tzdev,
 				  int *temp)
 {
-	struct adapter *adap = tzdev->devdata;
+	struct adapter *adap = thermal_zone_device_get_data(tzdev);
 	u32 param, val;
 	int ret;
 
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
index c5240d38c9db..228b6ffaef98 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_thermal.c
@@ -201,7 +201,7 @@ mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
 static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
 			      struct thermal_cooling_device *cdev)
 {
-	struct mlxsw_thermal *thermal = tzdev->devdata;
+	struct mlxsw_thermal *thermal = thermal_zone_device_get_data(tzdev);
 	struct device *dev = thermal->bus_info->dev;
 	int i, err;
 
@@ -227,7 +227,7 @@ static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
 static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
 				struct thermal_cooling_device *cdev)
 {
-	struct mlxsw_thermal *thermal = tzdev->devdata;
+	struct mlxsw_thermal *thermal = thermal_zone_device_get_data(tzdev);
 	struct device *dev = thermal->bus_info->dev;
 	int i;
 	int err;
@@ -249,7 +249,7 @@ static int mlxsw_thermal_unbind(struct thermal_zone_device *tzdev,
 static int mlxsw_thermal_get_temp(struct thermal_zone_device *tzdev,
 				  int *p_temp)
 {
-	struct mlxsw_thermal *thermal = tzdev->devdata;
+	struct mlxsw_thermal *thermal = thermal_zone_device_get_data(tzdev);
 	struct device *dev = thermal->bus_info->dev;
 	char mtmp_pl[MLXSW_REG_MTMP_LEN];
 	int temp;
@@ -281,7 +281,7 @@ static struct thermal_zone_device_ops mlxsw_thermal_ops = {
 static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
 				     struct thermal_cooling_device *cdev)
 {
-	struct mlxsw_thermal_module *tz = tzdev->devdata;
+	struct mlxsw_thermal_module *tz = thermal_zone_device_get_data(tzdev);
 	struct mlxsw_thermal *thermal = tz->parent;
 	int i, j, err;
 
@@ -310,7 +310,7 @@ static int mlxsw_thermal_module_bind(struct thermal_zone_device *tzdev,
 static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
 				       struct thermal_cooling_device *cdev)
 {
-	struct mlxsw_thermal_module *tz = tzdev->devdata;
+	struct mlxsw_thermal_module *tz = thermal_zone_device_get_data(tzdev);
 	struct mlxsw_thermal *thermal = tz->parent;
 	int i;
 	int err;
@@ -356,7 +356,7 @@ mlxsw_thermal_module_temp_and_thresholds_get(struct mlxsw_core *core,
 static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
 					 int *p_temp)
 {
-	struct mlxsw_thermal_module *tz = tzdev->devdata;
+	struct mlxsw_thermal_module *tz = thermal_zone_device_get_data(tzdev);
 	struct mlxsw_thermal *thermal = tz->parent;
 	int temp, crit_temp, emerg_temp;
 	struct device *dev;
@@ -391,7 +391,7 @@ static struct thermal_zone_device_ops mlxsw_thermal_module_ops = {
 static int mlxsw_thermal_gearbox_temp_get(struct thermal_zone_device *tzdev,
 					  int *p_temp)
 {
-	struct mlxsw_thermal_module *tz = tzdev->devdata;
+	struct mlxsw_thermal_module *tz = thermal_zone_device_get_data(tzdev);
 	struct mlxsw_thermal *thermal = tz->parent;
 	char mtmp_pl[MLXSW_REG_MTMP_LEN];
 	u16 index;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
index 232c200af38f..ee8fee29107f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
@@ -615,7 +615,7 @@ int iwl_mvm_send_temp_report_ths_cmd(struct iwl_mvm *mvm)
 static int iwl_mvm_tzone_get_temp(struct thermal_zone_device *device,
 				  int *temperature)
 {
-	struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata;
+	struct iwl_mvm *mvm = thermal_zone_device_get_data(device);
 	int ret;
 	int temp;
 
@@ -641,7 +641,7 @@ static int iwl_mvm_tzone_get_temp(struct thermal_zone_device *device,
 static int iwl_mvm_tzone_set_trip_temp(struct thermal_zone_device *device,
 				       int trip, int temp)
 {
-	struct iwl_mvm *mvm = (struct iwl_mvm *)device->devdata;
+	struct iwl_mvm *mvm = thermal_zone_device_get_data(device);
 	struct iwl_mvm_thermal_device *tzone;
 	int ret;
 
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index 7c790c41e2fe..166f0aacc797 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -1142,7 +1142,7 @@ static int power_supply_read_temp(struct thermal_zone_device *tzd,
 	int ret;
 
 	WARN_ON(tzd == NULL);
-	psy = tzd->devdata;
+	psy = thermal_zone_device_get_data(tzd);
 	ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_TEMP, &val);
 	if (ret)
 		return ret;
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
index 7e00a45db26a..ccacba66d367 100644
--- a/drivers/regulator/max8973-regulator.c
+++ b/drivers/regulator/max8973-regulator.c
@@ -436,7 +436,7 @@ static int max8973_init_dcdc(struct max8973_chip *max,
 
 static int max8973_thermal_read_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct max8973_chip *mchip = tz->devdata;
+	struct max8973_chip *mchip = thermal_zone_device_get_data(tz);
 	unsigned int val;
 	int ret;
 
diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c
index 2efc222a379b..82d3e15d51f6 100644
--- a/drivers/thermal/armada_thermal.c
+++ b/drivers/thermal/armada_thermal.c
@@ -398,7 +398,7 @@ static int armada_read_sensor(struct armada_thermal_priv *priv, int *temp)
 static int armada_get_temp_legacy(struct thermal_zone_device *thermal,
 				  int *temp)
 {
-	struct armada_thermal_priv *priv = thermal->devdata;
+	struct armada_thermal_priv *priv = thermal_zone_device_get_data(thermal);
 	int ret;
 
 	/* Valid check */
@@ -420,7 +420,7 @@ static struct thermal_zone_device_ops legacy_ops = {
 
 static int armada_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct armada_thermal_sensor *sensor = tz->devdata;
+	struct armada_thermal_sensor *sensor = thermal_zone_device_get_data(tz);
 	struct armada_thermal_priv *priv = sensor->priv;
 	int ret;
 
diff --git a/drivers/thermal/broadcom/bcm2711_thermal.c b/drivers/thermal/broadcom/bcm2711_thermal.c
index 1f8651d15160..18b1a4d9ecc7 100644
--- a/drivers/thermal/broadcom/bcm2711_thermal.c
+++ b/drivers/thermal/broadcom/bcm2711_thermal.c
@@ -33,7 +33,7 @@ struct bcm2711_thermal_priv {
 
 static int bcm2711_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct bcm2711_thermal_priv *priv = tz->devdata;
+	struct bcm2711_thermal_priv *priv = thermal_zone_device_get_data(tz);
 	int slope = thermal_zone_get_slope(tz);
 	int offset = thermal_zone_get_offset(tz);
 	u32 val;
diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c
index 23918bb76ae6..de2f573863da 100644
--- a/drivers/thermal/broadcom/bcm2835_thermal.c
+++ b/drivers/thermal/broadcom/bcm2835_thermal.c
@@ -90,7 +90,7 @@ static int bcm2835_thermal_temp2adc(int temp, int offset, int slope)
 
 static int bcm2835_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct bcm2835_thermal_data *data = tz->devdata;
+	struct bcm2835_thermal_data *data = thermal_zone_device_get_data(tz);
 	u32 val = readl(data->regs + BCM2835_TS_TSENSSTAT);
 
 	if (!(val & BCM2835_TS_TSENSSTAT_VALID))
diff --git a/drivers/thermal/broadcom/brcmstb_thermal.c b/drivers/thermal/broadcom/brcmstb_thermal.c
index 4d02c28331e3..668cdc16b108 100644
--- a/drivers/thermal/broadcom/brcmstb_thermal.c
+++ b/drivers/thermal/broadcom/brcmstb_thermal.c
@@ -152,7 +152,7 @@ static inline u32 avs_tmon_temp_to_code(struct brcmstb_thermal_priv *priv,
 
 static int brcmstb_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct brcmstb_thermal_priv *priv = tz->devdata;
+	struct brcmstb_thermal_priv *priv = thermal_zone_device_get_data(tz);
 	u32 val;
 	long t;
 
@@ -262,7 +262,7 @@ static irqreturn_t brcmstb_tmon_irq_thread(int irq, void *data)
 
 static int brcmstb_set_trips(struct thermal_zone_device *tz, int low, int high)
 {
-	struct brcmstb_thermal_priv *priv = tz->devdata;
+	struct brcmstb_thermal_priv *priv = thermal_zone_device_get_data(tz);
 
 	dev_dbg(priv->dev, "set trips %d <--> %d\n", low, high);
 
diff --git a/drivers/thermal/broadcom/ns-thermal.c b/drivers/thermal/broadcom/ns-thermal.c
index 07a8a3f49bd0..98296019ad4c 100644
--- a/drivers/thermal/broadcom/ns-thermal.c
+++ b/drivers/thermal/broadcom/ns-thermal.c
@@ -16,7 +16,7 @@
 
 static int ns_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	void __iomem *pvtmon = tz->devdata;
+	void __iomem *pvtmon = thermal_zone_device_get_data(tz);
 	int offset = thermal_zone_get_offset(tz);
 	int slope = thermal_zone_get_slope(tz);
 	u32 val;
diff --git a/drivers/thermal/broadcom/sr-thermal.c b/drivers/thermal/broadcom/sr-thermal.c
index 2b93502543ff..42b46125f409 100644
--- a/drivers/thermal/broadcom/sr-thermal.c
+++ b/drivers/thermal/broadcom/sr-thermal.c
@@ -32,7 +32,7 @@ struct sr_thermal {
 
 static int sr_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct sr_tmon *tmon = tz->devdata;
+	struct sr_tmon *tmon = thermal_zone_device_get_data(tz);
 	struct sr_thermal *sr_thermal = tmon->priv;
 
 	*temp = readl(sr_thermal->regs + SR_TMON_TEMP_BASE(tmon->tmon_id));
diff --git a/drivers/thermal/da9062-thermal.c b/drivers/thermal/da9062-thermal.c
index a805a6666c44..3d937f701e0b 100644
--- a/drivers/thermal/da9062-thermal.c
+++ b/drivers/thermal/da9062-thermal.c
@@ -123,7 +123,7 @@ static irqreturn_t da9062_thermal_irq_handler(int irq, void *data)
 static int da9062_thermal_get_temp(struct thermal_zone_device *z,
 				   int *temp)
 {
-	struct da9062_thermal *thermal = z->devdata;
+	struct da9062_thermal *thermal = thermal_zone_device_get_data(z);
 
 	mutex_lock(&thermal->lock);
 	*temp = thermal->temperature;
diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c
index 056622a58d00..ed7d1173d9fd 100644
--- a/drivers/thermal/dove_thermal.c
+++ b/drivers/thermal/dove_thermal.c
@@ -87,7 +87,7 @@ static int dove_get_temp(struct thermal_zone_device *thermal,
 			  int *temp)
 {
 	unsigned long reg;
-	struct dove_thermal_priv *priv = thermal->devdata;
+	struct dove_thermal_priv *priv = thermal_zone_device_get_data(thermal);
 
 	/* Valid check */
 	reg = readl_relaxed(priv->control + PMU_TEMP_DIOD_CTRL1_REG);
diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c
index 32a7c3cf073d..043751e6a31d 100644
--- a/drivers/thermal/hisi_thermal.c
+++ b/drivers/thermal/hisi_thermal.c
@@ -431,7 +431,7 @@ static int hi3660_thermal_probe(struct hisi_thermal_data *data)
 
 static int hisi_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct hisi_thermal_sensor *sensor = tz->devdata;
+	struct hisi_thermal_sensor *sensor = thermal_zone_device_get_data(tz);
 	struct hisi_thermal_data *data = sensor->data;
 
 	*temp = data->ops->get_temp(sensor);
diff --git a/drivers/thermal/imx8mm_thermal.c b/drivers/thermal/imx8mm_thermal.c
index 72b5d6f319c1..750240f4fa32 100644
--- a/drivers/thermal/imx8mm_thermal.c
+++ b/drivers/thermal/imx8mm_thermal.c
@@ -141,7 +141,7 @@ static int imx8mp_tmu_get_temp(void *data, int *temp)
 
 static int tmu_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct tmu_sensor *sensor = tz->devdata;
+	struct tmu_sensor *sensor = thermal_zone_device_get_data(tz);
 	struct imx8mm_tmu *tmu = sensor->priv;
 
 	return tmu->socdata->get_temp(sensor, temp);
diff --git a/drivers/thermal/imx_sc_thermal.c b/drivers/thermal/imx_sc_thermal.c
index f32e59e74623..ca10d6a68f0f 100644
--- a/drivers/thermal/imx_sc_thermal.c
+++ b/drivers/thermal/imx_sc_thermal.c
@@ -46,7 +46,7 @@ static int imx_sc_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 {
 	struct imx_sc_msg_misc_get_temp msg;
 	struct imx_sc_rpc_msg *hdr = &msg.hdr;
-	struct imx_sc_sensor *sensor = tz->devdata;
+	struct imx_sc_sensor *sensor = thermal_zone_device_get_data(tz);
 	int ret;
 
 	msg.data.req.resource_id = sensor->resource_id;
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index fb0d5cab70af..c3c14cd26aee 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -252,7 +252,7 @@ static void imx_set_alarm_temp(struct imx_thermal_data *data,
 
 static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct imx_thermal_data *data = tz->devdata;
+	struct imx_thermal_data *data = thermal_zone_device_get_data(tz);
 	const struct thermal_soc_data *soc_data = data->socdata;
 	struct regmap *map = data->tempmon;
 	unsigned int n_meas;
@@ -311,7 +311,7 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
 static int imx_change_mode(struct thermal_zone_device *tz,
 			   enum thermal_device_mode mode)
 {
-	struct imx_thermal_data *data = tz->devdata;
+	struct imx_thermal_data *data = thermal_zone_device_get_data(tz);
 
 	if (mode == THERMAL_DEVICE_ENABLED) {
 		pm_runtime_get(data->dev);
@@ -342,7 +342,7 @@ static int imx_get_crit_temp(struct thermal_zone_device *tz, int *temp)
 static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
 			     int temp)
 {
-	struct imx_thermal_data *data = tz->devdata;
+	struct imx_thermal_data *data = thermal_zone_device_get_data(tz);
 	int ret;
 
 	ret = pm_runtime_resume_and_get(data->dev);
diff --git a/drivers/thermal/intel/intel_pch_thermal.c b/drivers/thermal/intel/intel_pch_thermal.c
index b855d031a855..e53f8a8c06e5 100644
--- a/drivers/thermal/intel/intel_pch_thermal.c
+++ b/drivers/thermal/intel/intel_pch_thermal.c
@@ -119,7 +119,7 @@ static int pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd, int trip)
 
 static int pch_thermal_get_temp(struct thermal_zone_device *tzd, int *temp)
 {
-	struct pch_thermal_device *ptd = tzd->devdata;
+	struct pch_thermal_device *ptd = thermal_zone_device_get_data(tzd);
 
 	*temp = GET_WPT_TEMP(WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TEMP));
 	return 0;
diff --git a/drivers/thermal/intel/intel_soc_dts_iosf.c b/drivers/thermal/intel/intel_soc_dts_iosf.c
index 8c26f7b2316b..f7d995722e04 100644
--- a/drivers/thermal/intel/intel_soc_dts_iosf.c
+++ b/drivers/thermal/intel/intel_soc_dts_iosf.c
@@ -54,7 +54,7 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip,
 	struct intel_soc_dts_sensor_entry *dts;
 	struct intel_soc_dts_sensors *sensors;
 
-	dts = tzd->devdata;
+	dts = thermal_zone_device_get_data(tzd);
 	sensors = dts->sensors;
 	mutex_lock(&sensors->dts_update_lock);
 	status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
@@ -168,7 +168,7 @@ static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts,
 static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
 			     int temp)
 {
-	struct intel_soc_dts_sensor_entry *dts = tzd->devdata;
+	struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_get_data(tzd);
 	struct intel_soc_dts_sensors *sensors = dts->sensors;
 	int status;
 
@@ -176,7 +176,7 @@ static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
 		return -EINVAL;
 
 	mutex_lock(&sensors->dts_update_lock);
-	status = update_trip_temp(tzd->devdata, trip, temp,
+	status = update_trip_temp(dts, trip, temp,
 				  dts->trip_types[trip]);
 	mutex_unlock(&sensors->dts_update_lock);
 
@@ -186,9 +186,7 @@ static int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
 static int sys_get_trip_type(struct thermal_zone_device *tzd,
 			     int trip, enum thermal_trip_type *type)
 {
-	struct intel_soc_dts_sensor_entry *dts;
-
-	dts = tzd->devdata;
+	struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_get_data(tzd);
 
 	*type = dts->trip_types[trip];
 
@@ -200,11 +198,10 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd,
 {
 	int status;
 	u32 out;
-	struct intel_soc_dts_sensor_entry *dts;
+	struct intel_soc_dts_sensor_entry *dts = thermal_zone_device_get_data(tzd);
 	struct intel_soc_dts_sensors *sensors;
 	unsigned long raw;
 
-	dts = tzd->devdata;
 	sensors = dts->sensors;
 	status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
 			       SOC_DTS_OFFSET_TEMP, &out);
diff --git a/drivers/thermal/intel/x86_pkg_temp_thermal.c b/drivers/thermal/intel/x86_pkg_temp_thermal.c
index 1c2de84742df..22f0f206d8f2 100644
--- a/drivers/thermal/intel/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/intel/x86_pkg_temp_thermal.c
@@ -107,7 +107,7 @@ static struct zone_device *pkg_temp_thermal_get_dev(unsigned int cpu)
 
 static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
 {
-	struct zone_device *zonedev = tzd->devdata;
+	struct zone_device *zonedev = thermal_zone_device_get_data(tzd);
 	int val;
 
 	val = intel_tcc_get_temp(zonedev->cpu, true);
@@ -122,7 +122,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
 static int
 sys_set_trip_temp(struct thermal_zone_device *tzd, int trip, int temp)
 {
-	struct zone_device *zonedev = tzd->devdata;
+	struct zone_device *zonedev = thermal_zone_device_get_data(tzd);
 	u32 l, h, mask, shift, intr;
 	int tj_max, ret;
 
diff --git a/drivers/thermal/k3_bandgap.c b/drivers/thermal/k3_bandgap.c
index 22c9bcb899c3..8cbd7361b492 100644
--- a/drivers/thermal/k3_bandgap.c
+++ b/drivers/thermal/k3_bandgap.c
@@ -141,7 +141,7 @@ static int k3_bgp_read_temp(struct k3_thermal_data *devdata,
 
 static int k3_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct k3_thermal_data *data = tz->devdata;
+	struct k3_thermal_data *data = thermal_zone_device_get_data(tz);
 	int ret = 0;
 
 	ret = k3_bgp_read_temp(data, temp);
diff --git a/drivers/thermal/k3_j72xx_bandgap.c b/drivers/thermal/k3_j72xx_bandgap.c
index 031ea1091909..300a3f985776 100644
--- a/drivers/thermal/k3_j72xx_bandgap.c
+++ b/drivers/thermal/k3_j72xx_bandgap.c
@@ -248,7 +248,7 @@ static inline int k3_bgp_read_temp(struct k3_thermal_data *devdata,
 /* Get temperature callback function for thermal zone */
 static int k3_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	return k3_bgp_read_temp(tz->devdata, temp);
+	return k3_bgp_read_temp(thermal_zone_device_get_data(tz), temp);
 }
 
 static const struct thermal_zone_device_ops k3_of_thermal_ops = {
diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c
index bec7ec20e79d..8e39c875ba58 100644
--- a/drivers/thermal/kirkwood_thermal.c
+++ b/drivers/thermal/kirkwood_thermal.c
@@ -27,7 +27,7 @@ static int kirkwood_get_temp(struct thermal_zone_device *thermal,
 			  int *temp)
 {
 	unsigned long reg;
-	struct kirkwood_thermal_priv *priv = thermal->devdata;
+	struct kirkwood_thermal_priv *priv = thermal_zone_device_get_data(thermal);
 
 	reg = readl_relaxed(priv->sensor);
 
diff --git a/drivers/thermal/max77620_thermal.c b/drivers/thermal/max77620_thermal.c
index 6451a55eb582..05b6e9a2a283 100644
--- a/drivers/thermal/max77620_thermal.c
+++ b/drivers/thermal/max77620_thermal.c
@@ -46,7 +46,7 @@ struct max77620_therm_info {
 
 static int max77620_thermal_read_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct max77620_therm_info *mtherm = tz->devdata;
+	struct max77620_therm_info *mtherm = thermal_zone_device_get_data(tz);
 	unsigned int val;
 	int ret;
 
diff --git a/drivers/thermal/mediatek/auxadc_thermal.c b/drivers/thermal/mediatek/auxadc_thermal.c
index ab730f9552d0..d7bf725d224b 100644
--- a/drivers/thermal/mediatek/auxadc_thermal.c
+++ b/drivers/thermal/mediatek/auxadc_thermal.c
@@ -763,7 +763,7 @@ static int mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
 
 static int mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
 {
-	struct mtk_thermal *mt = tz->devdata;
+	struct mtk_thermal *mt = thermal_zone_device_get_data(tz);
 	int i;
 	int tempmax = INT_MIN;
 
diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c
index 84ba65a27acf..86d280187c83 100644
--- a/drivers/thermal/mediatek/lvts_thermal.c
+++ b/drivers/thermal/mediatek/lvts_thermal.c
@@ -252,7 +252,7 @@ static u32 lvts_temp_to_raw(int temperature)
 
 static int lvts_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct lvts_sensor *lvts_sensor = tz->devdata;
+	struct lvts_sensor *lvts_sensor = thermal_zone_device_get_data(tz);
 	void __iomem *msr = lvts_sensor->msr;
 	u32 value;
 
@@ -290,7 +290,7 @@ static int lvts_get_temp(struct thermal_zone_device *tz, int *temp)
 
 static int lvts_set_trips(struct thermal_zone_device *tz, int low, int high)
 {
-	struct lvts_sensor *lvts_sensor = tz->devdata;
+	struct lvts_sensor *lvts_sensor = thermal_zone_device_get_data(tz);
 	void __iomem *base = lvts_sensor->base;
 	u32 raw_low = lvts_temp_to_raw(low);
 	u32 raw_high = lvts_temp_to_raw(high);
diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
index 31164ade2dd1..b0269daf128a 100644
--- a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
+++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
@@ -360,7 +360,7 @@ static irqreturn_t adc_tm5_gen2_isr(int irq, void *data)
 
 static int adc_tm5_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct adc_tm5_channel *channel = tz->devdata;
+	struct adc_tm5_channel *channel = thermal_zone_device_get_data(tz);
 	int ret;
 
 	if (!channel || !channel->iio)
@@ -642,7 +642,7 @@ static int adc_tm5_gen2_configure(struct adc_tm5_channel *channel, int low, int
 
 static int adc_tm5_set_trips(struct thermal_zone_device *tz, int low, int high)
 {
-	struct adc_tm5_channel *channel = tz->devdata;
+	struct adc_tm5_channel *channel = thermal_zone_device_get_data(tz);
 	struct adc_tm5_chip *chip;
 	int ret;
 
diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
index 101c75d0e13f..c817b03deb00 100644
--- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
+++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
@@ -187,7 +187,7 @@ static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip)
 
 static int qpnp_tm_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct qpnp_tm_chip *chip = tz->devdata;
+	struct qpnp_tm_chip *chip = thermal_zone_device_get_data(tz);
 	int ret, mili_celsius;
 
 	if (!temp)
@@ -265,7 +265,7 @@ static int qpnp_tm_update_critical_trip_temp(struct qpnp_tm_chip *chip,
 
 static int qpnp_tm_set_trip_temp(struct thermal_zone_device *tz, int trip_id, int temp)
 {
-	struct qpnp_tm_chip *chip = tz->devdata;
+	struct qpnp_tm_chip *chip = thermal_zone_device_get_data(tz);
 	struct thermal_trip trip;
 	int ret;
 
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index 431c29c0898a..8b6fe0c9ade2 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -83,7 +83,7 @@ static struct qoriq_tmu_data *qoriq_sensor_to_data(struct qoriq_sensor *s)
 
 static int tmu_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct qoriq_sensor *qsensor = tz->devdata;
+	struct qoriq_sensor *qsensor = thermal_zone_device_get_data(tz);
 	struct qoriq_tmu_data *qdata = qoriq_sensor_to_data(qsensor);
 	u32 val;
 	/*
diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c
index d6b5b59c5c53..8ad713cb4bf7 100644
--- a/drivers/thermal/rcar_gen3_thermal.c
+++ b/drivers/thermal/rcar_gen3_thermal.c
@@ -167,7 +167,7 @@ static int rcar_gen3_thermal_round(int temp)
 
 static int rcar_gen3_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct rcar_gen3_thermal_tsc *tsc = tz->devdata;
+	struct rcar_gen3_thermal_tsc *tsc = thermal_zone_device_get_data(tz);
 	int mcelsius, val;
 	int reg;
 
@@ -206,7 +206,7 @@ static int rcar_gen3_thermal_mcelsius_to_temp(struct rcar_gen3_thermal_tsc *tsc,
 
 static int rcar_gen3_thermal_set_trips(struct thermal_zone_device *tz, int low, int high)
 {
-	struct rcar_gen3_thermal_tsc *tsc = tz->devdata;
+	struct rcar_gen3_thermal_tsc *tsc = thermal_zone_device_get_data(tz);
 	u32 irqmsk = 0;
 
 	if (low != -INT_MAX) {
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
index 436f5f9cf729..538ed6731589 100644
--- a/drivers/thermal/rcar_thermal.c
+++ b/drivers/thermal/rcar_thermal.c
@@ -101,7 +101,6 @@ struct rcar_thermal_priv {
 	list_for_each_entry(pos, &common->head, list)
 
 #define MCELSIUS(temp)			((temp) * 1000)
-#define rcar_zone_to_priv(zone)		((zone)->devdata)
 #define rcar_priv_to_dev(priv)		((priv)->common->dev)
 #define rcar_has_irq_support(priv)	((priv)->common->base)
 #define rcar_id_to_shift(priv)		((priv)->id * 8)
@@ -273,7 +272,7 @@ static int rcar_thermal_get_current_temp(struct rcar_thermal_priv *priv,
 
 static int rcar_thermal_get_temp(struct thermal_zone_device *zone, int *temp)
 {
-	struct rcar_thermal_priv *priv = rcar_zone_to_priv(zone);
+	struct rcar_thermal_priv *priv = thermal_zone_device_get_data(zone);
 
 	return rcar_thermal_get_current_temp(priv, temp);
 }
diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c
index 4b7c43f34d1a..dafbdbb7c0c0 100644
--- a/drivers/thermal/rockchip_thermal.c
+++ b/drivers/thermal/rockchip_thermal.c
@@ -1213,7 +1213,7 @@ static irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
 
 static int rockchip_thermal_set_trips(struct thermal_zone_device *tz, int low, int high)
 {
-	struct rockchip_thermal_sensor *sensor = tz->devdata;
+	struct rockchip_thermal_sensor *sensor = thermal_zone_device_get_data(tz);
 	struct rockchip_thermal_data *thermal = sensor->thermal;
 	const struct rockchip_tsadc_chip *tsadc = thermal->chip;
 
@@ -1226,7 +1226,7 @@ static int rockchip_thermal_set_trips(struct thermal_zone_device *tz, int low, i
 
 static int rockchip_thermal_get_temp(struct thermal_zone_device *tz, int *out_temp)
 {
-	struct rockchip_thermal_sensor *sensor = tz->devdata;
+	struct rockchip_thermal_sensor *sensor = thermal_zone_device_get_data(tz);
 	struct rockchip_thermal_data *thermal = sensor->thermal;
 	const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip;
 	int retval;
diff --git a/drivers/thermal/rzg2l_thermal.c b/drivers/thermal/rzg2l_thermal.c
index 2e0649f38506..d3ba2a74e42d 100644
--- a/drivers/thermal/rzg2l_thermal.c
+++ b/drivers/thermal/rzg2l_thermal.c
@@ -75,7 +75,7 @@ static inline void rzg2l_thermal_write(struct rzg2l_thermal_priv *priv, u32 reg,
 
 static int rzg2l_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct rzg2l_thermal_priv *priv = tz->devdata;
+	struct rzg2l_thermal_priv *priv = thermal_zone_device_get_data(tz);
 	u32 result = 0, dsensor, ts_code_ave;
 	int val, i;
 
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 527d1eb0663a..a2301e235a2b 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -645,7 +645,7 @@ static void exynos7_tmu_control(struct platform_device *pdev, bool on)
 
 static int exynos_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct exynos_tmu_data *data = tz->devdata;
+	struct exynos_tmu_data *data = thermal_zone_device_get_data(tz);
 	int value, ret = 0;
 
 	if (!data || !data->tmu_read)
@@ -723,7 +723,7 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
 
 static int exynos_tmu_set_emulation(struct thermal_zone_device *tz, int temp)
 {
-	struct exynos_tmu_data *data = tz->devdata;
+	struct exynos_tmu_data *data = thermal_zone_device_get_data(tz);
 	int ret = -EINVAL;
 
 	if (data->soc == SOC_ARCH_EXYNOS4210)
diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c
index 6a722b10d738..62cd9305eb9c 100644
--- a/drivers/thermal/spear_thermal.c
+++ b/drivers/thermal/spear_thermal.c
@@ -31,7 +31,7 @@ struct spear_thermal_dev {
 static inline int thermal_get_temp(struct thermal_zone_device *thermal,
 				int *temp)
 {
-	struct spear_thermal_dev *stdev = thermal->devdata;
+	struct spear_thermal_dev *stdev = thermal_zone_device_get_data(thermal);
 
 	/*
 	 * Data are ready to be read after 628 usec from POWERDOWN signal
@@ -48,7 +48,7 @@ static struct thermal_zone_device_ops ops = {
 static int __maybe_unused spear_thermal_suspend(struct device *dev)
 {
 	struct thermal_zone_device *spear_thermal = dev_get_drvdata(dev);
-	struct spear_thermal_dev *stdev = spear_thermal->devdata;
+	struct spear_thermal_dev *stdev = thermal_zone_device_get_data(spear_thermal);
 	unsigned int actual_mask = 0;
 
 	/* Disable SPEAr Thermal Sensor */
@@ -64,7 +64,7 @@ static int __maybe_unused spear_thermal_suspend(struct device *dev)
 static int __maybe_unused spear_thermal_resume(struct device *dev)
 {
 	struct thermal_zone_device *spear_thermal = dev_get_drvdata(dev);
-	struct spear_thermal_dev *stdev = spear_thermal->devdata;
+	struct spear_thermal_dev *stdev = thermal_zone_device_get_data(spear_thermal);
 	unsigned int actual_mask = 0;
 	int ret = 0;
 
@@ -154,7 +154,7 @@ static int spear_thermal_exit(struct platform_device *pdev)
 {
 	unsigned int actual_mask = 0;
 	struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev);
-	struct spear_thermal_dev *stdev = spear_thermal->devdata;
+	struct spear_thermal_dev *stdev = thermal_zone_device_get_data(spear_thermal);
 
 	thermal_zone_device_unregister(spear_thermal);
 
diff --git a/drivers/thermal/sprd_thermal.c b/drivers/thermal/sprd_thermal.c
index ac884514f116..69078a55dc0c 100644
--- a/drivers/thermal/sprd_thermal.c
+++ b/drivers/thermal/sprd_thermal.c
@@ -206,7 +206,7 @@ static int sprd_thm_temp_to_rawdata(int temp, struct sprd_thermal_sensor *sen)
 
 static int sprd_thm_read_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct sprd_thermal_sensor *sen = tz->devdata;
+	struct sprd_thermal_sensor *sen = thermal_zone_device_get_data(tz);
 	u32 data;
 
 	data = readl(sen->data->base + SPRD_THM_TEMP(sen->id)) &
diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c
index 497beac63e5d..085b7b0b7c72 100644
--- a/drivers/thermal/sun8i_thermal.c
+++ b/drivers/thermal/sun8i_thermal.c
@@ -110,7 +110,7 @@ static int sun50i_h5_calc_temp(struct ths_device *tmdev,
 
 static int sun8i_ths_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct tsensor *s = tz->devdata;
+	struct tsensor *s = thermal_zone_device_get_data(tz);
 	struct ths_device *tmdev = s->tmdev;
 	int val = 0;
 
diff --git a/drivers/thermal/tegra/tegra-bpmp-thermal.c b/drivers/thermal/tegra/tegra-bpmp-thermal.c
index 0b7a1a1948cb..31a660b009fc 100644
--- a/drivers/thermal/tegra/tegra-bpmp-thermal.c
+++ b/drivers/thermal/tegra/tegra-bpmp-thermal.c
@@ -62,12 +62,14 @@ static int __tegra_bpmp_thermal_get_temp(struct tegra_bpmp_thermal_zone *zone,
 
 static int tegra_bpmp_thermal_get_temp(struct thermal_zone_device *tz, int *out_temp)
 {
-	return __tegra_bpmp_thermal_get_temp(tz->devdata, out_temp);
+	struct tegra_bpmp_thermal_zone *zone = thermal_zone_device_get_data(tz);
+	
+	return __tegra_bpmp_thermal_get_temp(zone, out_temp);
 }
 
 static int tegra_bpmp_thermal_set_trips(struct thermal_zone_device *tz, int low, int high)
 {
-	struct tegra_bpmp_thermal_zone *zone = tz->devdata;
+	struct tegra_bpmp_thermal_zone *zone = thermal_zone_device_get_data(tz);
 	struct mrq_thermal_host_to_bpmp_request req;
 	struct tegra_bpmp_message msg;
 	int err;
diff --git a/drivers/thermal/tegra/tegra30-tsensor.c b/drivers/thermal/tegra/tegra30-tsensor.c
index b3218b71b6d9..537413acc6d2 100644
--- a/drivers/thermal/tegra/tegra30-tsensor.c
+++ b/drivers/thermal/tegra/tegra30-tsensor.c
@@ -160,7 +160,7 @@ static void devm_tegra_tsensor_hw_disable(void *data)
 
 static int tegra_tsensor_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	const struct tegra_tsensor_channel *tsc = tz->devdata;
+	const struct tegra_tsensor_channel *tsc = thermal_zone_device_get_data(tz);
 	const struct tegra_tsensor *ts = tsc->ts;
 	int err, c1, c2, c3, c4, counter;
 	u32 val;
@@ -218,7 +218,7 @@ static int tegra_tsensor_temp_to_counter(const struct tegra_tsensor *ts, int tem
 
 static int tegra_tsensor_set_trips(struct thermal_zone_device *tz, int low, int high)
 {
-	const struct tegra_tsensor_channel *tsc = tz->devdata;
+	const struct tegra_tsensor_channel *tsc = thermal_zone_device_get_data(tz);
 	const struct tegra_tsensor *ts = tsc->ts;
 	u32 val;
 
diff --git a/drivers/thermal/thermal-generic-adc.c b/drivers/thermal/thermal-generic-adc.c
index 323e273e3298..8e2ff0df7e64 100644
--- a/drivers/thermal/thermal-generic-adc.c
+++ b/drivers/thermal/thermal-generic-adc.c
@@ -54,7 +54,7 @@ static int gadc_thermal_adc_to_temp(struct gadc_thermal_info *gti, int val)
 
 static int gadc_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 {
-	struct gadc_thermal_info *gti = tz->devdata;
+	struct gadc_thermal_info *gti = thermal_zone_device_get_data(tz);
 	int val;
 	int ret;
 
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 0675df54c8e6..05e5a6bda695 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1378,6 +1378,12 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, int n
 }
 EXPORT_SYMBOL_GPL(thermal_zone_device_register);
 
+void *thermal_zone_device_get_data(struct thermal_zone_device *tzd)
+{
+	return tzd->devdata;
+}
+EXPORT_SYMBOL_GPL(thermal_zone_device_get_data);
+
 /**
  * thermal_zone_device_unregister - removes the registered thermal zone device
  * @tz: the thermal zone device to remove
diff --git a/drivers/thermal/thermal_mmio.c b/drivers/thermal/thermal_mmio.c
index ea616731066c..05a70205f86f 100644
--- a/drivers/thermal/thermal_mmio.c
+++ b/drivers/thermal/thermal_mmio.c
@@ -23,7 +23,7 @@ static u32 thermal_mmio_readb(void __iomem *mmio_base)
 static int thermal_mmio_get_temperature(struct thermal_zone_device *tz, int *temp)
 {
 	int t;
-	struct thermal_mmio *sensor = tz->devdata;
+	struct thermal_mmio *sensor = thermal_zone_device_get_data(tz);
 
 	t = sensor->read_mmio(sensor->mmio_base) & sensor->mask;
 	t *= sensor->factor;
diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
index 8a9055bd376e..7f6b71d11eed 100644
--- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
+++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c
@@ -68,7 +68,7 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c)
 static inline int __ti_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 {
 	struct thermal_zone_device *pcb_tz = NULL;
-	struct ti_thermal_data *data = tz->devdata;
+	struct ti_thermal_data *data = thermal_zone_device_get_data(tz);
 	struct ti_bandgap *bgp;
 	const struct ti_temp_sensor *s;
 	int ret, tmp, slope, constant;
@@ -109,7 +109,7 @@ static inline int __ti_thermal_get_temp(struct thermal_zone_device *tz, int *tem
 
 static int __ti_thermal_get_trend(struct thermal_zone_device *tz, int trip, enum thermal_trend *trend)
 {
-	struct ti_thermal_data *data = tz->devdata;
+	struct ti_thermal_data *data = thermal_zone_device_get_data(tz);
 	struct ti_bandgap *bgp;
 	int id, tr, ret = 0;
 
diff --git a/drivers/thermal/uniphier_thermal.c b/drivers/thermal/uniphier_thermal.c
index 47801841b3f5..25247de7780c 100644
--- a/drivers/thermal/uniphier_thermal.c
+++ b/drivers/thermal/uniphier_thermal.c
@@ -187,7 +187,7 @@ static void uniphier_tm_disable_sensor(struct uniphier_tm_dev *tdev)
 
 static int uniphier_tm_get_temp(struct thermal_zone_device *tz, int *out_temp)
 {
-	struct uniphier_tm_dev *tdev = tz->devdata;
+	struct uniphier_tm_dev *tdev = thermal_zone_device_get_data(tz);
 	struct regmap *map = tdev->regmap;
 	int ret;
 	u32 temp;
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 2bb4bf33f4f3..724b95662da9 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -365,6 +365,8 @@ thermal_zone_device_register_with_trips(const char *, struct thermal_trip *, int
 					void *, struct thermal_zone_device_ops *,
 					struct thermal_zone_params *, int, int);
 
+void *thermal_zone_device_get_data(struct thermal_zone_device *tzd);
+
 int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int,
 				     struct thermal_cooling_device *,
 				     unsigned long, unsigned long,
-- 
2.34.1


^ permalink raw reply related

* [PATCH v1 00/17] Self-encapsulate the thermal zone device structure
From: Daniel Lezcano @ 2023-02-19 14:36 UTC (permalink / raw)
  To: rafael, daniel.lezcano
  Cc: linux-pm, linux-kernel, Zhang Rui, Len Brown, Damien Le Moal,
	Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	NXP Linux Team, Jean Delvare, Guenter Roeck, Jonathan Cameron,
	Lars-Peter Clausen, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Dmitry Torokhov, Raju Rangoju, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Ido Schimmel, Petr Machata,
	Gregory Greenman, Kalle Valo, Sebastian Reichel, Liam Girdwood,
	Mark Brown, Miquel Raynal, Amit Kucheria, Florian Fainelli,
	Broadcom internal kernel review list, Ray Jui, Scott Branden,
	Markus Mayer, Support Opensource, Andy Gross, Bjorn Andersson,
	Konrad Dybcio, Thara Gopinath, Niklas Söderlund,
	Heiko Stuebner, Bartlomiej Zolnierkiewicz, Krzysztof Kozlowski,
	Alim Akhtar, Orson Zhai, Baolin Wang, Chunyan Zhang,
	Vasily Khoruzhick, Yangtao Li, Thierry Reding, Jonathan Hunter,
	Talel Shenhar, Eduardo Valentin, Keerthy, Kunihiko Hayashi,
	Masami Hiramatsu, Matthias Brugger, AngeloGioacchino Del Regno,
	Stefan Wahren, Zheng Yongjun, Yang Li, Srinivas Pandruvada,
	Daniel Golle, Balsam CHIHI, Mikko Perttunen, linux-acpi,
	linux-ide, linux-arm-kernel, linux-hwmon, linux-iio, linux-sunxi,
	linux-input, netdev, linux-wireless, linux-rpi-kernel,
	linux-arm-msm, linux-renesas-soc, linux-rockchip,
	linux-samsung-soc, linux-tegra, linux-omap, linux-mediatek

The exported thermal headers expose the thermal core structure while those
should be private to the framework. The initial idea was the thermal sensor
drivers use the thermal zone device structure pointer to pass it around from
the ops to the thermal framework API like a handler.

Unfortunately, different drivers are using and abusing the internals of this
structure to hook the associated struct device, read the internals values, take
the lock, etc ...

rn order to fix this situation, let's encapsulate the structure leaking the
more in the different drivers: the thermal_zone_device structure.

This series revisit the existing drivers using the thermal zone private
structure internals to change the access to something else. For instance, the
get_temp() ops is using the tz->dev to write a debug trace. Despite the trace
is not helpful, we can check the return value for the get_temp() ops in the
call site and show the message in this place.

With this set of changes, the thermal_zone_device is almost self-encapsulated.
As usual, the acpi driver needs a more complex changes, so that will come in a
separate series along with the structure moved the private core headers.

Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Zhang Rui <rui.zhang@intel.com>
Cc: Len Brown <lenb@kernel.org>
Cc: Damien Le Moal <damien.lemoal@opensource.wdc.com>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Pengutronix Kernel Team <kernel@pengutronix.de>
Cc: Fabio Estevam <festevam@gmail.com>
Cc: NXP Linux Team <linux-imx@nxp.com>
Cc: Jean Delvare <jdelvare@suse.com>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Jonathan Cameron <jic23@kernel.org>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Chen-Yu Tsai <wens@csie.org>
Cc: Jernej Skrabec <jernej.skrabec@gmail.com>
Cc: Samuel Holland <samuel@sholland.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Raju Rangoju <rajur@chelsio.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Ido Schimmel <idosch@nvidia.com>
Cc: Petr Machata <petrm@nvidia.com>
Cc: Gregory Greenman <gregory.greenman@intel.com>
Cc: Kalle Valo <kvalo@kernel.org>
Cc: Sebastian Reichel <sre@kernel.org>
Cc: Liam Girdwood <lgirdwood@gmail.com>
Cc: Mark Brown <broonie@kernel.org>
Cc: Miquel Raynal <miquel.raynal@bootlin.com>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Amit Kucheria <amitk@kernel.org>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
Cc: Ray Jui <rjui@broadcom.com>
Cc: Scott Branden <sbranden@broadcom.com>
Cc: Markus Mayer <mmayer@broadcom.com>
Cc: Support Opensource <support.opensource@diasemi.com>
Cc: Andy Gross <agross@kernel.org>
Cc: Bjorn Andersson <andersson@kernel.org>
Cc: Konrad Dybcio <konrad.dybcio@linaro.org>
Cc: Thara Gopinath <thara.gopinath@gmail.com>
Cc: "Niklas Söderlund" <niklas.soderlund@ragnatech.se>
Cc: Heiko Stuebner <heiko@sntech.de>
Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Cc: Alim Akhtar <alim.akhtar@samsung.com>
Cc: Orson Zhai <orsonzhai@gmail.com>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Chunyan Zhang <zhang.lyra@gmail.com>
Cc: Vasily Khoruzhick <anarsoul@gmail.com>
Cc: Yangtao Li <tiny.windzz@gmail.com>
Cc: Thierry Reding <thierry.reding@gmail.com>
Cc: Jonathan Hunter <jonathanh@nvidia.com>
Cc: Talel Shenhar <talel@amazon.com>
Cc: Eduardo Valentin <edubezval@gmail.com>
Cc: Keerthy <j-keerthy@ti.com>
Cc: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Matthias Brugger <matthias.bgg@gmail.com>
Cc: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Cc: Stefan Wahren <stefan.wahren@i2se.com>
Cc: Zheng Yongjun <zhengyongjun3@huawei.com>
Cc: Yang Li <yang.lee@linux.alibaba.com>
Cc: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Cc: Daniel Golle <daniel@makrotopia.org>
Cc: Balsam CHIHI <bchihi@baylibre.com>
Cc: Mikko Perttunen <mperttunen@nvidia.com>
Cc: linux-acpi@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-ide@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-hwmon@vger.kernel.org
Cc: linux-iio@vger.kernel.org
Cc: linux-sunxi@lists.linux.dev
Cc: linux-input@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: linux-wireless@vger.kernel.org
Cc: linux-pm@vger.kernel.org
Cc: linux-rpi-kernel@lists.infradead.org
Cc: linux-arm-msm@vger.kernel.org
Cc: linux-renesas-soc@vger.kernel.org
Cc: linux-rockchip@lists.infradead.org
Cc: linux-samsung-soc@vger.kernel.org
Cc: linux-tegra@vger.kernel.org
Cc: linux-omap@vger.kernel.org
Cc: linux-mediatek@lists.infradead.org


Daniel Lezcano (17):
  thermal/core: Add a thermal zone 'devdata' accessor
  thermal/core: Show a debug message when get_temp() fails
  thermal: Remove debug or error messages in get_temp() ops
  thermal/hwmon: Do not set no_hwmon before calling
    thermal_add_hwmon_sysfs()
  thermal/hwmon: Use the right device for devm_thermal_add_hwmon_sysfs()
  thermal: Don't use 'device' internal thermal zone structure field
  thermal/hwmon: Use the thermal API instead tampering the internals
  thermal/drivers/spear: Don't use tz->device but pdev->dev
  thermal: Add a thermal zone id accessor
  thermal: Do not access 'type' field, use the tz id instead
  thermal/drivers/da9062: Don't access the thermal zone device fields
  thermal/hwmon: Use the thermal_core.h header
  thermal/drivers/tegra: Remove unneeded lock when setting a trip point
  thermal/tegra: Do not enable the thermal zone, it is already enabled
  thermal/drivers/acerhdf: Make interval setting only at module load
    time
  thermal/drivers/acerhdf: Remove pointless governor test
  thermal/traces: Replace the thermal zone structure parameter with the
    field value

 drivers/acpi/thermal.c                        | 18 +++----
 drivers/ata/ahci_imx.c                        |  2 +-
 drivers/hwmon/hwmon.c                         |  4 +-
 drivers/hwmon/pmbus/pmbus_core.c              |  2 +-
 drivers/hwmon/scmi-hwmon.c                    |  4 +-
 drivers/hwmon/scpi-hwmon.c                    |  2 +-
 drivers/iio/adc/sun4i-gpadc-iio.c             |  2 +-
 drivers/input/touchscreen/sun4i-ts.c          |  2 +-
 .../ethernet/chelsio/cxgb4/cxgb4_thermal.c    |  2 +-
 .../ethernet/mellanox/mlxsw/core_thermal.c    | 18 +++----
 drivers/net/wireless/intel/iwlwifi/mvm/tt.c   |  4 +-
 drivers/platform/x86/acerhdf.c                | 19 ++------
 drivers/power/supply/power_supply_core.c      |  2 +-
 drivers/regulator/max8973-regulator.c         |  2 +-
 drivers/thermal/amlogic_thermal.c             |  2 +-
 drivers/thermal/armada_thermal.c              | 14 ++----
 drivers/thermal/broadcom/bcm2711_thermal.c    |  3 +-
 drivers/thermal/broadcom/bcm2835_thermal.c    |  3 +-
 drivers/thermal/broadcom/brcmstb_thermal.c    |  8 ++--
 drivers/thermal/broadcom/ns-thermal.c         |  2 +-
 drivers/thermal/broadcom/sr-thermal.c         |  2 +-
 drivers/thermal/da9062-thermal.c              | 13 +++--
 drivers/thermal/dove_thermal.c                |  7 +--
 drivers/thermal/gov_fair_share.c              |  2 +-
 drivers/thermal/gov_power_allocator.c         |  4 +-
 drivers/thermal/gov_step_wise.c               |  2 +-
 drivers/thermal/hisi_thermal.c                |  5 +-
 drivers/thermal/imx8mm_thermal.c              |  4 +-
 drivers/thermal/imx_sc_thermal.c              |  9 ++--
 drivers/thermal/imx_thermal.c                 | 47 +++++--------------
 drivers/thermal/intel/intel_pch_thermal.c     |  2 +-
 drivers/thermal/intel/intel_soc_dts_iosf.c    | 13 ++---
 drivers/thermal/intel/x86_pkg_temp_thermal.c  |  4 +-
 drivers/thermal/k3_bandgap.c                  |  4 +-
 drivers/thermal/k3_j72xx_bandgap.c            |  2 +-
 drivers/thermal/kirkwood_thermal.c            |  7 +--
 drivers/thermal/max77620_thermal.c            |  6 +--
 drivers/thermal/mediatek/auxadc_thermal.c     |  4 +-
 drivers/thermal/mediatek/lvts_thermal.c       |  9 ++--
 drivers/thermal/qcom/qcom-spmi-adc-tm5.c      |  6 +--
 drivers/thermal/qcom/qcom-spmi-temp-alarm.c   |  6 +--
 drivers/thermal/qcom/tsens.c                  |  4 +-
 drivers/thermal/qoriq_thermal.c               |  4 +-
 drivers/thermal/rcar_gen3_thermal.c           |  5 +-
 drivers/thermal/rcar_thermal.c                |  8 +---
 drivers/thermal/rockchip_thermal.c            |  8 +---
 drivers/thermal/rzg2l_thermal.c               |  3 +-
 drivers/thermal/samsung/exynos_tmu.c          |  4 +-
 drivers/thermal/spear_thermal.c               | 10 ++--
 drivers/thermal/sprd_thermal.c                |  2 +-
 drivers/thermal/st/st_thermal.c               |  2 -
 drivers/thermal/sun8i_thermal.c               |  4 +-
 drivers/thermal/tegra/tegra-bpmp-thermal.c    |  6 ++-
 drivers/thermal/tegra/tegra30-tsensor.c       | 31 ++++++------
 drivers/thermal/thermal-generic-adc.c         |  7 ++-
 drivers/thermal/thermal_core.c                | 17 ++++++-
 drivers/thermal/thermal_helpers.c             |  3 ++
 drivers/thermal/thermal_hwmon.c               | 19 +++-----
 drivers/thermal/thermal_hwmon.h               |  4 +-
 drivers/thermal/thermal_mmio.c                |  2 +-
 .../ti-soc-thermal/ti-thermal-common.c        | 10 ++--
 drivers/thermal/uniphier_thermal.c            |  2 +-
 include/linux/thermal.h                       |  4 ++
 include/trace/events/thermal.h                | 24 +++++-----
 .../trace/events/thermal_power_allocator.h    | 12 ++---
 65 files changed, 203 insertions(+), 265 deletions(-)

-- 
2.34.1


^ permalink raw reply

* Re: [PATCH v4 2/2] HID: hid-apple-magic-backlight: Add driver for keyboard backlight on internal Magic Keyboards
From: Andy Shevchenko @ 2023-02-19 14:09 UTC (permalink / raw)
  To: Orlando Chamberlain
  Cc: linux-doc, linux-input, Jonathan Corbet, Jiri Kosina,
	Benjamin Tissoires, linux-kernel, Pavel Machek, Aditya Garg,
	Aun-Ali Zaidi, Kerem Karabay, Andy Shevchenko,
	Thomas Weißschuh, Thomas Weißschuh
In-Reply-To: <20230218090709.7467-3-orlandoch.dev@gmail.com>

On Sat, Feb 18, 2023 at 11:08 AM Orlando Chamberlain
<orlandoch.dev@gmail.com> wrote:
>
> This driver adds support for the keyboard backlight on Intel T2 Macs
> with internal Magic Keyboards (MacBookPro16,x and MacBookAir9,1)

...

> +       help
> +       Say Y here if you want support for the keyboard backlight on Macs with
> +       the magic keyboard (MacBookPro16,x and MacBookAir9,1). Note that this
> +       driver is not for external magic keyboards.
> +
> +       To compile this driver as a module, choose M here: the
> +       module will be called hid-apple-magic-backlight.

Is it my email client or is the indentation of the help text incorrect?

Hint: the text of the help should be <TAB><SPACE><SPACE> indented.

I believe checkpatch.pl at least in --strict mode should complain about this.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply

* Re: [PATCH 03/11] selftests: hid: import hid-tools hid-gamepad tests
From: Silvan Jegen @ 2023-02-18 20:24 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Jiri Kosina, Shuah Khan, linux-input, linux-kselftest,
	linux-kernel, Candle Sun, Jose Torreguitar, Peter Hutterer,
	Roderick Colenbrander
In-Reply-To: <20230217-import-hid-tools-tests-v1-3-d1c48590d0ee@redhat.com>

Benjamin Tissoires <benjamin.tissoires@redhat.com> wrote:
> These tests have been developed in the hid-tools[0] tree for a while.
> Now that we have  a proper selftests/hid kernel entry and that the tests
> are more reliable, it is time to directly include those in the kernel
> tree.
> 
> [0] https://gitlab.freedesktop.org/libevdev/hid-tools
> 
> Cc: Candle Sun <candle.sun@unisoc.com>
> Cc: Jose Torreguitar <jtguitar@google.com>
> Cc: Peter Hutterer <peter.hutterer@who-t.net>
> Cc: Roderick Colenbrander <roderick.colenbrander@sony.com>
> Cc: Silvan Jegen <s.jegen@gmail.com>
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> ---
>  tools/testing/selftests/hid/Makefile              |   1 +
>  tools/testing/selftests/hid/hid-gamepad.sh        |   7 +
>  tools/testing/selftests/hid/tests/test_gamepad.py | 209 ++++++++++++++++++++++
>  3 files changed, 217 insertions(+)

It was only a one line change from my side but in any case.

Signed-off-by: Silvan Jegen <s.jegen@gmail.com>


> 
> diff --git a/tools/testing/selftests/hid/Makefile b/tools/testing/selftests/hid/Makefile
> index bdcb36d80c8c..d16a22477140 100644
> --- a/tools/testing/selftests/hid/Makefile
> +++ b/tools/testing/selftests/hid/Makefile
> @@ -6,6 +6,7 @@ include ../../../scripts/Makefile.arch
>  include ../../../scripts/Makefile.include
>  
>  TEST_PROGS := hid-core.sh
> +TEST_PROGS += hid-gamepad.sh
>  
>  CXX ?= $(CROSS_COMPILE)g++
>  
> diff --git a/tools/testing/selftests/hid/hid-gamepad.sh b/tools/testing/selftests/hid/hid-gamepad.sh
> new file mode 100755
> index 000000000000..1ba00c0ca95f
> --- /dev/null
> +++ b/tools/testing/selftests/hid/hid-gamepad.sh
> @@ -0,0 +1,7 @@
> +#!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0
> +# Runs tests for the HID subsystem
> +
> +export TARGET=test_gamepad.py
> +
> +bash ./run-hid-tools-tests.sh
> diff --git a/tools/testing/selftests/hid/tests/test_gamepad.py b/tools/testing/selftests/hid/tests/test_gamepad.py
> new file mode 100644
> index 000000000000..26c74040b796
> --- /dev/null
> +++ b/tools/testing/selftests/hid/tests/test_gamepad.py
> @@ -0,0 +1,209 @@
> +#!/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0
> +# -*- coding: utf-8 -*-
> +#
> +# Copyright (c) 2019 Benjamin Tissoires <benjamin.tissoires@gmail.com>
> +# Copyright (c) 2019 Red Hat, Inc.
> +#
> +
> +from . import base
> +import libevdev
> +import pytest
> +
> +from hidtools.device.base_gamepad import AsusGamepad, SaitekGamepad
> +
> +import logging
> +
> +logger = logging.getLogger("hidtools.test.gamepad")
> +
> +
> +class BaseTest:
> +    class TestGamepad(base.BaseTestCase.TestUhid):
> +        @pytest.fixture(autouse=True)
> +        def send_initial_state(self):
> +            """send an empty report to initialize the axes"""
> +            uhdev = self.uhdev
> +
> +            r = uhdev.event()
> +            events = uhdev.next_sync_events()
> +            self.debug_reports(r, uhdev, events)
> +
> +        def assert_button(self, button):
> +            uhdev = self.uhdev
> +            evdev = uhdev.get_evdev()
> +            syn_event = self.syn_event
> +
> +            buttons = {}
> +            key = libevdev.evbit(uhdev.buttons_map[button])
> +
> +            buttons[button] = True
> +            r = uhdev.event(buttons=buttons)
> +            expected_event = libevdev.InputEvent(key, 1)
> +            events = uhdev.next_sync_events()
> +            self.debug_reports(r, uhdev, events)
> +            self.assertInputEventsIn((syn_event, expected_event), events)
> +            assert evdev.value[key] == 1
> +
> +            buttons[button] = False
> +            r = uhdev.event(buttons=buttons)
> +            expected_event = libevdev.InputEvent(key, 0)
> +            events = uhdev.next_sync_events()
> +            self.debug_reports(r, uhdev, events)
> +            self.assertInputEventsIn((syn_event, expected_event), events)
> +            assert evdev.value[key] == 0
> +
> +        def test_buttons(self):
> +            """check for button reliability."""
> +            uhdev = self.uhdev
> +
> +            for b in uhdev.buttons:
> +                self.assert_button(b)
> +
> +        def test_dual_buttons(self):
> +            """check for button reliability when pressing 2 buttons"""
> +            uhdev = self.uhdev
> +            evdev = uhdev.get_evdev()
> +            syn_event = self.syn_event
> +
> +            # can change intended b1 b2 values
> +            b1 = uhdev.buttons[0]
> +            key1 = libevdev.evbit(uhdev.buttons_map[b1])
> +            b2 = uhdev.buttons[1]
> +            key2 = libevdev.evbit(uhdev.buttons_map[b2])
> +
> +            buttons = {b1: True, b2: True}
> +            r = uhdev.event(buttons=buttons)
> +            expected_event0 = libevdev.InputEvent(key1, 1)
> +            expected_event1 = libevdev.InputEvent(key2, 1)
> +            events = uhdev.next_sync_events()
> +            self.debug_reports(r, uhdev, events)
> +            self.assertInputEventsIn(
> +                (syn_event, expected_event0, expected_event1), events
> +            )
> +            assert evdev.value[key1] == 1
> +            assert evdev.value[key2] == 1
> +
> +            buttons = {b1: False, b2: None}
> +            r = uhdev.event(buttons=buttons)
> +            expected_event = libevdev.InputEvent(key1, 0)
> +            events = uhdev.next_sync_events()
> +            self.debug_reports(r, uhdev, events)
> +            self.assertInputEventsIn((syn_event, expected_event), events)
> +            assert evdev.value[key1] == 0
> +            assert evdev.value[key2] == 1
> +
> +            buttons = {b1: None, b2: False}
> +            r = uhdev.event(buttons=buttons)
> +            expected_event = libevdev.InputEvent(key2, 0)
> +            events = uhdev.next_sync_events()
> +            self.debug_reports(r, uhdev, events)
> +            self.assertInputEventsIn((syn_event, expected_event), events)
> +            assert evdev.value[key1] == 0
> +            assert evdev.value[key2] == 0
> +
> +        def _get_libevdev_abs_events(self, which):
> +            """Returns which ABS_* evdev axes are expected for the given stick"""
> +            abs_map = self.uhdev.axes_map[which]
> +
> +            x = abs_map["x"].evdev
> +            y = abs_map["y"].evdev
> +
> +            assert x
> +            assert y
> +
> +            return x, y
> +
> +        def _test_joystick_press(self, which, data):
> +            uhdev = self.uhdev
> +
> +            libevdev_axes = self._get_libevdev_abs_events(which)
> +
> +            r = None
> +            if which == "left_stick":
> +                r = uhdev.event(left=data)
> +            else:
> +                r = uhdev.event(right=data)
> +            events = uhdev.next_sync_events()
> +            self.debug_reports(r, uhdev, events)
> +
> +            for i, d in enumerate(data):
> +                if d is not None and d != 127:
> +                    assert libevdev.InputEvent(libevdev_axes[i], d) in events
> +                else:
> +                    assert libevdev.InputEvent(libevdev_axes[i]) not in events
> +
> +        def test_left_joystick_press_left(self):
> +            """check for the left joystick reliability"""
> +            self._test_joystick_press("left_stick", (63, None))
> +            self._test_joystick_press("left_stick", (0, 127))
> +
> +        def test_left_joystick_press_right(self):
> +            """check for the left joystick reliability"""
> +            self._test_joystick_press("left_stick", (191, 127))
> +            self._test_joystick_press("left_stick", (255, None))
> +
> +        def test_left_joystick_press_up(self):
> +            """check for the left joystick reliability"""
> +            self._test_joystick_press("left_stick", (None, 63))
> +            self._test_joystick_press("left_stick", (127, 0))
> +
> +        def test_left_joystick_press_down(self):
> +            """check for the left joystick reliability"""
> +            self._test_joystick_press("left_stick", (127, 191))
> +            self._test_joystick_press("left_stick", (None, 255))
> +
> +        def test_right_joystick_press_left(self):
> +            """check for the right joystick reliability"""
> +            self._test_joystick_press("right_stick", (63, None))
> +            self._test_joystick_press("right_stick", (0, 127))
> +
> +        def test_right_joystick_press_right(self):
> +            """check for the right joystick reliability"""
> +            self._test_joystick_press("right_stick", (191, 127))
> +            self._test_joystick_press("right_stick", (255, None))
> +
> +        def test_right_joystick_press_up(self):
> +            """check for the right joystick reliability"""
> +            self._test_joystick_press("right_stick", (None, 63))
> +            self._test_joystick_press("right_stick", (127, 0))
> +
> +        def test_right_joystick_press_down(self):
> +            """check for the right joystick reliability"""
> +            self._test_joystick_press("right_stick", (127, 191))
> +            self._test_joystick_press("right_stick", (None, 255))
> +
> +        @pytest.mark.skip_if_uhdev(
> +            lambda uhdev: "Hat switch" not in uhdev.fields,
> +            "Device not compatible, missing Hat switch usage",
> +        )
> +        @pytest.mark.parametrize(
> +            "hat_value,expected_evdev,evdev_value",
> +            [
> +                (0, "ABS_HAT0Y", -1),
> +                (2, "ABS_HAT0X", 1),
> +                (4, "ABS_HAT0Y", 1),
> +                (6, "ABS_HAT0X", -1),
> +            ],
> +        )
> +        def test_hat_switch(self, hat_value, expected_evdev, evdev_value):
> +            uhdev = self.uhdev
> +
> +            r = uhdev.event(hat_switch=hat_value)
> +            events = uhdev.next_sync_events()
> +            self.debug_reports(r, uhdev, events)
> +            assert (
> +                libevdev.InputEvent(
> +                    libevdev.evbit("EV_ABS", expected_evdev), evdev_value
> +                )
> +                in events
> +            )
> +
> +
> +class TestSaitekGamepad(BaseTest.TestGamepad):
> +    def create_device(self):
> +        return SaitekGamepad()
> +
> +
> +class TestAsusGamepad(BaseTest.TestGamepad):
> +    def create_device(self):
> +        return AsusGamepad()



^ permalink raw reply

* [PATCH v4 2/2] HID: hid-apple-magic-backlight: Add driver for keyboard backlight on internal Magic Keyboards
From: Orlando Chamberlain @ 2023-02-18  9:07 UTC (permalink / raw)
  To: linux-doc, linux-input
  Cc: Jonathan Corbet, Jiri Kosina, Benjamin Tissoires, linux-kernel,
	Pavel Machek, Aditya Garg, Aun-Ali Zaidi, Kerem Karabay,
	Andy Shevchenko, Thomas Weißschuh, Orlando Chamberlain,
	Andy Shevchenko, Thomas Weißschuh
In-Reply-To: <20230218090709.7467-1-orlandoch.dev@gmail.com>

This driver adds support for the keyboard backlight on Intel T2 Macs
with internal Magic Keyboards (MacBookPro16,x and MacBookAir9,1)

Co-developed-by: Kerem Karabay <kekrby@gmail.com>
Signed-off-by: Kerem Karabay <kekrby@gmail.com>
Signed-off-by: Orlando Chamberlain <orlandoch.dev@gmail.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Reviewed-by: Thomas Weißschuh <linux@weissschuh.net>
---
v3->v4:
- collect reviews from Andy and Thomas
- remove now unused hdev member of apple_magic_backlight
v2->v3:
- remove unneeded inclusion
- use s32 for report value type
- remove unneeded null check
- don't set drvdata as its never used
- prepend "hid-" to module name
v1->v2:
- drop unneeded remove function
- combine set functions
- add missing header inclusions
- avoid char as argument in favour of u8
- handful of style/formatting fixes
- use standard led name ":white:kbd_backlight"
- rename USAGE_MAGIC_BL to HID_USAGE_MAGIC_BL

 MAINTAINERS                             |   6 ++
 drivers/hid/Kconfig                     |  13 +++
 drivers/hid/Makefile                    |   1 +
 drivers/hid/hid-apple-magic-backlight.c | 120 ++++++++++++++++++++++++
 4 files changed, 140 insertions(+)
 create mode 100644 drivers/hid/hid-apple-magic-backlight.c

diff --git a/MAINTAINERS b/MAINTAINERS
index fb1471cb5ed3..3319f0c3ed1e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9201,6 +9201,12 @@ F:	include/linux/pm.h
 F:	include/linux/suspend.h
 F:	kernel/power/
 
+HID APPLE MAGIC BACKLIGHT DRIVER
+M:	Orlando Chamberlain <orlandoch.dev@gmail.com>
+L:	linux-input@vger.kernel.org
+S:	Maintained
+F:	drivers/hid/apple-magic-backlight.c
+
 HID CORE LAYER
 M:	Jiri Kosina <jikos@kernel.org>
 M:	Benjamin Tissoires <benjamin.tissoires@redhat.com>
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index e2a5d30c8895..fe489632bfd9 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -130,6 +130,19 @@ config HID_APPLE
 	Say Y here if you want support for keyboards of	Apple iBooks, PowerBooks,
 	MacBooks, MacBook Pros and Apple Aluminum.
 
+config HID_APPLE_MAGIC_BACKLIGHT
+	tristate "Apple Magic Keyboard Backlight"
+	depends on USB_HID
+	depends on LEDS_CLASS
+	depends on NEW_LEDS
+	help
+	Say Y here if you want support for the keyboard backlight on Macs with
+	the magic keyboard (MacBookPro16,x and MacBookAir9,1). Note that this
+	driver is not for external magic keyboards.
+
+	To compile this driver as a module, choose M here: the
+	module will be called hid-apple-magic-backlight.
+
 config HID_APPLEIR
 	tristate "Apple infrared receiver"
 	depends on (USB_HID)
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index e8014c1a2f8b..dc8df002bc86 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_HID_ACCUTOUCH)	+= hid-accutouch.o
 obj-$(CONFIG_HID_ALPS)		+= hid-alps.o
 obj-$(CONFIG_HID_ACRUX)		+= hid-axff.o
 obj-$(CONFIG_HID_APPLE)		+= hid-apple.o
+obj-$(CONFIG_HID_APPLE_MAGIC_BACKLIGHT)	+= hid-apple-magic-backlight.o
 obj-$(CONFIG_HID_APPLEIR)	+= hid-appleir.o
 obj-$(CONFIG_HID_CREATIVE_SB0540)	+= hid-creative-sb0540.o
 obj-$(CONFIG_HID_ASUS)		+= hid-asus.o
diff --git a/drivers/hid/hid-apple-magic-backlight.c b/drivers/hid/hid-apple-magic-backlight.c
new file mode 100644
index 000000000000..f0fc02ff3b2d
--- /dev/null
+++ b/drivers/hid/hid-apple-magic-backlight.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Apple Magic Keyboard Backlight Driver
+ *
+ * For Intel Macs with internal Magic Keyboard (MacBookPro16,1-4 and MacBookAir9,1)
+ *
+ * Copyright (c) 2022 Kerem Karabay <kekrby@gmail.com>
+ * Copyright (c) 2023 Orlando Chamberlain <orlandoch.dev@gmail.com>
+ */
+
+#include <linux/hid.h>
+#include <linux/leds.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <dt-bindings/leds/common.h>
+
+#include "hid-ids.h"
+
+#define HID_USAGE_MAGIC_BL	0xff00000f
+
+#define APPLE_MAGIC_REPORT_ID_POWER 3
+#define APPLE_MAGIC_REPORT_ID_BRIGHTNESS 1
+
+struct apple_magic_backlight {
+	struct led_classdev cdev;
+	struct hid_report *brightness;
+	struct hid_report *power;
+};
+
+static void apple_magic_backlight_report_set(struct hid_report *rep, s32 value, u8 rate)
+{
+	rep->field[0]->value[0] = value;
+	rep->field[1]->value[0] = 0x5e; /* Mimic Windows */
+	rep->field[1]->value[0] |= rate << 8;
+
+	hid_hw_request(rep->device, rep, HID_REQ_SET_REPORT);
+}
+
+static void apple_magic_backlight_set(struct apple_magic_backlight *backlight,
+				     int brightness, char rate)
+{
+	apple_magic_backlight_report_set(backlight->power, brightness ? 1 : 0, rate);
+	if (brightness)
+		apple_magic_backlight_report_set(backlight->brightness, brightness, rate);
+}
+
+static int apple_magic_backlight_led_set(struct led_classdev *led_cdev,
+					 enum led_brightness brightness)
+{
+	struct apple_magic_backlight *backlight = container_of(led_cdev,
+			struct apple_magic_backlight, cdev);
+
+	apple_magic_backlight_set(backlight, brightness, 1);
+	return 0;
+}
+
+static int apple_magic_backlight_probe(struct hid_device *hdev,
+				       const struct hid_device_id *id)
+{
+	struct apple_magic_backlight *backlight;
+	int rc;
+
+	rc = hid_parse(hdev);
+	if (rc)
+		return rc;
+
+	/*
+	 * Ensure this usb endpoint is for the keyboard backlight, not touchbar
+	 * backlight.
+	 */
+	if (hdev->collection[0].usage != HID_USAGE_MAGIC_BL)
+		return -ENODEV;
+
+	backlight = devm_kzalloc(&hdev->dev, sizeof(*backlight), GFP_KERNEL);
+	if (!backlight)
+		return -ENOMEM;
+
+	rc = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (rc)
+		return rc;
+
+	backlight->brightness = hid_register_report(hdev, HID_FEATURE_REPORT,
+			APPLE_MAGIC_REPORT_ID_BRIGHTNESS, 0);
+	backlight->power = hid_register_report(hdev, HID_FEATURE_REPORT,
+			APPLE_MAGIC_REPORT_ID_POWER, 0);
+
+	if (!backlight->brightness || !backlight->power) {
+		rc = -ENODEV;
+		goto hw_stop;
+	}
+
+	backlight->cdev.name = ":white:" LED_FUNCTION_KBD_BACKLIGHT;
+	backlight->cdev.max_brightness = backlight->brightness->field[0]->logical_maximum;
+	backlight->cdev.brightness_set_blocking = apple_magic_backlight_led_set;
+
+	apple_magic_backlight_set(backlight, 0, 0);
+
+	return devm_led_classdev_register(&hdev->dev, &backlight->cdev);
+
+hw_stop:
+	hid_hw_stop(hdev);
+	return rc;
+}
+
+static const struct hid_device_id apple_magic_backlight_hid_ids[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, apple_magic_backlight_hid_ids);
+
+static struct hid_driver apple_magic_backlight_hid_driver = {
+	.name = "hid-apple-magic-backlight",
+	.id_table = apple_magic_backlight_hid_ids,
+	.probe = apple_magic_backlight_probe,
+};
+module_hid_driver(apple_magic_backlight_hid_driver);
+
+MODULE_DESCRIPTION("MacBook Magic Keyboard Backlight");
+MODULE_AUTHOR("Orlando Chamberlain <orlandoch.dev@gmail.com>");
+MODULE_LICENSE("GPL");
-- 
2.39.1


^ permalink raw reply related

* [PATCH v4 1/2] Documentation: leds: standardise keyboard backlight led names
From: Orlando Chamberlain @ 2023-02-18  9:07 UTC (permalink / raw)
  To: linux-doc, linux-input
  Cc: Jonathan Corbet, Jiri Kosina, Benjamin Tissoires, linux-kernel,
	Pavel Machek, Aditya Garg, Aun-Ali Zaidi, Kerem Karabay,
	Andy Shevchenko, Thomas Weißschuh, Orlando Chamberlain
In-Reply-To: <20230218090709.7467-1-orlandoch.dev@gmail.com>

Advice use of either "input*:*:kbd_backlight" or ":*:kbd_backlight". We
don't want people using vendor or product name (e.g. "smc", "apple",
"asus") as this information is available from sysfs anyway, and it made the
folder names inconsistent.

Signed-off-by: Orlando Chamberlain <orlandoch.dev@gmail.com>
---
 Documentation/leds/well-known-leds.txt | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/leds/well-known-leds.txt b/Documentation/leds/well-known-leds.txt
index 2160382c86be..4e5429fce4d8 100644
--- a/Documentation/leds/well-known-leds.txt
+++ b/Documentation/leds/well-known-leds.txt
@@ -44,6 +44,14 @@ Legacy: "lp5523:kb{1,2,3,4,5,6}" (Nokia N900)
 
 Frontlight/backlight of main keyboard.
 
+Good: ":*:kbd_backlight"
+Good: "input*:*:kbd_backlight"
+Legacy: "*:*:kbd_backlight"
+
+Many drivers have the vendor or product name as the first field of the led name,
+this makes names inconsistent and is redundant as that information is already in
+sysfs.
+
 Legacy: "button-backlight" (Motorola Droid 4)
 
 Some phones have touch buttons below screen; it is different from main
-- 
2.39.1


^ permalink raw reply related

* [PATCH v4 0/2] Apple Magic Keyboard Backlight
From: Orlando Chamberlain @ 2023-02-18  9:07 UTC (permalink / raw)
  To: linux-doc, linux-input
  Cc: Jonathan Corbet, Jiri Kosina, Benjamin Tissoires, linux-kernel,
	Pavel Machek, Aditya Garg, Aun-Ali Zaidi, Kerem Karabay,
	Andy Shevchenko, Thomas Weißschuh, Orlando Chamberlain

This patchseries adds support for the internal keyboard backlight of
Macs with Apple's "Magic" keyboard (MacBookPro16,* and MacBookAir9,1),
and also documents what names should be used for keyboard backlight
leds in Documentation/leds/well-known-leds.txt.

v3->v4:
- collect reviews from Andy and Thomas
- remove now unused hdev member of apple_magic_backlight

v2->v3:
- remove unneeded header inclusion
- use s32 for report value type
- remove unneeded null check
- don't set drvdata as its never used
- prepend "hid-" to module name

v1->v2:
- drop unneeded remove function
- combine set functions
- add missing header inclusions
- avoid char as argument in favour of u8
- handful of style/formatting fixes
- use standard led name ":white:kbd_backlight"
- rename USAGE_MAGIC_BL to HID_USAGE_MAGIC_BL
- New patch documenting preferred keyboard backlight names

v1: https://lore.kernel.org/linux-input/7D70F1FE-7F54-4D0A-8922-5466AA2AD364@live.com/
v2: https://lore.kernel.org/linux-input/20230216041224.4731-1-orlandoch.dev@gmail.com/
v3: https://lore.kernel.org/linux-input/20230217102319.3419-1-orlandoch.dev@gmail.com/

Orlando Chamberlain (2):
  Documentation: leds: standardise keyboard backlight led names
  HID: hid-apple-magic-backlight: Add driver for keyboard backlight on
    internal Magic Keyboards

 Documentation/leds/well-known-leds.txt  |   8 ++
 MAINTAINERS                             |   6 ++
 drivers/hid/Kconfig                     |  13 +++
 drivers/hid/Makefile                    |   1 +
 drivers/hid/hid-apple-magic-backlight.c | 120 ++++++++++++++++++++++++
 5 files changed, 148 insertions(+)
 create mode 100644 drivers/hid/hid-apple-magic-backlight.c

-- 
2.39.1


^ permalink raw reply

* Re: [PATCH v3 2/2] HID: hid-apple-magic-backlight: Add driver for keyboard backlight on internal Magic Keyboards
From: Orlando Chamberlain @ 2023-02-18  8:58 UTC (permalink / raw)
  To: Thomas Weißschuh
  Cc: linux-doc, linux-input, Jonathan Corbet, Jiri Kosina,
	Benjamin Tissoires, linux-kernel, Pavel Machek, Aditya Garg,
	Aun-Ali Zaidi, Kerem Karabay, Andy Shevchenko
In-Reply-To: <20230217141359.hisamhdmjr6tzklp@t-8ch.de>

On Fri, 17 Feb 2023 14:13:59 +0000
Thomas Weißschuh <thomas@t-8ch.de> wrote:

> On Fri, Feb 17, 2023 at 09:23:20PM +1100, Orlando Chamberlain wrote:
> > This driver adds support for the keyboard backlight on Intel T2 Macs
> > with internal Magic Keyboards (MacBookPro16,x and MacBookAir9,1)  
> 
> Reviewed-by: Thomas Weißschuh <linux@weissschuh.net>
> 
> One other tiny nitpick below, if it goes to v4.

Thanks, I'll send a v4 with that fixed.

> 
> > Co-developed-by: Kerem Karabay <kekrby@gmail.com>
> > Signed-off-by: Kerem Karabay <kekrby@gmail.com>
> > Signed-off-by: Orlando Chamberlain <orlandoch.dev@gmail.com>
> > ---
> > v2->v3:
> > - remove unneeded inclusion
> > - use s32 for report value type
> > - remove unneeded null check
> > - don't set drvdata as its never used
> > - prepend "hid-" to module name
> > v1->v2:
> > - drop unneeded remove function
> > - combine set functions
> > - add missing header inclusions
> > - avoid char as argument in favour of u8
> > - handful of style/formatting fixes
> > - use standard led name ":white:kbd_backlight"
> > - rename USAGE_MAGIC_BL to HID_USAGE_MAGIC_BL
> >  MAINTAINERS                             |   6 ++
> >  drivers/hid/Kconfig                     |  13 +++
> >  drivers/hid/Makefile                    |   1 +
> >  drivers/hid/hid-apple-magic-backlight.c | 122
> > ++++++++++++++++++++++++ 4 files changed, 142 insertions(+)
> >  create mode 100644 drivers/hid/hid-apple-magic-backlight.c
> > 
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index fb1471cb5ed3..3319f0c3ed1e 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -9201,6 +9201,12 @@ F:	include/linux/pm.h
> >  F:	include/linux/suspend.h
> >  F:	kernel/power/
> >  
> > +HID APPLE MAGIC BACKLIGHT DRIVER
> > +M:	Orlando Chamberlain <orlandoch.dev@gmail.com>
> > +L:	linux-input@vger.kernel.org
> > +S:	Maintained
> > +F:	drivers/hid/apple-magic-backlight.c
> > +
> >  HID CORE LAYER
> >  M:	Jiri Kosina <jikos@kernel.org>
> >  M:	Benjamin Tissoires <benjamin.tissoires@redhat.com>
> > diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> > index e2a5d30c8895..fe489632bfd9 100644
> > --- a/drivers/hid/Kconfig
> > +++ b/drivers/hid/Kconfig
> > @@ -130,6 +130,19 @@ config HID_APPLE
> >  	Say Y here if you want support for keyboards of
> > Apple iBooks, PowerBooks, MacBooks, MacBook Pros and Apple Aluminum.
> >  
> > +config HID_APPLE_MAGIC_BACKLIGHT
> > +	tristate "Apple Magic Keyboard Backlight"
> > +	depends on USB_HID
> > +	depends on LEDS_CLASS
> > +	depends on NEW_LEDS
> > +	help
> > +	Say Y here if you want support for the keyboard backlight
> > on Macs with
> > +	the magic keyboard (MacBookPro16,x and MacBookAir9,1).
> > Note that this
> > +	driver is not for external magic keyboards.
> > +
> > +	To compile this driver as a module, choose M here: the
> > +	module will be called hid-apple-magic-backlight.
> > +
> >  config HID_APPLEIR
> >  	tristate "Apple infrared receiver"
> >  	depends on (USB_HID)
> > diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> > index e8014c1a2f8b..dc8df002bc86 100644
> > --- a/drivers/hid/Makefile
> > +++ b/drivers/hid/Makefile
> > @@ -26,6 +26,7 @@ obj-$(CONFIG_HID_ACCUTOUCH)	+=
> > hid-accutouch.o obj-$(CONFIG_HID_ALPS)		+= hid-alps.o
> >  obj-$(CONFIG_HID_ACRUX)		+= hid-axff.o
> >  obj-$(CONFIG_HID_APPLE)		+= hid-apple.o
> > +obj-$(CONFIG_HID_APPLE_MAGIC_BACKLIGHT)	+=
> > hid-apple-magic-backlight.o obj-$(CONFIG_HID_APPLEIR)	+=
> > hid-appleir.o obj-$(CONFIG_HID_CREATIVE_SB0540)	+=
> > hid-creative-sb0540.o obj-$(CONFIG_HID_ASUS)		+=
> > hid-asus.o diff --git a/drivers/hid/hid-apple-magic-backlight.c
> > b/drivers/hid/hid-apple-magic-backlight.c new file mode 100644
> > index 000000000000..210af2849e78
> > --- /dev/null
> > +++ b/drivers/hid/hid-apple-magic-backlight.c
> > @@ -0,0 +1,122 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Apple Magic Keyboard Backlight Driver
> > + *
> > + * For Intel Macs with internal Magic Keyboard (MacBookPro16,1-4
> > and MacBookAir9,1)
> > + *
> > + * Copyright (c) 2022 Kerem Karabay <kekrby@gmail.com>
> > + * Copyright (c) 2023 Orlando Chamberlain <orlandoch.dev@gmail.com>
> > + */
> > +
> > +#include <linux/hid.h>
> > +#include <linux/leds.h>
> > +#include <linux/device.h>
> > +#include <linux/errno.h>
> > +#include <dt-bindings/leds/common.h>
> > +
> > +#include "hid-ids.h"
> > +
> > +#define HID_USAGE_MAGIC_BL	0xff00000f
> > +
> > +#define APPLE_MAGIC_REPORT_ID_POWER 3
> > +#define APPLE_MAGIC_REPORT_ID_BRIGHTNESS 1
> > +
> > +struct apple_magic_backlight {
> > +	struct led_classdev cdev;
> > +	struct hid_device *hdev;  
> 
> hdev is not used anymore.
> 
> > +	struct hid_report *brightness;
> > +	struct hid_report *power;
> > +};
> > +
> > +static void apple_magic_backlight_report_set(struct hid_report
> > *rep, s32 value, u8 rate) +{
> > +	rep->field[0]->value[0] = value;
> > +	rep->field[1]->value[0] = 0x5e; /* Mimic Windows */
> > +	rep->field[1]->value[0] |= rate << 8;
> > +
> > +	hid_hw_request(rep->device, rep, HID_REQ_SET_REPORT);
> > +}
> > +
> > +static void apple_magic_backlight_set(struct apple_magic_backlight
> > *backlight,
> > +				     int brightness, char rate)
> > +{
> > +	apple_magic_backlight_report_set(backlight->power,
> > brightness ? 1 : 0, rate);
> > +	if (brightness)
> > +
> > apple_magic_backlight_report_set(backlight->brightness, brightness,
> > rate); +} +
> > +static int apple_magic_backlight_led_set(struct led_classdev
> > *led_cdev,
> > +					 enum led_brightness
> > brightness) +{
> > +	struct apple_magic_backlight *backlight =
> > container_of(led_cdev,
> > +			struct apple_magic_backlight, cdev);
> > +
> > +	apple_magic_backlight_set(backlight, brightness, 1);
> > +	return 0;
> > +}
> > +
> > +static int apple_magic_backlight_probe(struct hid_device *hdev,
> > +				       const struct hid_device_id
> > *id) +{
> > +	struct apple_magic_backlight *backlight;
> > +	int rc;
> > +
> > +	rc = hid_parse(hdev);
> > +	if (rc)
> > +		return rc;
> > +
> > +	/*
> > +	 * Ensure this usb endpoint is for the keyboard backlight,
> > not touchbar
> > +	 * backlight.
> > +	 */
> > +	if (hdev->collection[0].usage != HID_USAGE_MAGIC_BL)
> > +		return -ENODEV;
> > +
> > +	backlight = devm_kzalloc(&hdev->dev, sizeof(*backlight),
> > GFP_KERNEL);
> > +	if (!backlight)
> > +		return -ENOMEM;
> > +
> > +	rc = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> > +	if (rc)
> > +		return rc;
> > +
> > +	backlight->brightness = hid_register_report(hdev,
> > HID_FEATURE_REPORT,
> > +			APPLE_MAGIC_REPORT_ID_BRIGHTNESS, 0);
> > +	backlight->power = hid_register_report(hdev,
> > HID_FEATURE_REPORT,
> > +			APPLE_MAGIC_REPORT_ID_POWER, 0);
> > +
> > +	if (!backlight->brightness || !backlight->power) {
> > +		rc = -ENODEV;
> > +		goto hw_stop;
> > +	}
> > +
> > +	backlight->hdev = hdev;
> > +	backlight->cdev.name = ":white:"
> > LED_FUNCTION_KBD_BACKLIGHT;
> > +	backlight->cdev.max_brightness =
> > backlight->brightness->field[0]->logical_maximum;
> > +	backlight->cdev.brightness_set_blocking =
> > apple_magic_backlight_led_set; +
> > +	apple_magic_backlight_set(backlight, 0, 0);
> > +
> > +	return devm_led_classdev_register(&hdev->dev,
> > &backlight->cdev); +
> > +hw_stop:
> > +	hid_hw_stop(hdev);
> > +	return rc;
> > +}
> > +
> > +static const struct hid_device_id apple_magic_backlight_hid_ids[]
> > = {
> > +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
> > USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT) },
> > +	{ }
> > +};
> > +MODULE_DEVICE_TABLE(hid, apple_magic_backlight_hid_ids);
> > +
> > +static struct hid_driver apple_magic_backlight_hid_driver = {
> > +	.name = "hid-apple-magic-backlight",
> > +	.id_table = apple_magic_backlight_hid_ids,
> > +	.probe = apple_magic_backlight_probe,
> > +};
> > +module_hid_driver(apple_magic_backlight_hid_driver);
> > +
> > +MODULE_DESCRIPTION("MacBook Magic Keyboard Backlight");
> > +MODULE_AUTHOR("Orlando Chamberlain <orlandoch.dev@gmail.com>");
> > +MODULE_LICENSE("GPL");
> > -- 
> > 2.39.1
> >   


^ permalink raw reply

* Re: [PATCH] Input: mainstone: fix pxa2xx_ac97 dependency
From: Robert Jarzmik @ 2023-02-17 21:12 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Dmitry Torokhov, Robert Jarzmik, Arnd Bergmann, Mark Brown,
	alsa-devel, linux-input, linux-kernel
In-Reply-To: <20230214090728.1737140-1-arnd@kernel.org>


Arnd Bergmann <arnd@kernel.org> writes:

> From: Arnd Bergmann <arnd@arndb.de>
... zip ...
>
> Fixes: e217b085a1ac ("Input: touchscreen: use wrapper for pxa2xx 
> ac97 registers")
> Fixes: b401d1fd8053 ("ASoC: pxa: remove unused board support")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Robert Jarzmik <robert.jarzmik@free.fr>

Cheers.

--
Robert

^ permalink raw reply

* Re: [PATCH v6 3/3] HID: cp2112: Fwnode Support
From: Andy Shevchenko @ 2023-02-17 19:13 UTC (permalink / raw)
  To: Danny Kaehn
  Cc: robh+dt, krzysztof.kozlowski+dt, jikos, benjamin.tissoires,
	bartosz.golaszewski, dmitry.torokhov, devicetree, linux-input,
	ethan.twardy
In-Reply-To: <20230217184904.1290-4-kaehndan@gmail.com>

On Fri, Feb 17, 2023 at 12:49:04PM -0600, Danny Kaehn wrote:
> Bind i2c and gpio interfaces to subnodes with names

I2C
GPIO

> "i2c" and "gpio" if they exist, respectively. This
> allows the gpio and i2c controllers to be described

GPIO
I2C

> in firmware as usual. Additionally, support configuring the
> i2c bus speed from the clock-frequency device property.

I2C

...

> +err_free_i2c_of:
> +	fwnode_handle_put(dev->adap.dev.fwnode);

Please, use dev_fwnode(&dev->adap.dev)

...

> +	fwnode_handle_put(dev->adap.dev.fwnode);

Ditto.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [PATCH v6 2/3] HID: usbhid: Share USB device firmware node with child HID device
From: Andy Shevchenko @ 2023-02-17 19:10 UTC (permalink / raw)
  To: Danny Kaehn
  Cc: robh+dt, krzysztof.kozlowski+dt, jikos, benjamin.tissoires,
	bartosz.golaszewski, dmitry.torokhov, devicetree, linux-input,
	ethan.twardy
In-Reply-To: <20230217184904.1290-3-kaehndan@gmail.com>

On Fri, Feb 17, 2023 at 12:49:03PM -0600, Danny Kaehn wrote:
> USB HID core now shares its fwnode with its child HID device.
> Since there can only be one HID device on a USB interface, it is redundant
> to specify a hid node under the USB device. This allows usb HID device
> drivers to be described in firmware and make use of device properties.

FWIW,
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> Signed-off-by: Danny Kaehn <kaehndan@gmail.com>
> ---
>  drivers/hid/usbhid/hid-core.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
> index be4c731aaa65..a0859c49d9f4 100644
> --- a/drivers/hid/usbhid/hid-core.c
> +++ b/drivers/hid/usbhid/hid-core.c
> @@ -19,6 +19,7 @@
>  #include <linux/list.h>
>  #include <linux/mm.h>
>  #include <linux/mutex.h>
> +#include <linux/property.h>
>  #include <linux/spinlock.h>
>  #include <asm/unaligned.h>
>  #include <asm/byteorder.h>
> @@ -1369,6 +1370,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
>  	hid->hiddev_report_event = hiddev_report_event;
>  #endif
>  	hid->dev.parent = &intf->dev;
> +	device_set_node(&hid->dev, dev_fwnode(&intf->dev));
>  	hid->bus = BUS_USB;
>  	hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
>  	hid->product = le16_to_cpu(dev->descriptor.idProduct);
> -- 
> 2.25.1
> 

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* [PATCH v6 3/3] HID: cp2112: Fwnode Support
From: Danny Kaehn @ 2023-02-17 18:49 UTC (permalink / raw)
  To: robh+dt, krzysztof.kozlowski+dt, jikos, benjamin.tissoires
  Cc: bartosz.golaszewski, andriy.shevchenko, dmitry.torokhov,
	devicetree, linux-input, ethan.twardy
In-Reply-To: <20230217184904.1290-1-kaehndan@gmail.com>

Bind i2c and gpio interfaces to subnodes with names
"i2c" and "gpio" if they exist, respectively. This
allows the gpio and i2c controllers to be described
in firmware as usual. Additionally, support configuring the
i2c bus speed from the clock-frequency device property.

Signed-off-by: Danny Kaehn <kaehndan@gmail.com>
---
 drivers/hid/hid-cp2112.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index 27cadadda7c9..0013bf863f0f 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -1234,6 +1234,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	u8 buf[3];
 	struct cp2112_smbus_config_report config;
 	struct gpio_irq_chip *girq;
+	struct i2c_timings timings;
 	int ret;
 
 	dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL);
@@ -1292,6 +1293,10 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
 		goto err_power_normal;
 	}
 
+	device_set_node(&dev->adap.dev, device_get_named_child_node(&hdev->dev, "i2c"));
+	i2c_parse_fw_timings(&dev->adap.dev, &timings, true);
+
+	config.clock_speed = cpu_to_be32(timings.bus_freq_hz);
 	config.retry_time = cpu_to_be16(1);
 
 	ret = cp2112_hid_output(hdev, (u8 *)&config, sizeof(config),
@@ -1300,7 +1305,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
 		hid_err(hdev, "error setting SMBus config\n");
 		if (ret >= 0)
 			ret = -EIO;
-		goto err_power_normal;
+		goto err_free_i2c_of;
 	}
 
 	hid_set_drvdata(hdev, (void *)dev);
@@ -1322,7 +1327,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
 	if (ret) {
 		hid_err(hdev, "error registering i2c adapter\n");
-		goto err_power_normal;
+		goto err_free_i2c_of;
 	}
 
 	hid_dbg(hdev, "adapter registered\n");
@@ -1336,6 +1341,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	dev->gc.ngpio			= 8;
 	dev->gc.can_sleep		= 1;
 	dev->gc.parent			= &hdev->dev;
+	dev->gc.fwnode			= device_get_named_child_node(&hdev->dev, "gpio");
 
 	dev->irq.name = "cp2112-gpio";
 	dev->irq.irq_startup = cp2112_gpio_irq_startup;
@@ -1376,7 +1382,10 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id)
 err_gpiochip_remove:
 	gpiochip_remove(&dev->gc);
 err_free_i2c:
+	fwnode_handle_put(dev->gc.fwnode);
 	i2c_del_adapter(&dev->adap);
+err_free_i2c_of:
+	fwnode_handle_put(dev->adap.dev.fwnode);
 err_power_normal:
 	hid_hw_power(hdev, PM_HINT_NORMAL);
 err_hid_close:
@@ -1391,6 +1400,8 @@ static void cp2112_remove(struct hid_device *hdev)
 	struct cp2112_device *dev = hid_get_drvdata(hdev);
 	int i;
 
+	fwnode_handle_put(dev->gc.fwnode);
+	fwnode_handle_put(dev->adap.dev.fwnode);
 	sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group);
 	i2c_del_adapter(&dev->adap);
 
-- 
2.25.1


^ permalink raw reply related

* [PATCH v6 2/3] HID: usbhid: Share USB device firmware node with child HID device
From: Danny Kaehn @ 2023-02-17 18:49 UTC (permalink / raw)
  To: robh+dt, krzysztof.kozlowski+dt, jikos, benjamin.tissoires
  Cc: bartosz.golaszewski, andriy.shevchenko, dmitry.torokhov,
	devicetree, linux-input, ethan.twardy
In-Reply-To: <20230217184904.1290-1-kaehndan@gmail.com>

USB HID core now shares its fwnode with its child HID device.
Since there can only be one HID device on a USB interface, it is redundant
to specify a hid node under the USB device. This allows usb HID device
drivers to be described in firmware and make use of device properties.

Signed-off-by: Danny Kaehn <kaehndan@gmail.com>
---
 drivers/hid/usbhid/hid-core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index be4c731aaa65..a0859c49d9f4 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -19,6 +19,7 @@
 #include <linux/list.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
+#include <linux/property.h>
 #include <linux/spinlock.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
@@ -1369,6 +1370,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
 	hid->hiddev_report_event = hiddev_report_event;
 #endif
 	hid->dev.parent = &intf->dev;
+	device_set_node(&hid->dev, dev_fwnode(&intf->dev));
 	hid->bus = BUS_USB;
 	hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
 	hid->product = le16_to_cpu(dev->descriptor.idProduct);
-- 
2.25.1


^ permalink raw reply related

* [PATCH v6 1/3] dt-bindings: i2c: Add CP2112 HID USB to SMBus Bridge
From: Danny Kaehn @ 2023-02-17 18:49 UTC (permalink / raw)
  To: robh+dt, krzysztof.kozlowski+dt, jikos, benjamin.tissoires
  Cc: bartosz.golaszewski, andriy.shevchenko, dmitry.torokhov,
	devicetree, linux-input, ethan.twardy
In-Reply-To: <20230217184904.1290-1-kaehndan@gmail.com>

This is a USB HID device which includes an I2C controller and 8 GPIO pins.

The binding allows describing the chip's gpio and i2c controller in DT
using the subnodes named "gpio" and "i2c", respectively. This is
intended to be used in configurations where the CP2112 is permanently
connected in hardware.

Signed-off-by: Danny Kaehn <kaehndan@gmail.com>
---
 .../bindings/i2c/silabs,cp2112.yaml           | 113 ++++++++++++++++++
 1 file changed, 113 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/i2c/silabs,cp2112.yaml

diff --git a/Documentation/devicetree/bindings/i2c/silabs,cp2112.yaml b/Documentation/devicetree/bindings/i2c/silabs,cp2112.yaml
new file mode 100644
index 000000000000..a27509627804
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/silabs,cp2112.yaml
@@ -0,0 +1,113 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/i2c/silabs,cp2112.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: CP2112 HID USB to SMBus/I2C Bridge
+
+maintainers:
+  - Danny Kaehn <kaehndan@gmail.com>
+
+description:
+  The CP2112 is a USB HID device which includes an integrated I2C controller
+  and 8 GPIO pins. Its GPIO pins can each be configured as inputs, open-drain
+  outputs, or push-pull outputs.
+
+properties:
+  compatible:
+    const: usb10c4,ea90
+
+  reg:
+    maxItems: 1
+    description: The USB port number on the host controller
+
+  i2c:
+    description: The SMBus/I2C controller node for the CP2112
+    $ref: /schemas/i2c/i2c-controller.yaml#
+    unevaluatedProperties: false
+
+    properties:
+      sda-gpios:
+        maxItems: 1
+
+      scl-gpios:
+        maxItems: 1
+
+      clock-frequency:
+        minimum: 10000
+        default: 100000
+        maximum: 400000
+
+  gpio:
+    description: The GPIO controller node for the CP2112
+    type: object
+    unevaluatedProperties: false
+
+    properties:
+      interrupt-controller: true
+      "#interrupt-cells":
+        const: 2
+
+      gpio-controller: true
+      "#gpio-cells":
+        const: 2
+
+      gpio-line-names:
+        minItems: 1
+        maxItems: 8
+
+    patternProperties:
+      "-hog(-[0-9]+)?$":
+        type: object
+
+        required:
+          - gpio-hog
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/gpio/gpio.h>
+
+    usb {
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      device@1 {
+        compatible = "usb10c4,ea90";
+        reg = <1>;
+
+        i2c {
+          #address-cells = <1>;
+          #size-cells = <0>;
+          sda-gpios = <&cp2112_gpio 0 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+          scl-gpios = <&cp2112_gpio 1 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+
+          temp@48 {
+            compatible = "national,lm75";
+            reg = <0x48>;
+          };
+        };
+
+        cp2112_gpio: gpio {
+          gpio-controller;
+          interrupt-controller;
+          #gpio-cells = <2>;
+          gpio-line-names = "CP2112_SDA", "CP2112_SCL", "TEST2",
+            "TEST3","TEST4", "TEST5", "TEST6";
+
+          fan-rst-hog {
+              gpio-hog;
+              gpios = <7 GPIO_ACTIVE_HIGH>;
+              output-high;
+              line-name = "FAN_RST";
+          };
+        };
+      };
+    };
-- 
2.25.1


^ permalink raw reply related

* [PATCH v6 0/3] Firmware Support for USB-HID Devices and CP2112
From: Danny Kaehn @ 2023-02-17 18:49 UTC (permalink / raw)
  To: robh+dt, krzysztof.kozlowski+dt, jikos, benjamin.tissoires
  Cc: bartosz.golaszewski, andriy.shevchenko, dmitry.torokhov,
	devicetree, linux-input, ethan.twardy

This patchset allows USB-HID devices to have DeviceTree bindings through sharing
the USB of_node with the HID driver, and adds such a binding and driver
implementation for the CP2112 USB to SMBus Bridge (which necessitated the
USB-HID change). This change allows a CP2112 permanently attached in hardware to
be described in DT and interoperate with other drivers.

Changes in v6:
- Fix fwnode_handle reference leaks in hid-cp21112.c
- Simplify hog node pattern in silabs,cp2112.yaml

Changes in v5:
 - Use fwnode API instead of of_node api in hid-core.c and hid-cp2112.c
 - Include sda-gpios and scl-gpios in silabs,cp2112.yaml
 - Additional fixups to silabs,cp2112.yaml to address comments
 - Submit threaded interrupt bugfix separately from this patchset, as requested

Changes in v4:
 - Moved silabs,cp2112.yaml to /Documentation/devicetree/bindings/i2c

Changes in v3:
 - Additional fixups to silabs,cp2112.yaml to address comments

Changes in v2:
 - Added more detail to silabs,cp2112.yaml dt-binding
 - Moved silabs,cp2112.yaml to /Documentation/devicetree/bindings/input
 - Added support for setting smbus clock-frequency from DT in hid-cp2112.c
 - Added freeing of of_nodes on error paths of _probe in hid-cp2112.c

Danny Kaehn (3):
  dt-bindings: i2c: Add CP2112 HID USB to SMBus Bridge
  HID: usbhid: Share USB device firmware node with child HID device
  HID: cp2112: Fwnode Support

 .../bindings/i2c/silabs,cp2112.yaml           | 113 ++++++++++++++++++
 drivers/hid/hid-cp2112.c                      |  15 ++-
 drivers/hid/usbhid/hid-core.c                 |   2 +
 3 files changed, 128 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/i2c/silabs,cp2112.yaml

-- 
2.25.1


^ permalink raw reply

* Re: [PATCH 06/11] selftests: hid: import hid-tools hid-multitouch and hid-tablets tests
From: Ahelenia Ziemiańska @ 2023-02-17 16:38 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Jiri Kosina, Shuah Khan, linux-input, linux-kselftest,
	linux-kernel
In-Reply-To: <20230217-import-hid-tools-tests-v1-6-d1c48590d0ee@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 1416 bytes --]

On Fri, Feb 17, 2023 at 05:18:00PM +0100, Benjamin Tissoires wrote:
> These tests have been developed in the hid-tools[0] tree for a while.
> Now that we have  a proper selftests/hid kernel entry and that the tests
> are more reliable, it is time to directly include those in the kernel
> tree.
> 
> There are a lot of multitouch tests, and the default timeout of 45 seconds
> is not big enough. Bump it to 200 seconds.
> 
> [0] https://gitlab.freedesktop.org/libevdev/hid-tools
> 
> Cc: Peter Hutterer <peter.hutterer@who-t.net>
> Cc: Kai-Heng Feng <kai.heng.feng@canonical.com>
> Cc: Roderick Colenbrander <roderick.colenbrander@sony.com>
> Cc: наб <nabijaczleweli@nabijaczleweli.xyz>
> Cc: Blaž Hrastnik <blaz@mxxn.io>
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> ---
>  tools/testing/selftests/hid/Makefile               |    2 +
>  tools/testing/selftests/hid/config                 |    1 +
>  tools/testing/selftests/hid/hid-multitouch.sh      |    7 +
>  tools/testing/selftests/hid/hid-tablet.sh          |    7 +
>  tools/testing/selftests/hid/settings               |    3 +
>  .../testing/selftests/hid/tests/test_multitouch.py | 2088 ++++++++++++++++++++
>  tools/testing/selftests/hid/tests/test_tablet.py   |  872 ++++++++
>  7 files changed, 2980 insertions(+)

Signed-off-by: Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>

Best,

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* [PATCH 11/11] selftests: hid: import hid-tools usb-crash tests
From: Benjamin Tissoires @ 2023-02-17 16:18 UTC (permalink / raw)
  To: Jiri Kosina, Shuah Khan
  Cc: linux-input, linux-kselftest, linux-kernel, Benjamin Tissoires
In-Reply-To: <20230217-import-hid-tools-tests-v1-0-d1c48590d0ee@redhat.com>

These tests have been developed in the hid-tools[0] tree for a while.
Now that we have  a proper selftests/hid kernel entry and that the tests
are more reliable, it is time to directly include those in the kernel
tree.

This one gets skipped when run by vmtest.sh as we currently need to test
against actual kernel modules (.ko), not built-in to fetch the list
of supported devices.

[0] https://gitlab.freedesktop.org/libevdev/hid-tools

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 tools/testing/selftests/hid/Makefile               |   1 +
 tools/testing/selftests/hid/hid-usb_crash.sh       |   7 ++
 .../testing/selftests/hid/tests/test_usb_crash.py  | 103 +++++++++++++++++++++
 3 files changed, 111 insertions(+)

diff --git a/tools/testing/selftests/hid/Makefile b/tools/testing/selftests/hid/Makefile
index dcea4f1e9369..01c0491d64da 100644
--- a/tools/testing/selftests/hid/Makefile
+++ b/tools/testing/selftests/hid/Makefile
@@ -14,6 +14,7 @@ TEST_PROGS += hid-mouse.sh
 TEST_PROGS += hid-multitouch.sh
 TEST_PROGS += hid-sony.sh
 TEST_PROGS += hid-tablet.sh
+TEST_PROGS += hid-usb_crash.sh
 TEST_PROGS += hid-wacom.sh
 
 CXX ?= $(CROSS_COMPILE)g++
diff --git a/tools/testing/selftests/hid/hid-usb_crash.sh b/tools/testing/selftests/hid/hid-usb_crash.sh
new file mode 100755
index 000000000000..3f0debe7e8fd
--- /dev/null
+++ b/tools/testing/selftests/hid/hid-usb_crash.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# Runs tests for the HID subsystem
+
+export TARGET=test_usb_crash.py
+
+bash ./run-hid-tools-tests.sh
diff --git a/tools/testing/selftests/hid/tests/test_usb_crash.py b/tools/testing/selftests/hid/tests/test_usb_crash.py
new file mode 100644
index 000000000000..e98bff9197c7
--- /dev/null
+++ b/tools/testing/selftests/hid/tests/test_usb_crash.py
@@ -0,0 +1,103 @@
+#!/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2021 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+# Copyright (c) 2021 Red Hat, Inc.
+#
+
+# This is to ensure we don't crash when emulating USB devices
+
+from . import base
+import pytest
+import logging
+
+logger = logging.getLogger("hidtools.test.usb")
+
+
+class USBDev(base.UHIDTestDevice):
+    # fmt: off
+    report_descriptor = [
+        0x05, 0x01,  # .Usage Page (Generic Desktop)        0
+        0x09, 0x02,  # .Usage (Mouse)                       2
+        0xa1, 0x01,  # .Collection (Application)            4
+        0x09, 0x02,  # ..Usage (Mouse)                      6
+        0xa1, 0x02,  # ..Collection (Logical)               8
+        0x09, 0x01,  # ...Usage (Pointer)                   10
+        0xa1, 0x00,  # ...Collection (Physical)             12
+        0x05, 0x09,  # ....Usage Page (Button)              14
+        0x19, 0x01,  # ....Usage Minimum (1)                16
+        0x29, 0x03,  # ....Usage Maximum (3)                18
+        0x15, 0x00,  # ....Logical Minimum (0)              20
+        0x25, 0x01,  # ....Logical Maximum (1)              22
+        0x75, 0x01,  # ....Report Size (1)                  24
+        0x95, 0x03,  # ....Report Count (3)                 26
+        0x81, 0x02,  # ....Input (Data,Var,Abs)             28
+        0x75, 0x05,  # ....Report Size (5)                  30
+        0x95, 0x01,  # ....Report Count (1)                 32
+        0x81, 0x03,  # ....Input (Cnst,Var,Abs)             34
+        0x05, 0x01,  # ....Usage Page (Generic Desktop)     36
+        0x09, 0x30,  # ....Usage (X)                        38
+        0x09, 0x31,  # ....Usage (Y)                        40
+        0x15, 0x81,  # ....Logical Minimum (-127)           42
+        0x25, 0x7f,  # ....Logical Maximum (127)            44
+        0x75, 0x08,  # ....Report Size (8)                  46
+        0x95, 0x02,  # ....Report Count (2)                 48
+        0x81, 0x06,  # ....Input (Data,Var,Rel)             50
+        0xc0,        # ...End Collection                    52
+        0xc0,        # ..End Collection                     53
+        0xc0,        # .End Collection                      54
+    ]
+    # fmt: on
+
+    def __init__(self, name=None, input_info=None):
+        super().__init__(
+            name, "Mouse", input_info=input_info, rdesc=USBDev.report_descriptor
+        )
+
+    # skip witing for udev events, it's likely that the report
+    # descriptor is wrong
+    def is_ready(self):
+        return True
+
+    # we don't have an evdev node here, so paper over
+    # the checks
+    def get_evdev(self, application=None):
+        return "OK"
+
+
+class TestUSBDevice(base.BaseTestCase.TestUhid):
+    """
+    Test class to test if an emulated USB device crashes
+    the kernel.
+    """
+
+    # conftest.py is generating the following fixture:
+    #
+    # @pytest.fixture(params=[('modulename', 1, 2)])
+    # def usbVidPid(self, request):
+    #     return request.param
+
+    @pytest.fixture()
+    def new_uhdev(self, usbVidPid, request):
+        self.module, self.vid, self.pid = usbVidPid
+        self._load_kernel_module(None, self.module)
+        return USBDev(input_info=(3, self.vid, self.pid))
+
+    def test_creation(self):
+        """
+        inject the USB dev through uhid and immediately see if there is a crash:
+
+        uhid can create a USB device with the BUS_USB bus, and some
+        drivers assume that they can then access USB related structures
+        when they are actually provided a uhid device. This leads to
+        a crash because those access result in a segmentation fault.
+
+        The kernel should not crash on any (random) user space correct
+        use of its API. So run through all available modules and declared
+        devices to see if we can generate a uhid device without a crash.
+
+        The test is empty as the fixture `check_taint` is doing the job (and
+        honestly, when the kernel crashes, the whole machine freezes).
+        """
+        assert True

-- 
2.39.1


^ permalink raw reply related

* [PATCH 10/11] selftests: hid: import hid-tools hid-sony and hid-playstation tests
From: Benjamin Tissoires @ 2023-02-17 16:18 UTC (permalink / raw)
  To: Jiri Kosina, Shuah Khan
  Cc: linux-input, linux-kselftest, linux-kernel, Benjamin Tissoires,
	Roderick Colenbrander, Jose Torreguitar
In-Reply-To: <20230217-import-hid-tools-tests-v1-0-d1c48590d0ee@redhat.com>

These tests have been developed in the hid-tools[0] tree for a while.
Now that we have  a proper selftests/hid kernel entry and that the tests
are more reliable, it is time to directly include those in the kernel
tree.

[0] https://gitlab.freedesktop.org/libevdev/hid-tools

Cc: Roderick Colenbrander <roderick.colenbrander@sony.com>
Cc: Jose Torreguitar <jtguitar@google.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 tools/testing/selftests/hid/Makefile           |   1 +
 tools/testing/selftests/hid/config             |   5 +
 tools/testing/selftests/hid/hid-sony.sh        |   7 +
 tools/testing/selftests/hid/tests/test_sony.py | 282 +++++++++++++++++++++++++
 4 files changed, 295 insertions(+)

diff --git a/tools/testing/selftests/hid/Makefile b/tools/testing/selftests/hid/Makefile
index 3ca696c44aab..dcea4f1e9369 100644
--- a/tools/testing/selftests/hid/Makefile
+++ b/tools/testing/selftests/hid/Makefile
@@ -12,6 +12,7 @@ TEST_PROGS += hid-ite.sh
 TEST_PROGS += hid-keyboard.sh
 TEST_PROGS += hid-mouse.sh
 TEST_PROGS += hid-multitouch.sh
+TEST_PROGS += hid-sony.sh
 TEST_PROGS += hid-tablet.sh
 TEST_PROGS += hid-wacom.sh
 
diff --git a/tools/testing/selftests/hid/config b/tools/testing/selftests/hid/config
index f400b8d94e3c..442a5ea16325 100644
--- a/tools/testing/selftests/hid/config
+++ b/tools/testing/selftests/hid/config
@@ -19,9 +19,14 @@ CONFIG_HIDRAW=y
 CONFIG_HID=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_UHID=y
+CONFIG_LEDS_CLASS_MULTICOLOR=y
 CONFIG_USB=y
 CONFIG_USB_HID=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_ITE=y
 CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_PLAYSTATION=y
+CONFIG_PLAYSTATION_FF=y
+CONFIG_HID_SONY=y
+CONFIG_SONY_FF=y
 CONFIG_HID_WACOM=y
diff --git a/tools/testing/selftests/hid/hid-sony.sh b/tools/testing/selftests/hid/hid-sony.sh
new file mode 100755
index 000000000000..c863c442686e
--- /dev/null
+++ b/tools/testing/selftests/hid/hid-sony.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# Runs tests for the HID subsystem
+
+export TARGET=test_sony.py
+
+bash ./run-hid-tools-tests.sh
diff --git a/tools/testing/selftests/hid/tests/test_sony.py b/tools/testing/selftests/hid/tests/test_sony.py
new file mode 100644
index 000000000000..c80f50ed29d3
--- /dev/null
+++ b/tools/testing/selftests/hid/tests/test_sony.py
@@ -0,0 +1,282 @@
+#!/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2020 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+# Copyright (c) 2020 Red Hat, Inc.
+#
+
+from .base import application_matches
+from .test_gamepad import BaseTest
+from hidtools.device.sony_gamepad import (
+    PS3Controller,
+    PS4ControllerBluetooth,
+    PS4ControllerUSB,
+    PS5ControllerBluetooth,
+    PS5ControllerUSB,
+    PSTouchPoint,
+)
+from hidtools.util import BusType
+
+import libevdev
+import logging
+import pytest
+
+logger = logging.getLogger("hidtools.test.sony")
+
+PS3_MODULE = ("sony", "hid_sony")
+PS4_MODULE = ("playstation", "hid_playstation")
+PS5_MODULE = ("playstation", "hid_playstation")
+
+
+class SonyBaseTest:
+    class SonyTest(BaseTest.TestGamepad):
+        pass
+
+    class SonyPS4ControllerTest(SonyTest):
+        kernel_modules = [PS4_MODULE]
+
+        def test_accelerometer(self):
+            uhdev = self.uhdev
+            evdev = uhdev.get_evdev("Accelerometer")
+
+            for x in range(-32000, 32000, 4000):
+                r = uhdev.event(accel=(x, None, None))
+                events = uhdev.next_sync_events("Accelerometer")
+                self.debug_reports(r, uhdev, events)
+
+                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_X) in events
+                value = evdev.value[libevdev.EV_ABS.ABS_X]
+                # Check against range due to small loss in precision due
+                # to inverse calibration, followed by calibration by hid-sony.
+                assert x - 1 <= value <= x + 1
+
+            for y in range(-32000, 32000, 4000):
+                r = uhdev.event(accel=(None, y, None))
+                events = uhdev.next_sync_events("Accelerometer")
+                self.debug_reports(r, uhdev, events)
+
+                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_Y) in events
+                value = evdev.value[libevdev.EV_ABS.ABS_Y]
+                assert y - 1 <= value <= y + 1
+
+            for z in range(-32000, 32000, 4000):
+                r = uhdev.event(accel=(None, None, z))
+                events = uhdev.next_sync_events("Accelerometer")
+                self.debug_reports(r, uhdev, events)
+
+                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_Z) in events
+                value = evdev.value[libevdev.EV_ABS.ABS_Z]
+                assert z - 1 <= value <= z + 1
+
+        def test_gyroscope(self):
+            uhdev = self.uhdev
+            evdev = uhdev.get_evdev("Accelerometer")
+
+            for rx in range(-2000000, 2000000, 200000):
+                r = uhdev.event(gyro=(rx, None, None))
+                events = uhdev.next_sync_events("Accelerometer")
+                self.debug_reports(r, uhdev, events)
+
+                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_RX) in events
+                value = evdev.value[libevdev.EV_ABS.ABS_RX]
+                # Sensor internal value is 16-bit, but calibrated is 22-bit, so
+                # 6-bit (64) difference, so allow a range of +/- 64.
+                assert rx - 64 <= value <= rx + 64
+
+            for ry in range(-2000000, 2000000, 200000):
+                r = uhdev.event(gyro=(None, ry, None))
+                events = uhdev.next_sync_events("Accelerometer")
+                self.debug_reports(r, uhdev, events)
+
+                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_RY) in events
+                value = evdev.value[libevdev.EV_ABS.ABS_RY]
+                assert ry - 64 <= value <= ry + 64
+
+            for rz in range(-2000000, 2000000, 200000):
+                r = uhdev.event(gyro=(None, None, rz))
+                events = uhdev.next_sync_events("Accelerometer")
+                self.debug_reports(r, uhdev, events)
+
+                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_RZ) in events
+                value = evdev.value[libevdev.EV_ABS.ABS_RZ]
+                assert rz - 64 <= value <= rz + 64
+
+        def test_battery(self):
+            uhdev = self.uhdev
+
+            assert uhdev.power_supply_class is not None
+
+            # DS4 capacity levels are in increments of 10.
+            # Battery is never below 5%.
+            for i in range(5, 105, 10):
+                uhdev.battery.capacity = i
+                uhdev.event()
+                assert uhdev.power_supply_class.capacity == i
+
+            # Discharging tests only make sense for BlueTooth.
+            if uhdev.bus == BusType.BLUETOOTH:
+                uhdev.battery.cable_connected = False
+                uhdev.battery.capacity = 45
+                uhdev.event()
+                assert uhdev.power_supply_class.status == "Discharging"
+
+            uhdev.battery.cable_connected = True
+            uhdev.battery.capacity = 5
+            uhdev.event()
+            assert uhdev.power_supply_class.status == "Charging"
+
+            uhdev.battery.capacity = 100
+            uhdev.event()
+            assert uhdev.power_supply_class.status == "Charging"
+
+            uhdev.battery.full = True
+            uhdev.event()
+            assert uhdev.power_supply_class.status == "Full"
+
+        def test_mt_single_touch(self):
+            """send a single touch in the first slot of the device,
+            and release it."""
+            uhdev = self.uhdev
+            evdev = uhdev.get_evdev("Touch Pad")
+
+            t0 = PSTouchPoint(1, 50, 100)
+            r = uhdev.event(touch=[t0])
+            events = uhdev.next_sync_events("Touch Pad")
+            self.debug_reports(r, uhdev, events)
+
+            assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events
+            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0
+            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50
+            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100
+
+            t0.tipswitch = False
+            r = uhdev.event(touch=[t0])
+            events = uhdev.next_sync_events("Touch Pad")
+            self.debug_reports(r, uhdev, events)
+            assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 0) in events
+            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1
+
+        def test_mt_dual_touch(self):
+            """Send 2 touches in the first 2 slots.
+            Make sure the kernel sees this as a dual touch.
+            Release and check
+
+            Note: PTP will send here BTN_DOUBLETAP emulation"""
+            uhdev = self.uhdev
+            evdev = uhdev.get_evdev("Touch Pad")
+
+            t0 = PSTouchPoint(1, 50, 100)
+            t1 = PSTouchPoint(2, 150, 200)
+
+            r = uhdev.event(touch=[t0])
+            events = uhdev.next_sync_events("Touch Pad")
+            self.debug_reports(r, uhdev, events)
+
+            assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events
+            assert evdev.value[libevdev.EV_KEY.BTN_TOUCH] == 1
+            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0
+            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50
+            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100
+            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1
+
+            r = uhdev.event(touch=[t0, t1])
+            events = uhdev.next_sync_events("Touch Pad")
+            self.debug_reports(r, uhdev, events)
+            assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH) not in events
+            assert evdev.value[libevdev.EV_KEY.BTN_TOUCH] == 1
+            assert (
+                libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_X, 5) not in events
+            )
+            assert (
+                libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_Y, 10) not in events
+            )
+            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0
+            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50
+            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100
+            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 1
+            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_POSITION_X] == 150
+            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 200
+
+            t0.tipswitch = False
+            r = uhdev.event(touch=[t0, t1])
+            events = uhdev.next_sync_events("Touch Pad")
+            self.debug_reports(r, uhdev, events)
+            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1
+            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 1
+            assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_X) not in events
+            assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_Y) not in events
+
+            t1.tipswitch = False
+            r = uhdev.event(touch=[t1])
+
+            events = uhdev.next_sync_events("Touch Pad")
+            self.debug_reports(r, uhdev, events)
+            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1
+            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1
+
+
+class TestPS3Controller(SonyBaseTest.SonyTest):
+    kernel_modules = [PS3_MODULE]
+
+    def create_device(self):
+        controller = PS3Controller()
+        controller.application_matches = application_matches
+        return controller
+
+    @pytest.fixture(autouse=True)
+    def start_controller(self):
+        # emulate a 'PS' button press to tell the kernel we are ready to accept events
+        self.assert_button(17)
+
+        # drain any remaining udev events
+        while self.uhdev.dispatch(10):
+            pass
+
+        def test_led(self):
+            for k, v in self.uhdev.led_classes.items():
+                # the kernel might have set a LED for us
+                logger.info(f"{k}: {v.brightness}")
+
+                idx = int(k[-1]) - 1
+                assert self.uhdev.hw_leds.get_led(idx)[0] == bool(v.brightness)
+
+                v.brightness = 0
+                self.uhdev.dispatch(10)
+                assert self.uhdev.hw_leds.get_led(idx)[0] is False
+
+                v.brightness = v.max_brightness
+                self.uhdev.dispatch(10)
+                assert self.uhdev.hw_leds.get_led(idx)[0]
+
+
+class TestPS4ControllerBluetooth(SonyBaseTest.SonyPS4ControllerTest):
+    def create_device(self):
+        controller = PS4ControllerBluetooth()
+        controller.application_matches = application_matches
+        return controller
+
+
+class TestPS4ControllerUSB(SonyBaseTest.SonyPS4ControllerTest):
+    def create_device(self):
+        controller = PS4ControllerUSB()
+        controller.application_matches = application_matches
+        return controller
+
+
+class TestPS5ControllerBluetooth(SonyBaseTest.SonyPS4ControllerTest):
+    kernel_modules = [PS5_MODULE]
+
+    def create_device(self):
+        controller = PS5ControllerBluetooth()
+        controller.application_matches = application_matches
+        return controller
+
+
+class TestPS5ControllerUSB(SonyBaseTest.SonyPS4ControllerTest):
+    kernel_modules = [PS5_MODULE]
+
+    def create_device(self):
+        controller = PS5ControllerUSB()
+        controller.application_matches = application_matches
+        return controller

-- 
2.39.1


^ permalink raw reply related

* [PATCH 09/11] selftests: hid: import hid-tools hid-ite tests
From: Benjamin Tissoires @ 2023-02-17 16:18 UTC (permalink / raw)
  To: Jiri Kosina, Shuah Khan
  Cc: linux-input, linux-kselftest, linux-kernel, Benjamin Tissoires,
	Peter Hutterer, Roderick Colenbrander
In-Reply-To: <20230217-import-hid-tools-tests-v1-0-d1c48590d0ee@redhat.com>

These tests have been developed in the hid-tools[0] tree for a while.
Now that we have  a proper selftests/hid kernel entry and that the tests
are more reliable, it is time to directly include those in the kernel
tree.

[0] https://gitlab.freedesktop.org/libevdev/hid-tools

Cc: Peter Hutterer <peter.hutterer@who-t.net>
Cc: Roderick Colenbrander <roderick.colenbrander@sony.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 tools/testing/selftests/hid/Makefile               |   1 +
 tools/testing/selftests/hid/config                 |   1 +
 tools/testing/selftests/hid/hid-ite.sh             |   7 +
 .../selftests/hid/tests/test_ite_keyboard.py       | 166 +++++++++++++++++++++
 4 files changed, 175 insertions(+)

diff --git a/tools/testing/selftests/hid/Makefile b/tools/testing/selftests/hid/Makefile
index ce03c65bfba0..3ca696c44aab 100644
--- a/tools/testing/selftests/hid/Makefile
+++ b/tools/testing/selftests/hid/Makefile
@@ -8,6 +8,7 @@ include ../../../scripts/Makefile.include
 TEST_PROGS := hid-core.sh
 TEST_PROGS += hid-apple.sh
 TEST_PROGS += hid-gamepad.sh
+TEST_PROGS += hid-ite.sh
 TEST_PROGS += hid-keyboard.sh
 TEST_PROGS += hid-mouse.sh
 TEST_PROGS += hid-multitouch.sh
diff --git a/tools/testing/selftests/hid/config b/tools/testing/selftests/hid/config
index 52b527cc2260..f400b8d94e3c 100644
--- a/tools/testing/selftests/hid/config
+++ b/tools/testing/selftests/hid/config
@@ -22,5 +22,6 @@ CONFIG_UHID=y
 CONFIG_USB=y
 CONFIG_USB_HID=y
 CONFIG_HID_APPLE=y
+CONFIG_HID_ITE=y
 CONFIG_HID_MULTITOUCH=y
 CONFIG_HID_WACOM=y
diff --git a/tools/testing/selftests/hid/hid-ite.sh b/tools/testing/selftests/hid/hid-ite.sh
new file mode 100755
index 000000000000..52c5ccf42292
--- /dev/null
+++ b/tools/testing/selftests/hid/hid-ite.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# Runs tests for the HID subsystem
+
+export TARGET=test_ite_keyboard.py
+
+bash ./run-hid-tools-tests.sh
diff --git a/tools/testing/selftests/hid/tests/test_ite_keyboard.py b/tools/testing/selftests/hid/tests/test_ite_keyboard.py
new file mode 100644
index 000000000000..38550c167bae
--- /dev/null
+++ b/tools/testing/selftests/hid/tests/test_ite_keyboard.py
@@ -0,0 +1,166 @@
+#!/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2020 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+# Copyright (c) 2020 Red Hat, Inc.
+#
+
+from .test_keyboard import ArrayKeyboard, TestArrayKeyboard
+from hidtools.util import BusType
+
+import libevdev
+import logging
+
+logger = logging.getLogger("hidtools.test.ite-keyboard")
+
+KERNEL_MODULE = ("itetech", "hid_ite")
+
+
+class KbdData(object):
+    pass
+
+
+# The ITE keyboards have an issue regarding the Wifi key:
+# nothing comes in when pressing the key, but we get a null
+# event on the key release.
+# This test covers this case.
+class ITEKeyboard(ArrayKeyboard):
+    # fmt: off
+    report_descriptor = [
+        0x06, 0x85, 0xff,              # Usage Page (Vendor Usage Page 0xff85)
+        0x09, 0x95,                    # Usage (Vendor Usage 0x95)           3
+        0xa1, 0x01,                    # Collection (Application)            5
+        0x85, 0x5a,                    # .Report ID (90)                     7
+        0x09, 0x01,                    # .Usage (Vendor Usage 0x01)          9
+        0x15, 0x00,                    # .Logical Minimum (0)                11
+        0x26, 0xff, 0x00,              # .Logical Maximum (255)              13
+        0x75, 0x08,                    # .Report Size (8)                    16
+        0x95, 0x10,                    # .Report Count (16)                  18
+        0xb1, 0x00,                    # .Feature (Data,Arr,Abs)             20
+        0xc0,                          # End Collection                      22
+        0x05, 0x01,                    # Usage Page (Generic Desktop)        23
+        0x09, 0x06,                    # Usage (Keyboard)                    25
+        0xa1, 0x01,                    # Collection (Application)            27
+        0x85, 0x01,                    # .Report ID (1)                      29
+        0x75, 0x01,                    # .Report Size (1)                    31
+        0x95, 0x08,                    # .Report Count (8)                   33
+        0x05, 0x07,                    # .Usage Page (Keyboard)              35
+        0x19, 0xe0,                    # .Usage Minimum (224)                37
+        0x29, 0xe7,                    # .Usage Maximum (231)                39
+        0x15, 0x00,                    # .Logical Minimum (0)                41
+        0x25, 0x01,                    # .Logical Maximum (1)                43
+        0x81, 0x02,                    # .Input (Data,Var,Abs)               45
+        0x95, 0x01,                    # .Report Count (1)                   47
+        0x75, 0x08,                    # .Report Size (8)                    49
+        0x81, 0x03,                    # .Input (Cnst,Var,Abs)               51
+        0x95, 0x05,                    # .Report Count (5)                   53
+        0x75, 0x01,                    # .Report Size (1)                    55
+        0x05, 0x08,                    # .Usage Page (LEDs)                  57
+        0x19, 0x01,                    # .Usage Minimum (1)                  59
+        0x29, 0x05,                    # .Usage Maximum (5)                  61
+        0x91, 0x02,                    # .Output (Data,Var,Abs)              63
+        0x95, 0x01,                    # .Report Count (1)                   65
+        0x75, 0x03,                    # .Report Size (3)                    67
+        0x91, 0x03,                    # .Output (Cnst,Var,Abs)              69
+        0x95, 0x06,                    # .Report Count (6)                   71
+        0x75, 0x08,                    # .Report Size (8)                    73
+        0x15, 0x00,                    # .Logical Minimum (0)                75
+        0x26, 0xff, 0x00,              # .Logical Maximum (255)              77
+        0x05, 0x07,                    # .Usage Page (Keyboard)              80
+        0x19, 0x00,                    # .Usage Minimum (0)                  82
+        0x2a, 0xff, 0x00,              # .Usage Maximum (255)                84
+        0x81, 0x00,                    # .Input (Data,Arr,Abs)               87
+        0xc0,                          # End Collection                      89
+        0x05, 0x0c,                    # Usage Page (Consumer Devices)       90
+        0x09, 0x01,                    # Usage (Consumer Control)            92
+        0xa1, 0x01,                    # Collection (Application)            94
+        0x85, 0x02,                    # .Report ID (2)                      96
+        0x19, 0x00,                    # .Usage Minimum (0)                  98
+        0x2a, 0x3c, 0x02,              # .Usage Maximum (572)                100
+        0x15, 0x00,                    # .Logical Minimum (0)                103
+        0x26, 0x3c, 0x02,              # .Logical Maximum (572)              105
+        0x75, 0x10,                    # .Report Size (16)                   108
+        0x95, 0x01,                    # .Report Count (1)                   110
+        0x81, 0x00,                    # .Input (Data,Arr,Abs)               112
+        0xc0,                          # End Collection                      114
+        0x05, 0x01,                    # Usage Page (Generic Desktop)        115
+        0x09, 0x0c,                    # Usage (Wireless Radio Controls)     117
+        0xa1, 0x01,                    # Collection (Application)            119
+        0x85, 0x03,                    # .Report ID (3)                      121
+        0x15, 0x00,                    # .Logical Minimum (0)                123
+        0x25, 0x01,                    # .Logical Maximum (1)                125
+        0x09, 0xc6,                    # .Usage (Wireless Radio Button)      127
+        0x95, 0x01,                    # .Report Count (1)                   129
+        0x75, 0x01,                    # .Report Size (1)                    131
+        0x81, 0x06,                    # .Input (Data,Var,Rel)               133
+        0x75, 0x07,                    # .Report Size (7)                    135
+        0x81, 0x03,                    # .Input (Cnst,Var,Abs)               137
+        0xc0,                          # End Collection                      139
+        0x05, 0x88,                    # Usage Page (Vendor Usage Page 0x88) 140
+        0x09, 0x01,                    # Usage (Vendor Usage 0x01)           142
+        0xa1, 0x01,                    # Collection (Application)            144
+        0x85, 0x04,                    # .Report ID (4)                      146
+        0x19, 0x00,                    # .Usage Minimum (0)                  148
+        0x2a, 0xff, 0xff,              # .Usage Maximum (65535)              150
+        0x15, 0x00,                    # .Logical Minimum (0)                153
+        0x26, 0xff, 0xff,              # .Logical Maximum (65535)            155
+        0x75, 0x08,                    # .Report Size (8)                    158
+        0x95, 0x02,                    # .Report Count (2)                   160
+        0x81, 0x02,                    # .Input (Data,Var,Abs)               162
+        0xc0,                          # End Collection                      164
+        0x05, 0x01,                    # Usage Page (Generic Desktop)        165
+        0x09, 0x80,                    # Usage (System Control)              167
+        0xa1, 0x01,                    # Collection (Application)            169
+        0x85, 0x05,                    # .Report ID (5)                      171
+        0x19, 0x81,                    # .Usage Minimum (129)                173
+        0x29, 0x83,                    # .Usage Maximum (131)                175
+        0x15, 0x00,                    # .Logical Minimum (0)                177
+        0x25, 0x01,                    # .Logical Maximum (1)                179
+        0x95, 0x08,                    # .Report Count (8)                   181
+        0x75, 0x01,                    # .Report Size (1)                    183
+        0x81, 0x02,                    # .Input (Data,Var,Abs)               185
+        0xc0,                          # End Collection                      187
+    ]
+    # fmt: on
+
+    def __init__(
+        self,
+        rdesc=report_descriptor,
+        name=None,
+        input_info=(BusType.USB, 0x06CB, 0x2968),
+    ):
+        super().__init__(rdesc, name, input_info)
+
+    def event(self, keys, reportID=None, application=None):
+        application = application or "Keyboard"
+        return super().event(keys, reportID, application)
+
+
+class TestITEKeyboard(TestArrayKeyboard):
+    kernel_modules = [KERNEL_MODULE]
+
+    def create_device(self):
+        return ITEKeyboard()
+
+    def test_wifi_key(self):
+        uhdev = self.uhdev
+        syn_event = self.syn_event
+
+        # the following sends a 'release' event on the Wifi key.
+        # the kernel is supposed to translate this into Wifi key
+        # down and up
+        r = [0x03, 0x00]
+        uhdev.call_input_event(r)
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_RFKILL, 1))
+        events = uhdev.next_sync_events()
+        self.debug_reports([r], uhdev, events)
+        self.assertInputEventsIn(expected, events)
+
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_RFKILL, 0))
+        # the kernel sends the two down/up key events in a batch, no need to
+        # call events = uhdev.next_sync_events()
+        self.debug_reports([], uhdev, events)
+        self.assertInputEventsIn(expected, events)

-- 
2.39.1


^ permalink raw reply related

* [PATCH 08/11] selftests: hid: import hid-tools hid-apple tests
From: Benjamin Tissoires @ 2023-02-17 16:18 UTC (permalink / raw)
  To: Jiri Kosina, Shuah Khan
  Cc: linux-input, linux-kselftest, linux-kernel, Benjamin Tissoires,
	Roderick Colenbrander
In-Reply-To: <20230217-import-hid-tools-tests-v1-0-d1c48590d0ee@redhat.com>

These tests have been developed in the hid-tools[0] tree for a while.
Now that we have  a proper selftests/hid kernel entry and that the tests
are more reliable, it is time to directly include those in the kernel
tree.

[0] https://gitlab.freedesktop.org/libevdev/hid-tools

Cc: Roderick Colenbrander <roderick.colenbrander@sony.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 tools/testing/selftests/hid/Makefile               |   1 +
 tools/testing/selftests/hid/config                 |   1 +
 tools/testing/selftests/hid/hid-apple.sh           |   7 +
 .../selftests/hid/tests/test_apple_keyboard.py     | 440 +++++++++++++++++++++
 4 files changed, 449 insertions(+)

diff --git a/tools/testing/selftests/hid/Makefile b/tools/testing/selftests/hid/Makefile
index 4f11e865bbb3..ce03c65bfba0 100644
--- a/tools/testing/selftests/hid/Makefile
+++ b/tools/testing/selftests/hid/Makefile
@@ -6,6 +6,7 @@ include ../../../scripts/Makefile.arch
 include ../../../scripts/Makefile.include
 
 TEST_PROGS := hid-core.sh
+TEST_PROGS += hid-apple.sh
 TEST_PROGS += hid-gamepad.sh
 TEST_PROGS += hid-keyboard.sh
 TEST_PROGS += hid-mouse.sh
diff --git a/tools/testing/selftests/hid/config b/tools/testing/selftests/hid/config
index 266fbd84ae9c..52b527cc2260 100644
--- a/tools/testing/selftests/hid/config
+++ b/tools/testing/selftests/hid/config
@@ -21,5 +21,6 @@ CONFIG_INPUT_EVDEV=y
 CONFIG_UHID=y
 CONFIG_USB=y
 CONFIG_USB_HID=y
+CONFIG_HID_APPLE=y
 CONFIG_HID_MULTITOUCH=y
 CONFIG_HID_WACOM=y
diff --git a/tools/testing/selftests/hid/hid-apple.sh b/tools/testing/selftests/hid/hid-apple.sh
new file mode 100755
index 000000000000..656f2d5ae5a9
--- /dev/null
+++ b/tools/testing/selftests/hid/hid-apple.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# Runs tests for the HID subsystem
+
+export TARGET=test_apple_keyboard.py
+
+bash ./run-hid-tools-tests.sh
diff --git a/tools/testing/selftests/hid/tests/test_apple_keyboard.py b/tools/testing/selftests/hid/tests/test_apple_keyboard.py
new file mode 100644
index 000000000000..f81071d46166
--- /dev/null
+++ b/tools/testing/selftests/hid/tests/test_apple_keyboard.py
@@ -0,0 +1,440 @@
+#!/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2019 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+# Copyright (c) 2019 Red Hat, Inc.
+#
+
+from .test_keyboard import ArrayKeyboard, TestArrayKeyboard
+from hidtools.util import BusType
+
+import libevdev
+import logging
+
+logger = logging.getLogger("hidtools.test.apple-keyboard")
+
+KERNEL_MODULE = ("apple", "hid-apple")
+
+
+class KbdData(object):
+    pass
+
+
+class AppleKeyboard(ArrayKeyboard):
+    # fmt: off
+    report_descriptor = [
+        0x05, 0x01,         # Usage Page (Generic Desktop)
+        0x09, 0x06,         # Usage (Keyboard)
+        0xa1, 0x01,         # Collection (Application)
+        0x85, 0x01,         # .Report ID (1)
+        0x05, 0x07,         # .Usage Page (Keyboard)
+        0x19, 0xe0,         # .Usage Minimum (224)
+        0x29, 0xe7,         # .Usage Maximum (231)
+        0x15, 0x00,         # .Logical Minimum (0)
+        0x25, 0x01,         # .Logical Maximum (1)
+        0x75, 0x01,         # .Report Size (1)
+        0x95, 0x08,         # .Report Count (8)
+        0x81, 0x02,         # .Input (Data,Var,Abs)
+        0x75, 0x08,         # .Report Size (8)
+        0x95, 0x01,         # .Report Count (1)
+        0x81, 0x01,         # .Input (Cnst,Arr,Abs)
+        0x75, 0x01,         # .Report Size (1)
+        0x95, 0x05,         # .Report Count (5)
+        0x05, 0x08,         # .Usage Page (LEDs)
+        0x19, 0x01,         # .Usage Minimum (1)
+        0x29, 0x05,         # .Usage Maximum (5)
+        0x91, 0x02,         # .Output (Data,Var,Abs)
+        0x75, 0x03,         # .Report Size (3)
+        0x95, 0x01,         # .Report Count (1)
+        0x91, 0x01,         # .Output (Cnst,Arr,Abs)
+        0x75, 0x08,         # .Report Size (8)
+        0x95, 0x06,         # .Report Count (6)
+        0x15, 0x00,         # .Logical Minimum (0)
+        0x26, 0xff, 0x00,   # .Logical Maximum (255)
+        0x05, 0x07,         # .Usage Page (Keyboard)
+        0x19, 0x00,         # .Usage Minimum (0)
+        0x2a, 0xff, 0x00,   # .Usage Maximum (255)
+        0x81, 0x00,         # .Input (Data,Arr,Abs)
+        0xc0,               # End Collection
+        0x05, 0x0c,         # Usage Page (Consumer Devices)
+        0x09, 0x01,         # Usage (Consumer Control)
+        0xa1, 0x01,         # Collection (Application)
+        0x85, 0x47,         # .Report ID (71)
+        0x05, 0x01,         # .Usage Page (Generic Desktop)
+        0x09, 0x06,         # .Usage (Keyboard)
+        0xa1, 0x02,         # .Collection (Logical)
+        0x05, 0x06,         # ..Usage Page (Generic Device Controls)
+        0x09, 0x20,         # ..Usage (Battery Strength)
+        0x15, 0x00,         # ..Logical Minimum (0)
+        0x26, 0xff, 0x00,   # ..Logical Maximum (255)
+        0x75, 0x08,         # ..Report Size (8)
+        0x95, 0x01,         # ..Report Count (1)
+        0x81, 0x02,         # ..Input (Data,Var,Abs)
+        0xc0,               # .End Collection
+        0xc0,               # End Collection
+        0x05, 0x0c,         # Usage Page (Consumer Devices)
+        0x09, 0x01,         # Usage (Consumer Control)
+        0xa1, 0x01,         # Collection (Application)
+        0x85, 0x11,         # .Report ID (17)
+        0x15, 0x00,         # .Logical Minimum (0)
+        0x25, 0x01,         # .Logical Maximum (1)
+        0x75, 0x01,         # .Report Size (1)
+        0x95, 0x03,         # .Report Count (3)
+        0x81, 0x01,         # .Input (Cnst,Arr,Abs)
+        0x75, 0x01,         # .Report Size (1)
+        0x95, 0x01,         # .Report Count (1)
+        0x05, 0x0c,         # .Usage Page (Consumer Devices)
+        0x09, 0xb8,         # .Usage (Eject)
+        0x81, 0x02,         # .Input (Data,Var,Abs)
+        0x06, 0xff, 0x00,   # .Usage Page (Vendor Usage Page 0xff)
+        0x09, 0x03,         # .Usage (Vendor Usage 0x03)
+        0x81, 0x02,         # .Input (Data,Var,Abs)
+        0x75, 0x01,         # .Report Size (1)
+        0x95, 0x03,         # .Report Count (3)
+        0x81, 0x01,         # .Input (Cnst,Arr,Abs)
+        0x05, 0x0c,         # .Usage Page (Consumer Devices)
+        0x85, 0x12,         # .Report ID (18)
+        0x15, 0x00,         # .Logical Minimum (0)
+        0x25, 0x01,         # .Logical Maximum (1)
+        0x75, 0x01,         # .Report Size (1)
+        0x95, 0x01,         # .Report Count (1)
+        0x09, 0xcd,         # .Usage (Play/Pause)
+        0x81, 0x02,         # .Input (Data,Var,Abs)
+        0x09, 0xb3,         # .Usage (Fast Forward)
+        0x81, 0x02,         # .Input (Data,Var,Abs)
+        0x09, 0xb4,         # .Usage (Rewind)
+        0x81, 0x02,         # .Input (Data,Var,Abs)
+        0x09, 0xb5,         # .Usage (Scan Next Track)
+        0x81, 0x02,         # .Input (Data,Var,Abs)
+        0x09, 0xb6,         # .Usage (Scan Previous Track)
+        0x81, 0x02,         # .Input (Data,Var,Abs)
+        0x81, 0x01,         # .Input (Cnst,Arr,Abs)
+        0x81, 0x01,         # .Input (Cnst,Arr,Abs)
+        0x81, 0x01,         # .Input (Cnst,Arr,Abs)
+        0x85, 0x13,         # .Report ID (19)
+        0x15, 0x00,         # .Logical Minimum (0)
+        0x25, 0x01,         # .Logical Maximum (1)
+        0x75, 0x01,         # .Report Size (1)
+        0x95, 0x01,         # .Report Count (1)
+        0x06, 0x01, 0xff,   # .Usage Page (Vendor Usage Page 0xff01)
+        0x09, 0x0a,         # .Usage (Vendor Usage 0x0a)
+        0x81, 0x02,         # .Input (Data,Var,Abs)
+        0x06, 0x01, 0xff,   # .Usage Page (Vendor Usage Page 0xff01)
+        0x09, 0x0c,         # .Usage (Vendor Usage 0x0c)
+        0x81, 0x22,         # .Input (Data,Var,Abs,NoPref)
+        0x75, 0x01,         # .Report Size (1)
+        0x95, 0x06,         # .Report Count (6)
+        0x81, 0x01,         # .Input (Cnst,Arr,Abs)
+        0x85, 0x09,         # .Report ID (9)
+        0x09, 0x0b,         # .Usage (Vendor Usage 0x0b)
+        0x75, 0x08,         # .Report Size (8)
+        0x95, 0x01,         # .Report Count (1)
+        0xb1, 0x02,         # .Feature (Data,Var,Abs)
+        0x75, 0x08,         # .Report Size (8)
+        0x95, 0x02,         # .Report Count (2)
+        0xb1, 0x01,         # .Feature (Cnst,Arr,Abs)
+        0xc0,               # End Collection
+    ]
+    # fmt: on
+
+    def __init__(
+        self,
+        rdesc=report_descriptor,
+        name="Apple Wireless Keyboard",
+        input_info=(BusType.BLUETOOTH, 0x05AC, 0x0256),
+    ):
+        super().__init__(rdesc, name, input_info)
+        self.default_reportID = 1
+
+    def send_fn_state(self, state):
+        data = KbdData()
+        setattr(data, "0xff0003", state)
+        r = self.create_report(data, reportID=17)
+        self.call_input_event(r)
+        return [r]
+
+
+class TestAppleKeyboard(TestArrayKeyboard):
+    kernel_modules = [KERNEL_MODULE]
+
+    def create_device(self):
+        return AppleKeyboard()
+
+    def test_single_function_key(self):
+        """check for function key reliability."""
+        uhdev = self.uhdev
+        evdev = uhdev.get_evdev()
+        syn_event = self.syn_event
+
+        r = uhdev.event(["F4"])
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 1))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0
+
+        r = uhdev.event([])
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 0))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 0
+
+    def test_single_fn_function_key(self):
+        """check for function key reliability with the fn key."""
+        uhdev = self.uhdev
+        evdev = uhdev.get_evdev()
+        syn_event = self.syn_event
+
+        r = uhdev.send_fn_state(1)
+        r.extend(uhdev.event(["F4"]))
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 1))
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 1
+
+        r = uhdev.event([])
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 0))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
+
+        r = uhdev.send_fn_state(0)
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+
+    def test_single_fn_function_key_release_first(self):
+        """check for function key reliability with the fn key."""
+        uhdev = self.uhdev
+        evdev = uhdev.get_evdev()
+        syn_event = self.syn_event
+
+        r = uhdev.send_fn_state(1)
+        r.extend(uhdev.event(["F4"]))
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 1))
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 1
+
+        r = uhdev.send_fn_state(0)
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+
+        r = uhdev.event([])
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 0))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
+
+    def test_single_fn_function_key_inverted(self):
+        """check for function key reliability with the fn key."""
+        uhdev = self.uhdev
+        evdev = uhdev.get_evdev()
+        syn_event = self.syn_event
+
+        r = uhdev.event(["F4"])
+        r.extend(uhdev.send_fn_state(1))
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 1))
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1
+
+        r = uhdev.event([])
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 0))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
+
+        r = uhdev.send_fn_state(0)
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+
+    def test_multiple_fn_function_key_release_first(self):
+        """check for function key reliability with the fn key."""
+        uhdev = self.uhdev
+        evdev = uhdev.get_evdev()
+        syn_event = self.syn_event
+
+        r = uhdev.send_fn_state(1)
+        r.extend(uhdev.event(["F4"]))
+        r.extend(uhdev.event(["F4", "F6"]))
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 1))
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 1))
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 1
+        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
+
+        r = uhdev.event(["F6"])
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F4, 0))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
+
+        r = uhdev.send_fn_state(0)
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0
+
+        r = uhdev.event([])
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 0))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0
+
+    def test_multiple_fn_function_key_release_between(self):
+        """check for function key reliability with the fn key."""
+        uhdev = self.uhdev
+        evdev = uhdev.get_evdev()
+        syn_event = self.syn_event
+
+        # press F4
+        r = uhdev.event(["F4"])
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 1))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1
+        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0
+
+        # press Fn key
+        r = uhdev.send_fn_state(1)
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1
+        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
+
+        # keep F4 and press F6
+        r = uhdev.event(["F4", "F6"])
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 1))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1
+        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1
+        assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
+
+        # keep F4 and F6
+        r = uhdev.event(["F4", "F6"])
+        expected = []
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 1
+        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 1
+        assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
+
+        # release Fn key and all keys
+        r = uhdev.send_fn_state(0)
+        r.extend(uhdev.event([]))
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_ALL_APPLICATIONS, 0))
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_F6, 0))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_F4] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_ALL_APPLICATIONS] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_F6] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_KBDILLUMUP] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0
+
+    def test_single_pageup_key_release_first(self):
+        """check for function key reliability with the [page] up key."""
+        uhdev = self.uhdev
+        evdev = uhdev.get_evdev()
+        syn_event = self.syn_event
+
+        r = uhdev.send_fn_state(1)
+        r.extend(uhdev.event(["UpArrow"]))
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_PAGEUP, 1))
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 1))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_PAGEUP] == 1
+        assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 1
+
+        r = uhdev.send_fn_state(0)
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_FN, 0))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_PAGEUP] == 1
+        assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0
+
+        r = uhdev.event([])
+        expected = [syn_event]
+        expected.append(libevdev.InputEvent(libevdev.EV_KEY.KEY_PAGEUP, 0))
+        events = uhdev.next_sync_events()
+        self.debug_reports(r, uhdev, events)
+        self.assertInputEventsIn(expected, events)
+        assert evdev.value[libevdev.EV_KEY.KEY_PAGEUP] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_UP] == 0
+        assert evdev.value[libevdev.EV_KEY.KEY_FN] == 0

-- 
2.39.1


^ permalink raw reply related

* [PATCH 03/11] selftests: hid: import hid-tools hid-gamepad tests
From: Benjamin Tissoires @ 2023-02-17 16:17 UTC (permalink / raw)
  To: Jiri Kosina, Shuah Khan
  Cc: linux-input, linux-kselftest, linux-kernel, Benjamin Tissoires,
	Candle Sun, Jose Torreguitar, Peter Hutterer,
	Roderick Colenbrander, Silvan Jegen
In-Reply-To: <20230217-import-hid-tools-tests-v1-0-d1c48590d0ee@redhat.com>

These tests have been developed in the hid-tools[0] tree for a while.
Now that we have  a proper selftests/hid kernel entry and that the tests
are more reliable, it is time to directly include those in the kernel
tree.

[0] https://gitlab.freedesktop.org/libevdev/hid-tools

Cc: Candle Sun <candle.sun@unisoc.com>
Cc: Jose Torreguitar <jtguitar@google.com>
Cc: Peter Hutterer <peter.hutterer@who-t.net>
Cc: Roderick Colenbrander <roderick.colenbrander@sony.com>
Cc: Silvan Jegen <s.jegen@gmail.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 tools/testing/selftests/hid/Makefile              |   1 +
 tools/testing/selftests/hid/hid-gamepad.sh        |   7 +
 tools/testing/selftests/hid/tests/test_gamepad.py | 209 ++++++++++++++++++++++
 3 files changed, 217 insertions(+)

diff --git a/tools/testing/selftests/hid/Makefile b/tools/testing/selftests/hid/Makefile
index bdcb36d80c8c..d16a22477140 100644
--- a/tools/testing/selftests/hid/Makefile
+++ b/tools/testing/selftests/hid/Makefile
@@ -6,6 +6,7 @@ include ../../../scripts/Makefile.arch
 include ../../../scripts/Makefile.include
 
 TEST_PROGS := hid-core.sh
+TEST_PROGS += hid-gamepad.sh
 
 CXX ?= $(CROSS_COMPILE)g++
 
diff --git a/tools/testing/selftests/hid/hid-gamepad.sh b/tools/testing/selftests/hid/hid-gamepad.sh
new file mode 100755
index 000000000000..1ba00c0ca95f
--- /dev/null
+++ b/tools/testing/selftests/hid/hid-gamepad.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# Runs tests for the HID subsystem
+
+export TARGET=test_gamepad.py
+
+bash ./run-hid-tools-tests.sh
diff --git a/tools/testing/selftests/hid/tests/test_gamepad.py b/tools/testing/selftests/hid/tests/test_gamepad.py
new file mode 100644
index 000000000000..26c74040b796
--- /dev/null
+++ b/tools/testing/selftests/hid/tests/test_gamepad.py
@@ -0,0 +1,209 @@
+#!/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2019 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+# Copyright (c) 2019 Red Hat, Inc.
+#
+
+from . import base
+import libevdev
+import pytest
+
+from hidtools.device.base_gamepad import AsusGamepad, SaitekGamepad
+
+import logging
+
+logger = logging.getLogger("hidtools.test.gamepad")
+
+
+class BaseTest:
+    class TestGamepad(base.BaseTestCase.TestUhid):
+        @pytest.fixture(autouse=True)
+        def send_initial_state(self):
+            """send an empty report to initialize the axes"""
+            uhdev = self.uhdev
+
+            r = uhdev.event()
+            events = uhdev.next_sync_events()
+            self.debug_reports(r, uhdev, events)
+
+        def assert_button(self, button):
+            uhdev = self.uhdev
+            evdev = uhdev.get_evdev()
+            syn_event = self.syn_event
+
+            buttons = {}
+            key = libevdev.evbit(uhdev.buttons_map[button])
+
+            buttons[button] = True
+            r = uhdev.event(buttons=buttons)
+            expected_event = libevdev.InputEvent(key, 1)
+            events = uhdev.next_sync_events()
+            self.debug_reports(r, uhdev, events)
+            self.assertInputEventsIn((syn_event, expected_event), events)
+            assert evdev.value[key] == 1
+
+            buttons[button] = False
+            r = uhdev.event(buttons=buttons)
+            expected_event = libevdev.InputEvent(key, 0)
+            events = uhdev.next_sync_events()
+            self.debug_reports(r, uhdev, events)
+            self.assertInputEventsIn((syn_event, expected_event), events)
+            assert evdev.value[key] == 0
+
+        def test_buttons(self):
+            """check for button reliability."""
+            uhdev = self.uhdev
+
+            for b in uhdev.buttons:
+                self.assert_button(b)
+
+        def test_dual_buttons(self):
+            """check for button reliability when pressing 2 buttons"""
+            uhdev = self.uhdev
+            evdev = uhdev.get_evdev()
+            syn_event = self.syn_event
+
+            # can change intended b1 b2 values
+            b1 = uhdev.buttons[0]
+            key1 = libevdev.evbit(uhdev.buttons_map[b1])
+            b2 = uhdev.buttons[1]
+            key2 = libevdev.evbit(uhdev.buttons_map[b2])
+
+            buttons = {b1: True, b2: True}
+            r = uhdev.event(buttons=buttons)
+            expected_event0 = libevdev.InputEvent(key1, 1)
+            expected_event1 = libevdev.InputEvent(key2, 1)
+            events = uhdev.next_sync_events()
+            self.debug_reports(r, uhdev, events)
+            self.assertInputEventsIn(
+                (syn_event, expected_event0, expected_event1), events
+            )
+            assert evdev.value[key1] == 1
+            assert evdev.value[key2] == 1
+
+            buttons = {b1: False, b2: None}
+            r = uhdev.event(buttons=buttons)
+            expected_event = libevdev.InputEvent(key1, 0)
+            events = uhdev.next_sync_events()
+            self.debug_reports(r, uhdev, events)
+            self.assertInputEventsIn((syn_event, expected_event), events)
+            assert evdev.value[key1] == 0
+            assert evdev.value[key2] == 1
+
+            buttons = {b1: None, b2: False}
+            r = uhdev.event(buttons=buttons)
+            expected_event = libevdev.InputEvent(key2, 0)
+            events = uhdev.next_sync_events()
+            self.debug_reports(r, uhdev, events)
+            self.assertInputEventsIn((syn_event, expected_event), events)
+            assert evdev.value[key1] == 0
+            assert evdev.value[key2] == 0
+
+        def _get_libevdev_abs_events(self, which):
+            """Returns which ABS_* evdev axes are expected for the given stick"""
+            abs_map = self.uhdev.axes_map[which]
+
+            x = abs_map["x"].evdev
+            y = abs_map["y"].evdev
+
+            assert x
+            assert y
+
+            return x, y
+
+        def _test_joystick_press(self, which, data):
+            uhdev = self.uhdev
+
+            libevdev_axes = self._get_libevdev_abs_events(which)
+
+            r = None
+            if which == "left_stick":
+                r = uhdev.event(left=data)
+            else:
+                r = uhdev.event(right=data)
+            events = uhdev.next_sync_events()
+            self.debug_reports(r, uhdev, events)
+
+            for i, d in enumerate(data):
+                if d is not None and d != 127:
+                    assert libevdev.InputEvent(libevdev_axes[i], d) in events
+                else:
+                    assert libevdev.InputEvent(libevdev_axes[i]) not in events
+
+        def test_left_joystick_press_left(self):
+            """check for the left joystick reliability"""
+            self._test_joystick_press("left_stick", (63, None))
+            self._test_joystick_press("left_stick", (0, 127))
+
+        def test_left_joystick_press_right(self):
+            """check for the left joystick reliability"""
+            self._test_joystick_press("left_stick", (191, 127))
+            self._test_joystick_press("left_stick", (255, None))
+
+        def test_left_joystick_press_up(self):
+            """check for the left joystick reliability"""
+            self._test_joystick_press("left_stick", (None, 63))
+            self._test_joystick_press("left_stick", (127, 0))
+
+        def test_left_joystick_press_down(self):
+            """check for the left joystick reliability"""
+            self._test_joystick_press("left_stick", (127, 191))
+            self._test_joystick_press("left_stick", (None, 255))
+
+        def test_right_joystick_press_left(self):
+            """check for the right joystick reliability"""
+            self._test_joystick_press("right_stick", (63, None))
+            self._test_joystick_press("right_stick", (0, 127))
+
+        def test_right_joystick_press_right(self):
+            """check for the right joystick reliability"""
+            self._test_joystick_press("right_stick", (191, 127))
+            self._test_joystick_press("right_stick", (255, None))
+
+        def test_right_joystick_press_up(self):
+            """check for the right joystick reliability"""
+            self._test_joystick_press("right_stick", (None, 63))
+            self._test_joystick_press("right_stick", (127, 0))
+
+        def test_right_joystick_press_down(self):
+            """check for the right joystick reliability"""
+            self._test_joystick_press("right_stick", (127, 191))
+            self._test_joystick_press("right_stick", (None, 255))
+
+        @pytest.mark.skip_if_uhdev(
+            lambda uhdev: "Hat switch" not in uhdev.fields,
+            "Device not compatible, missing Hat switch usage",
+        )
+        @pytest.mark.parametrize(
+            "hat_value,expected_evdev,evdev_value",
+            [
+                (0, "ABS_HAT0Y", -1),
+                (2, "ABS_HAT0X", 1),
+                (4, "ABS_HAT0Y", 1),
+                (6, "ABS_HAT0X", -1),
+            ],
+        )
+        def test_hat_switch(self, hat_value, expected_evdev, evdev_value):
+            uhdev = self.uhdev
+
+            r = uhdev.event(hat_switch=hat_value)
+            events = uhdev.next_sync_events()
+            self.debug_reports(r, uhdev, events)
+            assert (
+                libevdev.InputEvent(
+                    libevdev.evbit("EV_ABS", expected_evdev), evdev_value
+                )
+                in events
+            )
+
+
+class TestSaitekGamepad(BaseTest.TestGamepad):
+    def create_device(self):
+        return SaitekGamepad()
+
+
+class TestAsusGamepad(BaseTest.TestGamepad):
+    def create_device(self):
+        return AsusGamepad()

-- 
2.39.1


^ permalink raw reply related

* [PATCH 02/11] selftests: hid: import hid-tools hid-core tests
From: Benjamin Tissoires @ 2023-02-17 16:17 UTC (permalink / raw)
  To: Jiri Kosina, Shuah Khan
  Cc: linux-input, linux-kselftest, linux-kernel, Benjamin Tissoires,
	Peter Hutterer
In-Reply-To: <20230217-import-hid-tools-tests-v1-0-d1c48590d0ee@redhat.com>

These tests have been developed in the hid-tools[0] tree for a while.
Now that we have  a proper selftests/hid kernel entry and that the tests
are more reliable, it is time to directly include those in the kernel
tree.

I haven't imported all of hid-tools, the python module, but only the
tests related to the kernel. We can rely on pip to fetch the latest
hid-tools release, and then run the tests directly from the tree.

This should now be easier to request tests when something is not behaving
properly in the HID subsystem.

[0] https://gitlab.freedesktop.org/libevdev/hid-tools

Cc: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 tools/testing/selftests/hid/Makefile               |   2 +
 tools/testing/selftests/hid/hid-core.sh            |   7 +
 tools/testing/selftests/hid/run-hid-tools-tests.sh |  28 ++
 tools/testing/selftests/hid/tests/__init__.py      |   2 +
 tools/testing/selftests/hid/tests/base.py          | 345 +++++++++++++++++++++
 tools/testing/selftests/hid/tests/conftest.py      |  81 +++++
 tools/testing/selftests/hid/tests/test_hid_core.py | 154 +++++++++
 tools/testing/selftests/hid/vmtest.sh              |   2 +-
 8 files changed, 620 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/hid/Makefile b/tools/testing/selftests/hid/Makefile
index 83e8f87d643a..bdcb36d80c8c 100644
--- a/tools/testing/selftests/hid/Makefile
+++ b/tools/testing/selftests/hid/Makefile
@@ -5,6 +5,8 @@ include ../../../build/Build.include
 include ../../../scripts/Makefile.arch
 include ../../../scripts/Makefile.include
 
+TEST_PROGS := hid-core.sh
+
 CXX ?= $(CROSS_COMPILE)g++
 
 HOSTPKG_CONFIG := pkg-config
diff --git a/tools/testing/selftests/hid/hid-core.sh b/tools/testing/selftests/hid/hid-core.sh
new file mode 100755
index 000000000000..5bbabc12c34f
--- /dev/null
+++ b/tools/testing/selftests/hid/hid-core.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# Runs tests for the HID subsystem
+
+export TARGET=test_hid_core.py
+
+bash ./run-hid-tools-tests.sh
diff --git a/tools/testing/selftests/hid/run-hid-tools-tests.sh b/tools/testing/selftests/hid/run-hid-tools-tests.sh
new file mode 100755
index 000000000000..bdae8464da86
--- /dev/null
+++ b/tools/testing/selftests/hid/run-hid-tools-tests.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# Runs tests for the HID subsystem
+
+if ! command -v python3 > /dev/null 2>&1; then
+	echo "hid-tools: [SKIP] python3 not installed"
+	exit 77
+fi
+
+if ! python3 -c "import pytest" > /dev/null 2>&1; then
+	echo "hid: [SKIP/ pytest module not installed"
+	exit 77
+fi
+
+if ! python3 -c "import pytest_tap" > /dev/null 2>&1; then
+	echo "hid: [SKIP/ pytest_tap module not installed"
+	exit 77
+fi
+
+if ! python3 -c "import hidtools" > /dev/null 2>&1; then
+	echo "hid: [SKIP/ hid-tools module not installed"
+	exit 77
+fi
+
+TARGET=${TARGET:=.}
+
+echo TAP version 13
+python3 -u -m pytest $PYTEST_XDIST ./tests/$TARGET --tap-stream --udevd
diff --git a/tools/testing/selftests/hid/tests/__init__.py b/tools/testing/selftests/hid/tests/__init__.py
new file mode 100644
index 000000000000..c940e9275252
--- /dev/null
+++ b/tools/testing/selftests/hid/tests/__init__.py
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+# Just to make sphinx-apidoc document this directory
diff --git a/tools/testing/selftests/hid/tests/base.py b/tools/testing/selftests/hid/tests/base.py
new file mode 100644
index 000000000000..1305cfc9646e
--- /dev/null
+++ b/tools/testing/selftests/hid/tests/base.py
@@ -0,0 +1,345 @@
+#!/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+# Copyright (c) 2017 Red Hat, Inc.
+
+import libevdev
+import os
+import pytest
+import time
+
+import logging
+
+from hidtools.device.base_device import BaseDevice, EvdevMatch, SysfsFile
+from pathlib import Path
+from typing import Final
+
+logger = logging.getLogger("hidtools.test.base")
+
+# application to matches
+application_matches: Final = {
+    # pyright: ignore
+    "Accelerometer": EvdevMatch(
+        req_properties=[
+            libevdev.INPUT_PROP_ACCELEROMETER,
+        ]
+    ),
+    "Game Pad": EvdevMatch(  # in systemd, this is a lot more complex, but that will do
+        requires=[
+            libevdev.EV_ABS.ABS_X,
+            libevdev.EV_ABS.ABS_Y,
+            libevdev.EV_ABS.ABS_RX,
+            libevdev.EV_ABS.ABS_RY,
+            libevdev.EV_KEY.BTN_START,
+        ],
+        excl_properties=[
+            libevdev.INPUT_PROP_ACCELEROMETER,
+        ],
+    ),
+    "Joystick": EvdevMatch(  # in systemd, this is a lot more complex, but that will do
+        requires=[
+            libevdev.EV_ABS.ABS_RX,
+            libevdev.EV_ABS.ABS_RY,
+            libevdev.EV_KEY.BTN_START,
+        ],
+        excl_properties=[
+            libevdev.INPUT_PROP_ACCELEROMETER,
+        ],
+    ),
+    "Key": EvdevMatch(
+        requires=[
+            libevdev.EV_KEY.KEY_A,
+        ],
+        excl_properties=[
+            libevdev.INPUT_PROP_ACCELEROMETER,
+            libevdev.INPUT_PROP_DIRECT,
+            libevdev.INPUT_PROP_POINTER,
+        ],
+    ),
+    "Mouse": EvdevMatch(
+        requires=[
+            libevdev.EV_REL.REL_X,
+            libevdev.EV_REL.REL_Y,
+            libevdev.EV_KEY.BTN_LEFT,
+        ],
+        excl_properties=[
+            libevdev.INPUT_PROP_ACCELEROMETER,
+        ],
+    ),
+    "Pad": EvdevMatch(
+        requires=[
+            libevdev.EV_KEY.BTN_0,
+        ],
+        excludes=[
+            libevdev.EV_KEY.BTN_TOOL_PEN,
+            libevdev.EV_KEY.BTN_TOUCH,
+            libevdev.EV_ABS.ABS_DISTANCE,
+        ],
+        excl_properties=[
+            libevdev.INPUT_PROP_ACCELEROMETER,
+        ],
+    ),
+    "Pen": EvdevMatch(
+        requires=[
+            libevdev.EV_KEY.BTN_STYLUS,
+            libevdev.EV_ABS.ABS_X,
+            libevdev.EV_ABS.ABS_Y,
+        ],
+        excl_properties=[
+            libevdev.INPUT_PROP_ACCELEROMETER,
+        ],
+    ),
+    "Stylus": EvdevMatch(
+        requires=[
+            libevdev.EV_KEY.BTN_STYLUS,
+            libevdev.EV_ABS.ABS_X,
+            libevdev.EV_ABS.ABS_Y,
+        ],
+        excl_properties=[
+            libevdev.INPUT_PROP_ACCELEROMETER,
+        ],
+    ),
+    "Touch Pad": EvdevMatch(
+        requires=[
+            libevdev.EV_KEY.BTN_LEFT,
+            libevdev.EV_ABS.ABS_X,
+            libevdev.EV_ABS.ABS_Y,
+        ],
+        excludes=[libevdev.EV_KEY.BTN_TOOL_PEN, libevdev.EV_KEY.BTN_STYLUS],
+        req_properties=[
+            libevdev.INPUT_PROP_POINTER,
+        ],
+        excl_properties=[
+            libevdev.INPUT_PROP_ACCELEROMETER,
+        ],
+    ),
+    "Touch Screen": EvdevMatch(
+        requires=[
+            libevdev.EV_KEY.BTN_TOUCH,
+            libevdev.EV_ABS.ABS_X,
+            libevdev.EV_ABS.ABS_Y,
+        ],
+        excludes=[libevdev.EV_KEY.BTN_TOOL_PEN, libevdev.EV_KEY.BTN_STYLUS],
+        req_properties=[
+            libevdev.INPUT_PROP_DIRECT,
+        ],
+        excl_properties=[
+            libevdev.INPUT_PROP_ACCELEROMETER,
+        ],
+    ),
+}
+
+
+class UHIDTestDevice(BaseDevice):
+    def __init__(self, name, application, rdesc_str=None, rdesc=None, input_info=None):
+        super().__init__(name, application, rdesc_str, rdesc, input_info)
+        self.application_matches = application_matches
+        if name is None:
+            name = f"uhid test {self.__class__.__name__}"
+        if not name.startswith("uhid test "):
+            name = "uhid test " + self.name
+        self.name = name
+
+
+class BaseTestCase:
+    class TestUhid(object):
+        syn_event = libevdev.InputEvent(libevdev.EV_SYN.SYN_REPORT)  # type: ignore
+        key_event = libevdev.InputEvent(libevdev.EV_KEY)  # type: ignore
+        abs_event = libevdev.InputEvent(libevdev.EV_ABS)  # type: ignore
+        rel_event = libevdev.InputEvent(libevdev.EV_REL)  # type: ignore
+        msc_event = libevdev.InputEvent(libevdev.EV_MSC.MSC_SCAN)  # type: ignore
+
+        # List of kernel modules to load before starting the test
+        # if any module is not available (not compiled), the test will skip.
+        # Each element is a tuple '(kernel driver name, kernel module)',
+        # for example ("playstation", "hid-playstation")
+        kernel_modules = []
+
+        def assertInputEventsIn(self, expected_events, effective_events):
+            effective_events = effective_events.copy()
+            for ev in expected_events:
+                assert ev in effective_events
+                effective_events.remove(ev)
+            return effective_events
+
+        def assertInputEvents(self, expected_events, effective_events):
+            remaining = self.assertInputEventsIn(expected_events, effective_events)
+            assert remaining == []
+
+        @classmethod
+        def debug_reports(cls, reports, uhdev=None, events=None):
+            data = [" ".join([f"{v:02x}" for v in r]) for r in reports]
+
+            if uhdev is not None:
+                human_data = [
+                    uhdev.parsed_rdesc.format_report(r, split_lines=True)
+                    for r in reports
+                ]
+                try:
+                    human_data = [
+                        f'\n\t       {" " * h.index("/")}'.join(h.split("\n"))
+                        for h in human_data
+                    ]
+                except ValueError:
+                    # '/' not found: not a numbered report
+                    human_data = ["\n\t      ".join(h.split("\n")) for h in human_data]
+                data = [f"{d}\n\t ====> {h}" for d, h in zip(data, human_data)]
+
+            reports = data
+
+            if len(reports) == 1:
+                print("sending 1 report:")
+            else:
+                print(f"sending {len(reports)} reports:")
+            for report in reports:
+                print("\t", report)
+
+            if events is not None:
+                print("events received:", events)
+
+        def create_device(self):
+            raise Exception("please reimplement me in subclasses")
+
+        def _load_kernel_module(self, kernel_driver, kernel_module):
+            sysfs_path = Path("/sys/bus/hid/drivers")
+            if kernel_driver is not None:
+                sysfs_path /= kernel_driver
+            else:
+                # special case for when testing all available modules:
+                # we don't know beforehand the name of the module from modinfo
+                sysfs_path = Path("/sys/module") / kernel_module.replace("-", "_")
+            if not sysfs_path.exists():
+                import subprocess
+
+                ret = subprocess.run(["/usr/sbin/modprobe", kernel_module])
+                if ret.returncode != 0:
+                    pytest.skip(
+                        f"module {kernel_module} could not be loaded, skipping the test"
+                    )
+
+        @pytest.fixture()
+        def load_kernel_module(self):
+            for kernel_driver, kernel_module in self.kernel_modules:
+                self._load_kernel_module(kernel_driver, kernel_module)
+            yield
+
+        @pytest.fixture()
+        def new_uhdev(self, load_kernel_module):
+            return self.create_device()
+
+        def assertName(self, uhdev):
+            evdev = uhdev.get_evdev()
+            assert uhdev.name in evdev.name
+
+        @pytest.fixture(autouse=True)
+        def context(self, new_uhdev, request):
+            try:
+                with HIDTestUdevRule.instance():
+                    with new_uhdev as self.uhdev:
+                        skip_cond = request.node.get_closest_marker("skip_if_uhdev")
+                        if skip_cond:
+                            test, message, *rest = skip_cond.args
+
+                            if test(self.uhdev):
+                                pytest.skip(message)
+
+                        self.uhdev.create_kernel_device()
+                        now = time.time()
+                        while not self.uhdev.is_ready() and time.time() - now < 5:
+                            self.uhdev.dispatch(1)
+                        if self.uhdev.get_evdev() is None:
+                            logger.warning(
+                                f"available list of input nodes: (default application is '{self.uhdev.application}')"
+                            )
+                            logger.warning(self.uhdev.input_nodes)
+                        yield
+                        self.uhdev = None
+            except PermissionError:
+                pytest.skip("Insufficient permissions, run me as root")
+
+        @pytest.fixture(autouse=True)
+        def check_taint(self):
+            # we are abusing SysfsFile here, it's in /proc, but meh
+            taint_file = SysfsFile("/proc/sys/kernel/tainted")
+            taint = taint_file.int_value
+
+            yield
+
+            assert taint_file.int_value == taint
+
+        def test_creation(self):
+            """Make sure the device gets processed by the kernel and creates
+            the expected application input node.
+
+            If this fail, there is something wrong in the device report
+            descriptors."""
+            uhdev = self.uhdev
+            assert uhdev is not None
+            assert uhdev.get_evdev() is not None
+            self.assertName(uhdev)
+            assert len(uhdev.next_sync_events()) == 0
+            assert uhdev.get_evdev() is not None
+
+
+class HIDTestUdevRule(object):
+    _instance = None
+    """
+    A context-manager compatible class that sets up our udev rules file and
+    deletes it on context exit.
+
+    This class is tailored to our test setup: it only sets up the udev rule
+    on the **second** context and it cleans it up again on the last context
+    removed. This matches the expected pytest setup: we enter a context for
+    the session once, then once for each test (the first of which will
+    trigger the udev rule) and once the last test exited and the session
+    exited, we clean up after ourselves.
+    """
+
+    def __init__(self):
+        self.refs = 0
+        self.rulesfile = None
+
+    def __enter__(self):
+        self.refs += 1
+        if self.refs == 2 and self.rulesfile is None:
+            self.create_udev_rule()
+            self.reload_udev_rules()
+
+    def __exit__(self, exc_type, exc_value, traceback):
+        self.refs -= 1
+        if self.refs == 0 and self.rulesfile:
+            os.remove(self.rulesfile.name)
+            self.reload_udev_rules()
+
+    def reload_udev_rules(self):
+        import subprocess
+
+        subprocess.run("udevadm control --reload-rules".split())
+        subprocess.run("systemd-hwdb update".split())
+
+    def create_udev_rule(self):
+        import tempfile
+
+        os.makedirs("/run/udev/rules.d", exist_ok=True)
+        with tempfile.NamedTemporaryFile(
+            prefix="91-uhid-test-device-REMOVEME-",
+            suffix=".rules",
+            mode="w+",
+            dir="/run/udev/rules.d",
+            delete=False,
+        ) as f:
+            f.write(
+                'KERNELS=="*input*", ATTRS{name}=="*uhid test *", ENV{LIBINPUT_IGNORE_DEVICE}="1"\n'
+            )
+            f.write(
+                'KERNELS=="*input*", ATTRS{name}=="*uhid test * System Multi Axis", ENV{ID_INPUT_TOUCHSCREEN}="", ENV{ID_INPUT_SYSTEM_MULTIAXIS}="1"\n'
+            )
+            self.rulesfile = f
+
+    @classmethod
+    def instance(cls):
+        if not cls._instance:
+            cls._instance = HIDTestUdevRule()
+        return cls._instance
diff --git a/tools/testing/selftests/hid/tests/conftest.py b/tools/testing/selftests/hid/tests/conftest.py
new file mode 100644
index 000000000000..1361ec981db6
--- /dev/null
+++ b/tools/testing/selftests/hid/tests/conftest.py
@@ -0,0 +1,81 @@
+#!/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+# Copyright (c) 2017 Red Hat, Inc.
+
+import platform
+import pytest
+import re
+import resource
+import subprocess
+from .base import HIDTestUdevRule
+from pathlib import Path
+
+
+# See the comment in HIDTestUdevRule, this doesn't set up but it will clean
+# up once the last test exited.
+@pytest.fixture(autouse=True, scope="session")
+def udev_rules_session_setup():
+    with HIDTestUdevRule.instance():
+        yield
+
+
+@pytest.fixture(autouse=True, scope="session")
+def setup_rlimit():
+    resource.setrlimit(resource.RLIMIT_CORE, (0, 0))
+
+
+@pytest.fixture(autouse=True, scope="session")
+def start_udevd(pytestconfig):
+    if pytestconfig.getoption("udevd"):
+        import subprocess
+
+        with subprocess.Popen("/usr/lib/systemd/systemd-udevd") as proc:
+            yield
+            proc.kill()
+    else:
+        yield
+
+
+def pytest_configure(config):
+    config.addinivalue_line(
+        "markers",
+        "skip_if_uhdev(condition, message): mark test to skip if the condition on the uhdev device is met",
+    )
+
+
+# Generate the list of modules and modaliases
+# for the tests that need to be parametrized with those
+def pytest_generate_tests(metafunc):
+    if "usbVidPid" in metafunc.fixturenames:
+        modules = (
+            Path("/lib/modules/")
+            / platform.uname().release
+            / "kernel"
+            / "drivers"
+            / "hid"
+        )
+
+        modalias_re = re.compile(r"alias:\s+hid:b0003g.*v([0-9a-fA-F]+)p([0-9a-fA-F]+)")
+
+        params = []
+        ids = []
+        for module in modules.glob("*.ko"):
+            p = subprocess.run(
+                ["modinfo", module], capture_output=True, check=True, encoding="utf-8"
+            )
+            for line in p.stdout.split("\n"):
+                m = modalias_re.match(line)
+                if m is not None:
+                    vid, pid = m.groups()
+                    vid = int(vid, 16)
+                    pid = int(pid, 16)
+                    params.append([module.name.replace(".ko", ""), vid, pid])
+                    ids.append(f"{module.name} {vid:04x}:{pid:04x}")
+        metafunc.parametrize("usbVidPid", params, ids=ids)
+
+
+def pytest_addoption(parser):
+    parser.addoption("--udevd", action="store_true", default=False)
diff --git a/tools/testing/selftests/hid/tests/test_hid_core.py b/tools/testing/selftests/hid/tests/test_hid_core.py
new file mode 100644
index 000000000000..9a7fe40020d2
--- /dev/null
+++ b/tools/testing/selftests/hid/tests/test_hid_core.py
@@ -0,0 +1,154 @@
+#!/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com>
+# Copyright (c) 2017 Red Hat, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# This is for generic devices
+
+from . import base
+import logging
+
+logger = logging.getLogger("hidtools.test.hid")
+
+
+class TestCollectionOverflow(base.BaseTestCase.TestUhid):
+    """
+    Test class to test re-allocation of the HID collection stack in
+    hid-core.c.
+    """
+
+    def create_device(self):
+        # fmt: off
+        report_descriptor = [
+            0x05, 0x01,         # .Usage Page (Generic Desktop)
+            0x09, 0x02,         # .Usage (Mouse)
+            0xa1, 0x01,         # .Collection (Application)
+            0x09, 0x02,         # ..Usage (Mouse)
+            0xa1, 0x02,         # ..Collection (Logical)
+            0x09, 0x01,         # ...Usage (Pointer)
+            0xa1, 0x00,         # ...Collection (Physical)
+            0x05, 0x09,         # ....Usage Page (Button)
+            0x19, 0x01,         # ....Usage Minimum (1)
+            0x29, 0x03,         # ....Usage Maximum (3)
+            0x15, 0x00,         # ....Logical Minimum (0)
+            0x25, 0x01,         # ....Logical Maximum (1)
+            0x75, 0x01,         # ....Report Size (1)
+            0x95, 0x03,         # ....Report Count (3)
+            0x81, 0x02,         # ....Input (Data,Var,Abs)
+            0x75, 0x05,         # ....Report Size (5)
+            0x95, 0x01,         # ....Report Count (1)
+            0x81, 0x03,         # ....Input (Cnst,Var,Abs)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0xa1, 0x02,         # ....Collection (Logical)
+            0x09, 0x01,         # .....Usage (Pointer)
+            0x05, 0x01,         # .....Usage Page (Generic Desktop)
+            0x09, 0x30,         # .....Usage (X)
+            0x09, 0x31,         # .....Usage (Y)
+            0x15, 0x81,         # .....Logical Minimum (-127)
+            0x25, 0x7f,         # .....Logical Maximum (127)
+            0x75, 0x08,         # .....Report Size (8)
+            0x95, 0x02,         # .....Report Count (2)
+            0x81, 0x06,         # .....Input (Data,Var,Rel)
+            0xa1, 0x02,         # ...Collection (Logical)
+            0x85, 0x12,         # ....Report ID (18)
+            0x09, 0x48,         # ....Usage (Resolution Multiplier)
+            0x95, 0x01,         # ....Report Count (1)
+            0x75, 0x02,         # ....Report Size (2)
+            0x15, 0x00,         # ....Logical Minimum (0)
+            0x25, 0x01,         # ....Logical Maximum (1)
+            0x35, 0x01,         # ....Physical Minimum (1)
+            0x45, 0x0c,         # ....Physical Maximum (12)
+            0xb1, 0x02,         # ....Feature (Data,Var,Abs)
+            0x85, 0x1a,         # ....Report ID (26)
+            0x09, 0x38,         # ....Usage (Wheel)
+            0x35, 0x00,         # ....Physical Minimum (0)
+            0x45, 0x00,         # ....Physical Maximum (0)
+            0x95, 0x01,         # ....Report Count (1)
+            0x75, 0x10,         # ....Report Size (16)
+            0x16, 0x01, 0x80,   # ....Logical Minimum (-32767)
+            0x26, 0xff, 0x7f,   # ....Logical Maximum (32767)
+            0x81, 0x06,         # ....Input (Data,Var,Rel)
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ...End Collection
+            0xc0,               # ..End Collection
+            0xc0,               # .End Collection
+        ]
+        # fmt: on
+        return base.UHIDTestDevice(
+            name=None, rdesc=report_descriptor, application="Mouse"
+        )
+
+    def test_rdesc(self):
+        """
+        This test can only check for negatives. If the kernel crashes, you
+        know why. If this test passes, either the bug isn't present or just
+        didn't get triggered. No way to know.
+
+        For an explanation, see kernel patch
+            HID: core: replace the collection tree pointers with indices
+        """
+        pass
diff --git a/tools/testing/selftests/hid/vmtest.sh b/tools/testing/selftests/hid/vmtest.sh
index 6346b0620dba..681b906b4853 100755
--- a/tools/testing/selftests/hid/vmtest.sh
+++ b/tools/testing/selftests/hid/vmtest.sh
@@ -27,7 +27,7 @@ EXIT_STATUS_FILE="${LOG_FILE_BASE}.exit_status"
 CONTAINER_IMAGE="registry.freedesktop.org/libevdev/hid-tools/fedora/37:2023-02-17.1"
 
 TARGETS="${TARGETS:=$(basename ${SCRIPT_DIR})}"
-DEFAULT_COMMAND="make -C tools/testing/selftests TARGETS=${TARGETS} run_tests"
+DEFAULT_COMMAND="pip3 install hid-tools; make -C tools/testing/selftests TARGETS=${TARGETS} run_tests"
 
 usage()
 {

-- 
2.39.1


^ permalink raw reply related


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