Commit 79d11de9 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-2022100501' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid

Pull HID updates from Benjamin Tissoires:

 - handle of all Logitech Bluetooth HID++ devices in the Logitech HID++
   drivers (Bastien Nocera)

 - fix broken atomic checks in hid-multitouch by adding memory barriers
   (Andri Yngvason)

 - better handling of devices with AMD SFH1.1 (Basavaraj Natikar)

 - better support of Nintendo clone controllers (Icenowy Zheng and
   Johnothan King)

 - Support for various RC controllers (Marcus Folkesson)

 - Add UGEEv2 support in hid-uclogic (XP-PEN Deco Pro S and Parblo A610
   PRO) (José Expósito)

 - some conversions to use dev_groups (Greg Kroah-Hartman)

 - HID-BPF preparatory patches, mostly to convert blank defines as enums
   (Benjamin Tissoires)

* tag 'for-linus-2022100501' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (38 commits)
  HID: wacom: add three styli to wacom_intuos_get_tool_type
  HID: amd_sfh: Handle condition of "no sensors" for SFH1.1
  HID: amd_sfh: Change dev_err to dev_dbg for additional debug info
  HID: nintendo: check analog user calibration for plausibility
  HID: nintendo: deregister home LED when it fails
  HID: roccat: Fix use-after-free in roccat_read()
  hid: topre: Add driver fixing report descriptor
  HID: multitouch: Add memory barriers
  HID: convert defines of HID class requests into a proper enum
  HID: export hid_report_type to uapi
  HID: core: store the unique system identifier in hid_device
  HID: Add driver for PhoenixRC Flight Controller
  HID: Add driver for VRC-2 Car Controller
  HID: sony: Fix double word in comments
  hid: hid-logitech-hidpp: avoid unnecessary assignments in hidpp_connect_event
  HID: logitech-hidpp: Detect hi-res scrolling support
  HID: logitech-hidpp: Remove hard-coded "Sw. Id." for HID++ 2.0 commands
  HID: logitech-hidpp: Fix "Sw. Id." for HID++ 2.0 commands
  HID: logitech-hidpp: Remove special-casing of Bluetooth devices
  HID: logitech-hidpp: Enable HID++ for all the Logitech Bluetooth devices
  ...
