mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-04 04:40:25 +01:00
Implement a quirks system to replace the udev property parsing
Previously, we had all extra device information ("This is an Apple Touchpad",
"This touchpad causes pointer jumps", etc.) in the udev hwdb. The problem with
the hwdb is that updating it is nontrivial for the average user and debugging
when things go wrong is even harder. Plus, the hwdb has a matching scheme that
is unpredictable unless one is familiar with the implementation.
This patch set moves the hwdb entries into .ini style text files, with a
simple line-based parser. A new libinput list-quirks tool can list the quirks
applied to any given device, in --verbose mode it prints all matches as they
apply or not apply.
The data files are currently unused by libinput, that comes in a later patch.
They're installed though, the defaults point to the /usr/share/libinput
directory and for *temporary* local overrides the single file
/etc/libinput/local-overrides.quirks.
Failure to parse any file is a hard failure for the quirks system, but if the
local override file doesn't exist that's fine.
THIS IS NOT A CONFIGURATION INTERFACE! None of these settings are exposed via
the libinput_device_config_* calls. There is no API guarantee for these files,
think of them as source code.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
be647fbb0d
commit
5792af9a5f
32 changed files with 3512 additions and 2 deletions
4
data/10-generic-keyboard.quirks
Normal file
4
data/10-generic-keyboard.quirks
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[Serial Keyboards]
|
||||
MatchUdevType=keyboard
|
||||
MatchBus=ps2
|
||||
AttrKeyboardIntegration=internal
|
||||
9
data/10-generic-lid.quirks
Normal file
9
data/10-generic-lid.quirks
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[Lid Switch Ct9]
|
||||
MatchName=*Lid Switch*
|
||||
MatchDMIModalias=dmi:*:ct9:*
|
||||
AttrLidSwitchReliability=reliable
|
||||
|
||||
[Lid Switch Ct10]
|
||||
MatchName=*Lid Switch*
|
||||
MatchDMIModalias=dmi:*:ct10:*
|
||||
AttrLidSwitchReliability=reliable
|
||||
3
data/10-generic-trackball.quirks
Normal file
3
data/10-generic-trackball.quirks
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[Trackball]
|
||||
MatchName=*Trackball*
|
||||
ModelTrackball=1
|
||||
5
data/30-vendor-aiptek.quirks
Normal file
5
data/30-vendor-aiptek.quirks
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
[Aiptek No Tilt Tablet]
|
||||
MatchUdevType=tablet
|
||||
MatchBus=usb
|
||||
MatchVendor=0x08CA
|
||||
ModelTabletNoTilt=1
|
||||
9
data/30-vendor-alps.quirks
Normal file
9
data/30-vendor-alps.quirks
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[AlpsTouchpadDualPoint]
|
||||
MatchUdevType=touchpad
|
||||
MatchName=*AlpsPS/2 ALPS DualPoint TouchPad
|
||||
ModelALPSTouchpad=1
|
||||
|
||||
[AlpsTouchpadGlidePoint]
|
||||
MatchUdevType=touchpad
|
||||
MatchName=*AlpsPS/2 ALPS GlidePoint
|
||||
ModelALPSTouchpad=1
|
||||
3
data/30-vendor-cyapa.quirks
Normal file
3
data/30-vendor-cyapa.quirks
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[Cyapa Touchpads]
|
||||
MatchName=*Cypress APA Trackpad ?cyapa?
|
||||
AttrPressureRange=10:8
|
||||
4
data/30-vendor-elantech.quirks
Normal file
4
data/30-vendor-elantech.quirks
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[Elantech Touchpads]
|
||||
MatchName=*Elantech Touchpad*
|
||||
AttrResolutionHint=31x31
|
||||
AttrPressureRange=10:8
|
||||
12
data/30-vendor-huion.quirks
Normal file
12
data/30-vendor-huion.quirks
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# HUION PenTablet device. Some of these devices send a BTN_TOOL_PEN event
|
||||
# with value 1 on the first event received by the device but never send the
|
||||
# matching BTN_TOOL_PEN value 0 event. The device appears as if it was
|
||||
# permanently in proximity.
|
||||
#
|
||||
# HUION re-uses USB IDs for its devices, not every HUION tablet is
|
||||
# affected by this bug, libinput will auto-disable this feature
|
||||
[HUION PenTablet]
|
||||
MatchUdevType=tablet
|
||||
MatchBus=usb
|
||||
MatchVendor=0x256C
|
||||
ModelTabletNoProximityOut=1
|
||||
39
data/30-vendor-ibm.quirks
Normal file
39
data/30-vendor-ibm.quirks
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# IBM/Lenovo Scrollpoint mouse. Instead of a scroll wheel these mice
|
||||
# feature trackpoint-like sticks which generate a huge amount of scroll
|
||||
# events that need to be handled differently than scroll wheel events
|
||||
|
||||
[IBM ScrollPoint Mouse 3100]
|
||||
MatchUdevType=mouse
|
||||
MatchVendor=0x04B3
|
||||
MatchProduct=0x3100
|
||||
ModelLenovoScrollPoint=1
|
||||
|
||||
[IBM ScrollPoint Mouse 3103]
|
||||
MatchUdevType=mouse
|
||||
MatchVendor=0x04B3
|
||||
MatchProduct=0x3103
|
||||
ModelLenovoScrollPoint=1
|
||||
|
||||
[IBM ScrollPoint Mouse 3105]
|
||||
MatchUdevType=mouse
|
||||
MatchVendor=0x04B3
|
||||
MatchProduct=0x3105
|
||||
ModelLenovoScrollPoint=1
|
||||
|
||||
[IBM ScrollPoint Mouse 3108]
|
||||
MatchUdevType=mouse
|
||||
MatchVendor=0x04B3
|
||||
MatchProduct=0x3108
|
||||
ModelLenovoScrollPoint=1
|
||||
|
||||
[IBM ScrollPoint Mouse 3109]
|
||||
MatchUdevType=mouse
|
||||
MatchVendor=0x04B3
|
||||
MatchProduct=0x3109
|
||||
ModelLenovoScrollPoint=1
|
||||
|
||||
[IBM ScrollPoint Mouse 6049]
|
||||
MatchUdevType=mouse
|
||||
MatchVendor=0x17EF
|
||||
MatchProduct=0x6049
|
||||
ModelLenovoScrollPoint=1
|
||||
44
data/30-vendor-logitech.quirks
Normal file
44
data/30-vendor-logitech.quirks
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
[Logitech M570]
|
||||
MatchName=*Logitech M570*
|
||||
ModelTrackball=1
|
||||
|
||||
[Logitech Marble Mouse Trackball]
|
||||
MatchUdevType=mouse
|
||||
MatchBus=usb
|
||||
MatchVendor=0x46D
|
||||
MatchProduct=0xC408
|
||||
ModelLogitechMarbleMouse=1
|
||||
|
||||
[Logitech K400]
|
||||
MatchUdevType=mouse
|
||||
MatchBus=usb
|
||||
MatchVendor=0x046D
|
||||
MatchProduct=0x4024
|
||||
ModelBouncingKeys=1
|
||||
|
||||
[Logitech K400r]
|
||||
MatchUdevType=mouse
|
||||
MatchBus=usb
|
||||
MatchVendor=0x046D
|
||||
MatchProduct=0x404B
|
||||
ModelBouncingKeys=1
|
||||
|
||||
[Logitech K830]
|
||||
MatchUdevType=mouse
|
||||
MatchBus=usb
|
||||
MatchVendor=0x046D
|
||||
MatchProduct=0x404C
|
||||
ModelBouncingKeys=1
|
||||
|
||||
[Logitech K400Plus]
|
||||
MatchUdevType=mouse
|
||||
MatchBus=usb
|
||||
MatchVendor=0x046D
|
||||
MatchProduct=0x404D
|
||||
ModelBouncingKeys=1
|
||||
|
||||
[Logitech Wireless Touchpad]
|
||||
MatchBus=usb
|
||||
MatchVendor=0x046D
|
||||
MatchProduct=0x4011
|
||||
AttrPalmPressureThreshold=400
|
||||
16
data/30-vendor-microsoft.quirks
Normal file
16
data/30-vendor-microsoft.quirks
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
[Microsoft Surface 3 Lid Switch]
|
||||
MatchName=*Lid Switch*
|
||||
MatchDMIModalias=dmi:*svnMicrosoftCorporation:pnSurface3:*
|
||||
AttrLidSwitchReliability=write_open
|
||||
|
||||
[Microsoft Surface 3 Type Cover Keyboard]
|
||||
MatchName=*Microsoft Surface Type Cover Keyboard*
|
||||
MatchDMIModalias=dmi:*svnMicrosoftCorporation:pnSurface3:*
|
||||
AttrKeyboardIntegration=internal
|
||||
|
||||
[Microsoft Nano Transceiver v2.0]
|
||||
MatchUdevType=mouse
|
||||
MatchBus=usb
|
||||
MatchVendor=0x045E
|
||||
MatchProduct=0x8000
|
||||
ModelBouncingKeys=1
|
||||
11
data/30-vendor-razer.quirks
Normal file
11
data/30-vendor-razer.quirks
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[Razer Blade Keyboard]
|
||||
MatchUdevType=keyboard
|
||||
MatchBus=usb
|
||||
MatchVendor=0x1532
|
||||
MatchProduct=0x0220
|
||||
AttrKeyboardIntegration=internal
|
||||
|
||||
[Razer Blade Lid Switch]
|
||||
MatchName=*Lid Switch*
|
||||
MatchDMIModalias=dmi:*svnRazer:pnBlade*
|
||||
AttrLidSwitchReliability=write_open
|
||||
6
data/30-vendor-synaptics.quirks
Normal file
6
data/30-vendor-synaptics.quirks
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[Synaptics Serial Touchpads]
|
||||
MatchUdevType=touchpad
|
||||
MatchBus=ps2
|
||||
MatchVendor=0x0002
|
||||
MatchProduct=0x0007
|
||||
ModelSynapticsSerialTouchpad=1
|
||||
12
data/30-vendor-wacom.quirks
Normal file
12
data/30-vendor-wacom.quirks
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
[Wacom Touchpads]
|
||||
MatchUdevType=touchpad
|
||||
MatchBus=usb
|
||||
MatchVendor=0x056A
|
||||
ModelWacomTouchpad=1
|
||||
|
||||
[Wacom Intuos Pro PTH660]
|
||||
MatchUdevType=touchpad
|
||||
MatchBus=usb
|
||||
MatchVendor=0x056A
|
||||
MatchProduct=0x0357
|
||||
AttrPalmSizeThreshold=1
|
||||
48
data/50-system-apple.quirks
Normal file
48
data/50-system-apple.quirks
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
[Apple Touchpads USB]
|
||||
MatchVendor=0x05AC
|
||||
MatchBus=usb
|
||||
MatchUdevType=touchpad
|
||||
ModelAppleTouchpad=1
|
||||
AttrSizeHint=104x75
|
||||
AttrTouchSizeRange=150:130
|
||||
AttrPalmSizeThreshold=800
|
||||
|
||||
[Apple Touchpads Bluetooth]
|
||||
MatchVendor=0x05AC
|
||||
MatchBus=bluetooth
|
||||
MatchUdevType=touchpad
|
||||
ModelAppleTouchpad=1
|
||||
|
||||
[Apple Internal Keyboard]
|
||||
MatchName=*Apple Inc. Apple Internal Keyboard*
|
||||
AttrKeyboardIntegration=internal
|
||||
|
||||
[Apple MagicMouse]
|
||||
MatchUdevType=mouse
|
||||
MatchBus=bluetooth
|
||||
MatchVendor=0x05AC
|
||||
MatchProduct=0x030D
|
||||
ModelAppleMagicMouse=1
|
||||
|
||||
[Apple Magic Trackpad v1 (2010, clickpad)]
|
||||
MatchUdevType=touchpad
|
||||
MatchBus=bluetooth
|
||||
MatchVendor=0x5AC
|
||||
MatchProduct=0x030E
|
||||
AttrSizeHint=130x110
|
||||
AttrTouchSizeRange=20:10
|
||||
AttrPalmSizeThreshold=900
|
||||
|
||||
[Apple Touchpad OneButton]
|
||||
MatchUdevType=touchpad
|
||||
MatchBus=usb
|
||||
MatchVendor=0x5AC
|
||||
MatchProduct=0x021A
|
||||
ModelAppleTouchpadOneButton=1
|
||||
|
||||
[Apple Touchpad MacbookPro5,5]
|
||||
MatchUdevType=touchpad
|
||||
MatchBus=usb
|
||||
MatchVendor=0x05AC
|
||||
MatchProduct=0x0237
|
||||
AttrPalmSizeThreshold=1000
|
||||
9
data/50-system-asus.quirks
Normal file
9
data/50-system-asus.quirks
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
[Asus X555LAB]
|
||||
MatchName=*ETPS/2 Elantech Touchpad*
|
||||
MatchDMIModalias=dmi:*svnASUSTeKCOMPUTERINC.:pnX555LAB:*
|
||||
ModelTouchpadVisibleMarker=1
|
||||
|
||||
[Asus UX21E]
|
||||
MatchName=*ETPS/2 Elantech Touchpad*
|
||||
MatchDMIModalias=dmi:*svnASUSTeKComputerInc.:pnUX21E:*
|
||||
AttrPressureRange=24:10
|
||||
7
data/50-system-chicony.quirks
Normal file
7
data/50-system-chicony.quirks
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Acer Hawaii Keyboard, uses Chicony VID
|
||||
[Acer Hawaii Keyboard]
|
||||
MatchUdevType=touchpad
|
||||
MatchBus=usb
|
||||
MatchVendor=0x4F2
|
||||
MatchProduct=0x1558
|
||||
AttrTPKComboLayout=below
|
||||
6
data/50-system-cyborg.quirks
Normal file
6
data/50-system-cyborg.quirks
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[Saitek Cyborg RAT5]
|
||||
MatchUdevType=mouse
|
||||
MatchBus=usb
|
||||
MatchVendor=0x06A3
|
||||
MatchProduct=0x0CD5
|
||||
ModelCyborgRat=1
|
||||
15
data/50-system-dell.quirks
Normal file
15
data/50-system-dell.quirks
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[Dell Touchpads]
|
||||
MatchName=* Touchpad
|
||||
MatchDMIModalias=dmi:*svnDellInc.:*
|
||||
ModelTouchpadVisibleMarker=1
|
||||
|
||||
[Dell Lattitude E6220]
|
||||
MatchName=*AlpsPS/2 ALPS GlidePoint
|
||||
MatchDMIModalias=dmi:*svnDellInc.:pnLatitudeE6220:*
|
||||
AttrPressureRange=100:90
|
||||
|
||||
[Dell XPS L322X]
|
||||
MatchName=*CyPS/2 Cypress Trackpad
|
||||
MatchDMIModalias=dmi:*svnDell*:XPSL322X*
|
||||
AttrPressureRange=32:20
|
||||
AttrPalmPressureThreshold=254
|
||||
86
data/50-system-google.quirks
Normal file
86
data/50-system-google.quirks
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
[Google Chromebook R13 CB5-312T]
|
||||
MatchName=*Elan Touchpad*
|
||||
MatchDeviceTree=*Chromebook R13 CB5-312T*
|
||||
AttrPressureRange=6:4
|
||||
|
||||
[Google Chromebook CB5-312T]
|
||||
MatchName=*Elan Touchpad*
|
||||
MatchDeviceTree=*CB5-312T*
|
||||
AttrPressureRange=6:4
|
||||
|
||||
[Google Chromebook Elm]
|
||||
MatchName=*Elan Touchpad*
|
||||
MatchDeviceTree=*Elm*
|
||||
AttrPressureRange=6:4
|
||||
|
||||
[Google Chromebook Falco]
|
||||
MatchUdevType=touchpad
|
||||
MatchName=Cypress APA Trackpad ?cyapa?
|
||||
MatchDMIModalias=dmi:*pn*Falco*
|
||||
ModelChromebook=1
|
||||
|
||||
[Google Chromebook Mario]
|
||||
MatchUdevType=touchpad
|
||||
MatchName=SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*pn*Mario*
|
||||
ModelChromebook=1
|
||||
|
||||
[Google Chromebook Butterfly]
|
||||
MatchUdevType=touchpad
|
||||
MatchName=Cypress APA Trackpad ?cyapa?
|
||||
MatchDMIModalias=dmi:*pn*Butterfly*
|
||||
ModelChromebook=1
|
||||
|
||||
[Google Chromebook Peppy]
|
||||
MatchUdevType=touchpad
|
||||
MatchName=Cypress APA Trackpad ?cyapa?
|
||||
MatchDMIModalias=dmi:*pn*Peppy*
|
||||
ModelChromebook=1
|
||||
|
||||
[Google Chromebook ZGB]
|
||||
MatchUdevType=touchpad
|
||||
MatchName=SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*pn*ZGB*
|
||||
ModelChromebook=1
|
||||
|
||||
[Google Chromebook Parrot]
|
||||
MatchUdevType=touchpad
|
||||
MatchName=Cypress APA Trackpad ?cyapa?
|
||||
MatchDMIModalias=dmi:*pn*Parrot*
|
||||
ModelChromebook=1
|
||||
|
||||
[Google Chromebook Leon]
|
||||
MatchUdevType=touchpad
|
||||
MatchName=Cypress APA Trackpad ?cyapa?
|
||||
MatchDMIModalias=dmi:*bvn*coreboot*:pn*Leon*
|
||||
ModelChromebook=1
|
||||
|
||||
[Google Chromebook Wolf]
|
||||
MatchUdevType=touchpad
|
||||
MatchName=Cypress APA Trackpad ?cyapa?
|
||||
MatchDMIModalias=dmi:*bvn*coreboot*:pn*Wolf*
|
||||
ModelChromebook=1
|
||||
|
||||
[Google Chromebook Link]
|
||||
MatchUdevType=touchpad
|
||||
MatchName=Cypress APA Trackpad ?cyapa?
|
||||
MatchDMIModalias=dmi:*svn*GOOGLE*:pn*Link*
|
||||
ModelChromebook=1
|
||||
|
||||
[Google Chromebook Alex]
|
||||
MatchUdevType=touchpad
|
||||
MatchName=SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*pn*Alex*
|
||||
ModelChromebook=1
|
||||
|
||||
[Google Chromebook Lumpy]
|
||||
MatchUdevType=touchpad
|
||||
MatchName=Cypress APA Trackpad ?cyapa?
|
||||
MatchDMIModalias=dmi:*svn*SAMSUNG*:pn*Lumpy*
|
||||
ModelChromebook=1
|
||||
|
||||
[Google Chromebook Samus]
|
||||
MatchUdevType=touchpad
|
||||
MatchName=Atmel maXTouch Touchpad
|
||||
MatchDMIModalias=dmi:*svn*GOOGLE*:pn*Samus*
|
||||
ModelChromebook=1
|
||||
24
data/50-system-hp.quirks
Normal file
24
data/50-system-hp.quirks
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[HP Compaq 6910p]
|
||||
MatchName=*SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*svnHewlett-Packard:*pnHPCompaq6910p*
|
||||
ModelHP6910Touchpad=1
|
||||
|
||||
[HP Compaq 8510w]
|
||||
MatchName=*SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*svnHewlett-Packard:*pnHPCompaq8510w*
|
||||
ModelHP8510Touchpad=1
|
||||
|
||||
[HP Pavillion dmi4]
|
||||
MatchName=*SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*svnHewlett-Packard:*pnHPPaviliondm4NotebookPC*
|
||||
ModelHPPavilionDM4Touchpad=1
|
||||
|
||||
[HP Stream 11]
|
||||
MatchName=SYN1EDE:00 06CB:7442
|
||||
MatchDMIModalias=dmi:*svnHewlett-Packard:pnHPStreamNotebookPC11*
|
||||
ModelHPStream11Touchpad=1
|
||||
|
||||
[HP ZBook Studio G3]
|
||||
MatchName=AlpsPS/2 ALPS GlidePoint
|
||||
MatchDMIModalias=dmi:*svnHP:pnHPZBookStudioG3:*
|
||||
ModelHPZBookStudioG3=1
|
||||
78
data/50-system-lenovo.quirks
Normal file
78
data/50-system-lenovo.quirks
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
[Lenovo Thinkpad Touchpad]
|
||||
MatchName=*Synaptics*
|
||||
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPad*:*
|
||||
AttrThumbPressureThreshold=100
|
||||
|
||||
[Lenovo x230 Touchpad]
|
||||
MatchName=*SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadX230*
|
||||
ModelLenovoX230=1
|
||||
|
||||
[Lenovo T440p Touchpad PS/2]
|
||||
MatchName=SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadT440p*
|
||||
ModelLenovoT450Touchpad=1
|
||||
|
||||
[Lenovo T440p Touchpad RMI4]
|
||||
MatchName=Synaptics tm2964-001
|
||||
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadT440p*
|
||||
ModelLenovoT450Touchpad=1
|
||||
|
||||
[Lenovo T440s Trackpoint]
|
||||
MatchName=TPPS/2 IBM TrackPoint
|
||||
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadT440s*
|
||||
AttrTrackpointRange=30
|
||||
|
||||
[Lenovo T440s Trackpoint]
|
||||
MatchName=TPPS/2 IBM TrackPoint
|
||||
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadT450s*
|
||||
AttrTrackpointRange=50
|
||||
|
||||
[Lenovo P50 Touchpad]
|
||||
MatchName=SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadP50*:
|
||||
ModelLenovoT450Touchpad=1
|
||||
AttrPalmPressureThreshold=150
|
||||
|
||||
[Lenovo *50 Touchpad]
|
||||
MatchName=SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPad??50*:
|
||||
ModelLenovoT450Touchpad=1
|
||||
AttrPalmPressureThreshold=150
|
||||
|
||||
[Lenovo *60 Touchpad]
|
||||
MatchName=SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPad??60*:
|
||||
ModelLenovoT450Touchpad=1
|
||||
AttrPalmPressureThreshold=150
|
||||
|
||||
[Lenovo X1 Carbon 3rd Touchpad]
|
||||
MatchName=SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadX1Carbon3rd:*
|
||||
ModelLenovoT450Touchpad=1
|
||||
AttrPalmPressureThreshold=150
|
||||
|
||||
[Lenovo ThinkPad Compact USB Keyboard with TrackPoint]
|
||||
MatchUdevType=keyboard
|
||||
MatchBus=usb
|
||||
MatchVendor=0x17EF
|
||||
MatchProduct=0x6047
|
||||
AttrKeyboardIntegration=external
|
||||
|
||||
[Lenovo X280 Trackpoint]
|
||||
MatchName=*ALPS TrackPoint*
|
||||
MatchDMIModalias=dmi:*svnLENOVO:*:pvrThinkPadX280:*
|
||||
AttrTrackpointRange=70
|
||||
|
||||
# Lenovo Thinkpad X1 Yoga disables the keyboard anyway but has the same device
|
||||
# use a windows key on the screen and volume rocker on the side (#103749)
|
||||
[Lenovo Thinkpad X1 Yoga]
|
||||
MatchName=AT Translated Set 2 keyboard
|
||||
MatchDMIModalias=dmi:*svnLENOVO:*pvrThinkPadX1Yoga1st:*
|
||||
ModelTabletModeNoSuspend=1
|
||||
|
||||
# Lenovo Carbon X1 6th gen (RMI4 only, PS/2 is broken on this device)
|
||||
[Lenovo Carbon X1 6th gen]
|
||||
MatchName=Synaptics TM3288-010
|
||||
MatchDMIModalias=dmi:*svnLenovo:*pvrThinkPadX1Carbon6th:*
|
||||
ModelLenovoCarbonX16th=1
|
||||
19
data/50-system-system76.quirks
Normal file
19
data/50-system-system76.quirks
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
[System76 Bonobo Professional]
|
||||
MatchName=SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*svnSystem76*pvrbonp5*
|
||||
ModelSystem76Bonobo=1
|
||||
|
||||
[System76 Clevo]
|
||||
MatchName=SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*pnW740SU*rnW740SU*
|
||||
ModelClevoW740SU=1
|
||||
|
||||
[System76 Galago Ultra Pro]
|
||||
MatchName=SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*svnSystem76*pvrgalu1*
|
||||
ModelSystem76Galago=1
|
||||
|
||||
[System76 Kudu Professional]
|
||||
MatchName=SynPS/2 Synaptics TouchPad
|
||||
MatchDMIModalias=dmi:*svnSystem76*pvrkudp1*
|
||||
ModelSystem76Kudu=1
|
||||
78
data/README.md
Normal file
78
data/README.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
= libinput data file format =
|
||||
|
||||
This directory contains hardware quirks used by libinput to work around bugs
|
||||
in the hardware, device behavior and to supply information not obtained
|
||||
through the kernel device.
|
||||
|
||||
**THIS IS NOT STABLE API**
|
||||
|
||||
The data format may change at any time. If your data file is not part of the
|
||||
libinput git tree, do not expect it to work after an update. Absolutely no
|
||||
guarantees are made for backwards-compatibility.
|
||||
|
||||
**THIS IS NOT A CONFIGURATION API**
|
||||
|
||||
Use the `libinput_device_config_foo()` functions for device configuration.
|
||||
The quirks are hardware quirks only.
|
||||
|
||||
== Data file naming ==
|
||||
|
||||
Data files are read in versionsort order, read order determines how values
|
||||
override each other. A values read later override previously values. The
|
||||
current structure is 10-generic-foo.quirks for generic settings,
|
||||
30-vendor-foo.quirks for vendor-specific settings and 50-system-foo.quirks
|
||||
for system vendors. This is not a fixed naming scheme and may change at any
|
||||
time. It's an approximation only because some vendors are also system
|
||||
vendors, e.g. Microsoft makes devices and laptops.
|
||||
|
||||
Laptop-specific quirks should always go into the laptop vendor's file.
|
||||
|
||||
== Sections, matches and values ==
|
||||
|
||||
A data file must contain at least one section, each section must have at
|
||||
least one `Match` tag and at least one of either `Attr` or `Model`. Section
|
||||
names are free-form and may contain spaces.
|
||||
|
||||
```
|
||||
# This is a comment
|
||||
[Some touchpad]
|
||||
MatchBus=usb
|
||||
# No quotes around strings
|
||||
MatchName=*Synaptics Touchpad*
|
||||
AttrSizeHint=50x50
|
||||
ModelSynapticsTouchpad=1
|
||||
|
||||
[Apple touchpad]
|
||||
MatchVendor=0x5AC
|
||||
MatchProduct=0x123
|
||||
ModelAppleTouchpad=1
|
||||
```
|
||||
|
||||
Comments are lines starting with `#`.
|
||||
|
||||
All `Model` tags take a value of either `1` or `0`.
|
||||
|
||||
All `Attr` tag values are specific to that attribute.
|
||||
|
||||
== Parser errors ==
|
||||
|
||||
The following will cause parser errors and are considered invalid data
|
||||
files:
|
||||
|
||||
* Whitespace at the beginning of the line
|
||||
* Inline comments, e.g. `MatchBus=usb # oops, fail`
|
||||
* Sections without at least one `Match*` entry
|
||||
* Sections with the same `Match*` entry repeated
|
||||
* Sections without at least one of `Model*` or `Attr` entries
|
||||
* A `Model` tag with a value other than `1` or `0`
|
||||
* A string property with enclosing quotes
|
||||
|
||||
== Debugging ==
|
||||
|
||||
When modifying a data file, use the `libinput list-quirks` tool to
|
||||
verify the changes. The tool can be pointed at the data directory to
|
||||
analyse, use `--verbose` to get more info. For example:
|
||||
|
||||
```
|
||||
libinput list-quirks --data-dir /path/to/git/repo/data/ --verbose /dev/input/event0
|
||||
```
|
||||
102
doc/device-quirks.dox
Normal file
102
doc/device-quirks.dox
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
@page device-quirks Device quirks
|
||||
|
||||
libinput requires extra information from devices that is not always readily
|
||||
available. For example, some touchpads are known to have jumping cursors
|
||||
under specific conditions. libinput ships a set of files containting the
|
||||
so-called model quirks to provide that information. Model quirks are usually
|
||||
installed under `/usr/share/libinput/<filename>.quirks` and are standard
|
||||
`.ini` files. A file may contain multiple section headers (`[some
|
||||
identifier]`) followed by one or more `MatchFoo=Bar` directives, followed by
|
||||
at least one of `ModelFoo=1` or `AttrFoo=bar` directive. See the
|
||||
`data/README.md` file in the libinput source repository for more details on
|
||||
their contents.
|
||||
|
||||
@note Model quirks are internal API and may change at any time. No
|
||||
backwards-compatibility is guaranteed.
|
||||
|
||||
For example, a quirks file may have this content to label all keyboards on
|
||||
the serial bus (PS/2) as internal keyboards:
|
||||
|
||||
@verbatim
|
||||
[Serial Keyboards]
|
||||
MatchUdevType=keyboard
|
||||
MatchBus=serial
|
||||
AttrKeyboardIntegration=internal
|
||||
@endverbatim
|
||||
|
||||
The model quirks are part of the source distribution and should never be
|
||||
modified locally. Updates to libinput may overwrite modifications or even
|
||||
stop parsing any property. For temporary local workarounds, see @ref
|
||||
device-quirks-local.
|
||||
|
||||
Device quirks are parsed on libinput initialization. A parsing error in the
|
||||
device quirks disables **all** device quirks and may negatively impact
|
||||
device behavior on the host. If the quirks cannot be loaded, an error
|
||||
message is posted to the log and users should use the information in @ref
|
||||
device-quirks-debugging to verify their quirks files.
|
||||
|
||||
@section device-quirks-local Installing temporary local device quirks
|
||||
|
||||
The model quirks are part of the source distribution and should never be
|
||||
modified. For temporary local workarounds, libinput reads the
|
||||
`/etc/libinput/local-overrides.quirks` file. Users may add a sections to
|
||||
this file to add a device quirk for a local device but beware that **any
|
||||
modification must be upstreamed** or it may cease to work at any time.
|
||||
|
||||
@note Model quirks are internal API and may change at any time. No
|
||||
backwards-compatibility is guaranteed. Local overrides should only be used
|
||||
until the distribution updates the libinput packages.
|
||||
|
||||
The `local-overrides.quirks` file usually needs to be created by the user.
|
||||
Once the required section has been added, use the information from section
|
||||
@ref device-quirks-debugging to validate and test the quirks.
|
||||
|
||||
@section device-quirks-debugging Debugging device quirks
|
||||
|
||||
libinput provides the `libinput list-quirks` tool to list and debug model
|
||||
quirks that apply to one or more local devices.
|
||||
|
||||
@verbatim
|
||||
$ libinput list-quirks /dev/input/event19
|
||||
Device has no quirks defined
|
||||
$ libinput list-quirks /dev/input/event0
|
||||
AttrLidSwitchReliability
|
||||
@endverbatim
|
||||
|
||||
When called with the `--verbose` argument, `libinput list-quirks` prints
|
||||
information about all files and its attempts to match the device:
|
||||
|
||||
@verbatim
|
||||
$ libinput list-quirks --verbose /dev/input/event0
|
||||
quirks debug: /usr/share/share/libinput is data root
|
||||
quirks debug: /usr/share/share/libinput/10-generic-keyboard.quirks
|
||||
quirks debug: /usr/share/share/libinput/10-generic-lid.quirks
|
||||
[...]
|
||||
quirks debug: /usr/share/etc/libinput/local-overrides.quirks
|
||||
quirks debug: /dev/input/event0: fetching quirks
|
||||
quirks debug: [Serial Keyboards] (10-generic-keyboard.quirks) wants MatchBus but we don't have that
|
||||
quirks debug: [Lid Switch Ct9] (10-generic-lid.quirks) matches for MatchName
|
||||
quirks debug: [Lid Switch Ct10] (10-generic-lid.quirks) matches for MatchName
|
||||
quirks debug: [Lid Switch Ct10] (10-generic-lid.quirks) matches for MatchDMIModalias
|
||||
quirks debug: [Lid Switch Ct10] (10-generic-lid.quirks) is full match
|
||||
quirks debug: property added: AttrLidSwitchReliability from [Lid Switch Ct10] (10-generic-lid.quirks)
|
||||
quirks debug: [Aiptek No Tilt Tablet] (30-vendor-aiptek.quirks) wants MatchBus but we don't have that
|
||||
[...]
|
||||
quirks debug: [HUION PenTablet] (30-vendor-huion.quirks) wants MatchBus but we don't have that
|
||||
quirks debug: [Logitech Marble Mouse Trackball] (30-vendor-logitech.quirks) wants MatchBus but we don't have that
|
||||
quirks debug: [Logitech K400] (30-vendor-logitech.quirks) wants MatchBus but we don't have that
|
||||
quirks debug: [Logitech K400r] (30-vendor-logitech.quirks) wants MatchBus but we don't have that
|
||||
quirks debug: [Logitech K830] (30-vendor-logitech.quirks) wants MatchBus but we don't have that
|
||||
quirks debug: [Logitech K400Plus] (30-vendor-logitech.quirks) wants MatchBus but we don't have that
|
||||
quirks debug: [Logitech Wireless Touchpad] (30-vendor-logitech.quirks) wants MatchBus but we don't have that
|
||||
quirks debug: [Microsoft Surface 3 Lid Switch] (30-vendor-microsoft.quirks) matches for MatchName
|
||||
[...]
|
||||
AttrLidSwitchReliability
|
||||
@endverbatim
|
||||
|
||||
Note that this is an example only, the output may change over time. The tool
|
||||
uses the same parser as libinput and any parsing errors will show up in the
|
||||
output.
|
||||
|
||||
*/
|
||||
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
@page general General
|
||||
|
||||
- @subpage device-quirks
|
||||
- @subpage udev_config
|
||||
- @subpage seats
|
||||
- @subpage timestamps
|
||||
|
|
|
|||
72
meson.build
72
meson.build
|
|
@ -181,6 +181,54 @@ libfilter = static_library('filter', src_libfilter,
|
|||
include_directories : includes_include)
|
||||
dep_libfilter = declare_dependency(link_with : libfilter)
|
||||
|
||||
############ libquirks.a #############
|
||||
libinput_data_path = join_paths(get_option('prefix'), get_option('datadir'), 'libinput')
|
||||
libinput_data_override_path = join_paths(get_option('prefix'),
|
||||
get_option('sysconfdir'),
|
||||
'libinput',
|
||||
'local-overrides.quirks')
|
||||
config_h.set_quoted('LIBINPUT_DATA_DIR', libinput_data_path)
|
||||
config_h.set_quoted('LIBINPUT_DATA_OVERRIDE_FILE', libinput_data_override_path)
|
||||
|
||||
quirks_data = [
|
||||
'data/10-generic-keyboard.quirks',
|
||||
'data/10-generic-lid.quirks',
|
||||
'data/10-generic-trackball.quirks',
|
||||
'data/30-vendor-aiptek.quirks',
|
||||
'data/30-vendor-alps.quirks',
|
||||
'data/30-vendor-cyapa.quirks',
|
||||
'data/30-vendor-elantech.quirks',
|
||||
'data/30-vendor-huion.quirks',
|
||||
'data/30-vendor-ibm.quirks',
|
||||
'data/30-vendor-logitech.quirks',
|
||||
'data/30-vendor-microsoft.quirks',
|
||||
'data/30-vendor-razer.quirks',
|
||||
'data/30-vendor-synaptics.quirks',
|
||||
'data/30-vendor-wacom.quirks',
|
||||
'data/50-system-apple.quirks',
|
||||
'data/50-system-asus.quirks',
|
||||
'data/50-system-chicony.quirks',
|
||||
'data/50-system-cyborg.quirks',
|
||||
'data/50-system-dell.quirks',
|
||||
'data/50-system-google.quirks',
|
||||
'data/50-system-hp.quirks',
|
||||
'data/50-system-lenovo.quirks',
|
||||
'data/50-system-system76.quirks',
|
||||
]
|
||||
|
||||
install_data(quirks_data, install_dir : libinput_data_path)
|
||||
|
||||
src_libquirks = [
|
||||
'src/quirks.c',
|
||||
'src/quirks.h',
|
||||
]
|
||||
|
||||
deps_libquirks = [dep_udev, dep_libinput_util]
|
||||
libquirks = static_library('quirks', src_libquirks,
|
||||
dependencies : deps_libquirks,
|
||||
include_directories : includes_include)
|
||||
dep_libquirks = declare_dependency(link_with : libquirks)
|
||||
|
||||
############ libinput.so ############
|
||||
install_headers('src/libinput.h')
|
||||
src_libinput = src_libfilter + [
|
||||
|
|
@ -220,7 +268,8 @@ deps_libinput = [
|
|||
dep_lm,
|
||||
dep_rt,
|
||||
dep_libwacom,
|
||||
dep_libinput_util
|
||||
dep_libinput_util,
|
||||
dep_libquirks
|
||||
]
|
||||
|
||||
libinput_version_h_config = configuration_data()
|
||||
|
|
@ -317,6 +366,7 @@ if get_option('documentation')
|
|||
meson.source_root() + '/doc/clickpad-softbuttons.dox',
|
||||
meson.source_root() + '/doc/contributing.dox',
|
||||
meson.source_root() + '/doc/device-configuration-via-udev.dox',
|
||||
meson.source_root() + '/doc/device-quirks.dox',
|
||||
meson.source_root() + '/doc/faqs.dox',
|
||||
meson.source_root() + '/doc/gestures.dox',
|
||||
meson.source_root() + '/doc/middle-button-emulation.dox',
|
||||
|
|
@ -435,6 +485,22 @@ configure_file(input : 'tools/libinput-debug-events.man',
|
|||
install_dir : join_paths(get_option('mandir'), 'man1')
|
||||
)
|
||||
|
||||
libinput_list_quirks_sources = [ 'tools/libinput-list-quirks.c' ]
|
||||
executable('libinput-list-quirks',
|
||||
libinput_list_quirks_sources,
|
||||
dependencies : [dep_libquirks, dep_libinput],
|
||||
include_directories : [includes_src, includes_include],
|
||||
install_dir : libinput_tool_path,
|
||||
install : true
|
||||
)
|
||||
|
||||
configure_file(input : 'tools/libinput-list-quirks.man',
|
||||
output : 'libinput-list-quirks.1',
|
||||
configuration : man_config,
|
||||
install : true,
|
||||
install_dir : join_paths(get_option('mandir'), 'man1')
|
||||
)
|
||||
|
||||
libinput_list_devices_sources = [ 'tools/libinput-list-devices.c' ]
|
||||
executable('libinput-list-devices',
|
||||
libinput_list_devices_sources,
|
||||
|
|
@ -697,6 +763,7 @@ if get_option('tests')
|
|||
dep_dl,
|
||||
dep_lm,
|
||||
dep_libsystemd,
|
||||
dep_libquirks,
|
||||
]
|
||||
|
||||
configure_file(input : 'udev/80-libinput-test-device.rules',
|
||||
|
|
@ -763,7 +830,8 @@ if get_option('tests')
|
|||
'test/test-keyboard.c',
|
||||
'test/test-device.c',
|
||||
'test/test-gestures.c',
|
||||
'test/test-switch.c'
|
||||
'test/test-switch.c',
|
||||
'test/test-quirks.c',
|
||||
]
|
||||
def_LT_VERSION = '-DLIBINPUT_LT_VERSION="@0@:@1@:@2@"'.format(libinput_lt_c, libinput_lt_r, libinput_lt_a)
|
||||
libinput_test_runner = executable('libinput-test-suite-runner',
|
||||
|
|
|
|||
1437
src/quirks.c
Normal file
1437
src/quirks.c
Normal file
File diff suppressed because it is too large
Load diff
273
src/quirks.h
Normal file
273
src/quirks.h
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
/*
|
||||
* Copyright © 2018 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libudev.h>
|
||||
|
||||
#include "libinput.h"
|
||||
|
||||
/**
|
||||
* Handle to the quirks context.
|
||||
*/
|
||||
struct quirks_context;
|
||||
|
||||
/**
|
||||
* Contains all quirks set for a single device.
|
||||
*/
|
||||
struct quirks;
|
||||
|
||||
struct quirk_dimensions {
|
||||
size_t x, y;
|
||||
};
|
||||
|
||||
struct quirk_range {
|
||||
int lower, upper;
|
||||
};
|
||||
|
||||
/**
|
||||
* Quirks known to libinput
|
||||
*/
|
||||
enum quirk {
|
||||
QUIRK_MODEL_ALPS_TOUCHPAD = 100,
|
||||
QUIRK_MODEL_APPLE_TOUCHPAD,
|
||||
QUIRK_MODEL_APPLE_MAGICMOUSE,
|
||||
QUIRK_MODEL_TABLET_NO_TILT,
|
||||
QUIRK_MODEL_APPLE_TOUCHPAD_ONEBUTTON,
|
||||
QUIRK_MODEL_TOUCHPAD_VISIBLE_MARKER,
|
||||
QUIRK_MODEL_CYBORG_RAT,
|
||||
QUIRK_MODEL_CHROMEBOOK,
|
||||
QUIRK_MODEL_HP6910_TOUCHPAD,
|
||||
QUIRK_MODEL_HP8510_TOUCHPAD,
|
||||
QUIRK_MODEL_HP_PAVILION_DM4_TOUCHPAD,
|
||||
QUIRK_MODEL_HP_STREAM11_TOUCHPAD,
|
||||
QUIRK_MODEL_HP_ZBOOK_STUDIO_G3,
|
||||
QUIRK_MODEL_TABLET_NO_PROXIMITY_OUT,
|
||||
QUIRK_MODEL_LENOVO_SCROLLPOINT,
|
||||
QUIRK_MODEL_LENOVO_X230,
|
||||
QUIRK_MODEL_LENOVO_T450_TOUCHPAD,
|
||||
QUIRK_MODEL_TABLET_MODE_NO_SUSPEND,
|
||||
QUIRK_MODEL_LENOVO_CARBON_X1_6TH,
|
||||
QUIRK_MODEL_TRACKBALL,
|
||||
QUIRK_MODEL_LOGITECH_MARBLE_MOUSE,
|
||||
QUIRK_MODEL_BOUNCING_KEYS,
|
||||
QUIRK_MODEL_SYNAPTICS_SERIAL_TOUCHPAD,
|
||||
QUIRK_MODEL_SYSTEM76_BONOBO,
|
||||
QUIRK_MODEL_CLEVO_W740SU,
|
||||
QUIRK_MODEL_SYSTEM76_GALAGO,
|
||||
QUIRK_MODEL_SYSTEM76_KUDU,
|
||||
QUIRK_MODEL_WACOM_TOUCHPAD,
|
||||
QUIRK_MODEL_JUMPING_SEMI_MT,
|
||||
|
||||
|
||||
QUIRK_ATTR_SIZE_HINT = 300,
|
||||
QUIRK_ATTR_TOUCH_SIZE_RANGE,
|
||||
QUIRK_ATTR_PALM_SIZE_THRESHOLD,
|
||||
QUIRK_ATTR_LID_SWITCH_RELIABILITY,
|
||||
QUIRK_ATTR_KEYBOARD_INTEGRATION,
|
||||
QUIRK_ATTR_TPKBCOMBO_LAYOUT,
|
||||
QUIRK_ATTR_PRESSURE_RANGE,
|
||||
QUIRK_ATTR_PALM_PRESSURE_THRESHOLD,
|
||||
QUIRK_ATTR_RESOLUTION_HINT,
|
||||
QUIRK_ATTR_TRACKPOINT_RANGE,
|
||||
QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD,
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a printable name for the quirk. This name is for developer
|
||||
* tools, not user consumption. Do not display this in a GUI.
|
||||
*/
|
||||
const char*
|
||||
quirk_get_name(enum quirk which);
|
||||
|
||||
/**
|
||||
* Log priorities used if custom logging is enabled.
|
||||
*/
|
||||
enum quirks_log_priorities {
|
||||
QLOG_NOISE,
|
||||
QLOG_DEBUG = LIBINPUT_LOG_PRIORITY_DEBUG,
|
||||
QLOG_INFO = LIBINPUT_LOG_PRIORITY_INFO,
|
||||
QLOG_ERROR = LIBINPUT_LOG_PRIORITY_ERROR,
|
||||
QLOG_PARSER_ERROR,
|
||||
};
|
||||
|
||||
/**
|
||||
* Log type to be used for logging. Use the libinput logging to hook up a
|
||||
* libinput log handler. This will cause the quirks to reduce the noise and
|
||||
* only provide useful messages.
|
||||
*
|
||||
* QLOG_CUSTOM_LOG_PRIORITIES enables more fine-grained and verbose logging,
|
||||
* allowing debugging tools to be more useful.
|
||||
*/
|
||||
enum quirks_log_type {
|
||||
QLOG_LIBINPUT_LOGGING,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES,
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the quirks subsystem. This function must be called
|
||||
* before anything else.
|
||||
*
|
||||
* If log_type is QLOG_CUSTOM_LOG_PRIORITIES, the log handler is called with
|
||||
* the custom QLOG_* log priorities. Otherwise, the log handler only uses
|
||||
* the libinput log priorities.
|
||||
*
|
||||
* @param data_path The directory containing the various data files
|
||||
* @param override_file A file path containing custom overrides
|
||||
* @param log_handler The libinput log handler called for debugging output
|
||||
* @param libinput The libinput struct passed to the log handler
|
||||
*
|
||||
* @return an opaque handle to the context
|
||||
*/
|
||||
struct quirks_context *
|
||||
quirks_init_subsystem(const char *data_path,
|
||||
const char *override_file,
|
||||
libinput_log_handler log_handler,
|
||||
struct libinput *libinput,
|
||||
enum quirks_log_type log_type);
|
||||
|
||||
/**
|
||||
* Clean up after ourselves. This function must be called
|
||||
* as the last call to the quirks subsystem.
|
||||
*
|
||||
* All quirks returned to the caller in quirks_fetch_for_device() must be
|
||||
* unref'd before this call.
|
||||
*
|
||||
* @return Always NULL
|
||||
*/
|
||||
struct quirks_context *
|
||||
quirks_context_unref(struct quirks_context *ctx);
|
||||
|
||||
struct quirks_context *
|
||||
quirks_context_ref(struct quirks_context *ctx);
|
||||
|
||||
/**
|
||||
* Fetch the quirks for a given device. If no quirks are defined, this
|
||||
* function returns NULL.
|
||||
*
|
||||
* @return A new quirks struct, use quirks_unref() to release
|
||||
*/
|
||||
struct quirks *
|
||||
quirks_fetch_for_device(struct quirks_context *ctx,
|
||||
struct udev_device *device);
|
||||
|
||||
/**
|
||||
* Reduce the refcount by one. When the refcount reaches zero, the
|
||||
* associated struct is released.
|
||||
*
|
||||
* @return Always NULL
|
||||
*/
|
||||
struct quirks *
|
||||
quirks_unref(struct quirks *q);
|
||||
|
||||
/**
|
||||
* Returns true if the given quirk applies is in this quirk list.
|
||||
*/
|
||||
bool
|
||||
quirks_has_quirk(struct quirks *q, enum quirk which);
|
||||
|
||||
/**
|
||||
* Get the value of the given quirk, as unsigned integer.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, val is
|
||||
* unchanged.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_uint32(struct quirks *q,
|
||||
enum quirk which,
|
||||
uint32_t *val);
|
||||
|
||||
/**
|
||||
* Get the value of the given quirk, as signed integer.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, val is
|
||||
* unchanged.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_int32(struct quirks *q,
|
||||
enum quirk which,
|
||||
int32_t *val);
|
||||
|
||||
/**
|
||||
* Get the value of the given quirk, as string.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, val is
|
||||
* unchanged.
|
||||
*
|
||||
* val is set to the string, do not modify or free it. The lifetime of the
|
||||
* returned string is bound to the lifetime of the quirk.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_string(struct quirks *q,
|
||||
enum quirk which,
|
||||
char **val);
|
||||
|
||||
/**
|
||||
* Get the value of the given quirk, as bool.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, val is
|
||||
* unchanged.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_bool(struct quirks *q,
|
||||
enum quirk which,
|
||||
bool *val);
|
||||
|
||||
/**
|
||||
* Get the value of the given quirk, as dimension.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, val is
|
||||
* unchanged.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_dimensions(struct quirks *q,
|
||||
enum quirk which,
|
||||
struct quirk_dimensions *val);
|
||||
|
||||
/**
|
||||
* Get the value of the given quirk, as range.
|
||||
* This function will assert if the quirk type does not match the
|
||||
* requested type. If the quirk is not set for this device, val is
|
||||
* unchanged.
|
||||
*
|
||||
* @return true if the quirk value is valid, false otherwise.
|
||||
*/
|
||||
bool
|
||||
quirks_get_range(struct quirks *q,
|
||||
enum quirk which,
|
||||
struct quirk_range *val);
|
||||
809
test/test-quirks.c
Normal file
809
test/test-quirks.c
Normal file
|
|
@ -0,0 +1,809 @@
|
|||
/*
|
||||
* Copyright © 2018 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <check.h>
|
||||
#include <libinput.h>
|
||||
|
||||
#include "libinput-util.h"
|
||||
#include "litest.h"
|
||||
#include "quirks.h"
|
||||
|
||||
static void
|
||||
log_handler(struct libinput *this_is_null,
|
||||
enum libinput_log_priority priority,
|
||||
const char *format,
|
||||
va_list args)
|
||||
{
|
||||
#if 0
|
||||
vprintf(format, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct data_dir {
|
||||
char *dirname;
|
||||
char *filename;
|
||||
};
|
||||
|
||||
static struct data_dir
|
||||
make_data_dir(const char *file_content)
|
||||
{
|
||||
struct data_dir dir = {0};
|
||||
char dirname[PATH_MAX] = "/run/litest-quirk-test-XXXXXX";
|
||||
char *filename;
|
||||
FILE *fp;
|
||||
int rc;
|
||||
|
||||
litest_assert_notnull(mkdtemp(dirname));
|
||||
dir.dirname = safe_strdup(dirname);
|
||||
|
||||
if (file_content) {
|
||||
rc = xasprintf(&filename, "%s/testfile.quirks", dirname);
|
||||
litest_assert_int_eq(rc, (int)(strlen(dirname) + 16));
|
||||
|
||||
fp = fopen(filename, "w+");
|
||||
rc = fputs(file_content, fp);
|
||||
fclose(fp);
|
||||
litest_assert_int_ge(rc, 0);
|
||||
dir.filename = filename;
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup_data_dir(struct data_dir dd)
|
||||
{
|
||||
if (dd.filename) {
|
||||
unlink(dd.filename);
|
||||
free(dd.filename);
|
||||
}
|
||||
if (dd.dirname) {
|
||||
rmdir(dd.dirname);
|
||||
free(dd.dirname);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(quirks_invalid_dir)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
|
||||
ctx = quirks_init_subsystem("/does-not-exist",
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_LIBINPUT_LOGGING);
|
||||
ck_assert(ctx == NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_empty_dir)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
struct data_dir dd = make_data_dir(NULL);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_LIBINPUT_LOGGING);
|
||||
ck_assert(ctx == NULL);
|
||||
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_section_empty)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] = "[Empty Section]";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_section_double)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] = "[Section name]";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_section_missing_match)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"AttrSizeHint=10x10\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_section_missing_attr)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=mouse\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_section_match_after_attr)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=mouse\n"
|
||||
"AttrSizeHint=10x10\n"
|
||||
"MatchName=mouse\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_section_duplicate_match)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=mouse\n"
|
||||
"MatchUdevType=mouse\n"
|
||||
"AttrSizeHint=10x10\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_section_duplicate_attr)
|
||||
{
|
||||
/* This shouldn't be allowed but the current parser
|
||||
is happy with it */
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=mouse\n"
|
||||
"AttrSizeHint=10x10\n"
|
||||
"AttrSizeHint=10x10\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert_notnull(ctx);
|
||||
quirks_context_unref(ctx);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_error_section)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section Missing Bracket\n"
|
||||
"MatchUdevType=mouse\n"
|
||||
"AttrSizeHint=10x10\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_error_unknown_match)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"Matchblahblah=mouse\n"
|
||||
"AttrSizeHint=10x10\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_error_unknown_attr)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=mouse\n"
|
||||
"Attrblahblah=10x10\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_error_unknown_model)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=mouse\n"
|
||||
"Modelblahblah=1\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_error_model_not_one)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=mouse\n"
|
||||
"ModelAppleTouchpad=true\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_bustype)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchBus=usb\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchBus=bluetooth\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchBus=i2c\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchBus=rmi\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchBus=ps2\n"
|
||||
"ModelAppleTouchpad=1\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert_notnull(ctx);
|
||||
quirks_context_unref(ctx);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_bustype_invalid)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchBustype=venga\n"
|
||||
"ModelAppleTouchpad=1\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_vendor)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchVendor=0x0000\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchVendor=0x0001\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchVendor=0x2343\n"
|
||||
"ModelAppleTouchpad=1\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert_notnull(ctx);
|
||||
quirks_context_unref(ctx);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_vendor_invalid)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char *quirks_file[] = {
|
||||
"[Section name]\n"
|
||||
"MatchVendor=-1\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
"[Section name]\n"
|
||||
"MatchVendor=abc\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
"[Section name]\n"
|
||||
"MatchVendor=0xFFFFF\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
"[Section name]\n"
|
||||
"MatchVendor=123\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
};
|
||||
const char **qf;
|
||||
|
||||
ARRAY_FOR_EACH(quirks_file, qf) {
|
||||
struct data_dir dd = make_data_dir(*qf);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_product)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchProduct=0x0000\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchProduct=0x0001\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchProduct=0x2343\n"
|
||||
"ModelAppleTouchpad=1\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert_notnull(ctx);
|
||||
quirks_context_unref(ctx);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_product_invalid)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char *quirks_file[] = {
|
||||
"[Section name]\n"
|
||||
"MatchProduct=-1\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
"[Section name]\n"
|
||||
"MatchProduct=abc\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
"[Section name]\n"
|
||||
"MatchProduct=0xFFFFF\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
"[Section name]\n"
|
||||
"MatchProduct=123\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
};
|
||||
const char **qf;
|
||||
|
||||
ARRAY_FOR_EACH(quirks_file, qf) {
|
||||
struct data_dir dd = make_data_dir(*qf);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_name)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchName=1235\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchName=abc\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchName=*foo\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchName=foo*\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchName=foo[]\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchName=*foo*\n"
|
||||
"ModelAppleTouchpad=1\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert_notnull(ctx);
|
||||
quirks_context_unref(ctx);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_name_invalid)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char *quirks_file[] = {
|
||||
"[Section name]\n"
|
||||
"MatchName=\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
};
|
||||
const char **qf;
|
||||
|
||||
ARRAY_FOR_EACH(quirks_file, qf) {
|
||||
struct data_dir dd = make_data_dir(*qf);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_udev)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=touchpad\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=mouse\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=pointingstick\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=tablet\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=tablet-pad\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=keyboard\n"
|
||||
"ModelAppleTouchpad=1\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert_notnull(ctx);
|
||||
quirks_context_unref(ctx);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_udev_invalid)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char *quirks_file[] = {
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=blah\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=123\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
};
|
||||
const char **qf;
|
||||
|
||||
ARRAY_FOR_EACH(quirks_file, qf) {
|
||||
struct data_dir dd = make_data_dir(*qf);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_dmi)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchDMIModalias=dmi:*\n"
|
||||
"ModelAppleTouchpad=1\n"
|
||||
"\n"
|
||||
"[Section name]\n"
|
||||
"MatchDMIModalias=dmi:*svn*pn*:\n"
|
||||
"ModelAppleTouchpad=1\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert_notnull(ctx);
|
||||
quirks_context_unref(ctx);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_parse_dmi_invalid)
|
||||
{
|
||||
struct quirks_context *ctx;
|
||||
const char *quirks_file[] = {
|
||||
"[Section name]\n"
|
||||
"MatchDMIModalias=\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
"[Section name]\n"
|
||||
"MatchDMIModalias=*pn*\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
"[Section name]\n"
|
||||
"MatchDMIModalias=dmi*pn*\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
"[Section name]\n"
|
||||
"MatchDMIModalias=foo\n"
|
||||
"ModelAppleTouchpad=1\n",
|
||||
};
|
||||
const char **qf;
|
||||
|
||||
ARRAY_FOR_EACH(quirks_file, qf) {
|
||||
struct data_dir dd = make_data_dir(*qf);
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert(ctx == NULL);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_model_one)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct udev_device *ud = libinput_device_get_udev_device(dev->libinput_device);
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=mouse\n"
|
||||
"ModelAppleTouchpad=1\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
struct quirks *q;
|
||||
bool isset;
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert_notnull(ctx);
|
||||
|
||||
q = quirks_fetch_for_device(ctx, ud);
|
||||
ck_assert_notnull(q);
|
||||
|
||||
ck_assert(quirks_get_bool(q, QUIRK_MODEL_APPLE_TOUCHPAD, &isset));
|
||||
ck_assert(isset == true);
|
||||
|
||||
quirks_unref(q);
|
||||
quirks_context_unref(ctx);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(quirks_model_zero)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct udev_device *ud = libinput_device_get_udev_device(dev->libinput_device);
|
||||
struct quirks_context *ctx;
|
||||
const char quirks_file[] =
|
||||
"[Section name]\n"
|
||||
"MatchUdevType=mouse\n"
|
||||
"ModelAppleTouchpad=0\n";
|
||||
struct data_dir dd = make_data_dir(quirks_file);
|
||||
struct quirks *q;
|
||||
bool isset;
|
||||
|
||||
ctx = quirks_init_subsystem(dd.dirname,
|
||||
NULL,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
ck_assert_notnull(ctx);
|
||||
|
||||
q = quirks_fetch_for_device(ctx, ud);
|
||||
ck_assert_notnull(q);
|
||||
|
||||
ck_assert(quirks_get_bool(q, QUIRK_MODEL_APPLE_TOUCHPAD, &isset));
|
||||
ck_assert(isset == false);
|
||||
|
||||
quirks_unref(q);
|
||||
quirks_context_unref(ctx);
|
||||
cleanup_data_dir(dd);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
TEST_COLLECTION(quirks)
|
||||
{
|
||||
litest_add_for_device("quirks:datadir", quirks_invalid_dir, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:datadir", quirks_empty_dir, LITEST_MOUSE);
|
||||
|
||||
litest_add_for_device("quirks:structure", quirks_section_empty, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:structure", quirks_section_double, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:structure", quirks_section_missing_match, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:structure", quirks_section_missing_attr, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:structure", quirks_section_match_after_attr, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:structure", quirks_section_duplicate_match, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:structure", quirks_section_duplicate_attr, LITEST_MOUSE);
|
||||
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_error_section, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_error_unknown_match, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_error_unknown_attr, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_error_unknown_model, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_error_model_not_one, LITEST_MOUSE);
|
||||
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_bustype, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_bustype_invalid, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_vendor, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_vendor_invalid, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_product, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_product_invalid, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_name, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_name_invalid, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_udev, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_udev_invalid, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_dmi, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:parsing", quirks_parse_dmi_invalid, LITEST_MOUSE);
|
||||
|
||||
litest_add_for_device("quirks:model", quirks_model_one, LITEST_MOUSE);
|
||||
litest_add_for_device("quirks:model", quirks_model_zero, LITEST_MOUSE);
|
||||
}
|
||||
245
tools/libinput-list-quirks.c
Normal file
245
tools/libinput-list-quirks.c
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
* Copyright © 2018 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "libinput-util.h"
|
||||
#include "quirks.h"
|
||||
|
||||
static bool verbose = false;
|
||||
|
||||
static void
|
||||
log_handler(struct libinput *this_is_null,
|
||||
enum libinput_log_priority priority,
|
||||
const char *format,
|
||||
va_list args)
|
||||
{
|
||||
FILE *out = stdout;
|
||||
enum quirks_log_priorities p = priority;
|
||||
char buf[256] = {0};
|
||||
const char *prefix = "";
|
||||
|
||||
switch (p) {
|
||||
case QLOG_NOISE:
|
||||
case QLOG_DEBUG:
|
||||
if (!verbose)
|
||||
return;
|
||||
prefix = "quirks debug";
|
||||
break;
|
||||
case QLOG_INFO:
|
||||
prefix = "quirks info";
|
||||
break;
|
||||
case QLOG_ERROR:
|
||||
out = stderr;
|
||||
prefix = "quirks error";
|
||||
break;
|
||||
case QLOG_PARSER_ERROR:
|
||||
out = stderr;
|
||||
prefix = "quirks parser error";
|
||||
break;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s: %s", prefix, format);
|
||||
vfprintf(out, buf, args);
|
||||
}
|
||||
|
||||
static void
|
||||
list_device_quirks(struct quirks_context *ctx, struct udev_device *device)
|
||||
{
|
||||
struct quirks *quirks;
|
||||
|
||||
quirks = quirks_fetch_for_device(ctx, device);
|
||||
if (!quirks) {
|
||||
printf("Device has no quirks defined\n");
|
||||
} else {
|
||||
enum quirk qlist[] = {
|
||||
QUIRK_MODEL_ALPS_TOUCHPAD,
|
||||
QUIRK_MODEL_APPLE_TOUCHPAD,
|
||||
QUIRK_MODEL_APPLE_MAGICMOUSE,
|
||||
QUIRK_MODEL_TABLET_NO_TILT,
|
||||
QUIRK_MODEL_APPLE_TOUCHPAD_ONEBUTTON,
|
||||
QUIRK_MODEL_TOUCHPAD_VISIBLE_MARKER,
|
||||
QUIRK_MODEL_CYBORG_RAT,
|
||||
QUIRK_MODEL_CHROMEBOOK,
|
||||
QUIRK_MODEL_HP6910_TOUCHPAD,
|
||||
QUIRK_MODEL_HP8510_TOUCHPAD,
|
||||
QUIRK_MODEL_HP_PAVILION_DM4_TOUCHPAD,
|
||||
QUIRK_MODEL_HP_STREAM11_TOUCHPAD,
|
||||
QUIRK_MODEL_HP_ZBOOK_STUDIO_G3,
|
||||
QUIRK_MODEL_TABLET_NO_PROXIMITY_OUT,
|
||||
QUIRK_MODEL_LENOVO_SCROLLPOINT,
|
||||
QUIRK_MODEL_LENOVO_X230,
|
||||
QUIRK_MODEL_LENOVO_T450_TOUCHPAD,
|
||||
QUIRK_MODEL_TABLET_MODE_NO_SUSPEND,
|
||||
QUIRK_MODEL_LENOVO_CARBON_X1_6TH,
|
||||
QUIRK_MODEL_TRACKBALL,
|
||||
QUIRK_MODEL_LOGITECH_MARBLE_MOUSE,
|
||||
QUIRK_MODEL_BOUNCING_KEYS,
|
||||
QUIRK_MODEL_SYNAPTICS_SERIAL_TOUCHPAD,
|
||||
QUIRK_MODEL_SYSTEM76_BONOBO,
|
||||
QUIRK_MODEL_CLEVO_W740SU,
|
||||
QUIRK_MODEL_SYSTEM76_GALAGO,
|
||||
QUIRK_MODEL_SYSTEM76_KUDU,
|
||||
QUIRK_MODEL_WACOM_TOUCHPAD,
|
||||
|
||||
|
||||
QUIRK_ATTR_SIZE_HINT,
|
||||
QUIRK_ATTR_TOUCH_SIZE_RANGE,
|
||||
QUIRK_ATTR_PALM_SIZE_THRESHOLD,
|
||||
QUIRK_ATTR_LID_SWITCH_RELIABILITY,
|
||||
QUIRK_ATTR_KEYBOARD_INTEGRATION,
|
||||
QUIRK_ATTR_TPKBCOMBO_LAYOUT,
|
||||
QUIRK_ATTR_PRESSURE_RANGE,
|
||||
QUIRK_ATTR_PALM_PRESSURE_THRESHOLD,
|
||||
QUIRK_ATTR_RESOLUTION_HINT,
|
||||
QUIRK_ATTR_TRACKPOINT_RANGE,
|
||||
};
|
||||
enum quirk *q;
|
||||
|
||||
ARRAY_FOR_EACH(qlist, q) {
|
||||
if (!quirks_has_quirk(quirks, *q))
|
||||
continue;
|
||||
|
||||
printf("%s\n", quirk_get_name(*q));
|
||||
}
|
||||
}
|
||||
|
||||
quirks_unref(quirks);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage: %s [--data-dir /path/to/data/dir] /dev/input/event0\n",
|
||||
program_invocation_short_name);
|
||||
printf("Note: this tool also takes a syspath\n");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct udev *udev;
|
||||
struct udev_device *device = NULL;
|
||||
const char *path;
|
||||
const char *data_path = NULL,
|
||||
*override_file = NULL;
|
||||
int rc = 1;
|
||||
struct quirks_context *quirks;
|
||||
|
||||
while (1) {
|
||||
int c;
|
||||
int option_index = 0;
|
||||
enum {
|
||||
OPT_VERBOSE,
|
||||
OPT_DATADIR,
|
||||
};
|
||||
static struct option opts[] = {
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ "verbose", no_argument, 0, OPT_VERBOSE },
|
||||
{ "data-dir", required_argument, 0, OPT_DATADIR },
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "h", opts, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch(c) {
|
||||
case '?':
|
||||
exit(1);
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
exit(0);
|
||||
break;
|
||||
case OPT_VERBOSE:
|
||||
verbose = true;
|
||||
break;
|
||||
case OPT_DATADIR:
|
||||
data_path = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (optind >= argc) {
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Overriding the data dir means no custom override file */
|
||||
if (!data_path) {
|
||||
data_path = LIBINPUT_DATA_DIR;
|
||||
override_file = LIBINPUT_DATA_OVERRIDE_FILE;
|
||||
}
|
||||
|
||||
quirks = quirks_init_subsystem(data_path,
|
||||
override_file,
|
||||
log_handler,
|
||||
NULL,
|
||||
QLOG_CUSTOM_LOG_PRIORITIES);
|
||||
if (!quirks) {
|
||||
fprintf(stderr,
|
||||
"Failed to initialize the device quirks. "
|
||||
"Please see the above errors "
|
||||
"and/or re-run with --verbose for more details\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
udev = udev_new();
|
||||
path = argv[optind];
|
||||
if (strneq(path, "/sys/", 5)) {
|
||||
device = udev_device_new_from_syspath(udev, path);
|
||||
} else {
|
||||
struct stat st;
|
||||
if (stat(path, &st) < 0) {
|
||||
fprintf(stderr, "Error: %s: %m\n", path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
|
||||
}
|
||||
if (device) {
|
||||
list_device_quirks(quirks, device);
|
||||
rc = 0;
|
||||
} else {
|
||||
usage();
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
udev_device_unref(device);
|
||||
out:
|
||||
udev_unref(udev);
|
||||
|
||||
quirks_context_unref(quirks);
|
||||
|
||||
return rc;
|
||||
}
|
||||
28
tools/libinput-list-quirks.man
Normal file
28
tools/libinput-list-quirks.man
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
.TH libinput-list-quirks "1" "" "libinput @LIBINPUT_VERSION@" "libinput Manual"
|
||||
.SH NAME
|
||||
libinput\-list\-quirks \- quirk debug helper for libinput
|
||||
.SH SYNOPSIS
|
||||
.B libinput list\-quirks [\-\-help] [\-\-data\-dir /path/to/dir] [\-\-verbose\fB] \fI/dev/input/event0\fB
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
The
|
||||
.B "libinput list\-quirks"
|
||||
tool parses the quirks file in \fIdata\-dir\fR and prints all quirks applied
|
||||
to the given device.
|
||||
.PP
|
||||
This is a debugging tool only, its output and behavior may change at any
|
||||
time. Do not rely on the output.
|
||||
.SH OPTIONS
|
||||
.TP 8
|
||||
.B \-\-data\-dir \fI/path/to/dir\fR
|
||||
Use the given directory as data directory for quirks files.
|
||||
.TP 8
|
||||
.B \-\-help
|
||||
Print help
|
||||
.TP 8
|
||||
.B \-\-verbose
|
||||
Use verbose output, useful for debugging.
|
||||
.SH LIBINPUT
|
||||
Part of the
|
||||
.B libinput(1)
|
||||
suite
|
||||
Loading…
Add table
Reference in a new issue