The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data'
@ 2026-05-18 16:06 Pawel Zalewski (The Capable Hub)
  2026-05-18 16:06 ` [PATCH 01/11] HID: hid-input: use named initializer for 'hid_battery_quirks[]' Pawel Zalewski (The Capable Hub)
                   ` (12 more replies)
  0 siblings, 13 replies; 17+ messages in thread
From: Pawel Zalewski (The Capable Hub) @ 2026-05-18 16:06 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke
  Cc: linux-kernel, linux-input, Christian A. Ehrhardt,
	Christian A. Ehrhardt, Pawel Zalewski (The Capable Hub)

The <linux/mod_devicetable.h> has multiple structs that follow
the pattern of having either 'driver_data' or 'driver_info'
fields which are of the 'kernel_ulong_t' type. Then how to 
interpret that field is user defined, some users will treat
the value as an actual integer, others as a valid pointer to
dereference. 

One of instances of the above is the 'hid_device_id::driver_data'
field, for the most part it is used for setting HID quirks and
treated as an integer value for storing metadata in the subsystem
drivers. But in a few instances it is used as a valid pointer to
dereference, namely in:
- hid-tmff
- wacom
 
One of the ways to fixing this duality and improve code readability
and type-safety a bit is to use a '{kernel_ulong_t, const void *}'
union. That way the current drivers that treat 'hid_device_id::driver_data'
as an integer value for storing metadata are unaffected. The drivers
that actually store pointers in there benefit from a removed cast
(and more clear intent) at the cost of using the new 'const void *'
field instead.

With the union in place, some of the existing initializers for static
const data now need a named field for the 'driver_data' - this is
also addressed in the series as part of the pre-clean up in 
patches 1-4. 

It was found that some modules use a bit of a type-unsafe way of storing
integers in the 'void *driver_data' pointer of the 'struct hid_device'
- this required a cast during storage via 'hid_set_drvdata' and a cast
during retrieval when using 'hid_get_drvdata'. I can see why this was 
done - as we potentially save on an allocation - but really code is
more readable and better quality without resorting to this. This issue
is also addressed in this patch series in patches 5-8 as part of the
pre-clean up.

The actual implementation and post-clean up can be found in 
patches 9-11.

The change also makes the code more portable on architecture 
like CHERI [1], where a pointer is replaced with a new primitive
(called the capability) at the architecture level and is as twice as
wide as the greatest representable address, ie. for 64 bit address
space capabilities are 128 bits wide (the other 64 bits are used to
store meta-data relating to the 64 bit address). So you can not store 
valid pointers inside 'unsigned long' as effectively a different set of
instructions is being generated by the compiler based on the data-type
that was used in C (ie. capabilities have their own set of load/store
that also copy over the meta-data which are orthogonal to the load/store
instructions used for plain integers that would invalidate the meta-data).
There is slightly more detail to this, but the above is enough to
explain the motivation - the proposed changes make the code a bit
better even without considering CHERI at all - as it is more readable 
and type-safe.

The series was built and tested under QEMU (boots with relevant 
configs set to Y) on arm64.

This series is part of a larger effort led by Uwe [2]

[1] https://cheri-alliance.org/discover-cheri/
[2] https://lore.kernel.org/all/cover.1776429984.git.u.kleine-koenig@baylibre.com/ 

---
Pawel Zalewski (The Capable Hub) (11):
      HID: hid-input: use named initializer for 'hid_battery_quirks[]'
      HID: hid-quirks: use named initializer in 'hid_quirks[]'
      HID: hid-asus: use named initializer for 'asus_devices[]'
      HID: i2c-hid-dmi-quirks: use named initializer for 'i2c_hid_elan_flipped_quirks[]'
      HID: hid-belkin: clean up usage of 'driver_data'
      HID: hid-cypress: clean up usage of 'driver_data'
      HID: hid-gfrm: clean up usage of 'driver_data'
      HID: hid-ite: clean up usage of 'driver_data'
      HID: mod_devicetable: 'hid_device_id::driver_data' add union
      HID: hid-tmff: use 'hid_device_id::driver_data_ptr'
      HID: wacom: use 'hid_device_id::driver_data_ptr'

 drivers/hid/hid-asus.c                   |  46 ++-
 drivers/hid/hid-belkin.c                 |   5 +-
 drivers/hid/hid-cypress.c                |  32 +-
 drivers/hid/hid-gfrm.c                   |   8 +-
 drivers/hid/hid-input.c                  |  38 +-
 drivers/hid/hid-ite.c                    |   9 +-
 drivers/hid/hid-quirks.c                 | 575 ++++++++++++++++++++-----------
 drivers/hid/hid-tmff.c                   |  22 +-
 drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c |   2 +-
 drivers/hid/wacom_sys.c                  |  14 +-
 drivers/hid/wacom_wac.c                  |  10 +-
 include/linux/mod_devicetable.h          |   5 +-
 12 files changed, 496 insertions(+), 270 deletions(-)
---
base-commit: 25ccf4586bead3fe3cf2c57ff0480f31a0e335ad
change-id: 20260427-mod-devicetable-hid_device_id-7f30d877387c

Best regards,
--  
Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 01/11] HID: hid-input: use named initializer for 'hid_battery_quirks[]'
  2026-05-18 16:06 [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Pawel Zalewski (The Capable Hub)
@ 2026-05-18 16:06 ` Pawel Zalewski (The Capable Hub)
  2026-05-18 16:06 ` [PATCH 02/11] HID: hid-quirks: use named initializer in 'hid_quirks[]' Pawel Zalewski (The Capable Hub)
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Pawel Zalewski (The Capable Hub) @ 2026-05-18 16:06 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke
  Cc: linux-kernel, linux-input, Christian A. Ehrhardt,
	Christian A. Ehrhardt, Pawel Zalewski (The Capable Hub)

This makes the code a little bit more readable and consistent
with other drivers in the HID subsystem that assign the
'driver_data' field in the 'hid_device_id' struct explicitly.

While touching the 'hid_battery_quirks[]', align the list
terminator entry to use a space between the curly braces for
better matching the layout of the other entries.

It was confirmed that hid-input.o pre/post the patch are equal
using diffscope.

Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
 drivers/hid/hid-input.c | 38 ++++++++++++++++++++------------------
 1 file changed, 20 insertions(+), 18 deletions(-)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index d73cfa2e73d3..50ee03508806 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -359,49 +359,51 @@ static enum power_supply_property hidinput_battery_props[] = {
 static const struct hid_device_id hid_battery_quirks[] = {
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
 		USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
-	  HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
+	  .driver_data = HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
 		USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
-	  HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
+	  .driver_data = HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
 		USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI),
-	  HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
+	  .driver_data = HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
-			       USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO),
-	  HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
+		USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO),
+	  .driver_data = HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
 		USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI),
-	  HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
+	  .driver_data = HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
 		USB_DEVICE_ID_APPLE_MAGICTRACKPAD),
-	  HID_BATTERY_QUIRK_IGNORE },
+	  .driver_data = HID_BATTERY_QUIRK_IGNORE },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM,
 		USB_DEVICE_ID_ELECOM_BM084),
-	  HID_BATTERY_QUIRK_IGNORE },
+	  .driver_data = HID_BATTERY_QUIRK_IGNORE },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SYMBOL,
 		USB_DEVICE_ID_SYMBOL_SCANNER_3),
-	  HID_BATTERY_QUIRK_IGNORE },
+	  .driver_data = HID_BATTERY_QUIRK_IGNORE },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK,
 		USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD),
-	  HID_BATTERY_QUIRK_IGNORE },
+	  .driver_data = HID_BATTERY_QUIRK_IGNORE },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
 		USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD),
-	  HID_BATTERY_QUIRK_IGNORE },
+	  .driver_data = HID_BATTERY_QUIRK_IGNORE },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L),
-	  HID_BATTERY_QUIRK_AVOID_QUERY },
+	  .driver_data = HID_BATTERY_QUIRK_AVOID_QUERY },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_MW),
-	  HID_BATTERY_QUIRK_AVOID_QUERY },
+	  .driver_data = HID_BATTERY_QUIRK_AVOID_QUERY },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW),
-	  HID_BATTERY_QUIRK_AVOID_QUERY },
+	  .driver_data = HID_BATTERY_QUIRK_AVOID_QUERY },
 	{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM),
-	  HID_BATTERY_QUIRK_AVOID_QUERY },
+	  .driver_data = HID_BATTERY_QUIRK_AVOID_QUERY },
 	/*
 	 * Elan HID touchscreens seem to all report a non present battery,
 	 * set HID_BATTERY_QUIRK_IGNORE for all Elan I2C and USB HID devices.
 	 */
-	{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_DYNAMIC },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_DYNAMIC },
-	{}
+	{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID),
+	  .driver_data = HID_BATTERY_QUIRK_DYNAMIC },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID),
+	  .driver_data = HID_BATTERY_QUIRK_DYNAMIC },
+	{ }
 };
 
 static unsigned find_battery_quirk(struct hid_device *hdev)

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 02/11] HID: hid-quirks: use named initializer in 'hid_quirks[]'
  2026-05-18 16:06 [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Pawel Zalewski (The Capable Hub)
  2026-05-18 16:06 ` [PATCH 01/11] HID: hid-input: use named initializer for 'hid_battery_quirks[]' Pawel Zalewski (The Capable Hub)
@ 2026-05-18 16:06 ` Pawel Zalewski (The Capable Hub)
  2026-05-18 16:06 ` [PATCH 03/11] HID: hid-asus: use named initializer for 'asus_devices[]' Pawel Zalewski (The Capable Hub)
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Pawel Zalewski (The Capable Hub) @ 2026-05-18 16:06 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke
  Cc: linux-kernel, linux-input, Christian A. Ehrhardt,
	Christian A. Ehrhardt, Pawel Zalewski (The Capable Hub)

This makes the code a little bit more readable and consistent
with other drivers in the HID subsystem that assign the
'driver_data' field in the 'hid_device_id' struct explicitly.

While touching the 'hid_quirks[]', modify the terminator entry to use
a space between the curly braces as opposed to a 0 for consistency.

It was confirmed that hid-quirks.o pre/post the patch are equal
using diffscope.

Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
 drivers/hid/hid-quirks.c | 575 +++++++++++++++++++++++++++++++----------------
 1 file changed, 382 insertions(+), 193 deletions(-)

diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 9e88c9d6c6dc..36e1ef536cde 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -25,201 +25,390 @@
  */
 
 static const struct hid_device_id hid_quirks[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_8BITDO, USB_DEVICE_ID_8BITDO_PRO_3), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD), HID_QUIRK_BADPAD },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR), HID_QUIRK_BADPAD },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ADATA_XPG, USB_VENDOR_ID_ADATA_XPG_WL_GAMING_MOUSE), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ADATA_XPG, USB_VENDOR_ID_ADATA_XPG_WL_GAMING_MOUSE_DONGLE), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016), HID_QUIRK_FULLSPEED_INTERVAL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_AKAI_09E8, USB_DEVICE_ID_AKAI_09E8_MIDIMIX), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD), HID_QUIRK_BADPAD },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_AMI, USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS1758), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE2), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD), HID_QUIRK_BADPAD },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_COOLER_MASTER, USB_DEVICE_ID_COOLER_MASTER_MICE_DONGLE), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB_RAPIDFIRE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70R), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K95RGB), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_M65RGB), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_GLAIVE_RGB), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_STRAFE), HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PRO_WIRELESS_KM5221W), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_REDRAGON_SEYMUR2), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE3), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER), HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_EDIFIER, USB_DEVICE_ID_EDIFIER_QR30), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH_2968), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD), HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_8BITDO, USB_DEVICE_ID_8BITDO_PRO_3),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD),
+	  .driver_data = HID_QUIRK_BADPAD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR),
+	  .driver_data = HID_QUIRK_BADPAD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ADATA_XPG, USB_VENDOR_ID_ADATA_XPG_WL_GAMING_MOUSE),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ADATA_XPG, USB_VENDOR_ID_ADATA_XPG_WL_GAMING_MOUSE_DONGLE),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_AFATECH, USB_DEVICE_ID_AFATECH_AF9016),
+	  .driver_data = HID_QUIRK_FULLSPEED_INTERVAL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_AKAI_09E8, USB_DEVICE_ID_AKAI_09E8_MIDIMIX),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_AKAI, USB_DEVICE_ID_AKAI_MPKMINI2),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD),
+	  .driver_data = HID_QUIRK_BADPAD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_AMI,	USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_REVB_ANSI),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS1758),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS682),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS692),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_MULTI_TOUCH),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY,	USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY,	USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE2),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD),
+	  .driver_data = HID_QUIRK_BADPAD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FIGHTERSTICK),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_COOLER_MASTER, USB_DEVICE_ID_COOLER_MASTER_MICE_DONGLE),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB_RAPIDFIRE),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR,	USB_DEVICE_ID_CORSAIR_K70RGB_RAPIDFIRE),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70R),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K95RGB),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_M65RGB),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_GLAIVE_RGB),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR,	USB_DEVICE_ID_CORSAIR_SCIMITAR_PRO_RGB),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_STRAFE),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PRO_WIRELESS_KM5221W),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_REDRAGON_SEYMUR2),
+	  .driver_data = HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE3),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER),
+	  .driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_EDIFIER, USB_DEVICE_ID_EDIFIER_QR30),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH_2968),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_GAMEVICE, USB_DEVICE_ID_GAMEVICE_GV186),
-		HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+	  .driver_data = HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GAMEVICE, USB_DEVICE_ID_GAMEVICE_KISHI),
-		HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A293), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A), HID_QUIRK_ALWAYS_POLL },
-	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0941), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0641), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_1f4a), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M506), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406W), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_340), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_M508WX), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_M508X), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406XE), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_T609A), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_ODDOR_HANDBRAKE), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_LEGION_GO_DUAL_DINPUT), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_LEGION_GO2_DUAL_DINPUT), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6093), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C007), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C01A), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MCS, USB_DEVICE_ID_MCS_GAMEPADBLOCK), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_MOUSE_0783), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PIXART_MOUSE), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE3_COVER), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_NATSU, USB_DEVICE_ID_NATSU_GAMEPAD), HID_QUIRK_BADPAD },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD), HID_QUIRK_BADPAD },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_NEXTWINDOW, USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN), HID_QUIRK_MULTI_INPUT},
-	{ HID_USB_DEVICE(USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK), HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1610), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1640), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_PI_ENGINEERING, USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL), HID_QUIRK_HIDINPUT_FORCE },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4E2A), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D65), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPAD), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPORT), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD), HID_QUIRK_BADPAD },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52_2), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52_PRO), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X65), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS_TS), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DELL_K12A), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DELL_K15A), HID_QUIRK_NO_INIT_REPORTS },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD), HID_QUIRK_BADPAD },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8883), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD), HID_QUIRK_NOGET },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_WP5540), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_VRS, USB_DEVICE_ID_VRS_R295), HID_QUIRK_ALWAYS_POLL },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE), HID_QUIRK_MULTI_INPUT },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_GROUP_AUDIO), HID_QUIRK_NOGET },
-
-	{ 0 }
+	  .driver_data = HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING),
+	  .driver_data = HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING),
+	  .driver_data = HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING),
+	  .driver_data = HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A293),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_ELITE_PRESENTER_MOUSE_464A),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_094A),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0941),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_0641),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE_1f4a),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE_ID2),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M506),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406W),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_340),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_M508WX),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_M508X),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406XE),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_T609A),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_ODDOR_HANDBRAKE),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_LEGION_GO_DUAL_DINPUT),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_LEGION_GO2_DUAL_DINPUT),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_602E),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6093),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_BOLT_RECEIVER),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C007),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C01A),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MCS, USB_DEVICE_ID_MCS_GAMEPADBLOCK),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_MOUSE_0783),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PIXART_MOUSE),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE3_COVER),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MOJO, USB_DEVICE_ID_RETRO_ADAPTER),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_NATSU, USB_DEVICE_ID_NATSU_GAMEPAD),
+	  .driver_data = HID_QUIRK_BADPAD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_NEC, USB_DEVICE_ID_NEC_USB_GAME_PAD),
+	  .driver_data = HID_QUIRK_BADPAD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_NEXTWINDOW, USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN),
+	  .driver_data = HID_QUIRK_MULTI_INPUT},
+	{ HID_USB_DEVICE(USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK),
+	  .driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1610),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_1640),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PI_ENGINEERING,
+		USB_DEVICE_ID_PI_ENGINEERING_VEC_USB_FOOTPEDAL),
+	  .driver_data = HID_QUIRK_HIDINPUT_FORCE },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4E2A),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D65),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPAD),
+	  .driver_data = HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPORT),
+	  .driver_data = HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD),
+	  .driver_data = HID_QUIRK_BADPAD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52),
+	  .driver_data = HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52_2),
+	  .driver_data = HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52_PRO),
+	  .driver_data = HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X65),
+	  .driver_data = HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS9200_TOUCH),
+	  .driver_data =  HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS_TS),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_HD),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS1),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DELL_K12A),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DELL_K15A),
+	  .driver_data = HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD),
+	  .driver_data = HID_QUIRK_BADPAD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8883),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_WP5540),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_VRS, USB_DEVICE_ID_VRS_R295),
+	  .driver_data = HID_QUIRK_ALWAYS_POLL },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS),
+	  .driver_data = HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD),
+	  .driver_data = HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE),
+	  .driver_data = HID_QUIRK_MULTI_INPUT },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_GROUP_AUDIO),
+	  .driver_data = HID_QUIRK_NOGET },
+	{ }
 };
 
 /*

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 03/11] HID: hid-asus: use named initializer for 'asus_devices[]'
  2026-05-18 16:06 [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Pawel Zalewski (The Capable Hub)
  2026-05-18 16:06 ` [PATCH 01/11] HID: hid-input: use named initializer for 'hid_battery_quirks[]' Pawel Zalewski (The Capable Hub)
  2026-05-18 16:06 ` [PATCH 02/11] HID: hid-quirks: use named initializer in 'hid_quirks[]' Pawel Zalewski (The Capable Hub)
@ 2026-05-18 16:06 ` Pawel Zalewski (The Capable Hub)
  2026-05-18 16:06 ` [PATCH 04/11] HID: i2c-hid-dmi-quirks: use named initializer for 'i2c_hid_elan_flipped_quirks[]' Pawel Zalewski (The Capable Hub)
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Pawel Zalewski (The Capable Hub) @ 2026-05-18 16:06 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke
  Cc: linux-kernel, linux-input, Christian A. Ehrhardt,
	Christian A. Ehrhardt, Pawel Zalewski (The Capable Hub)

This makes the code a little bit more readable and consistent
with other drivers in the HID subsystem that assign the
'driver_data' field in the 'hid_device_id' struct explicitly.

It was confirmed that hid-asus.o pre/post the patch are equal
using diffscope.

Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
 drivers/hid/hid-asus.c | 46 ++++++++++++++++++++++++++++------------------
 1 file changed, 28 insertions(+), 18 deletions(-)

diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 3f5e96900b67..ba9a49e9c7f0 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -1476,33 +1476,41 @@ static const __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 
 static const struct hid_device_id asus_devices[] = {
 	{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
-		USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD), I2C_KEYBOARD_QUIRKS},
+		USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD),
+	  .driver_data = I2C_KEYBOARD_QUIRKS },
 	{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
-		USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD), I2C_TOUCHPAD_QUIRKS },
+		USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD),
+	  .driver_data = I2C_TOUCHPAD_QUIRKS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
-		USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1), QUIRK_USE_KBD_BACKLIGHT },
+		USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1),
+	  .driver_data = QUIRK_USE_KBD_BACKLIGHT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
-		USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2), QUIRK_USE_KBD_BACKLIGHT },
+		USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2),
+	  .driver_data = QUIRK_USE_KBD_BACKLIGHT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
-		USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3), QUIRK_G752_KEYBOARD },
+		USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3),
+	  .driver_data = QUIRK_G752_KEYBOARD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
 		USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD),
-	  QUIRK_USE_KBD_BACKLIGHT },
+	  .driver_data = QUIRK_USE_KBD_BACKLIGHT },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
 	    USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD),
-	  QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
+	  .driver_data = QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
 	    USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2),
-	  QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_HID_FN_LOCK },
+	  .driver_data = QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD |
+		QUIRK_HID_FN_LOCK },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
 	    USB_DEVICE_ID_ASUSTEK_ROG_Z13_LIGHTBAR),
-	  QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
+	  .driver_data = QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
 	    USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY),
-	  QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_ALLY_XPAD},
+	  .driver_data = QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD |
+		QUIRK_ROG_ALLY_XPAD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
 	    USB_DEVICE_ID_ASUSTEK_ROG_NKEY_ALLY_X),
-	  QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_ROG_ALLY_XPAD },
+	  .driver_data = QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD |
+		QUIRK_ROG_ALLY_XPAD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
 	    USB_DEVICE_ID_ASUSTEK_XGM_2022),
 	},
@@ -1511,29 +1519,31 @@ static const struct hid_device_id asus_devices[] = {
 	},
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
 	    USB_DEVICE_ID_ASUSTEK_ROG_CLAYMORE_II_KEYBOARD),
-	  QUIRK_ROG_CLAYMORE_II_KEYBOARD },
+	  .driver_data = QUIRK_ROG_CLAYMORE_II_KEYBOARD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
 		USB_DEVICE_ID_ASUSTEK_T100TA_KEYBOARD),
-	  QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
+	  .driver_data = QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
 		USB_DEVICE_ID_ASUSTEK_T100TAF_KEYBOARD),
-	  QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
+	  .driver_data = QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_ASUS_AK1D) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK,
-		USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD), QUIRK_T100CHI },
+		USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD),
+	  .driver_data = QUIRK_T100CHI },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE_MEDION_E1239T),
-		QUIRK_MEDION_E1239T },
+	  .driver_data = QUIRK_MEDION_E1239T },
 	/*
 	 * Note bind to the HID_GROUP_GENERIC group, so that we only bind to the keyboard
 	 * part, while letting hid-multitouch.c handle the touchpad.
 	 */
 	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
 		USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_Z13_FOLIO),
-	  QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
+	  .driver_data = QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
 	{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
-		USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T101HA_KEYBOARD) },
+		USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T101HA_KEYBOARD),
+	  .driver_data = 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, asus_devices);

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 04/11] HID: i2c-hid-dmi-quirks: use named initializer for 'i2c_hid_elan_flipped_quirks[]'
  2026-05-18 16:06 [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Pawel Zalewski (The Capable Hub)
                   ` (2 preceding siblings ...)
  2026-05-18 16:06 ` [PATCH 03/11] HID: hid-asus: use named initializer for 'asus_devices[]' Pawel Zalewski (The Capable Hub)
@ 2026-05-18 16:06 ` Pawel Zalewski (The Capable Hub)
  2026-05-18 16:06 ` [PATCH 05/11] HID: hid-belkin: clean up usage of 'driver_data' Pawel Zalewski (The Capable Hub)
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Pawel Zalewski (The Capable Hub) @ 2026-05-18 16:06 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke
  Cc: linux-kernel, linux-input, Christian A. Ehrhardt,
	Christian A. Ehrhardt, Pawel Zalewski (The Capable Hub)

This makes the code a little bit more readable and consistent
with other drivers in the HID subsystem that assign the
'driver_data' field in the 'hid_device_id' struct explicitly.

It was confirmed that i2c-hid-dmi-quirks.o pre/post patch are equal
using diffscope.

Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
 drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
index 210f17c3a0be..f3e3cf73641e 100644
--- a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
+++ b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
@@ -420,7 +420,7 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
 
 static const struct hid_device_id i2c_hid_elan_flipped_quirks = {
 	HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, USB_VENDOR_ID_ELAN, 0x2dcd),
-		HID_QUIRK_X_INVERT | HID_QUIRK_Y_INVERT
+	.driver_data = HID_QUIRK_X_INVERT | HID_QUIRK_Y_INVERT,
 };
 
 /*

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 05/11] HID: hid-belkin: clean up usage of 'driver_data'
  2026-05-18 16:06 [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Pawel Zalewski (The Capable Hub)
                   ` (3 preceding siblings ...)
  2026-05-18 16:06 ` [PATCH 04/11] HID: i2c-hid-dmi-quirks: use named initializer for 'i2c_hid_elan_flipped_quirks[]' Pawel Zalewski (The Capable Hub)
@ 2026-05-18 16:06 ` Pawel Zalewski (The Capable Hub)
  2026-05-18 16:06 ` [PATCH 06/11] HID: hid-cypress: " Pawel Zalewski (The Capable Hub)
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Pawel Zalewski (The Capable Hub) @ 2026-05-18 16:06 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke
  Cc: linux-kernel, linux-input, Christian A. Ehrhardt,
	Christian A. Ehrhardt, Pawel Zalewski (The Capable Hub)

The module is storing an integer inside the drvdata pointer, which is
confusing, lets fix this and set the whole of 'hid_device_id' struct
as the drvdata and then simply use its integer 'driver_data' field for
quirks, which shall make the code cleaner, type-safe, consistent and
more readable.

This makes the cast to (void *) during storage a bit safer (just to
suppress the const qualifier warning) and the cast to (unsigned long)
during retrieval is removed.

Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
 drivers/hid/hid-belkin.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/hid-belkin.c b/drivers/hid/hid-belkin.c
index 75aaed35ee9f..84695115d37b 100644
--- a/drivers/hid/hid-belkin.c
+++ b/drivers/hid/hid-belkin.c
@@ -27,7 +27,8 @@ static int belkin_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
-	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+	const struct hid_device_id *id = hid_get_drvdata(hdev);
+	unsigned long quirks = id->driver_data;
 
 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER ||
 			!(quirks & BELKIN_WKBD))
@@ -48,7 +49,7 @@ static int belkin_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	unsigned long quirks = id->driver_data;
 	int ret;
 
-	hid_set_drvdata(hdev, (void *)quirks);
+	hid_set_drvdata(hdev, (void *)id);
 
 	ret = hid_parse(hdev);
 	if (ret) {

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 06/11] HID: hid-cypress: clean up usage of 'driver_data'
  2026-05-18 16:06 [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Pawel Zalewski (The Capable Hub)
                   ` (4 preceding siblings ...)
  2026-05-18 16:06 ` [PATCH 05/11] HID: hid-belkin: clean up usage of 'driver_data' Pawel Zalewski (The Capable Hub)
@ 2026-05-18 16:06 ` Pawel Zalewski (The Capable Hub)
  2026-05-18 16:06 ` [PATCH 07/11] HID: hid-gfrm: " Pawel Zalewski (The Capable Hub)
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Pawel Zalewski (The Capable Hub) @ 2026-05-18 16:06 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke
  Cc: linux-kernel, linux-input, Christian A. Ehrhardt,
	Christian A. Ehrhardt, Pawel Zalewski (The Capable Hub)

The module is storing an integer inside the drvdata pointer, which is
confusing - furthermore this integer is mutable. When its value is
changed it is set again using the 'hid_set_drvdata' API within
the 'cp_event' function.

Let's fix this, create and allocate the 'cp_device' struct that is then
set as the drvdata and then simply use its integer 'quirks' field for
storing the quirks, which shall make the code cleaner, type-safe,
consistent and more readable.

This makes the cast to (void *) during storage unnecessary and the cast
to (unsigned long) during retrieval is also removed.

Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
 drivers/hid/hid-cypress.c | 32 ++++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 10 deletions(-)

diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c
index 98548201feec..f18fddc176d0 100644
--- a/drivers/hid/hid-cypress.c
+++ b/drivers/hid/hid-cypress.c
@@ -25,6 +25,10 @@
 
 #define VA_INVAL_LOGICAL_BOUNDARY	0x08
 
+struct cp_device {
+	unsigned long quirks;
+};
+
 /*
  * Some USB barcode readers from cypress have usage min and usage max in
  * the wrong order
@@ -70,7 +74,8 @@ static __u8 *va_logical_boundary_fixup(struct hid_device *hdev, __u8 *rdesc,
 static const __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 		unsigned int *rsize)
 {
-	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+	const struct cp_device *cp_device = hid_get_drvdata(hdev);
+	unsigned long quirks = cp_device->quirks;
 
 	if (quirks & CP_RDESC_SWAPPED_MIN_MAX)
 		rdesc = cp_rdesc_fixup(hdev, rdesc, rsize);
@@ -84,7 +89,8 @@ static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
-	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+	const struct cp_device *cp_device = hid_get_drvdata(hdev);
+	unsigned long quirks = cp_device->quirks;
 
 	if (!(quirks & CP_2WHEEL_MOUSE_HACK))
 		return 0;
@@ -100,22 +106,21 @@ static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi,
 static int cp_event(struct hid_device *hdev, struct hid_field *field,
 		struct hid_usage *usage, __s32 value)
 {
-	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+	struct cp_device *cp_device = hid_get_drvdata(hdev);
 
 	if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput ||
-			!usage->type || !(quirks & CP_2WHEEL_MOUSE_HACK))
+			!usage->type || !(cp_device->quirks & CP_2WHEEL_MOUSE_HACK))
 		return 0;
 
 	if (usage->hid == 0x00090005) {
 		if (value)
-			quirks |=  CP_2WHEEL_MOUSE_HACK_ON;
+			cp_device->quirks |= CP_2WHEEL_MOUSE_HACK_ON;
 		else
-			quirks &= ~CP_2WHEEL_MOUSE_HACK_ON;
-		hid_set_drvdata(hdev, (void *)quirks);
+			cp_device->quirks &= ~CP_2WHEEL_MOUSE_HACK_ON;
 		return 1;
 	}
 
-	if (usage->code == REL_WHEEL && (quirks & CP_2WHEEL_MOUSE_HACK_ON)) {
+	if (usage->code == REL_WHEEL && (cp_device->quirks & CP_2WHEEL_MOUSE_HACK_ON)) {
 		struct input_dev *input = field->hidinput->input;
 
 		input_event(input, usage->type, REL_HWHEEL, value);
@@ -127,10 +132,17 @@ static int cp_event(struct hid_device *hdev, struct hid_field *field,
 
 static int cp_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
-	unsigned long quirks = id->driver_data;
 	int ret;
+	struct cp_device *cp_device;
 
-	hid_set_drvdata(hdev, (void *)quirks);
+	cp_device = devm_kzalloc(&hdev->dev, sizeof(*cp_device), GFP_KERNEL);
+
+	if (!cp_device)
+		return -ENOMEM;
+
+	cp_device->quirks = id->driver_data;
+
+	hid_set_drvdata(hdev, cp_device);
 
 	ret = hid_parse(hdev);
 	if (ret) {

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 07/11] HID: hid-gfrm: clean up usage of 'driver_data'
  2026-05-18 16:06 [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Pawel Zalewski (The Capable Hub)
                   ` (5 preceding siblings ...)
  2026-05-18 16:06 ` [PATCH 06/11] HID: hid-cypress: " Pawel Zalewski (The Capable Hub)
@ 2026-05-18 16:06 ` Pawel Zalewski (The Capable Hub)
  2026-05-18 16:06 ` [PATCH 08/11] HID: hid-ite: " Pawel Zalewski (The Capable Hub)
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Pawel Zalewski (The Capable Hub) @ 2026-05-18 16:06 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke
  Cc: linux-kernel, linux-input, Christian A. Ehrhardt,
	Christian A. Ehrhardt, Pawel Zalewski (The Capable Hub)

The module is storing an integer inside the drvdata pointer, which is
confusing, lets fix this and set the whole of 'hid_device_id' struct
as the drvdata and then simply use its integer 'driver_data' field for
quirks, which shall make the code cleaner, type-safe, consistent and
more readable.

This makes the cast to (void *) during storage a bit safer (just to
suppress the const qualifier warning) and the cast to (unsigned long)
during retrieval is removed.

Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
 drivers/hid/hid-gfrm.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/hid/hid-gfrm.c b/drivers/hid/hid-gfrm.c
index 699186ff2349..0be49a93d28b 100644
--- a/drivers/hid/hid-gfrm.c
+++ b/drivers/hid/hid-gfrm.c
@@ -28,7 +28,8 @@ static int gfrm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 		struct hid_field *field, struct hid_usage *usage,
 		unsigned long **bit, int *max)
 {
-	unsigned long hdev_type = (unsigned long) hid_get_drvdata(hdev);
+	const struct hid_device_id *id = hid_get_drvdata(hdev);
+	unsigned long hdev_type = id->driver_data;
 
 	if (hdev_type == GFRM100) {
 		if (usage->hid == (HID_UP_CONSUMER | 0x4)) {
@@ -50,7 +51,8 @@ static int gfrm_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,
 		u8 *data, int size)
 {
-	unsigned long hdev_type = (unsigned long) hid_get_drvdata(hdev);
+	const struct hid_device_id *id = hid_get_drvdata(hdev);
+	unsigned long hdev_type = id->driver_data;
 	int ret = 0;
 
 	if (hdev_type != GFRM100)
@@ -99,7 +101,7 @@ static int gfrm_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
 	int ret;
 
-	hid_set_drvdata(hdev, (void *) id->driver_data);
+	hid_set_drvdata(hdev, (void *)id);
 
 	ret = hid_parse(hdev);
 	if (ret)

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 08/11] HID: hid-ite: clean up usage of 'driver_data'
  2026-05-18 16:06 [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Pawel Zalewski (The Capable Hub)
                   ` (6 preceding siblings ...)
  2026-05-18 16:06 ` [PATCH 07/11] HID: hid-gfrm: " Pawel Zalewski (The Capable Hub)
@ 2026-05-18 16:06 ` Pawel Zalewski (The Capable Hub)
  2026-05-18 16:06 ` [PATCH 09/11] HID: mod_devicetable: 'hid_device_id::driver_data' add union Pawel Zalewski (The Capable Hub)
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Pawel Zalewski (The Capable Hub) @ 2026-05-18 16:06 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke
  Cc: linux-kernel, linux-input, Christian A. Ehrhardt,
	Christian A. Ehrhardt, Pawel Zalewski (The Capable Hub)

The module is storing an integer inside the drvdata pointer, which is
confusing, lets fix this and set the whole of 'hid_device_id' struct
as the drvdata and then simply use its integer 'driver_data' field for
quirks, which shall make the code cleaner, type-safe, consistent and
more readable.

This makes the cast to (void *) during storage a bit safer (just to
suppress the const qualifier warning) and the cast to (unsigned long)
during retrieval is removed.

Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
 drivers/hid/hid-ite.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/hid/hid-ite.c b/drivers/hid/hid-ite.c
index 8e42780a2663..63908f24b524 100644
--- a/drivers/hid/hid-ite.c
+++ b/drivers/hid/hid-ite.c
@@ -15,7 +15,9 @@
 
 static const __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize)
 {
-	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+
+	const struct hid_device_id *id = hid_get_drvdata(hdev);
+	unsigned long quirks = id->driver_data;
 
 	if (quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) {
 		/* For Acer Aspire Switch 10 SW5-012 keyboard-dock */
@@ -44,7 +46,8 @@ static int ite_input_mapping(struct hid_device *hdev,
 		int *max)
 {
 
-	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
+	const struct hid_device_id *id = hid_get_drvdata(hdev);
+	unsigned long quirks = id->driver_data;
 
 	if ((quirks & QUIRK_TOUCHPAD_ON_OFF_REPORT) &&
 	    (usage->hid & HID_USAGE_PAGE) == 0x00880000) {
@@ -94,7 +97,7 @@ static int ite_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
 	int ret;
 
-	hid_set_drvdata(hdev, (void *)id->driver_data);
+	hid_set_drvdata(hdev, (void *)id);
 
 	ret = hid_open_report(hdev);
 	if (ret)

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 09/11] HID: mod_devicetable: 'hid_device_id::driver_data' add union
  2026-05-18 16:06 [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Pawel Zalewski (The Capable Hub)
                   ` (7 preceding siblings ...)
  2026-05-18 16:06 ` [PATCH 08/11] HID: hid-ite: " Pawel Zalewski (The Capable Hub)
@ 2026-05-18 16:06 ` Pawel Zalewski (The Capable Hub)
  2026-05-18 16:06 ` [PATCH 10/11] HID: hid-tmff: use 'hid_device_id::driver_data_ptr' Pawel Zalewski (The Capable Hub)
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Pawel Zalewski (The Capable Hub) @ 2026-05-18 16:06 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke
  Cc: linux-kernel, linux-input, Christian A. Ehrhardt,
	Christian A. Ehrhardt, Pawel Zalewski (The Capable Hub)

The 'driver_data' field can either be interpreted as an unsigned
numerical number or as a pointer - this depends on the driver within
HID subsystem. Unionise this unsigned value with a 'const void*'
pointer. This change allows to remove explicit casts to pointers
in the pointer-users case and as far as integer-users of the field
are concerned nothing has really changed.

The change doesn't affect the size and layout of struct hid_device_id
which is part of the userspace ABI.

This change aims to improve type-safety, readability - as the
intent is more clear - and portability of the code in the long term.

Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
 include/linux/mod_devicetable.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 23ff24080dfd..90b2dae75109 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -175,7 +175,10 @@ struct hid_device_id {
 	__u16 group;
 	__u32 vendor;
 	__u32 product;
-	kernel_ulong_t driver_data;
+	union {
+		kernel_ulong_t driver_data;
+		const void *driver_data_ptr;
+	};
 };
 
 /* s390 CCW devices */

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 10/11] HID: hid-tmff: use 'hid_device_id::driver_data_ptr'
  2026-05-18 16:06 [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Pawel Zalewski (The Capable Hub)
                   ` (8 preceding siblings ...)
  2026-05-18 16:06 ` [PATCH 09/11] HID: mod_devicetable: 'hid_device_id::driver_data' add union Pawel Zalewski (The Capable Hub)
@ 2026-05-18 16:06 ` Pawel Zalewski (The Capable Hub)
  2026-05-18 16:06 ` [PATCH 11/11] HID: wacom: " Pawel Zalewski (The Capable Hub)
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Pawel Zalewski (The Capable Hub) @ 2026-05-18 16:06 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke
  Cc: linux-kernel, linux-input, Christian A. Ehrhardt,
	Christian A. Ehrhardt, Pawel Zalewski (The Capable Hub)

Remove the casts to (unsigned long) and instead assign the
'ff_rumble' and 'ff_joystick' variables as they should, as pointers.
Remove the cast to (void *) during probe - tmff_init() second parameter
already accepts a const pointer, so no further action was needed here.
These changes improve readability of the code.

Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
 drivers/hid/hid-tmff.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/hid/hid-tmff.c b/drivers/hid/hid-tmff.c
index 423f395d01ac..0d7e73fba0fa 100644
--- a/drivers/hid/hid-tmff.c
+++ b/drivers/hid/hid-tmff.c
@@ -226,7 +226,7 @@ static int tm_probe(struct hid_device *hdev, const struct hid_device_id *id)
 		goto err;
 	}
 
-	tmff_init(hdev, (void *)id->driver_data);
+	tmff_init(hdev, id->driver_data_ptr);
 
 	return 0;
 err:
@@ -235,25 +235,25 @@ static int tm_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
 static const struct hid_device_id tm_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300),
-		.driver_data = (unsigned long)ff_rumble },
+		.driver_data_ptr = ff_rumble },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304),   /* FireStorm Dual Power 2 (and 3) */
-		.driver_data = (unsigned long)ff_rumble },
+		.driver_data_ptr = ff_rumble },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, THRUSTMASTER_DEVICE_ID_2_IN_1_DT),   /* Dual Trigger 2-in-1 */
-		.driver_data = (unsigned long)ff_rumble },
+		.driver_data_ptr = ff_rumble },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323),   /* Dual Trigger 3-in-1 (PC Mode) */
-		.driver_data = (unsigned long)ff_rumble },
+		.driver_data_ptr = ff_rumble },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb324),   /* Dual Trigger 3-in-1 (PS3 Mode) */
-		.driver_data = (unsigned long)ff_rumble },
+		.driver_data_ptr = ff_rumble },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb605),   /* NASCAR PRO FF2 Wheel */
-		.driver_data = (unsigned long)ff_joystick },
+		.driver_data_ptr = ff_joystick },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651),	/* FGT Rumble Force Wheel */
-		.driver_data = (unsigned long)ff_rumble },
+		.driver_data_ptr = ff_rumble },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb653),	/* RGT Force Feedback CLUTCH Raging Wheel */
-		.driver_data = (unsigned long)ff_joystick },
+		.driver_data_ptr = ff_joystick },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654),	/* FGT Force Feedback Wheel */
-		.driver_data = (unsigned long)ff_joystick },
+		.driver_data_ptr = ff_joystick },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a),	/* F430 Force Feedback Wheel */
-		.driver_data = (unsigned long)ff_joystick },
+		.driver_data_ptr = ff_joystick },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, tm_devices);

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 11/11] HID: wacom: use 'hid_device_id::driver_data_ptr'
  2026-05-18 16:06 [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Pawel Zalewski (The Capable Hub)
                   ` (9 preceding siblings ...)
  2026-05-18 16:06 ` [PATCH 10/11] HID: hid-tmff: use 'hid_device_id::driver_data_ptr' Pawel Zalewski (The Capable Hub)
@ 2026-05-18 16:06 ` Pawel Zalewski (The Capable Hub)
  2026-05-21 14:50 ` [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Benjamin Tissoires
  2026-06-01 18:18 ` (subset) " Benjamin Tissoires
  12 siblings, 0 replies; 17+ messages in thread
From: Pawel Zalewski (The Capable Hub) @ 2026-05-18 16:06 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, Ping Cheng, Jason Gerecke
  Cc: linux-kernel, linux-input, Christian A. Ehrhardt,
	Christian A. Ehrhardt, Pawel Zalewski (The Capable Hub)

Remove the casts to (kernel_ulong_t) and (struct wacom_features *)
and use the 'drvier_data_ptr' field instead to improve readability
of the code.

Signed-off-by: Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
---
 drivers/hid/wacom_sys.c | 14 +++++++++-----
 drivers/hid/wacom_wac.c | 10 +++++-----
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 0d1c6d90fe21..25408676c5f6 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -2555,8 +2555,9 @@ static void wacom_wireless_work(struct work_struct *work)
 		}
 
 		/* Stylus interface */
