summaryrefslogtreecommitdiff
path: root/drivers/hid
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-10-07 11:13:42 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2022-10-07 11:13:42 -0700
commit79d11de9637a37035b4a72ccb528b3dfebc1bf67 (patch)
tree60e625591aa681bdb76a641b7084f15c990ba009 /drivers/hid
parent5d435a3f7b6cb1db566d0f56f5f8dc33be0dde69 (diff)
parentcb7c02e91c31f55d08760f04a09bf9334d809426 (diff)
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 ...
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/Kconfig100
-rw-r--r--drivers/hid/Makefile7
-rw-r--r--drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c8
-rw-r--r--drivers/hid/hid-core.c22
-rw-r--r--drivers/hid/hid-google-hammer.c4
-rw-r--r--drivers/hid/hid-ids.h6
-rw-r--r--drivers/hid/hid-logitech-hidpp.c164
-rw-r--r--drivers/hid/hid-multitouch.c8
-rw-r--r--drivers/hid/hid-nintendo.c60
-rw-r--r--drivers/hid/hid-playstation.c16
-rw-r--r--drivers/hid/hid-pxrc.c112
-rw-r--r--drivers/hid/hid-rmi.c6
-rw-r--r--drivers/hid/hid-roccat.c4
-rw-r--r--drivers/hid/hid-sony.c2
-rw-r--r--drivers/hid/hid-steam.c8
-rw-r--r--drivers/hid/hid-topre.c49
-rw-r--r--drivers/hid/hid-uclogic-core.c5
-rw-r--r--drivers/hid/hid-uclogic-params-test.c192
-rw-r--r--drivers/hid/hid-uclogic-params.c230
-rw-r--r--drivers/hid/hid-uclogic-params.h10
-rw-r--r--drivers/hid/hid-uclogic-rdesc-test.c22
-rw-r--r--drivers/hid/hid-uclogic-rdesc.c76
-rw-r--r--drivers/hid/hid-uclogic-rdesc.h8
-rw-r--r--drivers/hid/hid-vivaldi-common.c29
-rw-r--r--drivers/hid/hid-vivaldi-common.h4
-rw-r--r--drivers/hid/hid-vivaldi.c4
-rw-r--r--drivers/hid/hid-vrc2.c91
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-core.c2
-rw-r--r--drivers/hid/usbhid/hid-core.c2
-rw-r--r--drivers/hid/usbhid/usbkbd.c2
-rw-r--r--drivers/hid/usbhid/usbmouse.c2
-rw-r--r--drivers/hid/wacom.h5
-rw-r--r--drivers/hid/wacom_sys.c11
-rw-r--r--drivers/hid/wacom_wac.c13
-rw-r--r--drivers/hid/wacom_wac.h4
35 files changed, 988 insertions, 300 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 6ce92830b5d1..185a077d59cd 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -28,7 +28,6 @@ if HID
config HID_BATTERY_STRENGTH
bool "Battery level reporting for HID devices"
- depends on HID
select POWER_SUPPLY
default n
help
@@ -38,7 +37,6 @@ config HID_BATTERY_STRENGTH
config HIDRAW
bool "/dev/hidraw raw HID device support"
- depends on HID
help
Say Y here if you want to support HID devices (from the USB
specification standpoint) that aren't strictly user interface
@@ -57,7 +55,6 @@ config HIDRAW
config UHID
tristate "User-space I/O driver support for HID subsystem"
- depends on HID
default n
help
Say Y here if you want to provide HID I/O Drivers from user-space.
@@ -78,7 +75,6 @@ config UHID
config HID_GENERIC
tristate "Generic HID driver"
- depends on HID
default HID
help
Support for generic devices on the HID bus. This includes most
@@ -90,11 +86,9 @@ config HID_GENERIC
If unsure, say Y.
menu "Special HID drivers"
- depends on HID
config HID_A4TECH
tristate "A4TECH mice"
- depends on HID
default !EXPERT
help
Support for some A4TECH mice with two scroll wheels.
@@ -113,7 +107,6 @@ config HID_ACCUTOUCH
config HID_ACRUX
tristate "ACRUX game controller support"
- depends on HID
help
Say Y here if you want to enable support for ACRUX game controllers.
@@ -127,7 +120,6 @@ config HID_ACRUX_FF
config HID_APPLE
tristate "Apple {i,Power,Mac}Books"
- depends on HID
depends on LEDS_CLASS
depends on NEW_LEDS
default !EXPERT
@@ -167,13 +159,11 @@ config HID_ASUS
config HID_AUREAL
tristate "Aureal"
- depends on HID
help
Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes.
config HID_BELKIN
tristate "Belkin Flip KVM and Wireless keyboard"
- depends on HID
default !EXPERT
help
Support for Belkin Flip KVM and Wireless keyboard.
@@ -202,7 +192,6 @@ config HID_BIGBEN_FF
config HID_CHERRY
tristate "Cherry Cymotion keyboard"
- depends on HID
default !EXPERT
help
Support for Cherry Cymotion keyboard.
@@ -227,7 +216,6 @@ config HID_CORSAIR
config HID_COUGAR
tristate "Cougar devices"
- depends on HID
help
Support for Cougar devices that are not fully compliant with the
HID standard.
@@ -237,7 +225,6 @@ config HID_COUGAR
config HID_MACALLY
tristate "Macally devices"
- depends on HID
help
Support for Macally devices that are not fully compliant with the
HID standard.
@@ -262,7 +249,6 @@ config HID_PRODIKEYS
config HID_CMEDIA
tristate "CMedia audio chips"
- depends on HID
help
Support for CMedia CM6533 HID audio jack controls
and HS100B mute buttons.
@@ -288,14 +274,12 @@ config HID_CREATIVE_SB0540
config HID_CYPRESS
tristate "Cypress mouse and barcode readers"
- depends on HID
default !EXPERT
help
Support for cypress mouse and barcode readers.
config HID_DRAGONRISE
tristate "DragonRise Inc. game controller"
- depends on HID
help
Say Y here if you have DragonRise Inc. game controllers.
These might be branded as:
@@ -314,7 +298,6 @@ config DRAGONRISE_FF
config HID_EMS_FF
tristate "EMS Production Inc. force feedback support"
- depends on HID
select INPUT_FF_MEMLESS
help
Say Y here if you want to enable force feedback support for devices by
@@ -332,7 +315,6 @@ config HID_ELAN
config HID_ELECOM
tristate "ELECOM HID devices"
- depends on HID
help
Support for ELECOM devices:
- BM084 Bluetooth Mouse
@@ -349,7 +331,6 @@ config HID_ELO
config HID_EZKEY
tristate "Ezkey BTC 8193 keyboard"
- depends on HID
default !EXPERT
help
Support for Ezkey BTC 8193 keyboard.
@@ -367,19 +348,16 @@ config HID_FT260
config HID_GEMBIRD
tristate "Gembird Joypad"
- depends on HID
help
Support for Gembird JPD-DualForce 2.
config HID_GFRM
tristate "Google Fiber TV Box remote control support"
- depends on HID
help
Support for Google Fiber TV Box remote controls
config HID_GLORIOUS
tristate "Glorious PC Gaming Race mice"
- depends on HID
help
Support for Glorious PC Gaming Race mice such as
the Glorious Model O, O- and D.
@@ -424,7 +402,6 @@ config HID_VIVALDI
tristate "Vivaldi Keyboard"
select HID_VIVALDI_COMMON
select INPUT_VIVALDIFMAP
- depends on HID
help
Say Y here if you want to enable support for Vivaldi keyboards.
@@ -447,7 +424,6 @@ config HID_GT683R
config HID_KEYTOUCH
tristate "Keytouch HID devices"
- depends on HID
help
Support for Keytouch HID devices not fully compliant with
the specification. Currently supported:
@@ -455,7 +431,6 @@ config HID_KEYTOUCH
config HID_KYE
tristate "KYE/Genius devices"
- depends on HID
help
Support for KYE/Genius devices not fully compliant with HID standard:
- Ergo Mouse
@@ -471,32 +446,37 @@ config HID_UCLOGIC
config HID_WALTOP
tristate "Waltop"
- depends on HID
help
Support for Waltop tablets.
config HID_VIEWSONIC
tristate "ViewSonic/Signotec"
- depends on HID
help
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
tristate "Xiaomi"
- depends on HID
help
Adds support for side buttons of Xiaomi Mi Dual Mode Wireless
Mouse Silent Edition.
config HID_GYRATION
tristate "Gyration remote control"
- depends on HID
help
Support for Gyration remote control.
config HID_ICADE
tristate "ION iCade arcade controller"
- depends on HID
help
Support for the ION iCade arcade controller to work as a joystick.
@@ -505,14 +485,12 @@ config HID_ICADE
config HID_ITE
tristate "ITE devices"
- depends on HID
default !EXPERT
help
Support for ITE devices not fully compliant with HID standard.
config HID_JABRA
tristate "Jabra USB HID Driver"
- depends on HID
help
Support for Jabra USB HID devices.
@@ -523,26 +501,22 @@ config HID_JABRA
config HID_TWINHAN
tristate "Twinhan IR remote control"
- depends on HID
help
Support for Twinhan IR remote control.
config HID_KENSINGTON
tristate "Kensington Slimblade Trackball"
- depends on HID
default !EXPERT
help
Support for Kensington Slimblade Trackball.
config HID_LCPOWER
tristate "LC-Power"
- depends on HID
help
Support for LC-Power RC1000MCE RF remote control.
config HID_LED
tristate "Simple RGB LED support"
- depends on HID
depends on LEDS_CLASS
help
Support for simple RGB LED devices. Currently supported are:
@@ -557,7 +531,6 @@ config HID_LED
config HID_LENOVO
tristate "Lenovo / Thinkpad devices"
- depends on HID
select NEW_LEDS
select LEDS_CLASS
help
@@ -675,7 +648,6 @@ config LOGIWHEELS_FF
config HID_MAGICMOUSE
tristate "Apple Magic Mouse/Trackpad multi-touch support"
- depends on HID
help
Support for the Apple Magic Mouse/Trackpad multi-touch.
@@ -684,14 +656,12 @@ config HID_MAGICMOUSE
config HID_MALTRON
tristate "Maltron L90 keyboard"
- depends on HID
help
Adds support for the volume up, volume down, mute, and play/pause buttons
of the Maltron L90 keyboard.
config HID_MAYFLASH
tristate "Mayflash game controller adapter force feedback"
- depends on HID
select INPUT_FF_MEMLESS
help
Say Y here if you have HJZ Mayflash PS3 game controller adapters
@@ -707,14 +677,12 @@ config HID_MEGAWORLD_FF
config HID_REDRAGON
tristate "Redragon keyboards"
- depends on HID
default !EXPERT
help
Support for Redragon keyboards that need fix-ups to work properly.
config HID_MICROSOFT
tristate "Microsoft non-fully HID-compliant devices"
- depends on HID
default !EXPERT
select INPUT_FF_MEMLESS
help
@@ -722,14 +690,12 @@ config HID_MICROSOFT
config HID_MONTEREY
tristate "Monterey Genius KB29E keyboard"
- depends on HID
default !EXPERT
help
Support for Monterey Genius KB29E.
config HID_MULTITOUCH
tristate "HID Multitouch panels"
- depends on HID
help
Generic support for HID multitouch panels.
@@ -775,7 +741,6 @@ config HID_MULTITOUCH
config HID_NINTENDO
tristate "Nintendo Joy-Con and Pro Controller support"
- depends on HID
depends on NEW_LEDS
depends on LEDS_CLASS
select POWER_SUPPLY
@@ -811,7 +776,6 @@ config HID_NTRIG
config HID_ORTEK
tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad"
- depends on HID
help
There are certain devices which have LogicalMaximum wrong in the keyboard
usage page of their report descriptor. The most prevailing ones so far
@@ -824,7 +788,6 @@ config HID_ORTEK
config HID_PANTHERLORD
tristate "Pantherlord/GreenAsia game controller"
- depends on HID
help
Say Y here if you have a PantherLord/GreenAsia based game controller
or adapter.
@@ -850,13 +813,11 @@ config HID_PENMOUNT
config HID_PETALYNX
tristate "Petalynx Maxter remote control"
- depends on HID
help
Support for Petalynx Maxter remote control.
config HID_PICOLCD
tristate "PicoLCD (graphic version)"
- depends on HID
help
This provides support for Minibox PicoLCD devices, currently
only the graphical ones are supported.
@@ -922,7 +883,6 @@ config HID_PICOLCD_CIR
config HID_PLANTRONICS
tristate "Plantronics USB HID Driver"
- depends on HID
help
Provides HID support for Plantronics USB audio devices.
Correctly maps vendor unique volume up/down HID usages to
@@ -933,7 +893,6 @@ config HID_PLANTRONICS
config HID_PLAYSTATION
tristate "PlayStation HID Driver"
- depends on HID
depends on LEDS_CLASS_MULTICOLOR
select CRC32
select POWER_SUPPLY
@@ -950,16 +909,23 @@ config PLAYSTATION_FF
Say Y here if you would like to enable force feedback support for
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
tristate "Razer non-fully HID-compliant devices"
- depends on HID
help
Support for Razer devices that are not fully compliant with the
HID standard.
config HID_PRIMAX
tristate "Primax non-fully HID-compliant devices"
- depends on HID
help
Support for Primax devices that are not fully compliant with the
HID standard.
@@ -981,7 +947,6 @@ config HID_ROCCAT
config HID_SAITEK
tristate "Saitek (Mad Catz) non-fully HID-compliant devices"
- depends on HID
help
Support for Saitek devices that are not fully compliant with the
HID standard.
@@ -999,7 +964,6 @@ config HID_SAMSUNG
config HID_SEMITEK
tristate "Semitek USB keyboards"
- depends on HID
help
Support for Semitek USB keyboards that are not fully compliant
with the HID standard.
@@ -1050,13 +1014,11 @@ config SONY_FF
config HID_SPEEDLINK
tristate "Speedlink VAD Cezanne mouse support"
- depends on HID
help
Support for Speedlink Vicious and Divine Cezanne mouse.
config HID_STEAM
tristate "Steam Controller support"
- depends on HID
select POWER_SUPPLY
help
Say Y here if you have a Steam Controller if you want to use it
@@ -1065,19 +1027,16 @@ config HID_STEAM
config HID_STEELSERIES
tristate "Steelseries SRW-S1 steering wheel support"
- depends on HID
help
Support for Steelseries SRW-S1 steering wheel
config HID_SUNPLUS
tristate "Sunplus wireless desktop"
- depends on HID
help
Support for Sunplus wireless desktop.
config HID_RMI
tristate "Synaptics RMI4 device support"
- depends on HID
select RMI4_CORE
select RMI4_F03
select RMI4_F11
@@ -1090,7 +1049,6 @@ config HID_RMI
config HID_GREENASIA
tristate "GreenAsia (Product ID 0x12) game controller support"
- depends on HID
help
Say Y here if you have a GreenAsia (Product ID 0x12) based game
controller or adapter.
@@ -1112,7 +1070,6 @@ config HID_HYPERV_MOUSE
config HID_SMARTJOYPLUS
tristate "SmartJoy PLUS PS2/USB adapter support"
- depends on HID
help
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.
@@ -1130,20 +1087,23 @@ config SMARTJOYPLUS_FF
config HID_TIVO
tristate "TiVo Slide Bluetooth remote control support"
- depends on HID
help
Say Y if you have a TiVo Slide Bluetooth remote control.
config HID_TOPSEED
tristate "TopSeed Cyberlink, BTC Emprex, Conceptronic remote control support"
- depends on HID
help
Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic
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
tristate "ThingM blink(1) USB RGB LED"
- depends on HID
depends on LEDS_CLASS
select HID_LED
help
@@ -1170,7 +1130,6 @@ config THRUSTMASTER_FF
config HID_UDRAW_PS3
tristate "THQ PS3 uDraw tablet"
- depends on HID
help
Say Y here if you want to use the THQ uDraw gaming tablet for
the PS3.
@@ -1207,7 +1166,6 @@ config HID_WACOM
config HID_WIIMOTE
tristate "Nintendo Wii / Wii U peripherals"
- depends on HID
depends on LEDS_CLASS
select POWER_SUPPLY
select INPUT_FF_MEMLESS
@@ -1232,7 +1190,6 @@ config HID_WIIMOTE
config HID_XINMO
tristate "Xin-Mo non-fully compliant devices"
- depends on HID
help
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
@@ -1240,7 +1197,6 @@ config HID_XINMO
config HID_ZEROPLUS
tristate "Zeroplus based game controller support"
- depends on HID
help
Say Y here if you have a Zeroplus based game controller.
@@ -1254,13 +1210,12 @@ config ZEROPLUS_FF
config HID_ZYDACRON
tristate "Zydacron remote control support"
- depends on HID
help
Support for Zydacron remote control.
config HID_SENSOR_HUB
tristate "HID Sensors framework support"
- depends on HID && HAS_IOMEM
+ depends on HAS_IOMEM
select MFD_CORE
default n
help
@@ -1289,7 +1244,6 @@ config HID_SENSOR_CUSTOM_SENSOR
config HID_ALPS
tristate "Alps HID device support"
- depends on HID
help
Support for Alps I2C HID touchpads and StickPointer.
Say Y here if you have a Alps touchpads over i2c-hid or usbhid
@@ -1307,7 +1261,7 @@ config HID_MCP2221
will be called hid-mcp2221.ko.
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 HID_UCLOGIC
default KUNIT_ALL_TESTS
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index b0bef8098139..e8014c1a2f8b 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -101,6 +101,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS) += hid-picolcd_debugfs.o
obj-$(CONFIG_HID_PLANTRONICS) += hid-plantronics.o
obj-$(CONFIG_HID_PLAYSTATION) += hid-playstation.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_REDRAGON) += hid-redragon.o
obj-$(CONFIG_HID_RETRODE) += hid-retrode.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_TIVO) += hid-tivo.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_U2FZERO) += hid-u2fzero.o
hid-uclogic-objs := hid-uclogic-core.o \
@@ -136,6 +138,7 @@ obj-$(CONFIG_HID_XINMO) += hid-xinmo.o
obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o
obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o
obj-$(CONFIG_HID_VIEWSONIC) += hid-viewsonic.o
+obj-$(CONFIG_HID_VRC2) += hid-vrc2.o
wacom-objs := wacom_wac.o wacom_sys.o
obj-$(CONFIG_HID_WACOM) += wacom.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_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
+obj-$(CONFIG_HID_KUNIT_TEST) += hid-uclogic-test.o
obj-$(CONFIG_USB_HID) += usbhid/
obj-$(CONFIG_USB_MOUSE) += usbhid/
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
index 70436f9fad2f..4da2f9f62aba 100644
--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
@@ -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);
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_buffer, amd_sfh_work_buffer);
@@ -286,13 +288,13 @@ int amd_sfh1_1_init(struct amd_mp2_dev *mp2)
phy_base <<= 21;
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;
}
mp2->vsbase = devm_ioremap(dev, phy_base, 128 * 1024);
if (!mp2->vsbase) {
- dev_err(dev, "failed to remap vsbase\n");
+ dev_dbg(dev, "failed to remap vsbase\n");
return -ENOMEM;
}
@@ -301,7 +303,7 @@ int amd_sfh1_1_init(struct amd_mp2_dev *mp2)
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) {
- dev_err(dev, "failed to get sensors\n");
+ dev_dbg(dev, "failed to get sensors\n");
return -EOPNOTSUPP;
}
dev_dbg(dev, "firmware version 0x%x\n", binfo.sbase.fw_info.fw_ver);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index b7f5566e338d..9c1d31f63f85 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -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,
- unsigned int type, unsigned int id,
+ enum hid_report_type type, unsigned int id,
unsigned int application)
{
struct hid_report_enum *report_enum = device->report_enum + type;
@@ -967,7 +967,7 @@ static const char * const hid_report_names[] = {
* parsing.
*/
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 report_counts)
{
@@ -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.
*/
int __hid_request(struct hid_device *hid, struct hid_report *report,
- int reqtype)
+ enum hid_class_request reqtype)
{
char *buf;
int ret;
@@ -1954,8 +1954,8 @@ out:
}
EXPORT_SYMBOL_GPL(__hid_request);
-int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
- int interrupt)
+int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
+ int interrupt)
{
struct hid_report_enum *report_enum = hid->report_enum + type;
struct hid_report *report;
@@ -2019,7 +2019,8 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event);
*
* 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_driver *hdrv;
@@ -2088,6 +2089,7 @@ const struct hid_device_id *hid_match_id(const struct hid_device *hdev,
return NULL;
}
+EXPORT_SYMBOL_GPL(hid_match_id);
static const struct hid_device_id hid_hiddev_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS) },
@@ -2352,7 +2354,7 @@ EXPORT_SYMBOL_GPL(hid_hw_close);
* @reqtype: hid request type
*/
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)
return hdev->ll_driver->request(hdev, report, reqtype);
@@ -2377,7 +2379,7 @@ EXPORT_SYMBOL_GPL(hid_hw_request);
*/
int hid_hw_raw_request(struct hid_device *hdev,
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)
return -EINVAL;
@@ -2739,10 +2741,12 @@ int hid_add_device(struct hid_device *hdev)
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
* is converted to allow more than 20 bytes as the device name? */
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));
ret = device_add(&hdev->dev);
diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c
index ff40f1e55c21..7ae5f27df54d 100644
--- a/drivers/hid/hid-google-hammer.c
+++ b/drivers/hid/hid-google-hammer.c
@@ -608,9 +608,11 @@ static struct hid_driver hammer_driver = {
.probe = hammer_probe,
.remove = hammer_remove,
.feature_mapping = vivaldi_feature_mapping,
- .input_configured = vivaldi_input_configured,
.input_mapping = hammer_input_mapping,
.event = hammer_event,
+ .driver = {
+ .dev_groups = vivaldi_attribute_groups,
+ },
};
static int __init hammer_init(void)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index f80d6193fca6..da86565f04d4 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -1231,6 +1231,9 @@
#define USB_DEVICE_ID_TIVO_SLIDE 0x1201
#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_DEVICE_ID_TOPSEED_CYBERLINK 0x0204
@@ -1279,10 +1282,12 @@
#define USB_DEVICE_ID_YIYNOVA_TABLET 0x004d
#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_G640 0x0094
#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_PRO_S 0x0909
#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078
#define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074
#define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071
@@ -1386,6 +1391,7 @@
#define USB_VENDOR_ID_MULTIPLE_1781 0x1781
#define USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD 0x0a9d
+#define USB_DEVICE_ID_PHOENIXRC 0x0898
#define USB_VENDOR_ID_DRACAL_RAPHNET 0x289b
#define USB_DEVICE_ID_RAPHNET_2NES2SNES 0x0002
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 68f9e9d207f4..71a9c258a20b 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -41,6 +41,9 @@ module_param(disable_tap_to_click, bool, 0644);
MODULE_PARM_DESC(disable_tap_to_click,
"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_LONG 0x11
#define REPORT_ID_HIDPP_VERY_LONG 0x12
@@ -71,21 +74,18 @@ MODULE_PARM_DESC(disable_tap_to_click,
#define HIDPP_QUIRK_NO_HIDINPUT BIT(23)
#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24)
#define HIDPP_QUIRK_UNIFYING BIT(25)
-#define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(26)
-#define HIDPP_QUIRK_HI_RES_SCROLL_X2120 BIT(27)
-#define HIDPP_QUIRK_HI_RES_SCROLL_X2121 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)
+#define HIDPP_QUIRK_HIDPP_WHEELS BIT(26)
+#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(27)
+#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(28)
/* These are just aliases for now */
#define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS
#define HIDPP_QUIRK_KBD_ZOOM_WHEEL HIDPP_QUIRK_HIDPP_WHEELS
/* Convenience constant to check for any high-res support. */
-#define HIDPP_QUIRK_HI_RES_SCROLL (HIDPP_QUIRK_HI_RES_SCROLL_1P0 | \
- HIDPP_QUIRK_HI_RES_SCROLL_X2120 | \
- HIDPP_QUIRK_HI_RES_SCROLL_X2121)
+#define HIDPP_CAPABILITY_HI_RES_SCROLL (HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL | \
+ HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL | \
+ HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL)
#define HIDPP_QUIRK_DELAYED_INIT HIDPP_QUIRK_NO_HIDINPUT
@@ -96,6 +96,9 @@ MODULE_PARM_DESC(disable_tap_to_click,
#define HIDPP_CAPABILITY_BATTERY_VOLTAGE BIT(4)
#define HIDPP_CAPABILITY_BATTERY_PERCENTAGE BIT(5)
#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))
@@ -343,7 +346,7 @@ static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp,
else
message->report_id = REPORT_ID_HIDPP_LONG;
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);
ret = hidpp_send_message_sync(hidpp, message, response);
@@ -856,8 +859,8 @@ static int hidpp_unifying_init(struct hidpp_device *hidpp)
#define HIDPP_PAGE_ROOT 0x0000
#define HIDPP_PAGE_ROOT_IDX 0x00
-#define CMD_ROOT_GET_FEATURE 0x01
-#define CMD_ROOT_GET_PROTOCOL_VERSION 0x11
+#define CMD_ROOT_GET_FEATURE 0x00
+#define CMD_ROOT_GET_PROTOCOL_VERSION 0x10
static int hidpp_root_get_feature(struct hidpp_device *hidpp, u16 feature,
u8 *feature_index, u8 *feature_type)
@@ -934,9 +937,9 @@ print_version:
#define HIDPP_PAGE_GET_DEVICE_NAME_TYPE 0x0005
-#define CMD_GET_DEVICE_NAME_TYPE_GET_COUNT 0x01
-#define CMD_GET_DEVICE_NAME_TYPE_GET_DEVICE_NAME 0x11
-#define CMD_GET_DEVICE_NAME_TYPE_GET_TYPE 0x21
+#define CMD_GET_DEVICE_NAME_TYPE_GET_COUNT 0x00
+#define CMD_GET_DEVICE_NAME_TYPE_GET_DEVICE_NAME 0x10
+#define CMD_GET_DEVICE_NAME_TYPE_GET_TYPE 0x20
static int hidpp_devicenametype_get_count(struct hidpp_device *hidpp,
u8 feature_index, u8 *nameLength)
@@ -1966,8 +1969,8 @@ static int hidpp_touchpad_fw_items_set(struct hidpp_device *hidpp,
#define HIDPP_PAGE_TOUCHPAD_RAW_XY 0x6100
-#define CMD_TOUCHPAD_GET_RAW_INFO 0x01
-#define CMD_TOUCHPAD_SET_RAW_REPORT_STATE 0x21
+#define CMD_TOUCHPAD_GET_RAW_INFO 0x00
+#define CMD_TOUCHPAD_SET_RAW_REPORT_STATE 0x20
#define EVENT_TOUCHPAD_RAW_XY 0x00
@@ -3415,14 +3418,14 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp)
int ret;
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);
if (ret == 0)
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,
&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);
multiplier = 8;
}
@@ -3437,6 +3440,49 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp)
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 */
/* -------------------------------------------------------------------------- */
@@ -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
* avoid a crash in hidpp_scroll_counter_handle_scroll.
*/
- if (!(hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) || value == 0
- || hidpp->input == NULL || counter->wheel_multiplier == 0)
+ if (!(hidpp->capabilities & HIDPP_CAPABILITY_HI_RES_SCROLL)
+ || value == 0 || hidpp->input == NULL
+ || counter->wheel_multiplier == 0)
return 0;
hidpp_scroll_counter_handle_scroll(hidpp->input, counter, value);
@@ -3924,6 +3971,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
}
hidpp_initialize_battery(hidpp);
+ hidpp_initialize_hires_scroll(hidpp);
/* forward current battery state */
if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_BATTERY) {
@@ -3943,7 +3991,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
if (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);
if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) || hidpp->delayed_input)
@@ -3959,8 +4007,10 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
hidpp_populate_input(hidpp, input);
ret = input_register_device(input);
- if (ret)
+ if (ret) {
input_free_device(input);
+ return;
+ }
hidpp->delayed_input = input;
}
@@ -4219,6 +4269,21 @@ static void hidpp_remove(struct hid_device *hdev)
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) \
HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, \
USB_VENDOR_ID_LOGITECH, (product))
@@ -4239,42 +4304,9 @@ static const struct hid_device_id hidpp_devices[] = {
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,
USB_DEVICE_ID_LOGITECH_T651),
.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 */
LDJ_DEVICE(0x402d),
- .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 },
+ .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 },
{ /* Keyboard logitech K400 */
LDJ_DEVICE(0x4024),
.driver_data = HIDPP_QUIRK_CLASS_K400 },
@@ -4335,18 +4367,9 @@ static const struct hid_device_id hidpp_devices[] = {
{ /* MX5500 keyboard over Bluetooth */
HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b),
.driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
- { /* M-RCQ142 V470 Cordless Laser Mouse over Bluetooth */
- HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb008) },
- { /* MX Master mouse over Bluetooth */
- 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 },
+
+ { /* And try to enable HID++ for all the Logitech Bluetooth devices */
+ HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_ANY, USB_VENDOR_ID_LOGITECH, HID_ANY_ID) },
{}
};
@@ -4360,6 +4383,7 @@ static const struct hid_usage_id hidpp_usages[] = {
static struct hid_driver hidpp_driver = {
.name = "logitech-hidpp-device",
.id_table = hidpp_devices,
+ .match = hidpp_match,
.report_fixup = hidpp_report_fixup,
.probe = hidpp_probe,
.remove = hidpp_remove,
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 2e72922e36f5..91a4d3fc30e0 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -1186,7 +1186,7 @@ static void mt_touch_report(struct hid_device *hid,
int contact_count = -1;
/* 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;
scantime = *app->scantime;
@@ -1267,7 +1267,7 @@ static void mt_touch_report(struct hid_device *hid,
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,
@@ -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,
* 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;
if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags))
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)
diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c
index 6028af3c3aae..5bfc0c450460 100644
--- a/drivers/hid/hid-nintendo.c
+++ b/drivers/hid/hid-nintendo.c
@@ -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->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_MAX = 3500;
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)
{
u16 left_stick_addr = JC_CAL_FCT_DATA_LEFT_ADDR;
@@ -793,38 +812,24 @@ static int joycon_request_calibration(struct joycon_ctlr *ctlr)
&ctlr->left_stick_cal_x,
&ctlr->left_stick_cal_y,
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;
- ctlr->left_stick_cal_x.max = DFLT_STICK_CAL_MAX;
- ctlr->left_stick_cal_x.min = DFLT_STICK_CAL_MIN;
-
- ctlr->left_stick_cal_y.center = DFLT_STICK_CAL_CEN;
- ctlr->left_stick_cal_y.max = DFLT_STICK_CAL_MAX;
- ctlr->left_stick_cal_y.min = DFLT_STICK_CAL_MIN;
- }
+ if (ret)
+ joycon_use_default_calibration(ctlr->hdev,
+ &ctlr->left_stick_cal_x,
+ &ctlr->left_stick_cal_y,
+ "left", ret);
/* read the right stick calibration data */
ret = joycon_read_stick_calibration(ctlr, right_stick_addr,
&ctlr->right_stick_cal_x,
&ctlr->right_stick_cal_y,
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;
- ctlr->right_stick_cal_y.max = DFLT_STICK_CAL_MAX;
- ctlr->right_stick_cal_y.min = DFLT_STICK_CAL_MIN;
- }
+ if (ret)
+ joycon_use_default_calibration(ctlr->hdev,
+ &ctlr->right_stick_cal_x,
+ &ctlr->right_stick_cal_y,
+ "right", ret);
hid_dbg(ctlr->hdev, "calibration:\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)
/* Set the home LED to 0 as default state */
ret = joycon_home_led_brightness_set(led, 0);
if (ret) {
- hid_err(hdev, "Failed to set home LED dflt; ret=%d\n",
- ret);
- return ret;
+ hid_warn(hdev, "Failed to set home LED default, unregistering home LED");
+ devm_led_classdev_unregister(&hdev->dev, led);
}
}
diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c
index b1b5721b5d8f..40050eb85c0a 100644
--- a/drivers/hid/hid-playstation.c
+++ b/drivers/hid/hid-playstation.c
@@ -692,15 +692,12 @@ static ssize_t hardware_version_show(struct device *dev,
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_hardware_version.attr,
NULL
};
-
-static const struct attribute_group ps_device_attribute_group = {
- .attrs = ps_device_attributes,
-};
+ATTRIBUTE_GROUPS(ps_device);
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)
}
}
- 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;
err_close:
@@ -1487,6 +1478,9 @@ static struct hid_driver ps_driver = {
.probe = ps_probe,
.remove = ps_remove,
.raw_event = ps_raw_event,
+ .driver = {
+ .dev_groups = ps_device_groups,
+ },
};
static int __init ps_init(void)
diff --git a/drivers/hid/hid-pxrc.c b/drivers/hid/hid-pxrc.c
new file mode 100644
index 000000000000..b0e517f9cde7
--- /dev/null
+++ b/drivers/hid/hid-pxrc.c
@@ -0,0 +1,112 @@
+// 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");
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
index 311eee599ce9..bb1f423f4ace 100644
--- a/drivers/hid/hid-rmi.c
+++ b/drivers/hid/hid-rmi.c
@@ -237,8 +237,7 @@ static int rmi_hid_read_block(struct rmi_transport_dev *xport, u16 addr,
read_input_count = data->readReport[1];
memcpy(buf + bytes_read, &data->readReport[2],
- read_input_count < bytes_needed ?
- read_input_count : bytes_needed);
+ min(read_input_count, bytes_needed));
bytes_read += 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)
return 0;
}
- memcpy(hdata->readReport, data, size < hdata->input_report_size ?
- size : hdata->input_report_size);
+ memcpy(hdata->readReport, data, min((u32)size, hdata->input_report_size));
set_bit(RMI_READ_DATA_PENDING, &hdata->flags);
wake_up(&hdata->wait);
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c
index 26373b82fe81..6da80e442fdd 100644
--- a/drivers/hid/hid-roccat.c
+++ b/drivers/hid/hid-roccat.c
@@ -257,6 +257,8 @@ int roccat_report_event(int minor, u8 const *data)
if (!new_value)
return -ENOMEM;
+ mutex_lock(&device->cbuf_lock);
+
report = &device->cbuf[device->cbuf_end];
/* passing NULL is safe */
@@ -276,6 +278,8 @@ int roccat_report_event(int minor, u8 const *data)
reader->cbuf_start = (reader->cbuf_start + 1) % ROCCAT_CBUF_SIZE;
}
+ mutex_unlock(&device->cbuf_lock);
+
wake_up_interruptible(&device->wait);
return 0;
}
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index 60ec2b29d54d..03691cdcfb8e 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -368,7 +368,7 @@ static const unsigned int buzz_keymap[] = {
};
/* 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
* the DS3, which uses the Linux gamepad spec.
*/
diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
index fc616db4231b..8ee43cb225fc 100644
--- a/drivers/hid/hid-steam.c
+++ b/drivers/hid/hid-steam.c
@@ -256,7 +256,7 @@ static int steam_get_serial(struct steam_device *steam)
if (reply[0] != 0xae || reply[1] != 0x15 || reply[2] != 0x01)
return -EIO;
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;
}
@@ -524,7 +524,7 @@ static int steam_register(struct steam_device *steam)
*/
mutex_lock(&steam->mutex);
if (steam_get_serial(steam) < 0)
- strlcpy(steam->serial_no, "XXXXXXXXXX",
+ strscpy(steam->serial_no, "XXXXXXXXXX",
sizeof(steam->serial_no));
mutex_unlock(&steam->mutex);
@@ -699,9 +699,9 @@ static struct hid_device *steam_create_client_hid(struct hid_device *hdev)
client_hdev->version = hdev->version;
client_hdev->type = hdev->type;
client_hdev->country = hdev->country;
- strlcpy(client_hdev->name, hdev->name,
+ strscpy(client_hdev->name, hdev->name,
sizeof(client_hdev->name));
- strlcpy(client_hdev->phys, hdev->phys,
+ strscpy(client_hdev->phys, hdev->phys,
sizeof(client_hdev->phys));
/*
* Since we use the same device info than the real interface to
diff --git a/drivers/hid/hid-topre.c b/drivers/hid/hid-topre.c
new file mode 100644
index 000000000000..88a91cdad5f8
--- /dev/null
+++ b/drivers/hid/hid-topre.c
@@ -0,0 +1,49 @@
+// 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);
diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c
index 47a17375c7fc..0fbc408c2607 100644
--- a/drivers/hid/hid-uclogic-core.c
+++ b/drivers/hid/hid-uclogic-core.c
@@ -153,6 +153,7 @@ static int uclogic_input_configured(struct hid_device *hdev,
suffix = "Pad";
break;
case HID_DG_PEN:
+ case HID_DG_DIGITIZER:
suffix = "Pen";
break;
case HID_CP_CONSUMER_CONTROL:
@@ -510,6 +511,8 @@ static const struct hid_device_id uclogic_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER,
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,
USB_DEVICE_ID_UGEE_TABLET_G5) },
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
USB_DEVICE_ID_UGEE_TABLET_EX07S) },
@@ -524,6 +527,8 @@ static const struct hid_device_id uclogic_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_UGEE,
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,
USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06) },
{ }
};
diff --git a/drivers/hid/hid-uclogic-params-test.c b/drivers/hid/hid-uclogic-params-test.c
new file mode 100644
index 000000000000..57ef5d3e4b74
--- /dev/null
+++ b/drivers/hid/hid-uclogic-params-test.c
@@ -0,0 +1,192 @@
+// 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>");
diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c
index c11fa239e6a2..34fa991e6267 100644
--- a/drivers/hid/hid-uclogic-params.c
+++ b/drivers/hid/hid-uclogic-params.c
@@ -1057,6 +1057,161 @@ cleanup:
}
/**
+ * 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
* discovering their parameters.
*
@@ -1084,9 +1239,8 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
const int str_desc_len = 12;
__u8 *str_desc = NULL;
__u8 *rdesc_pen = NULL;
- __u8 *rdesc_frame = NULL;
s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
- s32 resolution;
+ enum uclogic_params_frame_type frame_type;
__u8 magic_arr[] = {
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,
iface = to_usb_interface(hdev->dev.parent);
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) {
uclogic_params_init_invalid(&p);
goto output;
@@ -1128,25 +1291,13 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
goto output;
}
- desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] =
- get_unaligned_le16(str_desc + 2);
- desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] =
- get_unaligned_le16(str_desc + 4);
- desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = str_desc[6];
- desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] =
- 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;
- }
+ rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len,
+ desc_params,
+ ARRAY_SIZE(desc_params),
+ &frame_type);
+ if (rc)
+ goto cleanup;
+
kfree(str_desc);
str_desc = NULL;
@@ -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;
/* Initialize the frame interface */
- rdesc_frame = uclogic_rdesc_template_apply(
- uclogic_rdesc_ugee_v2_frame_btn_template_arr,
- uclogic_rdesc_ugee_v2_frame_btn_template_size,
- desc_params, ARRAY_SIZE(desc_params));
- if (!rdesc_frame) {
- rc = -ENOMEM;
- goto cleanup;
+ switch (frame_type) {
+ case UCLOGIC_PARAMS_FRAME_DIAL:
+ case UCLOGIC_PARAMS_FRAME_MOUSE:
+ rc = uclogic_params_ugee_v2_init_frame_dial(&p, desc_params,
+ ARRAY_SIZE(desc_params));
+ break;
+ 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],
- rdesc_frame,
- 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;
- }
+ if (rc)
+ goto cleanup;
output:
/* Output parameters */
@@ -1433,7 +1581,11 @@ int uclogic_params_init(struct uclogic_params *params,
}
break;
case VID_PID(USB_VENDOR_ID_UGEE,
+ USB_DEVICE_ID_UGEE_PARBLO_A610_PRO):
+ case VID_PID(USB_VENDOR_ID_UGEE,
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);
if (rc != 0)
goto cleanup;
@@ -1517,3 +1669,7 @@ cleanup:
uclogic_params_cleanup(&p);
return rc;
}
+
+#ifdef CONFIG_HID_KUNIT_TEST
+#include "hid-uclogic-params-test.c"
+#endif
diff --git a/drivers/hid/hid-uclogic-params.h b/drivers/hid/hid-uclogic-params.h
index 5bef8daaa607..a97477c02ff8 100644
--- a/drivers/hid/hid-uclogic-params.h
+++ b/drivers/hid/hid-uclogic-params.h
@@ -29,6 +29,16 @@ enum uclogic_params_pen_inrange {
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.
*/
diff --git a/drivers/hid/hid-uclogic-rdesc-test.c b/drivers/hid/hid-uclogic-rdesc-test.c
index ebebffef5f8a..3971a0854c3e 100644
--- a/drivers/hid/hid-uclogic-rdesc-test.c
+++ b/drivers/hid/hid-uclogic-rdesc-test.c
@@ -97,7 +97,7 @@ static const __u8 template_params_none[] = {
static struct uclogic_template_case uclogic_template_cases[] = {
{
- .name = "Empty template",
+ .name = "empty_template",
.template = template_empty,
.template_size = sizeof(template_empty),
.param_list = params_pen_all,
@@ -105,7 +105,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.expected = template_empty,
},
{
- .name = "Template smaller than the placeholder",
+ .name = "template_smaller_than_the_placeholder",
.template = template_small,
.template_size = sizeof(template_small),
.param_list = params_pen_all,
@@ -113,7 +113,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.expected = template_small,
},
{
- .name = "No placeholder",
+ .name = "no_placeholder",
.template = template_no_ph,
.template_size = sizeof(template_no_ph),
.param_list = params_pen_all,
@@ -121,7 +121,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.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_size = sizeof(template_pen_ph_end),
.param_list = params_pen_all,
@@ -129,7 +129,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.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_size = sizeof(template_btn_ph_end),
.param_list = params_frame_all,
@@ -137,7 +137,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.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_size = sizeof(template_pen_all_params),
.param_list = params_pen_all,
@@ -145,7 +145,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.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_size = sizeof(template_frame_all_params),
.param_list = params_frame_all,
@@ -153,7 +153,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.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_size = sizeof(template_pen_some_params),
.param_list = params_pen_all,
@@ -161,7 +161,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.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_size = sizeof(template_pen_some_params),
.param_list = params_pen_some,
@@ -169,7 +169,7 @@ static struct uclogic_template_case uclogic_template_cases[] = {
.expected = expected_pen_some_params,
},
{
- .name = "No params present in the template",
+ .name = "no_params_present_in_the_template",
.template = template_params_none,
.template_size = sizeof(template_params_none),
.param_list = params_pen_some,
@@ -208,7 +208,7 @@ static struct kunit_case hid_uclogic_rdesc_test_cases[] = {
};
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,
};
diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c
index 3d68e8b0784d..4bd54c4fb5b0 100644
--- a/drivers/hid/hid-uclogic-rdesc.c
+++ b/drivers/hid/hid-uclogic-rdesc.c
@@ -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 =
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 */
const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = {
0x05, 0x01, /* Usage Page (Desktop), */
@@ -1113,7 +1187,7 @@ __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr,
memcmp(p, pen_head, sizeof(pen_head)) == 0 &&
p[sizeof(pen_head)] < param_num) {
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;
} else if (memcmp(p, btn_head, sizeof(btn_head)) == 0 &&
p[sizeof(btn_head)] < param_num) {
diff --git a/drivers/hid/hid-uclogic-rdesc.h b/drivers/hid/hid-uclogic-rdesc.h
index 86e64a9ee6bd..0502a0656496 100644
--- a/drivers/hid/hid-uclogic-rdesc.h
+++ b/drivers/hid/hid-uclogic-rdesc.h
@@ -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 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 */
extern const __u8 uclogic_rdesc_ugee_ex07_frame_arr[];
extern const size_t uclogic_rdesc_ugee_ex07_frame_size;
diff --git a/drivers/hid/hid-vivaldi-common.c b/drivers/hid/hid-vivaldi-common.c
index 8b3e515d0f06..b0af2be94895 100644
--- a/drivers/hid/hid-vivaldi-common.c
+++ b/drivers/hid/hid-vivaldi-common.c
@@ -116,25 +116,26 @@ static struct attribute *vivaldi_sysfs_attrs[] = {
NULL
};
-static const struct attribute_group vivaldi_attribute_group = {
- .attrs = vivaldi_sysfs_attrs,
-};
-
-/**
- * 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)
+static umode_t vivaldi_is_visible(struct kobject *kobj, struct attribute *attr,
+ int n)
{
+ struct hid_device *hdev = to_hid_device(kobj_to_dev(kobj));
struct vivaldi_data *data = hid_get_drvdata(hdev);
if (!data->num_function_row_keys)
return 0;
-
- return devm_device_add_group(&hdev->dev, &vivaldi_attribute_group);
+ return attr->mode;
}
-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");
diff --git a/drivers/hid/hid-vivaldi-common.h b/drivers/hid/hid-vivaldi-common.h
index d42e82d77825..ba9adfa08a2d 100644
--- a/drivers/hid/hid-vivaldi-common.h
+++ b/drivers/hid/hid-vivaldi-common.h
@@ -4,13 +4,11 @@
struct hid_device;
struct hid_field;
-struct hid_input;
struct hid_usage;
void vivaldi_feature_mapping(struct hid_device *hdev,
struct hid_field *field, struct hid_usage *usage);
-int vivaldi_input_configured(struct hid_device *hdev,
- struct hid_input *hidinput);
+extern const struct attribute_group *vivaldi_attribute_groups[];
#endif /* _HID_VIVALDI_COMMON_H */
diff --git a/drivers/hid/hid-vivaldi.c b/drivers/hid/hid-vivaldi.c
index 3a979123e7d3..cda5938fb070 100644
--- a/drivers/hid/hid-vivaldi.c
+++ b/drivers/hid/hid-vivaldi.c
@@ -45,7 +45,9 @@ static struct hid_driver hid_vivaldi = {
.id_table = vivaldi_table,
.probe = vivaldi_probe,
.feature_mapping = vivaldi_feature_mapping,
- .input_configured = vivaldi_input_configured,
+ .driver = {
+ .dev_groups = vivaldi_attribute_groups,
+ },
};
module_hid_driver(hid_vivaldi);
diff --git a/drivers/hid/hid-vrc2.c b/drivers/hid/hid-vrc2.c
new file mode 100644
index 000000000000..80a2b7ef5e66
--- /dev/null
+++ b/drivers/hid/hid-vrc2.c
@@ -0,0 +1,91 @@
+// 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");
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index 95cefae47adf..0667b6022c3b 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -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",
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);
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 4490e2f7252a..be4c731aaa65 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -1381,7 +1381,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
hid->type = HID_TYPE_USBNONE;
if (dev->manufacturer)
- strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));
+ strscpy(hid->name, dev->manufacturer, sizeof(hid->name));
if (dev->product) {
if (dev->manufacturer)
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index b4b007c4beb6..c439ed2f16db 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -294,7 +294,7 @@ static int usb_kbd_probe(struct usb_interface *iface,
spin_lock_init(&kbd->leds_lock);
if (dev->manufacturer)
- strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name));
+ strscpy(kbd->name, dev->manufacturer, sizeof(kbd->name));
if (dev->product) {
if (dev->manufacturer)
diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c
index fb1d7d1f6999..3fd93c2e4f4a 100644
--- a/drivers/hid/usbhid/usbmouse.c
+++ b/drivers/hid/usbhid/usbmouse.c
@@ -142,7 +142,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
mouse->dev = input_dev;
if (dev->manufacturer)
- strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name));
+ strscpy(mouse->name, dev->manufacturer, sizeof(mouse->name));
if (dev->product) {
if (dev->manufacturer)
diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h
index 3f8b24a57014..4da50e19808e 100644
--- a/drivers/hid/wacom.h
+++ b/drivers/hid/wacom.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
- * drivers/input/tablet/wacom.h
- *
* USB Wacom tablet support
*
* Copyright (c) 2000-2004 Vojtech Pavlik <vojtech@ucw.cz>
@@ -78,10 +76,9 @@
* - integration of the Bluetooth devices
*/
-/*
- */
#ifndef WACOM_H
#define WACOM_H
+
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 194a2e327591..634263e4556b 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -1,13 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * drivers/input/tablet/wacom_sys.c
- *
* USB Wacom tablet support - system specific code
*/
-/*
- */
-
#include "wacom_wac.h"
#include "wacom.h"
#include <linux/input/mt.h>
@@ -2226,7 +2221,7 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)
} else if (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 {
snprintf(name, sizeof(name), "Wacom %s", product_name);
}
@@ -2244,7 +2239,7 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)
if (name[strlen(name)-1] == ' ')
name[strlen(name)-1] = '\0';
} else {
- strlcpy(name, features->name, sizeof(name));
+ strscpy(name, features->name, sizeof(name));
}
snprintf(wacom_wac->name, sizeof(wacom_wac->name), "%s%s",
@@ -2509,7 +2504,7 @@ static void wacom_wireless_work(struct work_struct *work)
goto fail;
}
- strlcpy(wacom_wac->name, wacom_wac1->name,
+ strscpy(wacom_wac->name, wacom_wac1->name,
sizeof(wacom_wac->name));
error = wacom_initialize_battery(wacom);
if (error)
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index d049239256a2..77486962a773 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -1,13 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * drivers/input/tablet/wacom_wac.c
- *
* USB Wacom tablet support - Wacom specific code
*/
-/*
- */
-
#include "wacom_wac.h"
#include "wacom.h"
#include <linux/input/mt.h>
@@ -713,11 +708,14 @@ static int wacom_intuos_get_tool_type(int tool_id)
case 0x802: /* Intuos4/5 13HD/24HD General Pen */
case 0x8e2: /* IntuosHT2 pen */
case 0x022:
+ case 0x200: /* Pro Pen 3 */
+ case 0x04200: /* Pro Pen 3 */
case 0x10842: /* MobileStudio Pro Pro Pen slim */
case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */
case 0x16802: /* Cintiq 13HD Pro Pen */
case 0x18802: /* DTH2242 Pen */
case 0x10802: /* Intuos4/5 13HD/24HD General Pen */
+ case 0x80842: /* Intuos Pro and Cintiq Pro 3D Pen */
tool_type = BTN_TOOL_PEN;
break;
@@ -4875,6 +4873,10 @@ static const struct wacom_features wacom_features_0x3c6 =
static const struct wacom_features wacom_features_0x3c8 =
{ "Wacom Intuos BT M", 21600, 13500, 4095, 63,
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 =
{ "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID };
@@ -5050,6 +5052,7 @@ const struct hid_device_id wacom_ids[] = {
{ BT_DEVICE_WACOM(0x393) },
{ BT_DEVICE_WACOM(0x3c6) },
{ BT_DEVICE_WACOM(0x3c8) },
+ { BT_DEVICE_WACOM(0x3dd) },
{ USB_DEVICE_WACOM(0x4001) },
{ USB_DEVICE_WACOM(0x4004) },
{ USB_DEVICE_WACOM(0x5000) },
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index fef1538005b5..5ca6c06d143b 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -1,7 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * drivers/input/tablet/wacom_wac.h
- */
+
#ifndef WACOM_WAC_H
#define WACOM_WAC_H