Assorted HID drivers updates and fixes for 6.1

-----BEGIN PGP SIGNATURE-----
 
 iQJSBAABCAA8FiEEoEVH9lhNrxiMPSyI7MXwXhnZSjYFAmM9UhweHGJlbmphbWlu
 LnRpc3NvaXJlc0ByZWRoYXQuY29tAAoJEOzF8F4Z2Uo2pE8P/23iRM/+kO2KDeU8
 3lp6z1Ny/Hp0HPAsWCgAywgPcNoG+JaxBdAFv2YXky0RI3/OMtI+6FK36XJs63E5
 twjFwySxupY2CXLIXjSkLunAWlZUwtpRLnrBpPwgG87wKkI8IvPmv1AwkiYO9GD9
 Q0vtd+GaE7Bx33XBga4IcVx1hODL/SDeT1ozS1czhv4NNutRsR7lxCsn6qKly9WK
 zwoTHEOIJnq4oLZElmnxuJeUU1vvRXy4g+xPV+rfqbnlZUh0zQeD//1G7lRchEel
 t6l5SDR9pZ+zbWUw7gtU/KoUtf4eJ5+4fX9ejMqtEvoQLquePYQOD6Pyzjqlq7ND
 x31MjTmVHaav4GZiON7ztkbUncnERYRVRiLr5iDw9xcS5MVnMg2a07VgY6Ld5Xnl
 FQ0ZaO7T1HUxl2Lig7kRdX/kIDVNMIgfS1e0H6yJC3b5sbouwSRknu6EoumK/6tG
 nx8njAYi8t+2DN7d/82Ck1Z3CfY100WONahBAVZeyNtu0p9QH1k0b6srZiCpFTvQ
 ffl6lXboiYYx3hV/HNoDiIJPTh/zJhjEAzi1MgUKlbt5ImYWJQ0tAnhY16e3+xt5
 83ryRFdUmjwxE/0Oh0yi1Nk8VWid+40DCpay9Qm6veyRr+ECviChwoI0OUFsTrfR
 p2+2ghZHwFf4JTpUNlHdV0Kz0OJ9
 =lo26
 -----END PGP SIGNATURE-----

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
  ...
This commit is contained in:
Linus Torvalds 2022-10-07 11:13:42 -07:00
commit 79d11de963
38 changed files with 1034 additions and 325 deletions

View file

@ -9082,6 +9082,12 @@ L: linux-input@vger.kernel.org
S: Supported
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
M: Jiri Kosina <jikos@kernel.org>
M: Jonathan Cameron <jic23@kernel.org>
@ -9094,6 +9100,12 @@ F: drivers/hid/hid-sensor-*
F: drivers/iio/*/hid-*
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
M: Ping Cheng <ping.cheng@wacom.com>
M: Jason Gerecke <jason.gerecke@wacom.com>

View file

@ -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

View file

@ -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/

View file

@ -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);

View file

@ -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 @@ int __hid_request(struct hid_device *hid, struct hid_report *report,
}
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);

View file

@ -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)

View file

@ -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

View file

@ -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 @@ static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp)
#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,

View file

@ -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)

View file

@ -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);
}
}

View file

@ -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)

112
drivers/hid/hid-pxrc.c Normal file
View file

@ -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");

View file

@ -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);

View file

@ -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;
}

View file

@ -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.
*/

View file

@ -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

49
drivers/hid/hid-topre.c Normal file
View file

@ -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);

View file

@ -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:
@ -509,6 +510,8 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UGTIZER_TABLET_GP0610) },
{ 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,
@ -523,6 +526,8 @@ static const struct hid_device_id uclogic_devices[] = {
USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01) },
{ 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) },
{ }

View file

@ -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>");

View file

@ -1056,6 +1056,161 @@ static int uclogic_probe_interface(struct hid_device *hdev, u8 *magic_arr,
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
* 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 */
@ -1432,8 +1580,12 @@ int uclogic_params_init(struct uclogic_params *params,
uclogic_params_init_invalid(&p);
}
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 @@ int uclogic_params_init(struct uclogic_params *params,
uclogic_params_cleanup(&p);
return rc;
}
#ifdef CONFIG_HID_KUNIT_TEST
#include "hid-uclogic-params-test.c"
#endif

View file

@ -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.
*/

View file

@ -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,
};

View file

@ -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) {

View file

@ -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;

View file

@ -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");

View file

@ -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 */

View file

@ -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);

91
drivers/hid/hid-vrc2.c Normal file
View file

@ -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");

View file

@ -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);

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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>

View file

@ -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)

View file

@ -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) },

View file

@ -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

View file

@ -314,15 +314,6 @@ struct hid_item {
#define HID_BAT_ABSOLUTESTATEOFCHARGE 0x00850065
#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
@ -509,7 +500,7 @@ struct hid_report {
struct list_head hidinput_list;
struct list_head field_entry_list; /* ordered list of input fields */
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 */
struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */
struct hid_field_entry *field_entries; /* allocated memory of input field_entry */
@ -658,6 +649,8 @@ struct hid_device { /* device report descriptor */
struct list_head debug_list;
spinlock_t debug_list_lock;
wait_queue_head_t debug_wait;
unsigned int id; /* system unique id */
};
#define to_hid_device(pdev) \
@ -924,20 +917,21 @@ extern int hidinput_connect(struct hid_device *hid, unsigned int force);
extern void hidinput_disconnect(struct hid_device *);
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);
unsigned int hidinput_count_leds(struct hid_device *hid);
__s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code);
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);
struct hid_device *hid_allocate_device(void);
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);
int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size);
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);
@ -1106,10 +1100,11 @@ void hid_hw_stop(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_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,
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);
/**
@ -1137,7 +1132,7 @@ static inline int hid_hw_power(struct hid_device *hdev, int level)
* @reqtype: hid request type
*/
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)
return hdev->ll_driver->idle(hdev, report, idle, reqtype);
@ -1182,8 +1177,8 @@ static inline u32 hid_report_len(struct hid_report *report)
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 interrupt);
int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size,
int interrupt);
/* HID quirks API */
unsigned long hid_lookup_quirk(const struct hid_device *hdev);

View file

@ -42,16 +42,30 @@
#define USB_INTERFACE_PROTOCOL_KEYBOARD 1
#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
*/
#define HID_REQ_GET_REPORT 0x01
#define HID_REQ_GET_IDLE 0x02
#define HID_REQ_GET_PROTOCOL 0x03
#define HID_REQ_SET_REPORT 0x09
#define HID_REQ_SET_IDLE 0x0A
#define HID_REQ_SET_PROTOCOL 0x0B
enum hid_class_request {
HID_REQ_GET_REPORT = 0x01,
HID_REQ_GET_IDLE = 0x02,
HID_REQ_GET_PROTOCOL = 0x03,
HID_REQ_SET_REPORT = 0x09,
HID_REQ_SET_IDLE = 0x0A,
HID_REQ_SET_PROTOCOL = 0x0B,
};
/*
* HID class descriptor types