-		wacom_wac1->features =
-			*((struct wacom_features *)id->driver_data);
+		const struct wacom_features *features = id->driver_data_ptr;
+
+		wacom_wac1->features = *features;
 
 		wacom_wac1->pid = wacom_wac->pid;
 		hid_hw_stop(hdev1);
@@ -2568,8 +2569,7 @@ static void wacom_wireless_work(struct work_struct *work)
 		if (wacom_wac1->features.touch_max ||
 		    (wacom_wac1->features.type >= INTUOSHT &&
 		    wacom_wac1->features.type <= BAMBOO_PT)) {
-			wacom_wac2->features =
-				*((struct wacom_features *)id->driver_data);
+			wacom_wac2->features = *features;
 			wacom_wac2->pid = wacom_wac->pid;
 			hid_hw_stop(hdev2);
 			error = wacom_parse_and_register(wacom2, true);
@@ -2839,7 +2839,11 @@ static int wacom_probe(struct hid_device *hdev,
 	wacom->hdev = hdev;
 
 	wacom_wac = &wacom->wacom_wac;
-	wacom_wac->features = *((struct wacom_features *)id->driver_data);
+
+	const struct wacom_features *id_features = id->driver_data_ptr;
+
+	wacom_wac->features = *id_features;
+
 	features = &wacom_wac->features;
 
 	if (features->check_for_hid_type && features->hid_type != hdev->type)
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index da1f0ea85625..034bde5af2df 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -4947,23 +4947,23 @@ static const struct wacom_features wacom_features_0x94 =
 
 #define USB_DEVICE_WACOM(prod)						\
 	HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
-	.driver_data = (kernel_ulong_t)&wacom_features_##prod
+	.driver_data_ptr = &wacom_features_##prod
 
 #define BT_DEVICE_WACOM(prod)						\
 	HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
-	.driver_data = (kernel_ulong_t)&wacom_features_##prod
+	.driver_data_ptr = &wacom_features_##prod
 
 #define I2C_DEVICE_WACOM(prod)						\
 	HID_DEVICE(BUS_I2C, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
-	.driver_data = (kernel_ulong_t)&wacom_features_##prod
+	.driver_data_ptr = &wacom_features_##prod
 
 #define PCI_DEVICE_WACOM(prod)						\
 	HID_DEVICE(BUS_PCI, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
-	.driver_data = (kernel_ulong_t)&wacom_features_##prod
+	.driver_data_ptr = &wacom_features_##prod
 
 #define USB_DEVICE_LENOVO(prod)					\
 	HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, prod),			\
-	.driver_data = (kernel_ulong_t)&wacom_features_##prod
+	.driver_data_ptr = &wacom_features_##prod
 
 const struct hid_device_id wacom_ids[] = {
 	{ USB_DEVICE_WACOM(0x00) },

-- 
2.43.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data'
  2026-05-18 16:06 [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Pawel Zalewski (The Capable Hub)
                   ` (10 preceding siblings ...)
  2026-05-18 16:06 ` [PATCH 11/11] HID: wacom: " Pawel Zalewski (The Capable Hub)
@ 2026-05-21 14:50 ` Benjamin Tissoires
  2026-05-22 14:18   ` Pawel Zalewski
  2026-06-01 18:18 ` (subset) " Benjamin Tissoires
  12 siblings, 1 reply; 17+ messages in thread
From: Benjamin Tissoires @ 2026-05-21 14:50 UTC (permalink / raw)
  To: Pawel Zalewski (The Capable Hub)
  Cc: Jiri Kosina, Ping Cheng, Jason Gerecke, linux-kernel, linux-input,
	Christian A. Ehrhardt, Christian A. Ehrhardt

On May 18 2026, Pawel Zalewski (The Capable Hub) wrote:
> The <linux/mod_devicetable.h> has multiple structs that follow
> the pattern of having either 'driver_data' or 'driver_info'
> fields which are of the 'kernel_ulong_t' type. Then how to 
> interpret that field is user defined, some users will treat
> the value as an actual integer, others as a valid pointer to
> dereference. 
> 
> One of instances of the above is the 'hid_device_id::driver_data'
> field, for the most part it is used for setting HID quirks and
> treated as an integer value for storing metadata in the subsystem
> drivers. But in a few instances it is used as a valid pointer to
> dereference, namely in:
> - hid-tmff
> - wacom

I would agree with sashiko that the series introduces an anti-pattern by
allowing .driver_data to be an arbitrary pointer. The reason is that we
can dynamically set driver_data through the kernel command line, and
when it's used as a pointer, bad things will happen.

I would think we should fix the 2 offenders to enforce not using a
direct pointer but an offset in a table of pointers.

How does that sound for you?

Cheers,
Benjamin

>  
> One of the ways to fixing this duality and improve code readability
> and type-safety a bit is to use a '{kernel_ulong_t, const void *}'
> union. That way the current drivers that treat 'hid_device_id::driver_data'
> as an integer value for storing metadata are unaffected. The drivers
> that actually store pointers in there benefit from a removed cast
> (and more clear intent) at the cost of using the new 'const void *'
> field instead.
> 
> With the union in place, some of the existing initializers for static
> const data now need a named field for the 'driver_data' - this is
> also addressed in the series as part of the pre-clean up in 
> patches 1-4. 
> 
> It was found that some modules use a bit of a type-unsafe way of storing
> integers in the 'void *driver_data' pointer of the 'struct hid_device'
> - this required a cast during storage via 'hid_set_drvdata' and a cast
> during retrieval when using 'hid_get_drvdata'. I can see why this was 
> done - as we potentially save on an allocation - but really code is
> more readable and better quality without resorting to this. This issue
> is also addressed in this patch series in patches 5-8 as part of the
> pre-clean up.
> 
> The actual implementation and post-clean up can be found in 
> patches 9-11.
> 
> The change also makes the code more portable on architecture 
> like CHERI [1], where a pointer is replaced with a new primitive
> (called the capability) at the architecture level and is as twice as
> wide as the greatest representable address, ie. for 64 bit address
> space capabilities are 128 bits wide (the other 64 bits are used to
> store meta-data relating to the 64 bit address). So you can not store 
> valid pointers inside 'unsigned long' as effectively a different set of
> instructions is being generated by the compiler based on the data-type
> that was used in C (ie. capabilities have their own set of load/store
> that also copy over the meta-data which are orthogonal to the load/store
> instructions used for plain integers that would invalidate the meta-data).
> There is slightly more detail to this, but the above is enough to
> explain the motivation - the proposed changes make the code a bit
> better even without considering CHERI at all - as it is more readable 
> and type-safe.
> 
> The series was built and tested under QEMU (boots with relevant 
> configs set to Y) on arm64.
> 
> This series is part of a larger effort led by Uwe [2]
> 
> [1] https://cheri-alliance.org/discover-cheri/
> [2] https://lore.kernel.org/all/cover.1776429984.git.u.kleine-koenig@baylibre.com/ 
> 
> ---
> Pawel Zalewski (The Capable Hub) (11):
>       HID: hid-input: use named initializer for 'hid_battery_quirks[]'
>       HID: hid-quirks: use named initializer in 'hid_quirks[]'
>       HID: hid-asus: use named initializer for 'asus_devices[]'
>       HID: i2c-hid-dmi-quirks: use named initializer for 'i2c_hid_elan_flipped_quirks[]'
>       HID: hid-belkin: clean up usage of 'driver_data'
>       HID: hid-cypress: clean up usage of 'driver_data'
>       HID: hid-gfrm: clean up usage of 'driver_data'
>       HID: hid-ite: clean up usage of 'driver_data'
>       HID: mod_devicetable: 'hid_device_id::driver_data' add union
>       HID: hid-tmff: use 'hid_device_id::driver_data_ptr'
>       HID: wacom: use 'hid_device_id::driver_data_ptr'
> 
>  drivers/hid/hid-asus.c                   |  46 ++-
>  drivers/hid/hid-belkin.c                 |   5 +-
>  drivers/hid/hid-cypress.c                |  32 +-
>  drivers/hid/hid-gfrm.c                   |   8 +-
>  drivers/hid/hid-input.c                  |  38 +-
>  drivers/hid/hid-ite.c                    |   9 +-
>  drivers/hid/hid-quirks.c                 | 575 ++++++++++++++++++++-----------
>  drivers/hid/hid-tmff.c                   |  22 +-
>  drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c |   2 +-
>  drivers/hid/wacom_sys.c                  |  14 +-
>  drivers/hid/wacom_wac.c                  |  10 +-
>  include/linux/mod_devicetable.h          |   5 +-
>  12 files changed, 496 insertions(+), 270 deletions(-)
> ---
> base-commit: 25ccf4586bead3fe3cf2c57ff0480f31a0e335ad
> change-id: 20260427-mod-devicetable-hid_device_id-7f30d877387c
> 
> Best regards,
> --  
> Pawel Zalewski (The Capable Hub) <pzalewski@thegoodpenguin.co.uk>
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data'
  2026-05-21 14:50 ` [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Benjamin Tissoires
@ 2026-05-22 14:18   ` Pawel Zalewski
  2026-05-28 16:00     ` Benjamin Tissoires
  0 siblings, 1 reply; 17+ messages in thread
From: Pawel Zalewski @ 2026-05-22 14:18 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Jiri Kosina, Ping Cheng, Jason Gerecke, linux-kernel, linux-input,
	Christian A. Ehrhardt, Christian A. Ehrhardt

> I would agree with sashiko that the series introduces an anti-pattern by
> allowing .driver_data to be an arbitrary pointer. The reason is that we
> can dynamically set driver_data through the kernel command line, and
> when it's used as a pointer, bad things will happen.

I have not considered the command line override ! This indeed would not
be a good case for having a pointer at all in there - in the current
form of the codebase.

The series does not introduce this anti-pattern - this is already the
current status quo in the codebase and the problem predates the patch
series itself. The series makes the problem more visible and validates
the existing status quo - agreed on this.

> I would think we should fix the 2 offenders to enforce not using a
> direct pointer but an offset in a table of pointers.
>
> How does that sound for you?

That could work, probably via a named enum (so that the idx is bounded
and validated to avoid out of bounds memory access) with its items mapped
into a table of const pointers. That way the command line override still
works as before and my goals set out in the series are met as well.

Perhaps an alternative solution would be to sanitize the user-input instead in
the 'hid-core::new_id_store' function, such that only 'driver_data' values
that match an existing entry in the driver's 'id_table' are accepted, this
is how it is done currently in the PCI subsystem in 'pci-driver::new_id_store',
so it would be consistent as well.

The bonus here is that all other drivers in the  HID subsystem benefit from
this aproach as opposed to just the two current offenders, as providing
'driver_data' from the command line is now mandatory and must match the
existing table entry - which is what we want ?

So something among the lines of:

@hid-core::new_id_store

```
struct hid_driver *hdrv = to_hid_driver(drv);
const struct hid_device_id *ids = hdrv->id_table;

(...)

/* Only accept driver_data values that match an existing id_table
    entry */
if (ids) {
        ret = -EINVAL;
        while (ids->vendor || ids->product) {
                if (driver_data == ids->driver_data) {
                        ret = 0;
                        break;
                }
                ids++;
        }
        if (ret)        /* No match */
                return ret;
}
```

Would that approach work for you ? Do help in what is the correct
termination for the while loop - for this demo I went with 'ids->vendor'
and 'ids->product' fields as common-sense would indicate that quirks need
to be device-specific by definition but that was without any actual research.

The downside is that 'new_id' drivers that actually use a pointer for the
'driver_data' will be rejected - which would be actually covered by the
solution that you have proposed in the first place. To think of it the
input sanitizer could work additionaly in tandem with the enum-based
solution if this fact is an issue, so it might not be an alternative
actually but a complement for it.

In the meantime I think that patches 1-8 can be reviewed regardless
without any changes (as they predate patch 9 that adds the union and the
commit messages does not mention anything about it).

Best regards,
Pawel


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data'
  2026-05-22 14:18   ` Pawel Zalewski
@ 2026-05-28 16:00     ` Benjamin Tissoires
  2026-06-02 13:57       ` Pawel Zalewski
  0 siblings, 1 reply; 17+ messages in thread
From: Benjamin Tissoires @ 2026-05-28 16:00 UTC (permalink / raw)
  To: Pawel Zalewski
  Cc: Jiri Kosina, Ping Cheng, Jason Gerecke, linux-kernel, linux-input,
	Christian A. Ehrhardt, Christian A. Ehrhardt

On May 22 2026, Pawel Zalewski wrote:
> > I would agree with sashiko that the series introduces an anti-pattern by
> > allowing .driver_data to be an arbitrary pointer. The reason is that we
> > can dynamically set driver_data through the kernel command line, and
> > when it's used as a pointer, bad things will happen.
> 
> I have not considered the command line override ! This indeed would not
> be a good case for having a pointer at all in there - in the current
> form of the codebase.
> 
> The series does not introduce this anti-pattern - this is already the
> current status quo in the codebase and�the problem predates the patch
> series itself. The series makes the problem more visible and validates
> the existing status quo - agreed on this.

Oh, yes sure. But the series makes the anti-pattern official, which
would encourage people to use it. (we are saying the same thing).

> 
> > I would think we should fix the 2 offenders to enforce not using a
> > direct pointer but an offset in a table of pointers.
> >
> > How does that sound for you?
> 
> That could work, probably via a named enum (so that the idx is bounded
> and validated to avoid out of bounds memory access) with its items mapped
> into a table of const pointers. That way the command line override still
> works as before and my goals set out in the series are met as well.
> 
> Perhaps an alternative solution would be to sanitize the user-input instead in
> the 'hid-core::new_id_store' function, such that only 'driver_data' values
> that match an existing entry in the driver's 'id_table' are accepted, this
> is how it is done currently in the PCI subsystem in 'pci-driver::new_id_store',
> so it would be consistent as well.
> 
> The bonus here is that all other drivers in the  HID subsystem benefit from
> this aproach as opposed to just the two current offenders, as providing
> 'driver_data' from the command line is now mandatory and must match the
> existing table entry - which is what we want ?
> 
> So something among the lines of:
> 
> @hid-core::new_id_store
> 
> ```
> struct hid_driver *hdrv = to_hid_driver(drv);
> const struct hid_device_id *ids = hdrv->id_table;
> 
> (...)
> 
> /* Only accept driver_data values that match an existing id_table
>     entry */
> if (ids) {
>         ret = -EINVAL;
>         while (ids->vendor || ids->product) {
>                 if (driver_data == ids->driver_data) {
>                         ret = 0;
>                         break;
>                 }
>                 ids++;
>         }
>         if (ret)        /* No match */
>                 return ret;
> }
> ```
> 
> Would that approach work for you ?

Yes, sanityzing the input seems like a good idea.

> Do help in what is the correct
> termination for the while loop - for this demo I went with 'ids->vendor'
> and 'ids->product' fields as common-sense would indicate that quirks need
> to be device-specific by definition but that was without any actual research.

hid-core.c does:

const struct hid_device_id *hid_match_id(const struct hid_device *hdev,
		const struct hid_device_id *id)
{
	for (; id->bus; id++)
		if (hid_match_one_id(hdev, id))
			return id;

	return NULL;
}

So I guess you can simply rely on id-bus being set.

> 
> The downside is that 'new_id' drivers that actually use a pointer for the
> 'driver_data' will be rejected - which would be actually covered by the
> solution that you have proposed in the first place. To think of it the
> input sanitizer could work additionaly in tandem with the enum-based
> solution if this fact is an issue, so it might not be an alternative
> actually but a complement for it.

Agree, we need both.

> 
> In the meantime I think that patches 1-8 can be reviewed regardless
> without any changes (as they predate patch 9 that adds the union and the
> commit messages does not mention anything about it).

I'd drop patches 1-4. I don't see the point of just rewriting the list
of hid_device_id if we ensure we have just one type.

I need to have a closer look at 5-8 TBH.

Cheers,
Benjamin

> 
> Best regards,
> Pawel
> 
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: (subset) [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data'
  2026-05-18 16:06 [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Pawel Zalewski (The Capable Hub)
                   ` (11 preceding siblings ...)
  2026-05-21 14:50 ` [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Benjamin Tissoires
@ 2026-06-01 18:18 ` Benjamin Tissoires
  12 siblings, 0 replies; 17+ messages in thread
From: Benjamin Tissoires @ 2026-06-01 18:18 UTC (permalink / raw)
  To: Jiri Kosina, Ping Cheng, Jason Gerecke,
	Pawel Zalewski (The Capable Hub)
  Cc: linux-kernel, linux-input, Christian A. Ehrhardt,
	Christian A. Ehrhardt

On Mon, 18 May 2026 17:06:19 +0100, Pawel Zalewski (The Capable Hub) wrote:
> The <linux/mod_devicetable.h> has multiple structs that follow
> the pattern of having either 'driver_data' or 'driver_info'
> fields which are of the 'kernel_ulong_t' type. Then how to
> interpret that field is user defined, some users will treat
> the value as an actual integer, others as a valid pointer to
> dereference.
> 
> [...]

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git (for-7.2/cleanup_driver_data), thanks!

[05/11] HID: hid-belkin: clean up usage of 'driver_data'
        https://git.kernel.org/hid/hid/c/4de4b8a5ddc2
[06/11] HID: hid-cypress: clean up usage of 'driver_data'
        https://git.kernel.org/hid/hid/c/73e784ddf895
[07/11] HID: hid-gfrm: clean up usage of 'driver_data'
        https://git.kernel.org/hid/hid/c/0b8bb8c3c913
[08/11] HID: hid-ite: clean up usage of 'driver_data'
        https://git.kernel.org/hid/hid/c/b11dfa6cc3c8

Cheers,
-- 
Benjamin Tissoires <bentiss@kernel.org>


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data'
  2026-05-28 16:00     ` Benjamin Tissoires
@ 2026-06-02 13:57       ` Pawel Zalewski
  0 siblings, 0 replies; 17+ messages in thread
From: Pawel Zalewski @ 2026-06-02 13:57 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Jiri Kosina, Ping Cheng, Jason Gerecke, linux-kernel, linux-input,
	Christian A. Ehrhardt, Christian A. Ehrhardt

> Agree, we need both.
Great, I will implement this in v2.

> I'd drop patches 1-4. I don't see the point of just rewriting the list
> of hid_device_id if we ensure we have just one type.
These patches really just enforce the use of a named initializer for
the `driver_data` field
in the lists and do not change the actual compiled binary. So, the
change applied is purely
cosmetic, and the modules touched there don't use `driver_data` as a
pointer anyway.
I do think that making the code more readable has merit (if it comes
with no risk).

> I need to have a closer look at 5-8 TBH.
Thanks.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2026-06-02 13:57 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-18 16:06 [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Pawel Zalewski (The Capable Hub)
2026-05-18 16:06 ` [PATCH 01/11] HID: hid-input: use named initializer for 'hid_battery_quirks[]' Pawel Zalewski (The Capable Hub)
2026-05-18 16:06 ` [PATCH 02/11] HID: hid-quirks: use named initializer in 'hid_quirks[]' Pawel Zalewski (The Capable Hub)
2026-05-18 16:06 ` [PATCH 03/11] HID: hid-asus: use named initializer for 'asus_devices[]' Pawel Zalewski (The Capable Hub)
2026-05-18 16:06 ` [PATCH 04/11] HID: i2c-hid-dmi-quirks: use named initializer for 'i2c_hid_elan_flipped_quirks[]' Pawel Zalewski (The Capable Hub)
2026-05-18 16:06 ` [PATCH 05/11] HID: hid-belkin: clean up usage of 'driver_data' Pawel Zalewski (The Capable Hub)
2026-05-18 16:06 ` [PATCH 06/11] HID: hid-cypress: " Pawel Zalewski (The Capable Hub)
2026-05-18 16:06 ` [PATCH 07/11] HID: hid-gfrm: " Pawel Zalewski (The Capable Hub)
2026-05-18 16:06 ` [PATCH 08/11] HID: hid-ite: " Pawel Zalewski (The Capable Hub)
2026-05-18 16:06 ` [PATCH 09/11] HID: mod_devicetable: 'hid_device_id::driver_data' add union Pawel Zalewski (The Capable Hub)
2026-05-18 16:06 ` [PATCH 10/11] HID: hid-tmff: use 'hid_device_id::driver_data_ptr' Pawel Zalewski (The Capable Hub)
2026-05-18 16:06 ` [PATCH 11/11] HID: wacom: " Pawel Zalewski (The Capable Hub)
2026-05-21 14:50 ` [PATCH 00/11] HID: storing pointers in 'hid_device_id::driver_data' Benjamin Tissoires
2026-05-22 14:18   ` Pawel Zalewski
2026-05-28 16:00     ` Benjamin Tissoires
2026-06-02 13:57       ` Pawel Zalewski
2026-06-01 18:18 ` (subset) " Benjamin Tissoires

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