Open NeoTheFox opened 3 years ago
I have limited knowledge about the inner working of GNOME, but since the recent update, it supports mapping keys on Huion tablets and recognizes their pens/pressure settings.
Interesting... do you know what components of gnome handle this? Does it include a GUI for configuring the tablet?
Yes, the GUI is a part of gnome-settings
I think mutter handles input right now, since this is the intended behavior for Wayland, where the compositor handles input.
They just started exposing these settings, even though the buttons and some other stuff had been in libinput
for some time now, you can look at its events with libinput debug-gui
.
I can't say for sure but my guess is libinput gets exclusive rights over the device node and captures events before they manage to reach hidraw.
Now there is python-libinput
that should give an ability to tap into that in theory, but their support is incomplete - for example, they lack the dial support, and of course no mode switching. But it does support button holding/modifiers if you map them through the GNOME GUI.
I don't really know if something should be done about this, other than just mentioning the device blacklisting in the README.
I've been investigating this issue further and it looks like I got it completely wrong. The root issue is not with GNOME at all, although I suspect running GNOME as opposed to some other lighter options contributes to the race condition somewhere in the udev or the kernel.
The problem lies in get_tablet_hidraw()
function. More than 2 hidraw devices are being created for the tablet, and it turns out the function is, indeed, is too fragile. The previous issues I've been having had been caused by a race condition that would name them in a different order every time I would plug the tablet in, hence the inconsistency in when it would work and when it wouldn't. But it looks like that in more recent kernel/digimend versions the race either stopped happening or is extremely rare because I've been unable to use the mapping and almost drove myself insane by various means, including trying to figure out more ways to blacklist the tablet from libinput and the system and even rewriting huion-keys.py
in Rust from scratch.
Everything works perfectly once again if I just manually select the appropriate hidraw device. I'll try and refactor the function to be more robust if I'll find a way to do so, but so far it looks like there isn't a good way to tell if it's the appropriate hidraw device without opening it first to test it or knowing its name beforehand.
The get_tablet_hidraw()
function is supposed to only select the device that has device/input
in a subdirectory (huion_keys.py:113
). Does your tablet have multiple hidraw with device/input
? My tablet shows up with two hidraw devices, but only one of them has device/input
.
Can you post what your /sys/devices/hidraw*/device/ directories contain for your tablet?
If that doesn't work, I was thinking we could check the HID report descriptor for each device which should list each device's capabilities.
For reference, here's mine:
/sys/class/hidraw$ readlink -f hidraw3 && ls hidraw3/device/
/sys/devices/pci0000:00/0000:00:14.0/usb1/1-6/1-6:1.0/0003:256C:006E.0004/hidraw/hidraw3
country hidraw modalias report_descriptor uevent
driver input power subsystem
/sys/class/hidraw$ readlink -f hidraw3 && ls hidraw4/device/
/sys/devices/pci0000:00/0000:00:14.0/usb1/1-6/1-6:1.0/0003:256C:006E.0004/hidraw/hidraw3
country driver hidraw modalias power report_descriptor subsystem uevent
Here's a section of the report descriptor for the device that reports the buttons:
Field(2)
Physical(Digitizers.TabletFunctionKey)
Application(GenericDesktop.Keypad)
Usage(10)
Button.0001
Button.0002
Button.0003
Button.0004
Button.0005
Button.0006
Button.0007
Button.0008
Button.0009
Button.000a
Logical Minimum(0)
Logical Maximum(1)
Report Size(1)
Report Count(10)
Report Offset(24)
Flags( Variable Absolute )
Field(3)
Physical(GenericDesktop.GamePad)
Application(GenericDesktop.Keypad)
Usage(2)
Button.0001
Button.0002
Logical Minimum(0)
Logical Maximum(1)
Report Size(1)
Report Count(2)
Report Offset(34)
Flags( Variable Absolute )
You can get the report descriptor by looking in /sys/kernel/debug/hid/[DEVICE_ID]/rdesc
as root.
Sure, here are the two devices '/dev/hidraw21', '/dev/hidraw22'
/sys/devices/pci0000:00/0000:00:01.3/0000:02:00.2/0000:03:03.0/0000:07:00.0/usb3/3-1/3-1.3/3-1.3:1.0/0003:256C:006D.0066/hidraw/hidraw21 country driver hidraw input modalias power report_descriptor subsystem uevent
/sys/devices/pci0000:00/0000:00:01.3/0000:02:00.2/0000:03:03.0/0000:07:00.0/usb3/3-1/3-1.3/3-1.3:1.1/0003:256C:006D.0067/hidraw/hidraw22 country driver hidraw input modalias power report_descriptor subsystem uevent
The rdesc reports on all 3 would be too long so I made a gist of it here https://gist.github.com/NeoTheFox/905b64d35830e14d0583fd1d00db91dc
I see why there's a problem - your tablet simulates a keyboard on one device for some reason, and it's not safe to look for device/input
. Since only one device reports TabletFunctionKey, maybe we can just look for that in get_tablet_hidraw
?
I'm not entirely sure how to get the report descriptor though... it seems that on my machine, the device's driver needs to be unbound first (e.g. libusb_detach_kernel_driver
) but that would cause the device's other features to stop working.
The threaded approach I've tried in the WIP branch works around that and also offers multi-device support on top, there seem to be no downsides to opening both devices. Or a "dumber" of doing that would be to ask the user what device to use interactively on start and add a cli flag so that could be set in stone (if the race condition that used to be the case on my PC is truly eliminated then we can somewhat rely on the order these appear in). So, for example, if started with no argument it could do this:
./huion_keys.py
Found Q620M with devices ['hidraw19', 'hidraw20']. Please select the appropriate device:
1: hidraw19
2: hidraw20
and then on next runs you do
./huion_keys.py -d 1
to always go with device 1, if there is only one device - default to it. If run in a non-interactive shell and no arguments - default to the first one.
The actual issue is not related to GNOME but instead has to do with hidraw device detection misfiring. Jump to
The following Is no longer relevat.