parents 5d435a3f cb7c02e9
...@@ -9082,6 +9082,12 @@ L: linux-input@vger.kernel.org ...@@ -9082,6 +9082,12 @@ L: linux-input@vger.kernel.org
S: Supported S: Supported
F: drivers/hid/hid-playstation.c F: drivers/hid/hid-playstation.c
HID PHOENIX RC FLIGHT CONTROLLER
M: Marcus Folkesson <marcus.folkesson@gmail.com>
L: linux-input@vger.kernel.org
S: Maintained
F: drivers/hid/hid-pxrc.c
HID SENSOR HUB DRIVERS HID SENSOR HUB DRIVERS
M: Jiri Kosina <jikos@kernel.org> M: Jiri Kosina <jikos@kernel.org>
M: Jonathan Cameron <jic23@kernel.org> M: Jonathan Cameron <jic23@kernel.org>
...@@ -9094,6 +9100,12 @@ F: drivers/hid/hid-sensor-* ...@@ -9094,6 +9100,12 @@ F: drivers/hid/hid-sensor-*
F: drivers/iio/*/hid-* F: drivers/iio/*/hid-*
F: include/linux/hid-sensor-* F: include/linux/hid-sensor-*
HID VRC-2 CAR CONTROLLER DRIVER
M: Marcus Folkesson <marcus.folkesson@gmail.com>
L: linux-input@vger.kernel.org
S: Maintained
F: drivers/hid/hid-vrc2.c
HID WACOM DRIVER HID WACOM DRIVER
M: Ping Cheng <ping.cheng@wacom.com> M: Ping Cheng <ping.cheng@wacom.com>
M: Jason Gerecke <jason.gerecke@wacom.com> M: Jason Gerecke <jason.gerecke@wacom.com>
......
...@@ -28,7 +28,6 @@ if HID ...@@ -28,7 +28,6 @@ if HID
config HID_BATTERY_STRENGTH config HID_BATTERY_STRENGTH
bool "Battery level reporting for HID devices" bool "Battery level reporting for HID devices"
depends on HID
select POWER_SUPPLY select POWER_SUPPLY
default n default n
help help
...@@ -38,7 +37,6 @@ config HID_BATTERY_STRENGTH ...@@ -38,7 +37,6 @@ config HID_BATTERY_STRENGTH
config HIDRAW config HIDRAW
bool "/dev/hidraw raw HID device support" bool "/dev/hidraw raw HID device support"
depends on HID
help help
Say Y here if you want to support HID devices (from the USB Say Y here if you want to support HID devices (from the USB
specification standpoint) that aren't strictly user interface specification standpoint) that aren't strictly user interface
...@@ -57,7 +55,6 @@ config HIDRAW ...@@ -57,7 +55,6 @@ config HIDRAW
config UHID config UHID
tristate "User-space I/O driver support for HID subsystem" tristate "User-space I/O driver support for HID subsystem"
depends on HID
default n default n
help help
Say Y here if you want to provide HID I/O Drivers from user-space. Say Y here if you want to provide HID I/O Drivers from user-space.
...@@ -78,7 +75,6 @@ config UHID ...@@ -78,7 +75,6 @@ config UHID
config HID_GENERIC config HID_GENERIC
tristate "Generic HID driver" tristate "Generic HID driver"
depends on HID
default HID default HID
help help
Support for generic devices on the HID bus. This includes most Support for generic devices on the HID bus. This includes most
...@@ -90,11 +86,9 @@ config HID_GENERIC ...@@ -90,11 +86,9 @@ config HID_GENERIC
If unsure, say Y. If unsure, say Y.
menu "Special HID drivers" menu "Special HID drivers"
depends on HID
config HID_A4TECH config HID_A4TECH
tristate "A4TECH mice" tristate "A4TECH mice"
depends on HID
default !EXPERT default !EXPERT
help help
Support for some A4TECH mice with two scroll wheels. Support for some A4TECH mice with two scroll wheels.
...@@ -113,7 +107,6 @@ config HID_ACCUTOUCH ...@@ -113,7 +107,6 @@ config HID_ACCUTOUCH
config HID_ACRUX config HID_ACRUX
tristate "ACRUX game controller support" tristate "ACRUX game controller support"
depends on HID
help help
Say Y here if you want to enable support for ACRUX game controllers. Say Y here if you want to enable support for ACRUX game controllers.
...@@ -127,7 +120,6 @@ config HID_ACRUX_FF ...@@ -127,7 +120,6 @@ config HID_ACRUX_FF
config HID_APPLE config HID_APPLE
tristate "Apple {i,Power,Mac}Books" tristate "Apple {i,Power,Mac}Books"
depends on HID
depends on LEDS_CLASS depends on LEDS_CLASS
depends on NEW_LEDS depends on NEW_LEDS
default !EXPERT default !EXPERT
...@@ -167,13 +159,11 @@ config HID_ASUS ...@@ -167,13 +159,11 @@ config HID_ASUS
config HID_AUREAL config HID_AUREAL
tristate "Aureal" tristate "Aureal"
depends on HID
help help
Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes. Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes.
config HID_BELKIN config HID_BELKIN
tristate "Belkin Flip KVM and Wireless keyboard" tristate "Belkin Flip KVM and Wireless keyboard"
depends on HID
default !EXPERT default !EXPERT
help help
Support for Belkin Flip KVM and Wireless keyboard. Support for Belkin Flip KVM and Wireless keyboard.
...@@ -202,7 +192,6 @@ config HID_BIGBEN_FF ...@@ -202,7 +192,6 @@ config HID_BIGBEN_FF
config HID_CHERRY config HID_CHERRY
tristate "Cherry Cymotion keyboard" tristate "Cherry Cymotion keyboard"
depends on HID
default !EXPERT default !EXPERT
help help
Support for Cherry Cymotion keyboard. Support for Cherry Cymotion keyboard.
...@@ -227,7 +216,6 @@ config HID_CORSAIR ...@@ -227,7 +216,6 @@ config HID_CORSAIR
config HID_COUGAR config HID_COUGAR
tristate "Cougar devices" tristate "Cougar devices"
depends on HID
help help
Support for Cougar devices that are not fully compliant with the Support for Cougar devices that are not fully compliant with the
HID standard. HID standard.
...@@ -237,7 +225,6 @@ config HID_COUGAR ...@@ -237,7 +225,6 @@ config HID_COUGAR
config HID_MACALLY config HID_MACALLY
tristate "Macally devices" tristate "Macally devices"
depends on HID
help help
Support for Macally devices that are not fully compliant with the Support for Macally devices that are not fully compliant with the
HID standard. HID standard.
...@@ -262,7 +249,6 @@ config HID_PRODIKEYS ...@@ -262,7 +249,6 @@ config HID_PRODIKEYS
config HID_CMEDIA config HID_CMEDIA
tristate "CMedia audio chips" tristate "CMedia audio chips"
depends on HID
help help
Support for CMedia CM6533 HID audio jack controls Support for CMedia CM6533 HID audio jack controls
and HS100B mute buttons. and HS100B mute buttons.
...@@ -288,14 +274,12 @@ config HID_CREATIVE_SB0540 ...@@ -288,14 +274,12 @@ config HID_CREATIVE_SB0540
config HID_CYPRESS config HID_CYPRESS
tristate "Cypress mouse and barcode readers" tristate "Cypress mouse and barcode readers"
depends on HID
default !EXPERT default !EXPERT
help help
Support for cypress mouse and barcode readers. Support for cypress mouse and barcode readers.
config HID_DRAGONRISE config HID_DRAGONRISE
tristate "DragonRise Inc. game controller" tristate "DragonRise Inc. game controller"
depends on HID
help help
Say Y here if you have DragonRise Inc. game controllers. Say Y here if you have DragonRise Inc. game controllers.
These might be branded as: These might be branded as:
...@@ -314,7 +298,6 @@ config DRAGONRISE_FF ...@@ -314,7 +298,6 @@ config DRAGONRISE_FF
config HID_EMS_FF config HID_EMS_FF
tristate "EMS Production Inc. force feedback support" tristate "EMS Production Inc. force feedback support"
depends on HID
select INPUT_FF_MEMLESS select INPUT_FF_MEMLESS
help help
Say Y here if you want to enable force feedback support for devices by Say Y here if you want to enable force feedback support for devices by
...@@ -332,7 +315,6 @@ config HID_ELAN ...@@ -332,7 +315,6 @@ config HID_ELAN
config HID_ELECOM config HID_ELECOM
tristate "ELECOM HID devices" tristate "ELECOM HID devices"
depends on HID
help help
Support for ELECOM devices: Support for ELECOM devices:
- BM084 Bluetooth Mouse - BM084 Bluetooth Mouse
...@@ -349,7 +331,6 @@ config HID_ELO ...@@ -349,7 +331,6 @@ config HID_ELO
config HID_EZKEY config HID_EZKEY
tristate "Ezkey BTC 8193 keyboard" tristate "Ezkey BTC 8193 keyboard"
depends on HID
default !EXPERT default !EXPERT
help help
Support for Ezkey BTC 8193 keyboard. Support for Ezkey BTC 8193 keyboard.
...@@ -367,19 +348,16 @@ config HID_FT260 ...@@ -367,19 +348,16 @@ config HID_FT260
config HID_GEMBIRD config HID_GEMBIRD
tristate "Gembird Joypad" tristate "Gembird Joypad"
depends on HID
help help
Support for Gembird JPD-DualForce 2. Support for Gembird JPD-DualForce 2.
config HID_GFRM config HID_GFRM
tristate "Google Fiber TV Box remote control support" tristate "Google Fiber TV Box remote control support"
depends on HID
help help
Support for Google Fiber TV Box remote controls Support for Google Fiber TV Box remote controls
config HID_GLORIOUS config HID_GLORIOUS
tristate "Glorious PC Gaming Race mice" tristate "Glorious PC Gaming Race mice"
depends on HID
help help
Support for Glorious PC Gaming Race mice such as Support for Glorious PC Gaming Race mice such as
the Glorious Model O, O- and D. the Glorious Model O, O- and D.
...@@ -424,7 +402,6 @@ config HID_VIVALDI ...@@ -424,7 +402,6 @@ config HID_VIVALDI
tristate "Vivaldi Keyboard" tristate "Vivaldi Keyboard"
select HID_VIVALDI_COMMON select HID_VIVALDI_COMMON
select INPUT_VIVALDIFMAP select INPUT_VIVALDIFMAP
depends on HID
help help
Say Y here if you want to enable support for Vivaldi keyboards. Say Y here if you want to enable support for Vivaldi keyboards.
...@@ -447,7 +424,6 @@ config HID_GT683R ...@@ -447,7 +424,6 @@ config HID_GT683R
config HID_KEYTOUCH config HID_KEYTOUCH
tristate "Keytouch HID devices" tristate "Keytouch HID devices"
depends on HID
help help
Support for Keytouch HID devices not fully compliant with Support for Keytouch HID devices not fully compliant with
the specification. Currently supported: the specification. Currently supported:
...@@ -455,7 +431,6 @@ config HID_KEYTOUCH ...@@ -455,7 +431,6 @@ config HID_KEYTOUCH
config HID_KYE config HID_KYE
tristate "KYE/Genius devices" tristate "KYE/Genius devices"
depends on HID
help help
Support for KYE/Genius devices not fully compliant with HID standard: Support for KYE/Genius devices not fully compliant with HID standard:
- Ergo Mouse - Ergo Mouse
...@@ -471,32 +446,37 @@ config HID_UCLOGIC ...@@ -471,32 +446,37 @@ config HID_UCLOGIC
config HID_WALTOP config HID_WALTOP
tristate "Waltop" tristate "Waltop"
depends on HID
help help
Support for Waltop tablets. Support for Waltop tablets.
config HID_VIEWSONIC config HID_VIEWSONIC
tristate "ViewSonic/Signotec" tristate "ViewSonic/Signotec"
depends on HID
help help
Support for ViewSonic/Signotec PD1011 signature pad. Support for ViewSonic/Signotec PD1011 signature pad.
config HID_VRC2
tristate "VRC-2 Car Controller"
depends on HID
help
Support for VRC-2 which is a 2-axis controller often used in
car simulators.
To compile this driver as a module, choose M here: the
module will be called hid-vrc2.
config HID_XIAOMI config HID_XIAOMI
tristate "Xiaomi" tristate "Xiaomi"
depends on HID
help help
Adds support for side buttons of Xiaomi Mi Dual Mode Wireless Adds support for side buttons of Xiaomi Mi Dual Mode Wireless
Mouse Silent Edition. Mouse Silent Edition.
config HID_GYRATION config HID_GYRATION
tristate "Gyration remote control" tristate "Gyration remote control"
depends on HID
help help
Support for Gyration remote control. Support for Gyration remote control.
config HID_ICADE config HID_ICADE
tristate "ION iCade arcade controller" tristate "ION iCade arcade controller"
depends on HID
help help
Support for the ION iCade arcade controller to work as a joystick. Support for the ION iCade arcade controller to work as a joystick.
...@@ -505,14 +485,12 @@ config HID_ICADE ...@@ -505,14 +485,12 @@ config HID_ICADE
config HID_ITE config HID_ITE
tristate "ITE devices" tristate "ITE devices"
depends on HID
default !EXPERT default !EXPERT
help help
Support for ITE devices not fully compliant with HID standard. Support for ITE devices not fully compliant with HID standard.
config HID_JABRA config HID_JABRA
tristate "Jabra USB HID Driver" tristate "Jabra USB HID Driver"
depends on HID
help help
Support for Jabra USB HID devices. Support for Jabra USB HID devices.
...@@ -523,26 +501,22 @@ config HID_JABRA ...@@ -523,26 +501,22 @@ config HID_JABRA
config HID_TWINHAN config HID_TWINHAN
tristate "Twinhan IR remote control" tristate "Twinhan IR remote control"
depends on HID
help help
Support for Twinhan IR remote control. Support for Twinhan IR remote control.
config HID_KENSINGTON config HID_KENSINGTON
tristate "Kensington Slimblade Trackball" tristate "Kensington Slimblade Trackball"
depends on HID
default !EXPERT default !EXPERT
help help
Support for Kensington Slimblade Trackball. Support for Kensington Slimblade Trackball.
config HID_LCPOWER config HID_LCPOWER
tristate "LC-Power" tristate "LC-Power"
depends on HID
help help
Support for LC-Power RC1000MCE RF remote control. Support for LC-Power RC1000MCE RF remote control.
config HID_LED config HID_LED
tristate "Simple RGB LED support" tristate "Simple RGB LED support"
depends on HID
depends on LEDS_CLASS depends on LEDS_CLASS
help help
Support for simple RGB LED devices. Currently supported are: Support for simple RGB LED devices. Currently supported are:
...@@ -557,7 +531,6 @@ config HID_LED ...@@ -557,7 +531,6 @@ config HID_LED
config HID_LENOVO config HID_LENOVO
tristate "Lenovo / Thinkpad devices" tristate "Lenovo / Thinkpad devices"
depends on HID
select NEW_LEDS select NEW_LEDS
select LEDS_CLASS select LEDS_CLASS
help help
...@@ -675,7 +648,6 @@ config LOGIWHEELS_FF ...@@ -675,7 +648,6 @@ config LOGIWHEELS_FF
config HID_MAGICMOUSE config HID_MAGICMOUSE
tristate "Apple Magic Mouse/Trackpad multi-touch support" tristate "Apple Magic Mouse/Trackpad multi-touch support"
depends on HID
help help
Support for the Apple Magic Mouse/Trackpad multi-touch. Support for the Apple Magic Mouse/Trackpad multi-touch.
...@@ -684,14 +656,12 @@ config HID_MAGICMOUSE ...@@ -684,14 +656,12 @@ config HID_MAGICMOUSE
config HID_MALTRON config HID_MALTRON
tristate "Maltron L90 keyboard" tristate "Maltron L90 keyboard"
depends on HID
help help
Adds support for the volume up, volume down, mute, and play/pause buttons Adds support for the volume up, volume down, mute, and play/pause buttons
of the Maltron L90 keyboard. of the Maltron L90 keyboard.
config HID_MAYFLASH config HID_MAYFLASH
tristate "Mayflash game controller adapter force feedback" tristate "Mayflash game controller adapter force feedback"
depends on HID
select INPUT_FF_MEMLESS select INPUT_FF_MEMLESS
help help
Say Y here if you have HJZ Mayflash PS3 game controller adapters Say Y here if you have HJZ Mayflash PS3 game controller adapters
...@@ -707,14 +677,12 @@ config HID_MEGAWORLD_FF ...@@ -707,14 +677,12 @@ config HID_MEGAWORLD_FF
config HID_REDRAGON config HID_REDRAGON
tristate "Redragon keyboards" tristate "Redragon keyboards"
depends on HID
default !EXPERT default !EXPERT
help help
Support for Redragon keyboards that need fix-ups to work properly. Support for Redragon keyboards that need fix-ups to work properly.
config HID_MICROSOFT config HID_MICROSOFT
tristate "Microsoft non-fully HID-compliant devices" tristate "Microsoft non-fully HID-compliant devices"
depends on HID
default !EXPERT default !EXPERT
select INPUT_FF_MEMLESS select INPUT_FF_MEMLESS
help help
...@@ -722,14 +690,12 @@ config HID_MICROSOFT ...@@ -722,14 +690,12 @@ config HID_MICROSOFT
config HID_MONTEREY config HID_MONTEREY
tristate "Monterey Genius KB29E keyboard" tristate "Monterey Genius KB29E keyboard"
depends on HID
default !EXPERT default !EXPERT
help help
Support for Monterey Genius KB29E. Support for Monterey Genius KB29E.
config HID_MULTITOUCH config HID_MULTITOUCH
tristate "HID Multitouch panels" tristate "HID Multitouch panels"
depends on HID
help help
Generic support for HID multitouch panels. Generic support for HID multitouch panels.
...@@ -775,7 +741,6 @@ config HID_MULTITOUCH ...@@ -775,7 +741,6 @@ config HID_MULTITOUCH
config HID_NINTENDO config HID_NINTENDO
tristate "Nintendo Joy-Con and Pro Controller support" tristate "Nintendo Joy-Con and Pro Controller support"
depends on HID
depends on NEW_LEDS depends on NEW_LEDS
depends on LEDS_CLASS depends on LEDS_CLASS
select POWER_SUPPLY select POWER_SUPPLY
...@@ -811,7 +776,6 @@ config HID_NTRIG ...@@ -811,7 +776,6 @@ config HID_NTRIG
config HID_ORTEK config HID_ORTEK
tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad" tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad"
depends on HID
help help
There are certain devices which have LogicalMaximum wrong in the keyboard There are certain devices which have LogicalMaximum wrong in the keyboard
usage page of their report descriptor. The most prevailing ones so far usage page of their report descriptor. The most prevailing ones so far
...@@ -824,7 +788,6 @@ config HID_ORTEK ...@@ -824,7 +788,6 @@ config HID_ORTEK
config HID_PANTHERLORD config HID_PANTHERLORD
tristate "Pantherlord/GreenAsia game controller" tristate "Pantherlord/GreenAsia game controller"
depends on HID
help help
Say Y here if you have a PantherLord/GreenAsia based game controller Say Y here if you have a PantherLord/GreenAsia based game controller
or adapter. or adapter.
...@@ -850,13 +813,11 @@ config HID_PENMOUNT ...@@ -850,13 +813,11 @@ config HID_PENMOUNT
config HID_PETALYNX config HID_PETALYNX
tristate "Petalynx Maxter remote control" tristate "Petalynx Maxter remote control"
depends on HID
help help
Support for Petalynx Maxter remote control. Support for Petalynx Maxter remote control.
config HID_PICOLCD config HID_PICOLCD
tristate "PicoLCD (graphic version)" tristate "PicoLCD (graphic version)"
depends on HID
help help
This provides support for Minibox PicoLCD devices, currently This provides support for Minibox PicoLCD devices, currently
only the graphical ones are supported. only the graphical ones are supported.
...@@ -922,7 +883,6 @@ config HID_PICOLCD_CIR ...@@ -922,7 +883,6 @@ config HID_PICOLCD_CIR
config HID_PLANTRONICS config HID_PLANTRONICS
tristate "Plantronics USB HID Driver" tristate "Plantronics USB HID Driver"
depends on HID
help help
Provides HID support for Plantronics USB audio devices. Provides HID support for Plantronics USB audio devices.
Correctly maps vendor unique volume up/down HID usages to Correctly maps vendor unique volume up/down HID usages to
...@@ -933,7 +893,6 @@ config HID_PLANTRONICS ...@@ -933,7 +893,6 @@ config HID_PLANTRONICS
config HID_PLAYSTATION config HID_PLAYSTATION
tristate "PlayStation HID Driver" tristate "PlayStation HID Driver"
depends on HID
depends on LEDS_CLASS_MULTICOLOR depends on LEDS_CLASS_MULTICOLOR
select CRC32 select CRC32
select POWER_SUPPLY select POWER_SUPPLY
...@@ -950,16 +909,23 @@ config PLAYSTATION_FF ...@@ -950,16 +909,23 @@ config PLAYSTATION_FF
Say Y here if you would like to enable force feedback support for Say Y here if you would like to enable force feedback support for
PlayStation game controllers. PlayStation game controllers.
config HID_PXRC
tristate "PhoenixRC HID Flight Controller"
depends on HID
help
Support for PhoenixRC HID Flight Controller, a 8-axis flight controller.
To compile this driver as a module, choose M here: the
module will be called hid-pxrc.
config HID_RAZER config HID_RAZER
tristate "Razer non-fully HID-compliant devices" tristate "Razer non-fully HID-compliant devices"
depends on HID
help help
Support for Razer devices that are not fully compliant with the Support for Razer devices that are not fully compliant with the
HID standard. HID standard.
config HID_PRIMAX config HID_PRIMAX
tristate "Primax non-fully HID-compliant devices" tristate "Primax non-fully HID-compliant devices"
depends on HID
help help
Support for Primax devices that are not fully compliant with the Support for Primax devices that are not fully compliant with the
HID standard. HID standard.
...@@ -981,7 +947,6 @@ config HID_ROCCAT ...@@ -981,7 +947,6 @@ config HID_ROCCAT
config HID_SAITEK config HID_SAITEK
tristate "Saitek (Mad Catz) non-fully HID-compliant devices" tristate "Saitek (Mad Catz) non-fully HID-compliant devices"
depends on HID
help help
Support for Saitek devices that are not fully compliant with the Support for Saitek devices that are not fully compliant with the
HID standard. HID standard.
...@@ -999,7 +964,6 @@ config HID_SAMSUNG ...@@ -999,7 +964,6 @@ config HID_SAMSUNG
config HID_SEMITEK config HID_SEMITEK
tristate "Semitek USB keyboards" tristate "Semitek USB keyboards"
depends on HID
help help
Support for Semitek USB keyboards that are not fully compliant Support for Semitek USB keyboards that are not fully compliant
with the HID standard. with the HID standard.
...@@ -1050,13 +1014,11 @@ config SONY_FF ...@@ -1050,13 +1014,11 @@ config SONY_FF
config HID_SPEEDLINK config HID_SPEEDLINK
tristate "Speedlink VAD Cezanne mouse support" tristate "Speedlink VAD Cezanne mouse support"
depends on HID
help help
Support for Speedlink Vicious and Divine Cezanne mouse. Support for Speedlink Vicious and Divine Cezanne mouse.
config HID_STEAM config HID_STEAM
tristate "Steam Controller support" tristate "Steam Controller support"
depends on HID
select POWER_SUPPLY select POWER_SUPPLY
help help
Say Y here if you have a Steam Controller if you want to use it Say Y here if you have a Steam Controller if you want to use it
...@@ -1065,19 +1027,16 @@ config HID_STEAM ...@@ -1065,19 +1027,16 @@ config HID_STEAM
config HID_STEELSERIES config HID_STEELSERIES
tristate "Steelseries SRW-S1 steering wheel support" tristate "Steelseries SRW-S1 steering wheel support"
depends on HID
help help
Support for Steelseries SRW-S1 steering wheel Support for Steelseries SRW-S1 steering wheel
config HID_SUNPLUS config HID_SUNPLUS
tristate "Sunplus wireless desktop" tristate "Sunplus wireless desktop"
depends on HID
help help
Support for Sunplus wireless desktop. Support for Sunplus wireless desktop.
config HID_RMI config HID_RMI
tristate "Synaptics RMI4 device support" tristate "Synaptics RMI4 device support"
depends on HID
select RMI4_CORE select RMI4_CORE
select RMI4_F03 select RMI4_F03
select RMI4_F11 select RMI4_F11
...@@ -1090,7 +1049,6 @@ config HID_RMI ...@@ -1090,7 +1049,6 @@ config HID_RMI
config HID_GREENASIA config HID_GREENASIA
tristate "GreenAsia (Product ID 0x12) game controller support" tristate "GreenAsia (Product ID 0x12) game controller support"
depends on HID
help help
Say Y here if you have a GreenAsia (Product ID 0x12) based game Say Y here if you have a GreenAsia (Product ID 0x12) based game
controller or adapter. controller or adapter.
...@@ -1112,7 +1070,6 @@ config HID_HYPERV_MOUSE ...@@ -1112,7 +1070,6 @@ config HID_HYPERV_MOUSE
config HID_SMARTJOYPLUS config HID_SMARTJOYPLUS
tristate "SmartJoy PLUS PS2/USB adapter support" tristate "SmartJoy PLUS PS2/USB adapter support"
depends on HID
help help
Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box, Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box,
Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro. Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro.
...@@ -1130,20 +1087,23 @@ config SMARTJOYPLUS_FF ...@@ -1130,20 +1087,23 @@ config SMARTJOYPLUS_FF
config HID_TIVO config HID_TIVO
tristate "TiVo Slide Bluetooth remote control support" tristate "TiVo Slide Bluetooth remote control support"
depends on HID
help help
Say Y if you have a TiVo Slide Bluetooth remote control. Say Y if you have a TiVo Slide Bluetooth remote control.
config HID_TOPSEED config HID_TOPSEED
tristate "TopSeed Cyberlink, BTC Emprex, Conceptronic remote control support" tristate "TopSeed Cyberlink, BTC Emprex, Conceptronic remote control support"
depends on HID
help help
Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic
CLLRCMCE remote control. CLLRCMCE remote control.
config HID_TOPRE
tristate "Topre REALFORCE keyboards"
depends on HID
help
Say Y for N-key rollover support on Topre REALFORCE R2 108 key keyboards.
config HID_THINGM config HID_THINGM
tristate "ThingM blink(1) USB RGB LED" tristate "ThingM blink(1) USB RGB LED"
depends on HID
depends on LEDS_CLASS depends on LEDS_CLASS
select HID_LED select HID_LED
help help
...@@ -1170,7 +1130,6 @@ config THRUSTMASTER_FF ...@@ -1170,7 +1130,6 @@ config THRUSTMASTER_FF
config HID_UDRAW_PS3 config HID_UDRAW_PS3
tristate "THQ PS3 uDraw tablet" tristate "THQ PS3 uDraw tablet"
depends on HID
help help
Say Y here if you want to use the THQ uDraw gaming tablet for Say Y here if you want to use the THQ uDraw gaming tablet for
the PS3. the PS3.
...@@ -1207,7 +1166,6 @@ config HID_WACOM ...@@ -1207,7 +1166,6 @@ config HID_WACOM
config HID_WIIMOTE config HID_WIIMOTE
tristate "Nintendo Wii / Wii U peripherals" tristate "Nintendo Wii / Wii U peripherals"
depends on HID
depends on LEDS_CLASS depends on LEDS_CLASS
select POWER_SUPPLY select POWER_SUPPLY
select INPUT_FF_MEMLESS select INPUT_FF_MEMLESS
...@@ -1232,7 +1190,6 @@ config HID_WIIMOTE ...@@ -1232,7 +1190,6 @@ config HID_WIIMOTE
config HID_XINMO config HID_XINMO
tristate "Xin-Mo non-fully compliant devices" tristate "Xin-Mo non-fully compliant devices"
depends on HID
help help
Support for Xin-Mo devices that are not fully compliant with the HID Support for Xin-Mo devices that are not fully compliant with the HID
standard. Currently only supports the Xin-Mo Dual Arcade. Say Y here standard. Currently only supports the Xin-Mo Dual Arcade. Say Y here
...@@ -1240,7 +1197,6 @@ config HID_XINMO ...@@ -1240,7 +1197,6 @@ config HID_XINMO
config HID_ZEROPLUS config HID_ZEROPLUS
tristate "Zeroplus based game controller support" tristate "Zeroplus based game controller support"
depends on HID
help help
Say Y here if you have a Zeroplus based game controller. Say Y here if you have a Zeroplus based game controller.
...@@ -1254,13 +1210,12 @@ config ZEROPLUS_FF ...@@ -1254,13 +1210,12 @@ config ZEROPLUS_FF
config HID_ZYDACRON config HID_ZYDACRON
tristate "Zydacron remote control support" tristate "Zydacron remote control support"
depends on HID
help help
Support for Zydacron remote control. Support for Zydacron remote control.
config HID_SENSOR_HUB config HID_SENSOR_HUB
tristate "HID Sensors framework support" tristate "HID Sensors framework support"
depends on HID && HAS_IOMEM depends on HAS_IOMEM
select MFD_CORE select MFD_CORE
default n default n
help help
...@@ -1289,7 +1244,6 @@ config HID_SENSOR_CUSTOM_SENSOR ...@@ -1289,7 +1244,6 @@ config HID_SENSOR_CUSTOM_SENSOR
config HID_ALPS config HID_ALPS
tristate "Alps HID device support" tristate "Alps HID device support"
depends on HID
help help
Support for Alps I2C HID touchpads and StickPointer. Support for Alps I2C HID touchpads and StickPointer.
Say Y here if you have a Alps touchpads over i2c-hid or usbhid Say Y here if you have a Alps touchpads over i2c-hid or usbhid
...@@ -1307,7 +1261,7 @@ config HID_MCP2221 ...@@ -1307,7 +1261,7 @@ config HID_MCP2221
will be called hid-mcp2221.ko. will be called hid-mcp2221.ko.
config HID_KUNIT_TEST config HID_KUNIT_TEST
bool "KUnit tests for HID" if !KUNIT_ALL_TESTS tristate "KUnit tests for HID" if !KUNIT_ALL_TESTS
depends on KUNIT=y depends on KUNIT=y
depends on HID_UCLOGIC depends on HID_UCLOGIC
default KUNIT_ALL_TESTS default KUNIT_ALL_TESTS
......
...@@ -101,6 +101,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS) += hid-picolcd_debugfs.o ...@@ -101,6 +101,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS) += hid-picolcd_debugfs.o
obj-$(CONFIG_HID_PLANTRONICS) += hid-plantronics.o obj-$(CONFIG_HID_PLANTRONICS) += hid-plantronics.o
obj-$(CONFIG_HID_PLAYSTATION) += hid-playstation.o obj-$(CONFIG_HID_PLAYSTATION) += hid-playstation.o
obj-$(CONFIG_HID_PRIMAX) += hid-primax.o obj-$(CONFIG_HID_PRIMAX) += hid-primax.o
obj-$(CONFIG_HID_PXRC) += hid-pxrc.o
obj-$(CONFIG_HID_RAZER) += hid-razer.o obj-$(CONFIG_HID_RAZER) += hid-razer.o
obj-$(CONFIG_HID_REDRAGON) += hid-redragon.o obj-$(CONFIG_HID_REDRAGON) += hid-redragon.o
obj-$(CONFIG_HID_RETRODE) += hid-retrode.o obj-$(CONFIG_HID_RETRODE) += hid-retrode.o
...@@ -123,6 +124,7 @@ obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o ...@@ -123,6 +124,7 @@ obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o
obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o hid-thrustmaster.o obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o hid-thrustmaster.o
obj-$(CONFIG_HID_TIVO) += hid-tivo.o obj-$(CONFIG_HID_TIVO) += hid-tivo.o
obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
obj-$(CONFIG_HID_TOPRE) += hid-topre.o
obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o
obj-$(CONFIG_HID_U2FZERO) += hid-u2fzero.o obj-$(CONFIG_HID_U2FZERO) += hid-u2fzero.o
hid-uclogic-objs := hid-uclogic-core.o \ hid-uclogic-objs := hid-uclogic-core.o \
...@@ -136,6 +138,7 @@ obj-$(CONFIG_HID_XINMO) += hid-xinmo.o ...@@ -136,6 +138,7 @@ obj-$(CONFIG_HID_XINMO) += hid-xinmo.o
obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o
obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o
obj-$(CONFIG_HID_VIEWSONIC) += hid-viewsonic.o obj-$(CONFIG_HID_VIEWSONIC) += hid-viewsonic.o
obj-$(CONFIG_HID_VRC2) += hid-vrc2.o
wacom-objs := wacom_wac.o wacom_sys.o wacom-objs := wacom_wac.o wacom_sys.o
obj-$(CONFIG_HID_WACOM) += wacom.o obj-$(CONFIG_HID_WACOM) += wacom.o
...@@ -144,8 +147,10 @@ obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o ...@@ -144,8 +147,10 @@ obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o
obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o
obj-$(CONFIG_HID_SENSOR_CUSTOM_SENSOR) += hid-sensor-custom.o obj-$(CONFIG_HID_SENSOR_CUSTOM_SENSOR) += hid-sensor-custom.o
obj-$(CONFIG_HID_KUNIT_TEST) += hid-uclogic-rdesc.o \ hid-uclogic-test-objs := hid-uclogic-rdesc.o \
hid-uclogic-params.o \
hid-uclogic-rdesc-test.o hid-uclogic-rdesc-test.o
obj-$(CONFIG_HID_KUNIT_TEST) += hid-uclogic-test.o
obj-$(CONFIG_USB_HID) += usbhid/ obj-$(CONFIG_USB_HID) += usbhid/
obj-$(CONFIG_USB_MOUSE) += usbhid/ obj-$(CONFIG_USB_MOUSE) += usbhid/
......
...@@ -110,6 +110,8 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata) ...@@ -110,6 +110,8 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
amd_sfh1_1_set_desc_ops(mp2_ops); amd_sfh1_1_set_desc_ops(mp2_ops);
cl_data->num_hid_devices = amd_sfh_get_sensor_num(privdata, &cl_data->sensor_idx[0]); cl_data->num_hid_devices = amd_sfh_get_sensor_num(privdata, &cl_data->sensor_idx[0]);
if (cl_data->num_hid_devices == 0)
return -ENODEV;
INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work); INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work);
INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer); INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer);
...@@ -286,13 +288,13 @@ int amd_sfh1_1_init(struct amd_mp2_dev *mp2) ...@@ -286,13 +288,13 @@ int amd_sfh1_1_init(struct amd_mp2_dev *mp2)
phy_base <<= 21; phy_base <<= 21;
if (!devm_request_mem_region(dev, phy_base, 128 * 1024, "amd_sfh")) { if (!devm_request_mem_region(dev, phy_base, 128 * 1024, "amd_sfh")) {
dev_err(dev, "can't reserve mmio registers\n"); dev_dbg(dev, "can't reserve mmio registers\n");
return -ENOMEM; return -ENOMEM;
} }
mp2->vsbase = devm_ioremap(dev, phy_base, 128 * 1024); mp2->vsbase = devm_ioremap(dev, phy_base, 128 * 1024);
if (!mp2->vsbase) { if (!mp2->vsbase) {
dev_err(dev, "failed to remap vsbase\n"); dev_dbg(dev, "failed to remap vsbase\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -301,7 +303,7 @@ int amd_sfh1_1_init(struct amd_mp2_dev *mp2) ...@@ -301,7 +303,7 @@ int amd_sfh1_1_init(struct amd_mp2_dev *mp2)
memcpy_fromio(&binfo, mp2->vsbase, sizeof(struct sfh_base_info)); memcpy_fromio(&binfo, mp2->vsbase, sizeof(struct sfh_base_info));
if (binfo.sbase.fw_info.fw_ver == 0 || binfo.sbase.s_list.sl.sensors == 0) { if (binfo.sbase.fw_info.fw_ver == 0 || binfo.sbase.s_list.sl.sensors == 0) {
dev_err(dev, "failed to get sensors\n"); dev_dbg(dev, "failed to get sensors\n");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
dev_dbg(dev, "firmware version 0x%x\n", binfo.sbase.fw_info.fw_ver); dev_dbg(dev, "firmware version 0x%x\n", binfo.sbase.fw_info.fw_ver);
......
...@@ -55,7 +55,7 @@ MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special drivers and handle ...@@ -55,7 +55,7 @@ MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special drivers and handle
*/ */
struct hid_report *hid_register_report(struct hid_device *device, struct hid_report *hid_register_report(struct hid_device *device,
unsigned int type, unsigned int id, enum hid_report_type type, unsigned int id,
unsigned int application) unsigned int application)
{ {
struct hid_report_enum *report_enum = device->report_enum + type; struct hid_report_enum *report_enum = device->report_enum + type;
...@@ -967,7 +967,7 @@ static const char * const hid_report_names[] = { ...@@ -967,7 +967,7 @@ static const char * const hid_report_names[] = {
* parsing. * parsing.
*/ */
struct hid_report *hid_validate_values(struct hid_device *hid, struct hid_report *hid_validate_values(struct hid_device *hid,
unsigned int type, unsigned int id, enum hid_report_type type, unsigned int id,
unsigned int field_index, unsigned int field_index,
unsigned int report_counts) unsigned int report_counts)
{ {
...@@ -1921,7 +1921,7 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum, ...@@ -1921,7 +1921,7 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum,
* DO NOT USE in hid drivers directly, but through hid_hw_request instead. * DO NOT USE in hid drivers directly, but through hid_hw_request instead.
*/ */
int __hid_request(struct hid_device *hid, struct hid_report *report, int __hid_request(struct hid_device *hid, struct hid_report *report,
int reqtype) enum hid_class_request reqtype)
{ {
char *buf; char *buf;
int ret; int ret;
...@@ -1954,8 +1954,8 @@ int __hid_request(struct hid_device *hid, struct hid_report *report, ...@@ -1954,8 +1954,8 @@ int __hid_request(struct hid_device *hid, struct hid_report *report,
} }
EXPORT_SYMBOL_GPL(__hid_request); EXPORT_SYMBOL_GPL(__hid_request);
int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
int interrupt) int interrupt)
{ {
struct hid_report_enum *report_enum = hid->report_enum + type; struct hid_report_enum *report_enum = hid->report_enum + type;
struct hid_report *report; struct hid_report *report;
...@@ -2019,7 +2019,8 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event); ...@@ -2019,7 +2019,8 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event);
* *
* This is data entry for lower layers. * This is data entry for lower layers.
*/ */
int hid_input_report(struct hid_device *hid, int type, u8 *data, u32 size, int interrupt) int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
int interrupt)
{ {
struct hid_report_enum *report_enum; struct hid_report_enum *report_enum;
struct hid_driver *hdrv; struct hid_driver *hdrv;
...@@ -2088,6 +2089,7 @@ const struct hid_device_id *hid_match_id(const struct hid_device *hdev, ...@@ -2088,6 +2089,7 @@ const struct hid_device_id *hid_match_id(const struct hid_device *hdev,
return NULL; return NULL;
} }
EXPORT_SYMBOL_GPL(hid_match_id);
static const struct hid_device_id hid_hiddev_list[] = { static const struct hid_device_id hid_hiddev_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS) }, { HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS) },
...@@ -2352,7 +2354,7 @@ EXPORT_SYMBOL_GPL(hid_hw_close); ...@@ -2352,7 +2354,7 @@ EXPORT_SYMBOL_GPL(hid_hw_close);
* @reqtype: hid request type * @reqtype: hid request type
*/ */
void hid_hw_request(struct hid_device *hdev, void hid_hw_request(struct hid_device *hdev,
struct hid_report *report, int reqtype) struct hid_report *report, enum hid_class_request reqtype)
{ {
if (hdev->ll_driver->request) if (hdev->ll_driver->request)
return hdev->ll_driver->request(hdev, report, reqtype); return hdev->ll_driver->request(hdev, report, reqtype);
...@@ -2377,7 +2379,7 @@ EXPORT_SYMBOL_GPL(hid_hw_request); ...@@ -2377,7 +2379,7 @@ EXPORT_SYMBOL_GPL(hid_hw_request);
*/ */
int hid_hw_raw_request(struct hid_device *hdev, int hid_hw_raw_request(struct hid_device *hdev,
unsigned char reportnum, __u8 *buf, unsigned char reportnum, __u8 *buf,
size_t len, unsigned char rtype, int reqtype) size_t len, enum hid_report_type rtype, enum hid_class_request reqtype)
{ {
if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf) if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf)
return -EINVAL; return -EINVAL;
...@@ -2739,10 +2741,12 @@ int hid_add_device(struct hid_device *hdev) ...@@ -2739,10 +2741,12 @@ int hid_add_device(struct hid_device *hdev)
hid_warn(hdev, "bad device descriptor (%d)\n", ret); hid_warn(hdev, "bad device descriptor (%d)\n", ret);
} }
hdev->id = atomic_inc_return(&id);
/* XXX hack, any other cleaner solution after the driver core /* XXX hack, any other cleaner solution after the driver core
* is converted to allow more than 20 bytes as the device name? */ * is converted to allow more than 20 bytes as the device name? */
dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus,
hdev->vendor, hdev->product, atomic_inc_return(&id)); hdev->vendor, hdev->product, hdev->id);
hid_debug_register(hdev, dev_name(&hdev->dev)); hid_debug_register(hdev, dev_name(&hdev->dev));
ret = device_add(&hdev->dev); ret = device_add(&hdev->dev);
......
...@@ -608,9 +608,11 @@ static struct hid_driver hammer_driver = { ...@@ -608,9 +608,11 @@ static struct hid_driver hammer_driver = {
.probe = hammer_probe, .probe = hammer_probe,
.remove = hammer_remove, .remove = hammer_remove,
.feature_mapping = vivaldi_feature_mapping, .feature_mapping = vivaldi_feature_mapping,
.input_configured = vivaldi_input_configured,
.input_mapping = hammer_input_mapping, .input_mapping = hammer_input_mapping,
.event = hammer_event, .event = hammer_event,
.driver = {
.dev_groups = vivaldi_attribute_groups,
},
}; };
static int __init hammer_init(void) static int __init hammer_init(void)
......
...@@ -1231,6 +1231,9 @@ ...@@ -1231,6 +1231,9 @@
#define USB_DEVICE_ID_TIVO_SLIDE 0x1201 #define USB_DEVICE_ID_TIVO_SLIDE 0x1201
#define USB_DEVICE_ID_TIVO_SLIDE_PRO 0x1203 #define USB_DEVICE_ID_TIVO_SLIDE_PRO 0x1203
#define USB_VENDOR_ID_TOPRE 0x0853
#define USB_DEVICE_ID_TOPRE_REALFORCE_R2_108 0x0148
#define USB_VENDOR_ID_TOPSEED 0x0766 #define USB_VENDOR_ID_TOPSEED 0x0766
#define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204 #define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204
...@@ -1279,10 +1282,12 @@ ...@@ -1279,10 +1282,12 @@
#define USB_DEVICE_ID_YIYNOVA_TABLET 0x004d #define USB_DEVICE_ID_YIYNOVA_TABLET 0x004d
#define USB_VENDOR_ID_UGEE 0x28bd #define USB_VENDOR_ID_UGEE 0x28bd
#define USB_DEVICE_ID_UGEE_PARBLO_A610_PRO 0x1903
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540 0x0075 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540 0x0075
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640 0x0094 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640 0x0094
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L 0x0935 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L 0x0935
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S 0x0909
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078
#define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074 #define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074
#define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071 #define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071
...@@ -1386,6 +1391,7 @@ ...@@ -1386,6 +1391,7 @@
#define USB_VENDOR_ID_MULTIPLE_1781 0x1781 #define USB_VENDOR_ID_MULTIPLE_1781 0x1781
#define USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD 0x0a9d #define USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD 0x0a9d
#define USB_DEVICE_ID_PHOENIXRC 0x0898
#define USB_VENDOR_ID_DRACAL_RAPHNET 0x289b #define USB_VENDOR_ID_DRACAL_RAPHNET 0x289b
#define USB_DEVICE_ID_RAPHNET_2NES2SNES 0x0002 #define USB_DEVICE_ID_RAPHNET_2NES2SNES 0x0002
......
...@@ -41,6 +41,9 @@ module_param(disable_tap_to_click, bool, 0644); ...@@ -41,6 +41,9 @@ module_param(disable_tap_to_click, bool, 0644);
MODULE_PARM_DESC(disable_tap_to_click, MODULE_PARM_DESC(disable_tap_to_click,
"Disable Tap-To-Click mode reporting for touchpads (only on the K400 currently)."); "Disable Tap-To-Click mode reporting for touchpads (only on the K400 currently).");
/* Define a non-zero software ID to identify our own requests */
#define LINUX_KERNEL_SW_ID 0x01
#define REPORT_ID_HIDPP_SHORT 0x10 #define REPORT_ID_HIDPP_SHORT 0x10
#define REPORT_ID_HIDPP_LONG 0x11 #define REPORT_ID_HIDPP_LONG 0x11
#define REPORT_ID_HIDPP_VERY_LONG 0x12 #define REPORT_ID_HIDPP_VERY_LONG 0x12
...@@ -71,21 +74,18 @@ MODULE_PARM_DESC(disable_tap_to_click, ...@@ -71,21 +74,18 @@ MODULE_PARM_DESC(disable_tap_to_click,
#define HIDPP_QUIRK_NO_HIDINPUT BIT(23) #define HIDPP_QUIRK_NO_HIDINPUT BIT(23)
#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24) #define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24)
#define HIDPP_QUIRK_UNIFYING BIT(25) #define HIDPP_QUIRK_UNIFYING BIT(25)
#define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(26) #define HIDPP_QUIRK_HIDPP_WHEELS BIT(26)
#define HIDPP_QUIRK_HI_RES_SCROLL_X2120 BIT(27) #define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(27)
#define HIDPP_QUIRK_HI_RES_SCROLL_X2121 BIT(28) #define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(28)
#define HIDPP_QUIRK_HIDPP_WHEELS BIT(29)
#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(30)
#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(31)
/* These are just aliases for now */ /* These are just aliases for now */
#define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS #define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS
#define HIDPP_QUIRK_KBD_ZOOM_WHEEL HIDPP_QUIRK_HIDPP_WHEELS #define HIDPP_QUIRK_KBD_ZOOM_WHEEL HIDPP_QUIRK_HIDPP_WHEELS
/* Convenience constant to check for any high-res support. */ /* Convenience constant to check for any high-res support. */
#define HIDPP_QUIRK_HI_RES_SCROLL (HIDPP_QUIRK_HI_RES_SCROLL_1P0 | \ #define HIDPP_CAPABILITY_HI_RES_SCROLL (HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL | \
HIDPP_QUIRK_HI_RES_SCROLL_X2120 | \ HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL | \
HIDPP_QUIRK_HI_RES_SCROLL_X2121) HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL)
#define HIDPP_QUIRK_DELAYED_INIT HIDPP_QUIRK_NO_HIDINPUT #define HIDPP_QUIRK_DELAYED_INIT HIDPP_QUIRK_NO_HIDINPUT
...@@ -96,6 +96,9 @@ MODULE_PARM_DESC(disable_tap_to_click, ...@@ -96,6 +96,9 @@ MODULE_PARM_DESC(disable_tap_to_click,
#define HIDPP_CAPABILITY_BATTERY_VOLTAGE BIT(4) #define HIDPP_CAPABILITY_BATTERY_VOLTAGE BIT(4)
#define HIDPP_CAPABILITY_BATTERY_PERCENTAGE BIT(5) #define HIDPP_CAPABILITY_BATTERY_PERCENTAGE BIT(5)
#define HIDPP_CAPABILITY_UNIFIED_BATTERY BIT(6) #define HIDPP_CAPABILITY_UNIFIED_BATTERY BIT(6)
#define HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL BIT(7)
#define HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL BIT(8)
#define HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL BIT(9)
#define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
...@@ -343,7 +346,7 @@ static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp, ...@@ -343,7 +346,7 @@ static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp,
else else
message->report_id = REPORT_ID_HIDPP_LONG; message->report_id = REPORT_ID_HIDPP_LONG;
message->fap.feature_index = feat_index; message->fap.feature_index = feat_index;
message->fap.funcindex_clientid = funcindex_clientid; message->fap.funcindex_clientid = funcindex_clientid | LINUX_KERNEL_SW_ID;
memcpy(&message->fap.params, params, param_count); memcpy(&message->fap.params, params, param_count);
ret = hidpp_send_message_sync(hidpp, message, response); ret = hidpp_send_message_sync(hidpp, message, response);
...@@ -856,8 +859,8 @@ static int hidpp_unifying_init(struct hidpp_device *hidpp) ...@@ -856,8 +859,8 @@ static int hidpp_unifying_init(struct hidpp_device *hidpp)
#define HIDPP_PAGE_ROOT 0x0000 #define HIDPP_PAGE_ROOT 0x0000
#define HIDPP_PAGE_ROOT_IDX 0x00 #define HIDPP_PAGE_ROOT_IDX 0x00
#define CMD_ROOT_GET_FEATURE 0x01 #define CMD_ROOT_GET_FEATURE 0x00
#define CMD_ROOT_GET_PROTOCOL_VERSION 0x11 #define CMD_ROOT_GET_PROTOCOL_VERSION 0x10
static int hidpp_root_get_feature(struct hidpp_device *hidpp, u16 feature, static int hidpp_root_get_feature(struct hidpp_device *hidpp, u16 feature,
u8 *feature_index, u8 *feature_type) u8 *feature_index, u8 *feature_type)
...@@ -934,9 +937,9 @@ static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp) ...@@ -934,9 +937,9 @@ static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp)
#define HIDPP_PAGE_GET_DEVICE_NAME_TYPE 0x0005 #define HIDPP_PAGE_GET_DEVICE_NAME_TYPE 0x0005
#define CMD_GET_DEVICE_NAME_TYPE_GET_COUNT 0x01 #define CMD_GET_DEVICE_NAME_TYPE_GET_COUNT 0x00
#define CMD_GET_DEVICE_NAME_TYPE_GET_DEVICE_NAME 0x11 #define CMD_GET_DEVICE_NAME_TYPE_GET_DEVICE_NAME 0x10
#define CMD_GET_DEVICE_NAME_TYPE_GET_TYPE 0x21 #define CMD_GET_DEVICE_NAME_TYPE_GET_TYPE 0x20
static int hidpp_devicenametype_get_count(struct hidpp_device *hidpp, static int hidpp_devicenametype_get_count(struct hidpp_device *hidpp,
u8 feature_index, u8 *nameLength) u8 feature_index, u8 *nameLength)
...@@ -1966,8 +1969,8 @@ static int hidpp_touchpad_fw_items_set(struct hidpp_device *hidpp, ...@@ -1966,8 +1969,8 @@ static int hidpp_touchpad_fw_items_set(struct hidpp_device *hidpp,
#define HIDPP_PAGE_TOUCHPAD_RAW_XY 0x6100 #define HIDPP_PAGE_TOUCHPAD_RAW_XY 0x6100
#define CMD_TOUCHPAD_GET_RAW_INFO 0x01 #define CMD_TOUCHPAD_GET_RAW_INFO 0x00
#define CMD_TOUCHPAD_SET_RAW_REPORT_STATE 0x21 #define CMD_TOUCHPAD_SET_RAW_REPORT_STATE 0x20
#define EVENT_TOUCHPAD_RAW_XY 0x00 #define EVENT_TOUCHPAD_RAW_XY 0x00
...@@ -3415,14 +3418,14 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp) ...@@ -3415,14 +3418,14 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp)
int ret; int ret;
u8 multiplier = 1; u8 multiplier = 1;
if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_X2121) { if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL) {
ret = hidpp_hrw_set_wheel_mode(hidpp, false, true, false); ret = hidpp_hrw_set_wheel_mode(hidpp, false, true, false);
if (ret == 0) if (ret == 0)
ret = hidpp_hrw_get_wheel_capability(hidpp, &multiplier); ret = hidpp_hrw_get_wheel_capability(hidpp, &multiplier);
} else if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_X2120) { } else if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL) {
ret = hidpp_hrs_set_highres_scrolling_mode(hidpp, true, ret = hidpp_hrs_set_highres_scrolling_mode(hidpp, true,
&multiplier); &multiplier);
} else /* if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_1P0) */ { } else /* if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL) */ {
ret = hidpp10_enable_scrolling_acceleration(hidpp); ret = hidpp10_enable_scrolling_acceleration(hidpp);
multiplier = 8; multiplier = 8;
} }
...@@ -3437,6 +3440,49 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp) ...@@ -3437,6 +3440,49 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp)
return 0; return 0;
} }
static int hidpp_initialize_hires_scroll(struct hidpp_device *hidpp)
{
int ret;
unsigned long capabilities;
capabilities = hidpp->capabilities;
if (hidpp->protocol_major >= 2) {
u8 feature_index;
u8 feature_type;
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HIRES_WHEEL,
&feature_index, &feature_type);
if (!ret) {
hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL;
hid_dbg(hidpp->hid_dev, "Detected HID++ 2.0 hi-res scroll wheel\n");
return 0;
}
ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HI_RESOLUTION_SCROLLING,
&feature_index, &feature_type);
if (!ret) {
hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL;
hid_dbg(hidpp->hid_dev, "Detected HID++ 2.0 hi-res scrolling\n");
}
} else {
struct hidpp_report response;
ret = hidpp_send_rap_command_sync(hidpp,
REPORT_ID_HIDPP_SHORT,
HIDPP_GET_REGISTER,
HIDPP_ENABLE_FAST_SCROLL,
NULL, 0, &response);
if (!ret) {
hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL;
hid_dbg(hidpp->hid_dev, "Detected HID++ 1.0 fast scroll\n");
}
}
if (hidpp->capabilities == capabilities)
hid_dbg(hidpp->hid_dev, "Did not detect HID++ hi-res scrolling hardware support\n");
return 0;
}
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* Generic HID++ devices */ /* Generic HID++ devices */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
...@@ -3691,8 +3737,9 @@ static int hidpp_event(struct hid_device *hdev, struct hid_field *field, ...@@ -3691,8 +3737,9 @@ static int hidpp_event(struct hid_device *hdev, struct hid_field *field,
* cases we must return early (falling back to default behaviour) to * cases we must return early (falling back to default behaviour) to
* avoid a crash in hidpp_scroll_counter_handle_scroll. * avoid a crash in hidpp_scroll_counter_handle_scroll.
*/ */
if (!(hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) || value == 0 if (!(hidpp->capabilities & HIDPP_CAPABILITY_HI_RES_SCROLL)
|| hidpp->input == NULL || counter->wheel_multiplier == 0) || value == 0 || hidpp->input == NULL
|| counter->wheel_multiplier == 0)
return 0; return 0;
hidpp_scroll_counter_handle_scroll(hidpp->input, counter, value); hidpp_scroll_counter_handle_scroll(hidpp->input, counter, value);
...@@ -3924,6 +3971,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) ...@@ -3924,6 +3971,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
} }
hidpp_initialize_battery(hidpp); hidpp_initialize_battery(hidpp);
hidpp_initialize_hires_scroll(hidpp);
/* forward current battery state */ /* forward current battery state */
if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_BATTERY) { if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_BATTERY) {
...@@ -3943,7 +3991,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) ...@@ -3943,7 +3991,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
if (hidpp->battery.ps) if (hidpp->battery.ps)
power_supply_changed(hidpp->battery.ps); power_supply_changed(hidpp->battery.ps);
if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) if (hidpp->capabilities & HIDPP_CAPABILITY_HI_RES_SCROLL)
hi_res_scroll_enable(hidpp); hi_res_scroll_enable(hidpp);
if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) || hidpp->delayed_input) if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) || hidpp->delayed_input)
...@@ -3959,8 +4007,10 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) ...@@ -3959,8 +4007,10 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
hidpp_populate_input(hidpp, input); hidpp_populate_input(hidpp, input);
ret = input_register_device(input); ret = input_register_device(input);
if (ret) if (ret) {
input_free_device(input); input_free_device(input);
return;
}
hidpp->delayed_input = input; hidpp->delayed_input = input;
} }
...@@ -4219,6 +4269,21 @@ static void hidpp_remove(struct hid_device *hdev) ...@@ -4219,6 +4269,21 @@ static void hidpp_remove(struct hid_device *hdev)
mutex_destroy(&hidpp->send_mutex); mutex_destroy(&hidpp->send_mutex);
} }
static const struct hid_device_id unhandled_hidpp_devices[] = {
/* Logitech Harmony Adapter for PS3, handled in hid-sony */
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) },
/* Handled in hid-generic */
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD) },
{}
};
static bool hidpp_match(struct hid_device *hdev,
bool ignore_special_driver)
{
/* Refuse to handle devices handled by other HID drivers */
return !hid_match_id(hdev, unhandled_hidpp_devices);
}
#define LDJ_DEVICE(product) \ #define LDJ_DEVICE(product) \
HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, \ HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, \
USB_VENDOR_ID_LOGITECH, (product)) USB_VENDOR_ID_LOGITECH, (product))
...@@ -4239,42 +4304,9 @@ static const struct hid_device_id hidpp_devices[] = { ...@@ -4239,42 +4304,9 @@ static const struct hid_device_id hidpp_devices[] = {
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
USB_DEVICE_ID_LOGITECH_T651), USB_DEVICE_ID_LOGITECH_T651),
.driver_data = HIDPP_QUIRK_CLASS_WTP }, .driver_data = HIDPP_QUIRK_CLASS_WTP },
{ /* Mouse Logitech Anywhere MX */
LDJ_DEVICE(0x1017), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 },
{ /* Mouse Logitech Cube */
LDJ_DEVICE(0x4010), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2120 },
{ /* Mouse Logitech M335 */
LDJ_DEVICE(0x4050), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ /* Mouse Logitech M515 */
LDJ_DEVICE(0x4007), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2120 },
{ /* Mouse logitech M560 */ { /* Mouse logitech M560 */
LDJ_DEVICE(0x402d), LDJ_DEVICE(0x402d),
.driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 },
| HIDPP_QUIRK_HI_RES_SCROLL_X2120 },
{ /* Mouse Logitech M705 (firmware RQM17) */
LDJ_DEVICE(0x101b), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 },
{ /* Mouse Logitech M705 (firmware RQM67) */
LDJ_DEVICE(0x406d), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ /* Mouse Logitech M720 */
LDJ_DEVICE(0x405e), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ /* Mouse Logitech MX Anywhere 2 */
LDJ_DEVICE(0x404a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ LDJ_DEVICE(0x4072), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ LDJ_DEVICE(0xb013), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ LDJ_DEVICE(0xb018), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ LDJ_DEVICE(0xb01f), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ /* Mouse Logitech MX Anywhere 2S */
LDJ_DEVICE(0x406a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ /* Mouse Logitech MX Master */
LDJ_DEVICE(0x4041), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ LDJ_DEVICE(0x4060), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ LDJ_DEVICE(0x4071), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ /* Mouse Logitech MX Master 2S */
LDJ_DEVICE(0x4069), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ /* Mouse Logitech MX Master 3 */
LDJ_DEVICE(0x4082), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ /* Mouse Logitech Performance MX */
LDJ_DEVICE(0x101a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 },
{ /* Keyboard logitech K400 */ { /* Keyboard logitech K400 */
LDJ_DEVICE(0x4024), LDJ_DEVICE(0x4024),
.driver_data = HIDPP_QUIRK_CLASS_K400 }, .driver_data = HIDPP_QUIRK_CLASS_K400 },
...@@ -4335,18 +4367,9 @@ static const struct hid_device_id hidpp_devices[] = { ...@@ -4335,18 +4367,9 @@ static const struct hid_device_id hidpp_devices[] = {
{ /* MX5500 keyboard over Bluetooth */ { /* MX5500 keyboard over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b), HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b),
.driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
{ /* M-RCQ142 V470 Cordless Laser Mouse over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb008) }, { /* And try to enable HID++ for all the Logitech Bluetooth devices */
{ /* MX Master mouse over Bluetooth */ HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_ANY, USB_VENDOR_ID_LOGITECH, HID_ANY_ID) },
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb012),
.driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ /* MX Ergo trackball over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01d) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01e),
.driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{ /* MX Master 3 mouse over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb023),
.driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 },
{} {}
}; };
...@@ -4360,6 +4383,7 @@ static const struct hid_usage_id hidpp_usages[] = { ...@@ -4360,6 +4383,7 @@ static const struct hid_usage_id hidpp_usages[] = {
static struct hid_driver hidpp_driver = { static struct hid_driver hidpp_driver = {
.name = "logitech-hidpp-device", .name = "logitech-hidpp-device",
.id_table = hidpp_devices, .id_table = hidpp_devices,
.match = hidpp_match,
.report_fixup = hidpp_report_fixup, .report_fixup = hidpp_report_fixup,
.probe = hidpp_probe, .probe = hidpp_probe,
.remove = hidpp_remove, .remove = hidpp_remove,
......
...@@ -1186,7 +1186,7 @@ static void mt_touch_report(struct hid_device *hid, ...@@ -1186,7 +1186,7 @@ static void mt_touch_report(struct hid_device *hid,
int contact_count = -1; int contact_count = -1;
/* sticky fingers release in progress, abort */ /* sticky fingers release in progress, abort */
if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags)) if (test_and_set_bit_lock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
return; return;
scantime = *app->scantime; scantime = *app->scantime;
...@@ -1267,7 +1267,7 @@ static void mt_touch_report(struct hid_device *hid, ...@@ -1267,7 +1267,7 @@ static void mt_touch_report(struct hid_device *hid,
del_timer(&td->release_timer); del_timer(&td->release_timer);
} }
clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags); clear_bit_unlock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
} }
static int mt_touch_input_configured(struct hid_device *hdev, static int mt_touch_input_configured(struct hid_device *hdev,
...@@ -1699,11 +1699,11 @@ static void mt_expired_timeout(struct timer_list *t) ...@@ -1699,11 +1699,11 @@ static void mt_expired_timeout(struct timer_list *t)
* An input report came in just before we release the sticky fingers, * An input report came in just before we release the sticky fingers,
* it will take care of the sticky fingers. * it will take care of the sticky fingers.
*/ */
if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags)) if (test_and_set_bit_lock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))
return; return;
if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags)) if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
mt_release_contacts(hdev); mt_release_contacts(hdev);
clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags); clear_bit_unlock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
} }
static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
......
...@@ -760,12 +760,31 @@ static int joycon_read_stick_calibration(struct joycon_ctlr *ctlr, u16 cal_addr, ...@@ -760,12 +760,31 @@ static int joycon_read_stick_calibration(struct joycon_ctlr *ctlr, u16 cal_addr,
cal_y->max = cal_y->center + y_max_above; cal_y->max = cal_y->center + y_max_above;
cal_y->min = cal_y->center - y_min_below; cal_y->min = cal_y->center - y_min_below;
return 0; /* check if calibration values are plausible */
if (cal_x->min >= cal_x->center || cal_x->center >= cal_x->max ||
cal_y->min >= cal_y->center || cal_y->center >= cal_y->max)
ret = -EINVAL;
return ret;
} }
static const u16 DFLT_STICK_CAL_CEN = 2000; static const u16 DFLT_STICK_CAL_CEN = 2000;
static const u16 DFLT_STICK_CAL_MAX = 3500; static const u16 DFLT_STICK_CAL_MAX = 3500;
static const u16 DFLT_STICK_CAL_MIN = 500; static const u16 DFLT_STICK_CAL_MIN = 500;
static void joycon_use_default_calibration(struct hid_device *hdev,
struct joycon_stick_cal *cal_x,
struct joycon_stick_cal *cal_y,
const char *stick, int ret)
{
hid_warn(hdev,
"Failed to read %s stick cal, using defaults; e=%d\n",
stick, ret);
cal_x->center = cal_y->center = DFLT_STICK_CAL_CEN;
cal_x->max = cal_y->max = DFLT_STICK_CAL_MAX;
cal_x->min = cal_y->min = DFLT_STICK_CAL_MIN;
}
static int joycon_request_calibration(struct joycon_ctlr *ctlr) static int joycon_request_calibration(struct joycon_ctlr *ctlr)
{ {
u16 left_stick_addr = JC_CAL_FCT_DATA_LEFT_ADDR; u16 left_stick_addr = JC_CAL_FCT_DATA_LEFT_ADDR;
...@@ -793,38 +812,24 @@ static int joycon_request_calibration(struct joycon_ctlr *ctlr) ...@@ -793,38 +812,24 @@ static int joycon_request_calibration(struct joycon_ctlr *ctlr)
&ctlr->left_stick_cal_x, &ctlr->left_stick_cal_x,
&ctlr->left_stick_cal_y, &ctlr->left_stick_cal_y,
true); true);
if (ret) {
hid_warn(ctlr->hdev,
"Failed to read left stick cal, using dflts; e=%d\n",
ret);
ctlr->left_stick_cal_x.center = DFLT_STICK_CAL_CEN; if (ret)
ctlr->left_stick_cal_x.max = DFLT_STICK_CAL_MAX; joycon_use_default_calibration(ctlr->hdev,
ctlr->left_stick_cal_x.min = DFLT_STICK_CAL_MIN; &ctlr->left_stick_cal_x,
&ctlr->left_stick_cal_y,
ctlr->left_stick_cal_y.center = DFLT_STICK_CAL_CEN; "left", ret);
ctlr->left_stick_cal_y.max = DFLT_STICK_CAL_MAX;
ctlr->left_stick_cal_y.min = DFLT_STICK_CAL_MIN;
}
/* read the right stick calibration data */ /* read the right stick calibration data */
ret = joycon_read_stick_calibration(ctlr, right_stick_addr, ret = joycon_read_stick_calibration(ctlr, right_stick_addr,
&ctlr->right_stick_cal_x, &ctlr->right_stick_cal_x,
&ctlr->right_stick_cal_y, &ctlr->right_stick_cal_y,
false); false);
if (ret) {
hid_warn(ctlr->hdev,
"Failed to read right stick cal, using dflts; e=%d\n",
ret);
ctlr->right_stick_cal_x.center = DFLT_STICK_CAL_CEN;
ctlr->right_stick_cal_x.max = DFLT_STICK_CAL_MAX;
ctlr->right_stick_cal_x.min = DFLT_STICK_CAL_MIN;
ctlr->right_stick_cal_y.center = DFLT_STICK_CAL_CEN; if (ret)
ctlr->right_stick_cal_y.max = DFLT_STICK_CAL_MAX; joycon_use_default_calibration(ctlr->hdev,
ctlr->right_stick_cal_y.min = DFLT_STICK_CAL_MIN; &ctlr->right_stick_cal_x,
} &ctlr->right_stick_cal_y,
"right", ret);
hid_dbg(ctlr->hdev, "calibration:\n" hid_dbg(ctlr->hdev, "calibration:\n"
"l_x_c=%d l_x_max=%d l_x_min=%d\n" "l_x_c=%d l_x_max=%d l_x_min=%d\n"
...@@ -1904,9 +1909,8 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr) ...@@ -1904,9 +1909,8 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr)
/* Set the home LED to 0 as default state */ /* Set the home LED to 0 as default state */
ret = joycon_home_led_brightness_set(led, 0); ret = joycon_home_led_brightness_set(led, 0);
if (ret) { if (ret) {
hid_err(hdev, "Failed to set home LED dflt; ret=%d\n", hid_warn(hdev, "Failed to set home LED default, unregistering home LED");
ret); devm_led_classdev_unregister(&hdev->dev, led);
return ret;
} }
} }
......
...@@ -692,15 +692,12 @@ static ssize_t hardware_version_show(struct device *dev, ...@@ -692,15 +692,12 @@ static ssize_t hardware_version_show(struct device *dev,
static DEVICE_ATTR_RO(hardware_version); static DEVICE_ATTR_RO(hardware_version);
static struct attribute *ps_device_attributes[] = { static struct attribute *ps_device_attrs[] = {
&dev_attr_firmware_version.attr, &dev_attr_firmware_version.attr,
&dev_attr_hardware_version.attr, &dev_attr_hardware_version.attr,
NULL NULL
}; };
ATTRIBUTE_GROUPS(ps_device);
static const struct attribute_group ps_device_attribute_group = {
.attrs = ps_device_attributes,
};
static int dualsense_get_calibration_data(struct dualsense *ds) static int dualsense_get_calibration_data(struct dualsense *ds)
{ {
...@@ -1448,12 +1445,6 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1448,12 +1445,6 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id)
} }
} }
ret = devm_device_add_group(&hdev->dev, &ps_device_attribute_group);
if (ret) {
hid_err(hdev, "Failed to register sysfs nodes.\n");
goto err_close;
}
return ret; return ret;
err_close: err_close:
...@@ -1487,6 +1478,9 @@ static struct hid_driver ps_driver = { ...@@ -1487,6 +1478,9 @@ static struct hid_driver ps_driver = {
.probe = ps_probe, .probe = ps_probe,
.remove = ps_remove, .remove = ps_remove,
.raw_event = ps_raw_event, .raw_event = ps_raw_event,
.driver = {
.dev_groups = ps_device_groups,
},
}; };
static int __init ps_init(void) static int __init ps_init(void)
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* HID driver for PhoenixRC 8-axis flight controller
*
* Copyright (C) 2022 Marcus Folkesson <marcus.folkesson@gmail.com>
*/
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
struct pxrc_priv {
u8 slider;
u8 dial;
bool alternate;
};
static __u8 pxrc_rdesc_fixed[] = {
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x04, // Usage (Joystick)
0xA1, 0x01, // Collection (Application)
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
0x09, 0x30, // Usage (X)
0x09, 0x36, // Usage (Slider)
0x09, 0x31, // Usage (Y)
0x09, 0x32, // Usage (Z)
0x09, 0x33, // Usage (Rx)
0x09, 0x34, // Usage (Ry)
0x09, 0x35, // Usage (Rz)
0x09, 0x37, // Usage (Dial)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x35, 0x00, // Physical Minimum (0)
0x46, 0xFF, 0x00, // Physical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x08, // Report Count (8)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0xC0, // End Collection
};
static __u8 *pxrc_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
hid_info(hdev, "fixing up PXRC report descriptor\n");
*rsize = sizeof(pxrc_rdesc_fixed);
return pxrc_rdesc_fixed;
}
static int pxrc_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *data, int size)
{
struct pxrc_priv *priv = hid_get_drvdata(hdev);
if (priv->alternate)
priv->slider = data[7];
else
priv->dial = data[7];
data[1] = priv->slider;
data[7] = priv->dial;
priv->alternate = !priv->alternate;
return 0;
}
static int pxrc_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret;
struct pxrc_priv *priv;
priv = devm_kzalloc(&hdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
hid_set_drvdata(hdev, priv);
ret = hid_parse(hdev);
if (ret) {
hid_err(hdev, "parse failed\n");
return ret;
}
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret) {
hid_err(hdev, "hw start failed\n");
return ret;
}
return 0;
}
static const struct hid_device_id pxrc_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_PHOENIXRC) },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(hid, pxrc_devices);
static struct hid_driver pxrc_driver = {
.name = "hid-pxrc",
.id_table = pxrc_devices,
.report_fixup = pxrc_report_fixup,
.probe = pxrc_probe,
.raw_event = pxrc_raw_event,
};
module_hid_driver(pxrc_driver);
MODULE_AUTHOR("Marcus Folkesson <marcus.folkesson@gmail.com>");
MODULE_DESCRIPTION("HID driver for PXRC 8-axis flight controller");
MODULE_LICENSE("GPL");
...@@ -237,8 +237,7 @@ static int rmi_hid_read_block(struct rmi_transport_dev *xport, u16 addr, ...@@ -237,8 +237,7 @@ static int rmi_hid_read_block(struct rmi_transport_dev *xport, u16 addr,
read_input_count = data->readReport[1]; read_input_count = data->readReport[1];
memcpy(buf + bytes_read, &data->readReport[2], memcpy(buf + bytes_read, &data->readReport[2],
read_input_count < bytes_needed ? min(read_input_count, bytes_needed));
read_input_count : bytes_needed);
bytes_read += read_input_count; bytes_read += read_input_count;
bytes_needed -= read_input_count; bytes_needed -= read_input_count;
...@@ -347,8 +346,7 @@ static int rmi_read_data_event(struct hid_device *hdev, u8 *data, int size) ...@@ -347,8 +346,7 @@ static int rmi_read_data_event(struct hid_device *hdev, u8 *data, int size)
return 0; return 0;
} }
memcpy(hdata->readReport, data, size < hdata->input_report_size ? memcpy(hdata->readReport, data, min((u32)size, hdata->input_report_size));
size : hdata->input_report_size);
set_bit(RMI_READ_DATA_PENDING, &hdata->flags); set_bit(RMI_READ_DATA_PENDING, &hdata->flags);
wake_up(&hdata->wait); wake_up(&hdata->wait);
......
...@@ -257,6 +257,8 @@ int roccat_report_event(int minor, u8 const *data) ...@@ -257,6 +257,8 @@ int roccat_report_event(int minor, u8 const *data)
if (!new_value) if (!new_value)
return -ENOMEM; return -ENOMEM;
mutex_lock(&device->cbuf_lock);
report = &device->cbuf[device->cbuf_end]; report = &device->cbuf[device->cbuf_end];
/* passing NULL is safe */ /* passing NULL is safe */
...@@ -276,6 +278,8 @@ int roccat_report_event(int minor, u8 const *data) ...@@ -276,6 +278,8 @@ int roccat_report_event(int minor, u8 const *data)
reader->cbuf_start = (reader->cbuf_start + 1) % ROCCAT_CBUF_SIZE; reader->cbuf_start = (reader->cbuf_start + 1) % ROCCAT_CBUF_SIZE;
} }
mutex_unlock(&device->cbuf_lock);
wake_up_interruptible(&device->wait); wake_up_interruptible(&device->wait);
return 0; return 0;
} }
......
...@@ -368,7 +368,7 @@ static const unsigned int buzz_keymap[] = { ...@@ -368,7 +368,7 @@ static const unsigned int buzz_keymap[] = {
}; };
/* The Navigation controller is a partial DS3 and uses the same HID report /* The Navigation controller is a partial DS3 and uses the same HID report
* and hence the same keymap indices, however not not all axes/buttons * and hence the same keymap indices, however not all axes/buttons
* are physically present. We use the same axis and button mapping as * are physically present. We use the same axis and button mapping as
* the DS3, which uses the Linux gamepad spec. * the DS3, which uses the Linux gamepad spec.
*/ */
......
...@@ -256,7 +256,7 @@ static int steam_get_serial(struct steam_device *steam) ...@@ -256,7 +256,7 @@ static int steam_get_serial(struct steam_device *steam)
if (reply[0] != 0xae || reply[1] != 0x15 || reply[2] != 0x01) if (reply[0] != 0xae || reply[1] != 0x15 || reply[2] != 0x01)
return -EIO; return -EIO;
reply[3 + STEAM_SERIAL_LEN] = 0; reply[3 + STEAM_SERIAL_LEN] = 0;
strlcpy(steam->serial_no, reply + 3, sizeof(steam->serial_no)); strscpy(steam->serial_no, reply + 3, sizeof(steam->serial_no));
return 0; return 0;
} }
...@@ -524,7 +524,7 @@ static int steam_register(struct steam_device *steam) ...@@ -524,7 +524,7 @@ static int steam_register(struct steam_device *steam)
*/ */
mutex_lock(&steam->mutex); mutex_lock(&steam->mutex);
if (steam_get_serial(steam) < 0) if (steam_get_serial(steam) < 0)
strlcpy(steam->serial_no, "XXXXXXXXXX", strscpy(steam->serial_no, "XXXXXXXXXX",
sizeof(steam->serial_no)); sizeof(steam->serial_no));
mutex_unlock(&steam->mutex); mutex_unlock(&steam->mutex);
...@@ -699,9 +699,9 @@ static struct hid_device *steam_create_client_hid(struct hid_device *hdev) ...@@ -699,9 +699,9 @@ static struct hid_device *steam_create_client_hid(struct hid_device *hdev)
client_hdev->version = hdev->version; client_hdev->version = hdev->version;
client_hdev->type = hdev->type; client_hdev->type = hdev->type;
client_hdev->country = hdev->country; client_hdev->country = hdev->country;
strlcpy(client_hdev->name, hdev->name, strscpy(client_hdev->name, hdev->name,
sizeof(client_hdev->name)); sizeof(client_hdev->name));
strlcpy(client_hdev->phys, hdev->phys, strscpy(client_hdev->phys, hdev->phys,
sizeof(client_hdev->phys)); sizeof(client_hdev->phys));
/* /*
* Since we use the same device info than the real interface to * Since we use the same device info than the real interface to
......
// SPDX-License-Identifier: GPL-2.0+
/*
* HID driver for Topre REALFORCE Keyboards
*
* Copyright (c) 2022 Harry Stern <harry@harrystern.net>
*
* Based on the hid-macally driver
*/
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
MODULE_AUTHOR("Harry Stern <harry@harrystern.net>");
MODULE_DESCRIPTION("REALFORCE R2 Keyboard driver");
MODULE_LICENSE("GPL");
/*
* Fix the REALFORCE R2's non-boot interface's report descriptor to match the
* events it's actually sending. It claims to send array events but is instead
* sending variable events.
*/
static __u8 *topre_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
if (*rsize >= 119 && rdesc[69] == 0x29 && rdesc[70] == 0xe7 &&
rdesc[71] == 0x81 && rdesc[72] == 0x00) {
hid_info(hdev,
"fixing up Topre REALFORCE keyboard report descriptor\n");
rdesc[72] = 0x02;
}
return rdesc;
}
static const struct hid_device_id topre_id_table[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPRE,
USB_DEVICE_ID_TOPRE_REALFORCE_R2_108) },
{ }
};
MODULE_DEVICE_TABLE(hid, topre_id_table);
static struct hid_driver topre_driver = {
.name = "topre",
.id_table = topre_id_table,
.report_fixup = topre_report_fixup,
};
module_hid_driver(topre_driver);
...@@ -153,6 +153,7 @@ static int uclogic_input_configured(struct hid_device *hdev, ...@@ -153,6 +153,7 @@ static int uclogic_input_configured(struct hid_device *hdev,
suffix = "Pad"; suffix = "Pad";
break; break;
case HID_DG_PEN: case HID_DG_PEN:
case HID_DG_DIGITIZER:
suffix = "Pen"; suffix = "Pen";
break; break;
case HID_CP_CONSUMER_CONTROL: case HID_CP_CONSUMER_CONTROL:
...@@ -509,6 +510,8 @@ static const struct hid_device_id uclogic_devices[] = { ...@@ -509,6 +510,8 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UGTIZER_TABLET_GP0610) }, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER,
USB_DEVICE_ID_UGTIZER_TABLET_GT5040) }, USB_DEVICE_ID_UGTIZER_TABLET_GT5040) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_PARBLO_A610_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_TABLET_G5) }, USB_DEVICE_ID_UGEE_TABLET_G5) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
...@@ -523,6 +526,8 @@ static const struct hid_device_id uclogic_devices[] = { ...@@ -523,6 +526,8 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01) }, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) }, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06) }, USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06) },
{ } { }
......
// SPDX-License-Identifier: GPL-2.0+
/*
* HID driver for UC-Logic devices not fully compliant with HID standard
*
* Copyright (c) 2022 José Expósito <jose.exposito89@gmail.com>
*/
#include <kunit/test.h>
#include "./hid-uclogic-params.h"
#include "./hid-uclogic-rdesc.h"
#define MAX_STR_DESC_SIZE 14
struct uclogic_parse_ugee_v2_desc_case {
const char *name;
int res;
const __u8 str_desc[MAX_STR_DESC_SIZE];
size_t str_desc_size;
const s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
enum uclogic_params_frame_type frame_type;
};
static struct uclogic_parse_ugee_v2_desc_case uclogic_parse_ugee_v2_desc_cases[] = {
{
.name = "invalid_str_desc",
.res = -EINVAL,
.str_desc = {},
.str_desc_size = 0,
.desc_params = {},
.frame_type = UCLOGIC_PARAMS_FRAME_BUTTONS,
},
{
.name = "resolution_with_value_0",
.res = 0,
.str_desc = {
0x0E, 0x03,
0x70, 0xB2,
0x10, 0x77,
0x08,
0x00,
0xFF, 0x1F,
0x00, 0x00,
},
.str_desc_size = 12,
.desc_params = {
[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 0xB270,
[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0,
[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 0x7710,
[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0,
[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF,
[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x08,
},
.frame_type = UCLOGIC_PARAMS_FRAME_BUTTONS,
},
/* XP-PEN Deco L str_desc: Frame with 8 buttons */
{
.name = "frame_type_buttons",
.res = 0,
.str_desc = {
0x0E, 0x03,
0x70, 0xB2,
0x10, 0x77,
0x08,
0x00,
0xFF, 0x1F,
0xD8, 0x13,
},
.str_desc_size = 12,
.desc_params = {
[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 0xB270,
[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0x2320,
[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 0x7710,
[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0x1770,
[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF,
[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x08,
},
.frame_type = UCLOGIC_PARAMS_FRAME_BUTTONS,
},
/* PARBLO A610 PRO str_desc: Frame with 9 buttons and dial */
{
.name = "frame_type_dial",
.res = 0,
.str_desc = {
0x0E, 0x03,
0x96, 0xC7,
0xF9, 0x7C,
0x09,
0x01,
0xFF, 0x1F,
0xD8, 0x13,
},
.str_desc_size = 12,
.desc_params = {
[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 0xC796,
[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0x2749,
[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 0x7CF9,
[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0x1899,
[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF,
[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x09,
},
.frame_type = UCLOGIC_PARAMS_FRAME_DIAL,
},
/* XP-PEN Deco Pro S str_desc: Frame with 8 buttons and mouse */
{
.name = "frame_type_mouse",
.res = 0,
.str_desc = {
0x0E, 0x03,
0xC8, 0xB3,
0x34, 0x65,
0x08,
0x02,
0xFF, 0x1F,
0xD8, 0x13,
},
.str_desc_size = 12,
.desc_params = {
[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 0xB3C8,
[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0x2363,
[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 0x6534,
[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0x13EC,
[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF,
[UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x08,
},
.frame_type = UCLOGIC_PARAMS_FRAME_MOUSE,
},
};
static void uclogic_parse_ugee_v2_desc_case_desc(struct uclogic_parse_ugee_v2_desc_case *t,
char *desc)
{
strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE);
}
KUNIT_ARRAY_PARAM(uclogic_parse_ugee_v2_desc, uclogic_parse_ugee_v2_desc_cases,
uclogic_parse_ugee_v2_desc_case_desc);
static void uclogic_parse_ugee_v2_desc_test(struct kunit *test)
{
int res;
s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
enum uclogic_params_frame_type frame_type;
const struct uclogic_parse_ugee_v2_desc_case *params = test->param_value;
res = uclogic_params_parse_ugee_v2_desc(params->str_desc,
params->str_desc_size,
desc_params,
ARRAY_SIZE(desc_params),
&frame_type);
KUNIT_ASSERT_EQ(test, res, params->res);
if (res)
return;
KUNIT_EXPECT_EQ(test,
params->desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM],
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM]);
KUNIT_EXPECT_EQ(test,
params->desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM],
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM]);
KUNIT_EXPECT_EQ(test,
params->desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM],
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM]);
KUNIT_EXPECT_EQ(test,
params->desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM],
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM]);
KUNIT_EXPECT_EQ(test,
params->desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM],
desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM]);
KUNIT_EXPECT_EQ(test,
params->desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM],
desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM]);
KUNIT_EXPECT_EQ(test, params->frame_type, frame_type);
}
static struct kunit_case hid_uclogic_params_test_cases[] = {
KUNIT_CASE_PARAM(uclogic_parse_ugee_v2_desc_test,
uclogic_parse_ugee_v2_desc_gen_params),
{}
};
static struct kunit_suite hid_uclogic_params_test_suite = {
.name = "hid_uclogic_params_test",
.test_cases = hid_uclogic_params_test_cases,
};
kunit_test_suite(hid_uclogic_params_test_suite);
MODULE_DESCRIPTION("KUnit tests for the UC-Logic driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("José Expósito <jose.exposito89@gmail.com>");
...@@ -1056,6 +1056,161 @@ static int uclogic_probe_interface(struct hid_device *hdev, u8 *magic_arr, ...@@ -1056,6 +1056,161 @@ static int uclogic_probe_interface(struct hid_device *hdev, u8 *magic_arr,
return rc; return rc;
} }
/**
* uclogic_params_parse_ugee_v2_desc - parse the string descriptor containing
* pen and frame parameters returned by UGEE v2 devices.
*
* @str_desc: String descriptor, cannot be NULL.
* @str_desc_size: Size of the string descriptor.
* @desc_params: Output description params list.
* @desc_params_size: Size of the output description params list.
* @frame_type: Output frame type.
*
* Returns:
* Zero, if successful. A negative errno code on error.
*/
static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc,
size_t str_desc_size,
s32 *desc_params,
size_t desc_params_size,
enum uclogic_params_frame_type *frame_type)
{
s32 pen_x_lm, pen_y_lm;
s32 pen_x_pm, pen_y_pm;
s32 pen_pressure_lm;
s32 frame_num_buttons;
s32 resolution;
/* Minimum descriptor length required, maximum seen so far is 14 */
const int min_str_desc_size = 12;
if (!str_desc || str_desc_size < min_str_desc_size)
return -EINVAL;
if (desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
return -EINVAL;
pen_x_lm = get_unaligned_le16(str_desc + 2);
pen_y_lm = get_unaligned_le16(str_desc + 4);
frame_num_buttons = str_desc[6];
*frame_type = str_desc[7];
pen_pressure_lm = get_unaligned_le16(str_desc + 8);
resolution = get_unaligned_le16(str_desc + 10);
if (resolution == 0) {
pen_x_pm = 0;
pen_y_pm = 0;
} else {
pen_x_pm = pen_x_lm * 1000 / resolution;
pen_y_pm = pen_y_lm * 1000 / resolution;
}
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = pen_x_lm;
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = pen_x_pm;
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = pen_y_lm;
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = pen_y_pm;
desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = pen_pressure_lm;
desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = frame_num_buttons;
return 0;
}
/**
* uclogic_params_ugee_v2_init_frame_buttons() - initialize a UGEE v2 frame with
* buttons.
* @p: Parameters to fill in, cannot be NULL.
* @desc_params: Device description params list.
* @desc_params_size: Size of the description params list.
*
* Returns:
* Zero, if successful. A negative errno code on error.
*/
static int uclogic_params_ugee_v2_init_frame_buttons(struct uclogic_params *p,
const s32 *desc_params,
size_t desc_params_size)
{
__u8 *rdesc_frame = NULL;
int rc = 0;
if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
return -EINVAL;
rdesc_frame = uclogic_rdesc_template_apply(
uclogic_rdesc_ugee_v2_frame_btn_template_arr,
uclogic_rdesc_ugee_v2_frame_btn_template_size,
desc_params, UCLOGIC_RDESC_PH_ID_NUM);
if (!rdesc_frame)
return -ENOMEM;
rc = uclogic_params_frame_init_with_desc(&p->frame_list[0],
rdesc_frame,
uclogic_rdesc_ugee_v2_frame_btn_template_size,
UCLOGIC_RDESC_V1_FRAME_ID);
kfree(rdesc_frame);
return rc;
}
/**
* uclogic_params_ugee_v2_init_frame_dial() - initialize a UGEE v2 frame with a
* bitmap dial.
* @p: Parameters to fill in, cannot be NULL.
* @desc_params: Device description params list.
* @desc_params_size: Size of the description params list.
*
* Returns:
* Zero, if successful. A negative errno code on error.
*/
static int uclogic_params_ugee_v2_init_frame_dial(struct uclogic_params *p,
const s32 *desc_params,
size_t desc_params_size)
{
__u8 *rdesc_frame = NULL;
int rc = 0;
if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM)
return -EINVAL;
rdesc_frame = uclogic_rdesc_template_apply(
uclogic_rdesc_ugee_v2_frame_dial_template_arr,
uclogic_rdesc_ugee_v2_frame_dial_template_size,
desc_params, UCLOGIC_RDESC_PH_ID_NUM);
if (!rdesc_frame)
return -ENOMEM;
rc = uclogic_params_frame_init_with_desc(&p->frame_list[0],
rdesc_frame,
uclogic_rdesc_ugee_v2_frame_dial_template_size,
UCLOGIC_RDESC_V1_FRAME_ID);
kfree(rdesc_frame);
if (rc)
return rc;
p->frame_list[0].bitmap_dial_byte = 7;
return 0;
}
/**
* uclogic_params_ugee_v2_init_frame_mouse() - initialize a UGEE v2 frame with a
* mouse.
* @p: Parameters to fill in, cannot be NULL.
*
* Returns:
* Zero, if successful. A negative errno code on error.
*/
static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p)
{
int rc = 0;
if (!p)
return -EINVAL;
rc = uclogic_params_frame_init_with_desc(&p->frame_list[1],
uclogic_rdesc_ugee_v2_frame_mouse_template_arr,
uclogic_rdesc_ugee_v2_frame_mouse_template_size,
UCLOGIC_RDESC_V1_FRAME_ID);
return rc;
}
/** /**
* uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by
* discovering their parameters. * discovering their parameters.
...@@ -1084,9 +1239,8 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, ...@@ -1084,9 +1239,8 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
const int str_desc_len = 12; const int str_desc_len = 12;
__u8 *str_desc = NULL; __u8 *str_desc = NULL;
__u8 *rdesc_pen = NULL; __u8 *rdesc_pen = NULL;
__u8 *rdesc_frame = NULL;
s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
s32 resolution; enum uclogic_params_frame_type frame_type;
__u8 magic_arr[] = { __u8 magic_arr[] = {
0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; };
...@@ -1100,6 +1254,15 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, ...@@ -1100,6 +1254,15 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
iface = to_usb_interface(hdev->dev.parent); iface = to_usb_interface(hdev->dev.parent);
bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber;
if (bInterfaceNumber == 0) {
rc = uclogic_params_ugee_v2_init_frame_mouse(&p);
if (rc)
goto cleanup;
goto output;
}
if (bInterfaceNumber != 2) { if (bInterfaceNumber != 2) {
uclogic_params_init_invalid(&p); uclogic_params_init_invalid(&p);
goto output; goto output;
...@@ -1128,25 +1291,13 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, ...@@ -1128,25 +1291,13 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
goto output; goto output;
} }
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len,
get_unaligned_le16(str_desc + 2); desc_params,
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = ARRAY_SIZE(desc_params),
get_unaligned_le16(str_desc + 4); &frame_type);
desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = str_desc[6]; if (rc)
desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = goto cleanup;
get_unaligned_le16(str_desc + 8);
resolution = get_unaligned_le16(str_desc + 10);
if (resolution == 0) {
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0;
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0;
} else {
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] =
desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 /
resolution;
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] =
desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 /
resolution;
}
kfree(str_desc); kfree(str_desc);
str_desc = NULL; str_desc = NULL;
...@@ -1167,24 +1318,21 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, ...@@ -1167,24 +1318,21 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID; p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID;
/* Initialize the frame interface */ /* Initialize the frame interface */
rdesc_frame = uclogic_rdesc_template_apply( switch (frame_type) {
uclogic_rdesc_ugee_v2_frame_btn_template_arr, case UCLOGIC_PARAMS_FRAME_DIAL:
uclogic_rdesc_ugee_v2_frame_btn_template_size, case UCLOGIC_PARAMS_FRAME_MOUSE:
desc_params, ARRAY_SIZE(desc_params)); rc = uclogic_params_ugee_v2_init_frame_dial(&p, desc_params,
if (!rdesc_frame) { ARRAY_SIZE(desc_params));
rc = -ENOMEM; break;
goto cleanup; case UCLOGIC_PARAMS_FRAME_BUTTONS:
default:
rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params,
ARRAY_SIZE(desc_params));
break;
} }
rc = uclogic_params_frame_init_with_desc(&p.frame_list[0], if (rc)
rdesc_frame, goto cleanup;
uclogic_rdesc_ugee_v2_frame_btn_template_size,
UCLOGIC_RDESC_V1_FRAME_ID);
kfree(rdesc_frame);
if (rc) {
uclogic_params_init_invalid(&p);
goto output;
}
output: output:
/* Output parameters */ /* Output parameters */
...@@ -1432,8 +1580,12 @@ int uclogic_params_init(struct uclogic_params *params, ...@@ -1432,8 +1580,12 @@ int uclogic_params_init(struct uclogic_params *params,
uclogic_params_init_invalid(&p); uclogic_params_init_invalid(&p);
} }
break; break;
case VID_PID(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_PARBLO_A610_PRO):
case VID_PID(USB_VENDOR_ID_UGEE, case VID_PID(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L): USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L):
case VID_PID(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S):
rc = uclogic_params_ugee_v2_init(&p, hdev); rc = uclogic_params_ugee_v2_init(&p, hdev);
if (rc != 0) if (rc != 0)
goto cleanup; goto cleanup;
...@@ -1517,3 +1669,7 @@ int uclogic_params_init(struct uclogic_params *params, ...@@ -1517,3 +1669,7 @@ int uclogic_params_init(struct uclogic_params *params,
uclogic_params_cleanup(&p); uclogic_params_cleanup(&p);
return rc; return rc;
} }
#ifdef CONFIG_HID_KUNIT_TEST
#include "hid-uclogic-params-test.c"
#endif
...@@ -29,6 +29,16 @@ enum uclogic_params_pen_inrange { ...@@ -29,6 +29,16 @@ enum uclogic_params_pen_inrange {
UCLOGIC_PARAMS_PEN_INRANGE_NONE, UCLOGIC_PARAMS_PEN_INRANGE_NONE,
}; };
/* Types of frames */
enum uclogic_params_frame_type {
/* Frame with buttons */
UCLOGIC_PARAMS_FRAME_BUTTONS = 0,
/* Frame with buttons and a dial */
UCLOGIC_PARAMS_FRAME_DIAL,
/* Frame with buttons and a mouse (shaped as a dial + touchpad) */
UCLOGIC_PARAMS_FRAME_MOUSE,
};
/* /*
* Pen report's subreport data. * Pen report's subreport data.
*/ */
......
...@@ -97,7 +97,7 @@ static const __u8 template_params_none[] = { ...@@ -97,7 +97,7 @@ static const __u8 template_params_none[] = {
static struct uclogic_template_case uclogic_template_cases[] = { static struct uclogic_template_case uclogic_template_cases[] = {
{ {
.name = "Empty template", .name = "empty_template",
.template = template_empty, .template = template_empty,
.template_size = sizeof(template_empty), .template_size = sizeof(template_empty),
.param_list = params_pen_all, .param_list = params_pen_all,
...@@ -105,7 +105,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { ...@@ -105,7 +105,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.expected = template_empty, .expected = template_empty,
}, },
{ {
.name = "Template smaller than the placeholder", .name = "template_smaller_than_the_placeholder",
.template = template_small, .template = template_small,
.template_size = sizeof(template_small), .template_size = sizeof(template_small),
.param_list = params_pen_all, .param_list = params_pen_all,
...@@ -113,7 +113,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { ...@@ -113,7 +113,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.expected = template_small, .expected = template_small,
}, },
{ {
.name = "No placeholder", .name = "no_placeholder",
.template = template_no_ph, .template = template_no_ph,
.template_size = sizeof(template_no_ph), .template_size = sizeof(template_no_ph),
.param_list = params_pen_all, .param_list = params_pen_all,
...@@ -121,7 +121,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { ...@@ -121,7 +121,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.expected = template_no_ph, .expected = template_no_ph,
}, },
{ {
.name = "Pen placeholder at the end, without ID", .name = "pen_placeholder_at_the_end_without_id",
.template = template_pen_ph_end, .template = template_pen_ph_end,
.template_size = sizeof(template_pen_ph_end), .template_size = sizeof(template_pen_ph_end),
.param_list = params_pen_all, .param_list = params_pen_all,
...@@ -129,7 +129,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { ...@@ -129,7 +129,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.expected = template_pen_ph_end, .expected = template_pen_ph_end,
}, },
{ {
.name = "Frame button placeholder at the end, without ID", .name = "frame_button_placeholder_at_the_end_without_id",
.template = template_btn_ph_end, .template = template_btn_ph_end,
.template_size = sizeof(template_btn_ph_end), .template_size = sizeof(template_btn_ph_end),
.param_list = params_frame_all, .param_list = params_frame_all,
...@@ -137,7 +137,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { ...@@ -137,7 +137,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.expected = template_btn_ph_end, .expected = template_btn_ph_end,
}, },
{ {
.name = "All params present in the pen template", .name = "all_params_present_in_the_pen_template",
.template = template_pen_all_params, .template = template_pen_all_params,
.template_size = sizeof(template_pen_all_params), .template_size = sizeof(template_pen_all_params),
.param_list = params_pen_all, .param_list = params_pen_all,
...@@ -145,7 +145,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { ...@@ -145,7 +145,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.expected = expected_pen_all_params, .expected = expected_pen_all_params,
}, },
{ {
.name = "All params present in the frame template", .name = "all_params_present_in_the_frame_template",
.template = template_frame_all_params, .template = template_frame_all_params,
.template_size = sizeof(template_frame_all_params), .template_size = sizeof(template_frame_all_params),
.param_list = params_frame_all, .param_list = params_frame_all,
...@@ -153,7 +153,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { ...@@ -153,7 +153,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.expected = expected_frame_all_params, .expected = expected_frame_all_params,
}, },
{ {
.name = "Some params present in the pen template (complete param list)", .name = "some_params_present_in_the_pen_template_with_complete_param_list",
.template = template_pen_some_params, .template = template_pen_some_params,
.template_size = sizeof(template_pen_some_params), .template_size = sizeof(template_pen_some_params),
.param_list = params_pen_all, .param_list = params_pen_all,
...@@ -161,7 +161,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { ...@@ -161,7 +161,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.expected = expected_pen_some_params, .expected = expected_pen_some_params,
}, },
{ {
.name = "Some params present in the pen template (incomplete param list)", .name = "some_params_present_in_the_pen_template_with_incomplete_param_list",
.template = template_pen_some_params, .template = template_pen_some_params,
.template_size = sizeof(template_pen_some_params), .template_size = sizeof(template_pen_some_params),
.param_list = params_pen_some, .param_list = params_pen_some,
...@@ -169,7 +169,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { ...@@ -169,7 +169,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.expected = expected_pen_some_params, .expected = expected_pen_some_params,
}, },
{ {
.name = "No params present in the template", .name = "no_params_present_in_the_template",
.template = template_params_none, .template = template_params_none,
.template_size = sizeof(template_params_none), .template_size = sizeof(template_params_none),
.param_list = params_pen_some, .param_list = params_pen_some,
...@@ -208,7 +208,7 @@ static struct kunit_case hid_uclogic_rdesc_test_cases[] = { ...@@ -208,7 +208,7 @@ static struct kunit_case hid_uclogic_rdesc_test_cases[] = {
}; };
static struct kunit_suite hid_uclogic_rdesc_test_suite = { static struct kunit_suite hid_uclogic_rdesc_test_suite = {
.name = "hid-uclogic-rdesc-test", .name = "hid_uclogic_rdesc_test",
.test_cases = hid_uclogic_rdesc_test_cases, .test_cases = hid_uclogic_rdesc_test_cases,
}; };
......
...@@ -961,6 +961,80 @@ const __u8 uclogic_rdesc_ugee_v2_frame_btn_template_arr[] = { ...@@ -961,6 +961,80 @@ const __u8 uclogic_rdesc_ugee_v2_frame_btn_template_arr[] = {
const size_t uclogic_rdesc_ugee_v2_frame_btn_template_size = const size_t uclogic_rdesc_ugee_v2_frame_btn_template_size =
sizeof(uclogic_rdesc_ugee_v2_frame_btn_template_arr); sizeof(uclogic_rdesc_ugee_v2_frame_btn_template_arr);
/* Fixed report descriptor template for UGEE v2 frame reports (dial) */
const __u8 uclogic_rdesc_ugee_v2_frame_dial_template_arr[] = {
0x05, 0x01, /* Usage Page (Desktop), */
0x09, 0x07, /* Usage (Keypad), */
0xA1, 0x01, /* Collection (Application), */
0x85, UCLOGIC_RDESC_V1_FRAME_ID,
/* Report ID, */
0x05, 0x0D, /* Usage Page (Digitizer), */
0x09, 0x39, /* Usage (Tablet Function Keys), */
0xA0, /* Collection (Physical), */
0x75, 0x01, /* Report Size (1), */
0x95, 0x08, /* Report Count (8), */
0x81, 0x01, /* Input (Constant), */
0x05, 0x09, /* Usage Page (Button), */
0x19, 0x01, /* Usage Minimum (01h), */
UCLOGIC_RDESC_FRAME_PH_BTN,
/* Usage Maximum (PLACEHOLDER), */
0x95, 0x0A, /* Report Count (10), */
0x14, /* Logical Minimum (0), */
0x25, 0x01, /* Logical Maximum (1), */
0x81, 0x02, /* Input (Variable), */
0x95, 0x06, /* Report Count (6), */
0x81, 0x01, /* Input (Constant), */
0x75, 0x08, /* Report Size (8), */
0x95, 0x03, /* Report Count (3), */
0x81, 0x01, /* Input (Constant), */
0x05, 0x01, /* Usage Page (Desktop), */
0x09, 0x38, /* Usage (Wheel), */
0x95, 0x01, /* Report Count (1), */
0x15, 0xFF, /* Logical Minimum (-1), */
0x25, 0x01, /* Logical Maximum (1), */
0x81, 0x06, /* Input (Variable, Relative), */
0x95, 0x02, /* Report Count (2), */
0x81, 0x01, /* Input (Constant), */
0xC0, /* End Collection, */
0xC0 /* End Collection */
};
const size_t uclogic_rdesc_ugee_v2_frame_dial_template_size =
sizeof(uclogic_rdesc_ugee_v2_frame_dial_template_arr);
/* Fixed report descriptor template for UGEE v2 frame reports (mouse) */
const __u8 uclogic_rdesc_ugee_v2_frame_mouse_template_arr[] = {
0x05, 0x01, /* Usage Page (Desktop), */
0x09, 0x02, /* Usage (Mouse), */
0xA1, 0x01, /* Collection (Application), */
0x85, 0x01, /* Report ID (1), */
0x05, 0x01, /* Usage Page (Pointer), */
0xA0, /* Collection (Physical), */
0x75, 0x01, /* Report Size (1), */
0x95, 0x02, /* Report Count (2), */
0x05, 0x09, /* Usage Page (Button), */
0x19, 0x01, /* Usage Minimum (01h), */
0x29, 0x02, /* Usage Maximum (02h), */
0x14, /* Logical Minimum (0), */
0x25, 0x01, /* Logical Maximum (1), */
0x81, 0x02, /* Input (Variable), */
0x95, 0x06, /* Report Count (6), */
0x81, 0x01, /* Input (Constant), */
0x05, 0x01, /* Usage Page (Generic Desktop), */
0x09, 0x30, /* Usage (X), */
0x09, 0x31, /* Usage (Y), */
0x75, 0x10, /* Report Size (16), */
0x95, 0x02, /* Report Count (2), */
0x16, 0x00, 0x80, /* Logical Minimum (-32768), */
0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */
0x81, 0x06, /* Input (Variable, Relative), */
0x95, 0x01, /* Report Count (1), */
0x81, 0x01, /* Input (Constant), */
0xC0, /* End Collection, */
0xC0 /* End Collection */
};
const size_t uclogic_rdesc_ugee_v2_frame_mouse_template_size =
sizeof(uclogic_rdesc_ugee_v2_frame_mouse_template_arr);
/* Fixed report descriptor for Ugee EX07 frame */ /* Fixed report descriptor for Ugee EX07 frame */
const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = { const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = {
0x05, 0x01, /* Usage Page (Desktop), */ 0x05, 0x01, /* Usage Page (Desktop), */
...@@ -1113,7 +1187,7 @@ __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr, ...@@ -1113,7 +1187,7 @@ __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr,
memcmp(p, pen_head, sizeof(pen_head)) == 0 && memcmp(p, pen_head, sizeof(pen_head)) == 0 &&
p[sizeof(pen_head)] < param_num) { p[sizeof(pen_head)] < param_num) {
v = param_list[p[sizeof(pen_head)]]; v = param_list[p[sizeof(pen_head)]];
put_unaligned(cpu_to_le32(v), (s32 *)p); put_unaligned((__force u32)cpu_to_le32(v), (s32 *)p);
p += sizeof(pen_head) + 1; p += sizeof(pen_head) + 1;
} else if (memcmp(p, btn_head, sizeof(btn_head)) == 0 && } else if (memcmp(p, btn_head, sizeof(btn_head)) == 0 &&
p[sizeof(btn_head)] < param_num) { p[sizeof(btn_head)] < param_num) {
......
...@@ -169,6 +169,14 @@ extern const size_t uclogic_rdesc_ugee_v2_pen_template_size; ...@@ -169,6 +169,14 @@ extern const size_t uclogic_rdesc_ugee_v2_pen_template_size;
extern const __u8 uclogic_rdesc_ugee_v2_frame_btn_template_arr[]; extern const __u8 uclogic_rdesc_ugee_v2_frame_btn_template_arr[];
extern const size_t uclogic_rdesc_ugee_v2_frame_btn_template_size; extern const size_t uclogic_rdesc_ugee_v2_frame_btn_template_size;
/* Fixed report descriptor template for UGEE v2 frame reports (dial) */
extern const __u8 uclogic_rdesc_ugee_v2_frame_dial_template_arr[];
extern const size_t uclogic_rdesc_ugee_v2_frame_dial_template_size;
/* Fixed report descriptor template for UGEE v2 frame reports (mouse) */
extern const __u8 uclogic_rdesc_ugee_v2_frame_mouse_template_arr[];
extern const size_t uclogic_rdesc_ugee_v2_frame_mouse_template_size;
/* Fixed report descriptor for Ugee EX07 frame */ /* Fixed report descriptor for Ugee EX07 frame */
extern const __u8 uclogic_rdesc_ugee_ex07_frame_arr[]; extern const __u8 uclogic_rdesc_ugee_ex07_frame_arr[];
extern const size_t uclogic_rdesc_ugee_ex07_frame_size; extern const size_t uclogic_rdesc_ugee_ex07_frame_size;
......
...@@ -116,25 +116,26 @@ static struct attribute *vivaldi_sysfs_attrs[] = { ...@@ -116,25 +116,26 @@ static struct attribute *vivaldi_sysfs_attrs[] = {
NULL NULL
}; };
static const struct attribute_group vivaldi_attribute_group = { static umode_t vivaldi_is_visible(struct kobject *kobj, struct attribute *attr,
.attrs = vivaldi_sysfs_attrs, int n)
};
/**
* vivaldi_input_configured - Complete initialization of device using vivaldi map
* @hdev: HID device to which vivaldi attributes should be attached
* @hidinput: HID input device (unused)
*/
int vivaldi_input_configured(struct hid_device *hdev,
struct hid_input *hidinput)
{ {
struct hid_device *hdev = to_hid_device(kobj_to_dev(kobj));
struct vivaldi_data *data = hid_get_drvdata(hdev); struct vivaldi_data *data = hid_get_drvdata(hdev);
if (!data->num_function_row_keys) if (!data->num_function_row_keys)
return 0; return 0;
return attr->mode;
return devm_device_add_group(&hdev->dev, &vivaldi_attribute_group);
} }
EXPORT_SYMBOL_GPL(vivaldi_input_configured);
static const struct attribute_group vivaldi_attribute_group = {
.attrs = vivaldi_sysfs_attrs,
.is_visible = vivaldi_is_visible,
};
const struct attribute_group *vivaldi_attribute_groups[] = {
&vivaldi_attribute_group,
NULL,
};
EXPORT_SYMBOL_GPL(vivaldi_attribute_groups);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -4,13 +4,11 @@ ...@@ -4,13 +4,11 @@
struct hid_device; struct hid_device;
struct hid_field; struct hid_field;
struct hid_input;
struct hid_usage; struct hid_usage;
void vivaldi_feature_mapping(struct hid_device *hdev, void vivaldi_feature_mapping(struct hid_device *hdev,
struct hid_field *field, struct hid_usage *usage); struct hid_field *field, struct hid_usage *usage);
int vivaldi_input_configured(struct hid_device *hdev, extern const struct attribute_group *vivaldi_attribute_groups[];
struct hid_input *hidinput);
#endif /* _HID_VIVALDI_COMMON_H */ #endif /* _HID_VIVALDI_COMMON_H */
...@@ -45,7 +45,9 @@ static struct hid_driver hid_vivaldi = { ...@@ -45,7 +45,9 @@ static struct hid_driver hid_vivaldi = {
.id_table = vivaldi_table, .id_table = vivaldi_table,
.probe = vivaldi_probe, .probe = vivaldi_probe,
.feature_mapping = vivaldi_feature_mapping, .feature_mapping = vivaldi_feature_mapping,
.input_configured = vivaldi_input_configured, .driver = {
.dev_groups = vivaldi_attribute_groups,
},
}; };
module_hid_driver(hid_vivaldi); module_hid_driver(hid_vivaldi);
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* HID driver for VRC-2 2-axis Car controller
*
* Copyright (C) 2022 Marcus Folkesson <marcus.folkesson@gmail.com>
*/
#include <linux/device.h>
#include <linux/hid.h>
#include <linux/module.h>
/*
* VID/PID are probably "borrowed", so keep them locally and
* do not populate hid-ids.h with those.
*/
#define USB_VENDOR_ID_VRC2 (0x07c0)
#define USB_DEVICE_ID_VRC2 (0x1125)
static __u8 vrc2_rdesc_fixed[] = {
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x04, // Usage (Joystick)
0xA1, 0x01, // Collection (Application)
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x07, // Logical Maximum (2047)
0x35, 0x00, // Physical Minimum (0)
0x46, 0xFF, 0x00, // Physical Maximum (255)
0x75, 0x10, // Report Size (16)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
0x75, 0x08, // Report Size (8)
0x95, 0x03, // Report Count (3)
0x81, 0x03, // Input (Cnst,Var,Abs)
0xC0, // End Collection
};
static __u8 *vrc2_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize)
{
hid_info(hdev, "fixing up VRC-2 report descriptor\n");
*rsize = sizeof(vrc2_rdesc_fixed);
return vrc2_rdesc_fixed;
}
static int vrc2_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
int ret;
/*
* The device gives us 2 separate USB endpoints.
* One of those (the one with report descriptor size of 23) is just bogus so ignore it
*/
if (hdev->dev_rsize == 23)
return -ENODEV;
ret = hid_parse(hdev);
if (ret) {
hid_err(hdev, "parse failed\n");
return ret;
}
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret) {
hid_err(hdev, "hw start failed\n");
return ret;
}
return 0;
}
static const struct hid_device_id vrc2_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_VRC2, USB_DEVICE_ID_VRC2) },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(hid, vrc2_devices);
static struct hid_driver vrc2_driver = {
.name = "vrc2",
.id_table = vrc2_devices,
.report_fixup = vrc2_report_fixup,
.probe = vrc2_probe,
};
module_hid_driver(vrc2_driver);
MODULE_AUTHOR("Marcus Folkesson <marcus.folkesson@gmail.com>");
MODULE_DESCRIPTION("HID driver for VRC-2 2-axis Car controller");
MODULE_LICENSE("GPL");
...@@ -1036,7 +1036,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, ...@@ -1036,7 +1036,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X",
client->name, (u16)hid->vendor, (u16)hid->product); client->name, (u16)hid->vendor, (u16)hid->product);
strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys)); strscpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys));
ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product); ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product);
......
...@@ -1381,7 +1381,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * ...@@ -1381,7 +1381,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
hid->type = HID_TYPE_USBNONE; hid->type = HID_TYPE_USBNONE;
if (dev->manufacturer) if (dev->manufacturer)
strlcpy(hid->name, dev->manufacturer, sizeof(hid->name)); strscpy(hid->name, dev->manufacturer, sizeof(hid->name));
if (dev->product) { if (dev->product) {
if (dev->manufacturer) if (dev->manufacturer)
......
...@@ -294,7 +294,7 @@ static int usb_kbd_probe(struct usb_interface *iface, ...@@ -294,7 +294,7 @@ static int usb_kbd_probe(struct usb_interface *iface,
spin_lock_init(&kbd->leds_lock); spin_lock_init(&kbd->leds_lock);
if (dev->manufacturer) if (dev->manufacturer)
strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); strscpy(kbd->name, dev->manufacturer, sizeof(kbd->name));
if (dev->product) { if (dev->product) {
if (dev->manufacturer) if (dev->manufacturer)
......
...@@ -142,7 +142,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i ...@@ -142,7 +142,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
mouse->dev = input_dev; mouse->dev = input_dev;
if (dev->manufacturer) if (dev->manufacturer)
strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name)); strscpy(mouse->name, dev->manufacturer, sizeof(mouse->name));
if (dev->product) { if (dev->product) {
if (dev->manufacturer) if (dev->manufacturer)
......
/* SPDX-License-Identifier: GPL-2.0-or-later */ /* SPDX-License-Identifier: GPL-2.0-or-later */
/* /*
* drivers/input/tablet/wacom.h
*
* USB Wacom tablet support * USB Wacom tablet support
* *
* Copyright (c) 2000-2004 Vojtech Pavlik <vojtech@ucw.cz> * Copyright (c) 2000-2004 Vojtech Pavlik <vojtech@ucw.cz>
...@@ -78,10 +76,9 @@ ...@@ -78,10 +76,9 @@
* - integration of the Bluetooth devices * - integration of the Bluetooth devices
*/ */
/*
*/
#ifndef WACOM_H #ifndef WACOM_H
#define WACOM_H #define WACOM_H
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
......
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
/* /*
* drivers/input/tablet/wacom_sys.c
*
* USB Wacom tablet support - system specific code * USB Wacom tablet support - system specific code
*/ */
/*
*/
#include "wacom_wac.h" #include "wacom_wac.h"
#include "wacom.h" #include "wacom.h"
#include <linux/input/mt.h> #include <linux/input/mt.h>
...@@ -2226,7 +2221,7 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix) ...@@ -2226,7 +2221,7 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)
} else if (strstr(product_name, "Wacom") || } else if (strstr(product_name, "Wacom") ||
strstr(product_name, "wacom") || strstr(product_name, "wacom") ||
strstr(product_name, "WACOM")) { strstr(product_name, "WACOM")) {
strlcpy(name, product_name, sizeof(name)); strscpy(name, product_name, sizeof(name));
} else { } else {
snprintf(name, sizeof(name), "Wacom %s", product_name); snprintf(name, sizeof(name), "Wacom %s", product_name);
} }
...@@ -2244,7 +2239,7 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix) ...@@ -2244,7 +2239,7 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)
if (name[strlen(name)-1] == ' ') if (name[strlen(name)-1] == ' ')
name[strlen(name)-1] = '\0'; name[strlen(name)-1] = '\0';
} else { } else {
strlcpy(name, features->name, sizeof(name)); strscpy(name, features->name, sizeof(name));
} }
snprintf(wacom_wac->name, sizeof(wacom_wac->name), "%s%s", snprintf(wacom_wac->name, sizeof(wacom_wac->name), "%s%s",
...@@ -2509,7 +2504,7 @@ static void wacom_wireless_work(struct work_struct *work) ...@@ -2509,7 +2504,7 @@ static void wacom_wireless_work(struct work_struct *work)
goto fail; goto fail;
} }
strlcpy(wacom_wac->name, wacom_wac1->name, strscpy(wacom_wac->name, wacom_wac1->name,
sizeof(wacom_wac->name)); sizeof(wacom_wac->name));
error = wacom_initialize_battery(wacom); error = wacom_initialize_battery(wacom);
if (error) if (error)
......
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
/* /*
* drivers/input/tablet/wacom_wac.c
*
* USB Wacom tablet support - Wacom specific code * USB Wacom tablet support - Wacom specific code
*/ */
/*
*/
#include "wacom_wac.h" #include "wacom_wac.h"
#include "wacom.h" #include "wacom.h"
#include <linux/input/mt.h> #include <linux/input/mt.h>
...@@ -713,11 +708,14 @@ static int wacom_intuos_get_tool_type(int tool_id) ...@@ -713,11 +708,14 @@ static int wacom_intuos_get_tool_type(int tool_id)
case 0x802: /* Intuos4/5 13HD/24HD General Pen */ case 0x802: /* Intuos4/5 13HD/24HD General Pen */
case 0x8e2: /* IntuosHT2 pen */ case 0x8e2: /* IntuosHT2 pen */
case 0x022: case 0x022:
case 0x200: /* Pro Pen 3 */
case 0x04200: /* Pro Pen 3 */
case 0x10842: /* MobileStudio Pro Pro Pen slim */ case 0x10842: /* MobileStudio Pro Pro Pen slim */
case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */ case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */
case 0x16802: /* Cintiq 13HD Pro Pen */ case 0x16802: /* Cintiq 13HD Pro Pen */
case 0x18802: /* DTH2242 Pen */ case 0x18802: /* DTH2242 Pen */
case 0x10802: /* Intuos4/5 13HD/24HD General Pen */ case 0x10802: /* Intuos4/5 13HD/24HD General Pen */
case 0x80842: /* Intuos Pro and Cintiq Pro 3D Pen */
tool_type = BTN_TOOL_PEN; tool_type = BTN_TOOL_PEN;
break; break;
...@@ -4875,6 +4873,10 @@ static const struct wacom_features wacom_features_0x3c6 = ...@@ -4875,6 +4873,10 @@ static const struct wacom_features wacom_features_0x3c6 =
static const struct wacom_features wacom_features_0x3c8 = static const struct wacom_features wacom_features_0x3c8 =
{ "Wacom Intuos BT M", 21600, 13500, 4095, 63, { "Wacom Intuos BT M", 21600, 13500, 4095, 63,
INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 }; INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 };
static const struct wacom_features wacom_features_0x3dd =
{ "Wacom Intuos Pro S", 31920, 19950, 8191, 63,
INTUOSP2S_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7,
.touch_max = 10 };
static const struct wacom_features wacom_features_HID_ANY_ID = static const struct wacom_features wacom_features_HID_ANY_ID =
{ "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID }; { "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID };
...@@ -5050,6 +5052,7 @@ const struct hid_device_id wacom_ids[] = { ...@@ -5050,6 +5052,7 @@ const struct hid_device_id wacom_ids[] = {
{ BT_DEVICE_WACOM(0x393) }, { BT_DEVICE_WACOM(0x393) },
{ BT_DEVICE_WACOM(0x3c6) }, { BT_DEVICE_WACOM(0x3c6) },
{ BT_DEVICE_WACOM(0x3c8) }, { BT_DEVICE_WACOM(0x3c8) },
{ BT_DEVICE_WACOM(0x3dd) },
{ USB_DEVICE_WACOM(0x4001) }, { USB_DEVICE_WACOM(0x4001) },
{ USB_DEVICE_WACOM(0x4004) }, { USB_DEVICE_WACOM(0x4004) },
{ USB_DEVICE_WACOM(0x5000) }, { USB_DEVICE_WACOM(0x5000) },
......
/* SPDX-License-Identifier: GPL-2.0-or-later */ /* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* drivers/input/tablet/wacom_wac.h
*/
#ifndef WACOM_WAC_H #ifndef WACOM_WAC_H
#define WACOM_WAC_H #define WACOM_WAC_H
......
...@@ -314,15 +314,6 @@ struct hid_item { ...@@ -314,15 +314,6 @@ struct hid_item {
#define HID_BAT_ABSOLUTESTATEOFCHARGE 0x00850065 #define HID_BAT_ABSOLUTESTATEOFCHARGE 0x00850065
#define HID_VD_ASUS_CUSTOM_MEDIA_KEYS 0xff310076 #define HID_VD_ASUS_CUSTOM_MEDIA_KEYS 0xff310076
/*
* HID report types --- Ouch! HID spec says 1 2 3!
*/
#define HID_INPUT_REPORT 0
#define HID_OUTPUT_REPORT 1
#define HID_FEATURE_REPORT 2
#define HID_REPORT_TYPES 3
/* /*
* HID connect requests * HID connect requests
...@@ -509,7 +500,7 @@ struct hid_report { ...@@ -509,7 +500,7 @@ struct hid_report {
struct list_head hidinput_list; struct list_head hidinput_list;
struct list_head field_entry_list; /* ordered list of input fields */ struct list_head field_entry_list; /* ordered list of input fields */
unsigned int id; /* id of this report */ unsigned int id; /* id of this report */
unsigned int type; /* report type */ enum hid_report_type type; /* report type */
unsigned int application; /* application usage for this report */ unsigned int application; /* application usage for this report */
struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */ struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */
struct hid_field_entry *field_entries; /* allocated memory of input field_entry */ struct hid_field_entry *field_entries; /* allocated memory of input field_entry */
...@@ -658,6 +649,8 @@ struct hid_device { /* device report descriptor */ ...@@ -658,6 +649,8 @@ struct hid_device { /* device report descriptor */
struct list_head debug_list; struct list_head debug_list;
spinlock_t debug_list_lock; spinlock_t debug_list_lock;
wait_queue_head_t debug_wait; wait_queue_head_t debug_wait;
unsigned int id; /* system unique id */
}; };
#define to_hid_device(pdev) \ #define to_hid_device(pdev) \
...@@ -924,20 +917,21 @@ extern int hidinput_connect(struct hid_device *hid, unsigned int force); ...@@ -924,20 +917,21 @@ extern int hidinput_connect(struct hid_device *hid, unsigned int force);
extern void hidinput_disconnect(struct hid_device *); extern void hidinput_disconnect(struct hid_device *);
int hid_set_field(struct hid_field *, unsigned, __s32); int hid_set_field(struct hid_field *, unsigned, __s32);
int hid_input_report(struct hid_device *, int type, u8 *, u32, int); int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
int interrupt);
struct hid_field *hidinput_get_led_field(struct hid_device *hid); struct hid_field *hidinput_get_led_field(struct hid_device *hid);
unsigned int hidinput_count_leds(struct hid_device *hid); unsigned int hidinput_count_leds(struct hid_device *hid);
__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code); __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code);
void hid_output_report(struct hid_report *report, __u8 *data); void hid_output_report(struct hid_report *report, __u8 *data);
int __hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype); int __hid_request(struct hid_device *hid, struct hid_report *rep, enum hid_class_request reqtype);
u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags); u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags);
struct hid_device *hid_allocate_device(void); struct hid_device *hid_allocate_device(void);
struct hid_report *hid_register_report(struct hid_device *device, struct hid_report *hid_register_report(struct hid_device *device,
unsigned int type, unsigned int id, enum hid_report_type type, unsigned int id,
unsigned int application); unsigned int application);
int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
struct hid_report *hid_validate_values(struct hid_device *hid, struct hid_report *hid_validate_values(struct hid_device *hid,
unsigned int type, unsigned int id, enum hid_report_type type, unsigned int id,
unsigned int field_index, unsigned int field_index,
unsigned int report_counts); unsigned int report_counts);
...@@ -1106,10 +1100,11 @@ void hid_hw_stop(struct hid_device *hdev); ...@@ -1106,10 +1100,11 @@ void hid_hw_stop(struct hid_device *hdev);
int __must_check hid_hw_open(struct hid_device *hdev); int __must_check hid_hw_open(struct hid_device *hdev);
void hid_hw_close(struct hid_device *hdev); void hid_hw_close(struct hid_device *hdev);
void hid_hw_request(struct hid_device *hdev, void hid_hw_request(struct hid_device *hdev,
struct hid_report *report, int reqtype); struct hid_report *report, enum hid_class_request reqtype);
int hid_hw_raw_request(struct hid_device *hdev, int hid_hw_raw_request(struct hid_device *hdev,
unsigned char reportnum, __u8 *buf, unsigned char reportnum, __u8 *buf,
size_t len, unsigned char rtype, int reqtype); size_t len, enum hid_report_type rtype,
enum hid_class_request reqtype);
int hid_hw_output_report(struct hid_device *hdev, __u8 *buf, size_t len); int hid_hw_output_report(struct hid_device *hdev, __u8 *buf, size_t len);
/** /**
...@@ -1137,7 +1132,7 @@ static inline int hid_hw_power(struct hid_device *hdev, int level) ...@@ -1137,7 +1132,7 @@ static inline int hid_hw_power(struct hid_device *hdev, int level)
* @reqtype: hid request type * @reqtype: hid request type
*/ */
static inline int hid_hw_idle(struct hid_device *hdev, int report, int idle, static inline int hid_hw_idle(struct hid_device *hdev, int report, int idle,
int reqtype) enum hid_class_request reqtype)
{ {
if (hdev->ll_driver->idle) if (hdev->ll_driver->idle)
return hdev->ll_driver->idle(hdev, report, idle, reqtype); return hdev->ll_driver->idle(hdev, report, idle, reqtype);
...@@ -1182,8 +1177,8 @@ static inline u32 hid_report_len(struct hid_report *report) ...@@ -1182,8 +1177,8 @@ static inline u32 hid_report_len(struct hid_report *report)
return DIV_ROUND_UP(report->size, 8) + (report->id > 0); return DIV_ROUND_UP(report->size, 8) + (report->id > 0);
} }
int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
int interrupt); int interrupt);
/* HID quirks API */ /* HID quirks API */
unsigned long hid_lookup_quirk(const struct hid_device *hdev); unsigned long hid_lookup_quirk(const struct hid_device *hdev);
......
...@@ -42,16 +42,30 @@ ...@@ -42,16 +42,30 @@
#define USB_INTERFACE_PROTOCOL_KEYBOARD 1 #define USB_INTERFACE_PROTOCOL_KEYBOARD 1
#define USB_INTERFACE_PROTOCOL_MOUSE 2 #define USB_INTERFACE_PROTOCOL_MOUSE 2
/*
* HID report types --- Ouch! HID spec says 1 2 3!
*/
enum hid_report_type {
HID_INPUT_REPORT = 0,
HID_OUTPUT_REPORT = 1,
HID_FEATURE_REPORT = 2,
HID_REPORT_TYPES,
};
/* /*
* HID class requests * HID class requests
*/ */
#define HID_REQ_GET_REPORT 0x01 enum hid_class_request {
#define HID_REQ_GET_IDLE 0x02 HID_REQ_GET_REPORT = 0x01,
#define HID_REQ_GET_PROTOCOL 0x03 HID_REQ_GET_IDLE = 0x02,
#define HID_REQ_SET_REPORT 0x09 HID_REQ_GET_PROTOCOL = 0x03,
#define HID_REQ_SET_IDLE 0x0A HID_REQ_SET_REPORT = 0x09,
#define HID_REQ_SET_PROTOCOL 0x0B HID_REQ_SET_IDLE = 0x0A,
HID_REQ_SET_PROTOCOL = 0x0B,
};
/* /*
* HID class descriptor types * HID class descriptor types
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment