Generic Graphics Tablets in Linux
Hardware peculiarities, software challenges, and how to make them work
Nikolai Kondrashov
- Software Engineer
- Electronics Enthusiast
- Maintainer of DIGImend
spbnick
Generic Tablets
What are Generic Tablets?
- Not made by Wacom
- Designed and built by a few OEMs in Asia
- Rebranded and sold under many brands
- Huion, Yiynova, Genius, Monoprice, Trust, Ugee, XP-Pen, Adesso, Aiptek, Iball, UGTizer, iVista, etc.
From tiny signature pads...
Genius WizardPen 4x3, barely usable for drawing, supported
...and affordable workhorses...
The popular Huion H610 Pro, about $75 on Amazon, supported
...through curiosities...
The rare Waltop Sirius, tilt detection, battery-free pen, supported
...to large wireless tablets...
Huion WH1409, not supported yet
...and giant tablet displays!
Yiynova MVP27U+RH, 27" IPS LCD, tilt detection, not supported yet
Why Generic Tablets?
Plenty of people can't afford a Wacom:
- People in developing countries
- Beginning artists
- Students
- Schools
Plenty of people can't afford a Wacom:
Same people who would rather use Linux
And, of course:
For Fun!
If Wacom is still better?
DIGImend
- Founded in 2008
- Trying to improve non-Wacom graphics tablet support in Linux
- Mostly me, but with various people contributing, coming and going
digimend.github.io
The Story
2005
- Got a Genius MousePen 8x6 for a birthday
- It didn't work
- Hacked a fork of the Aiptek driver, called
"xf86-input-wizardpen" (after a Genius tablet) - Supported that for a while with the author
- Kernel was sending garbage for those tablets
- The wizardpen driver was trying to deal with that
- It still does!
- Decided fixing kernel would be better
- Created DIGImend project on SourceForge
2008
- Fixing report descriptors seemed a good idea
- Studied USB HID spec
- Made converter/editor called hidrd-convert
- Made some tools: usbhid-dump and evdev-dump
- Started hacking on the kernel
2010
- Went around computer stores, asking to try tablets
- Made drivers, went back to test
- Got a bunch working
- People started coming asking about their tablets
- Made some work, remotely
- Got three tablets from Waltop
2012
2014
- Moved to GitHub
- Kernel got support for out-of-tree HID drivers
- Made an out-of-tree driver package
- More tablets supported, some contributed
2016
- No fun
- Hiatus
- Intermission
2017
- A company offered support to continue
- Then another asked for drivers
- Money is fun
- Also Patreon
2018
- Huion releases new tablets
- People buy, they don't work
- Talked to Huion
- They agree to pay, send tablets
- Got the new tablets supported
Huion
Huion
Huion
How do they work*?
* or supposed to
Tablet
USB
HID interface
Report Descriptor
Report
Report
Report
Report
PC
Reports
Report Descriptor
09 01 DB 37 0D 46 4E 00
08 00 02 F7 00 00
ID
Pen
Mouse
Buttons
Coords
Pressure
Wheel
UC-Logic WP8060U
0x05, 0x0D, /* Usage Page (Digitizer), */
0x09, 0x02, /* Usage (Pen), */
0xA1, 0x01, /* Collection (Application), */
0x85, 0x09, /* Report ID (9), */
0x09, 0x20, /* Usage (Stylus), */
0xA0, /* Collection (Physical), */
0x75, 0x01, /* Report Size (1), */
0x09, 0x42, /* Usage (Tip Switch), */
0x09, 0x44, /* Usage (Barrel Switch), */
0x09, 0x46, /* Usage (Tablet Pick), */
0x14, /* Logical Minimum (0), */
0x25, 0x01, /* Logical Maximum (1), */
0x95, 0x03, /* Report Count (3), */
0x81, 0x02, /* Input (Variable), */
0x95, 0x05, /* Report Count (5), */
0x81, 0x01, /* Input (Constant), */
0x75, 0x10, /* Report Size (16), */
0x95, 0x01, /* Report Count (1), */
0x14, /* Logical Minimum (0), */
0xA4, /* Push, */
0x05, 0x01, /* Usage Page (Desktop), */
0x55, 0xFD, /* Unit Exponent (-3), */
0x65, 0x13, /* Unit (Inch), */
0x34, /* Physical Minimum (0), */
0x09, 0x30, /* Usage (X), */
0x46, 0x40, 0x1F, /* Physical Maximum (8000), */
0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */
0x81, 0x02, /* Input (Variable), */
/* ... */
Report Descriptor
UC-Logic WP8060U (fixed)
USB
HID
Input
Generic
UC-Logic
Waltop
Kye
•••
Wacom
I2C
Bluetooth
Kernel
Evdev
libinput
Wayland
X.org
Userspace
Toolkits (GTK, Qt, ...)
Why don't they work?
Tablets, why don't they work?
- HID spec is too complex and vague
- Windows Generic HID driver is no good
- OEMs have no time for that
- Linux is not Windows
- "Graphics tablet = Wacom"
HID specification
- 97 pages define language for describing input reports
- 767 pages define ways to describe devices with it
- 8 of these define how to describe digitizers (tablets)
- Appear descriptive, written post-factum by paying members of USB HID working group, then forgotten
- Not much help implementing devices or drivers
HID specification, bonus
- Official report descriptor tool is buggy and confusing
- Misinterprets the specification
- Stores unit exponent incorrectly
- Now all devices have it wrong, limiting range
- USB IF doesn't act in the interest of users
Windows Generic HID driver
- Doesn't support s32 extents, only s16?
- Higher resolution requires custom driver?
Ain't no OEM got time for that
Oh, boy...
- Repeated usages in the same report descriptor
- Buttons on the pen reported whichever way
- Frame controls reported as app shortcuts
- Coordinates in tens of cubic terainches, or such
- But then, who even needs report descriptors?
- Default mode becomes increasingly useless
- Tablets require initialization for full functionality
- E.g. set a feature report (KYE, Waltop)
- Or request a string descriptor (UC-Logic)
- Then get parameters, full resolution, generic buttons
- But also, screw report descriptors!
Linux is not Windows
- Duplicate HID input usages no problem for Windows
- Linux offsets event codes for them
- Requires HID_QUIRK_MULTI_INPUT as a workaround
- Many a device was "fixed" that way
"Graphics Tablet = Wacom"
- Drivers, toolkits, apps test with Wacoms mostly
- Stuff breaks from time to time
- A rare tablet with tilt detection is a misfit
- "GNOME Wacom Tablet Configuration tool"
- - Requires a tablet entry in the database
- Generic tablets are cheap - get a few and test!
DIGImend drivers
Out-of-tree HID drivers
- Implemented in digimend-kernel-drivers
- Easier and faster for users to install
- Easier and faster to develop
- A bit of a hassle to sync with upstream
Keeping up with upstream
- Only keeping modules with new drivers
- Keeping as close to upstream as possible
- Copying some private definitions
- Adding some compatibility macros
Wrangling with the kernel
- Modprobe config works with stock custom drivers
- Which the generic HID driver knows about
- Otherwise it doesn't even look them up
- Digimend-kernel-drivers install udev rules and a script
- The script rebinds tablet to out-of-tree driver, if any
Make them work!
Tablets, make them work!
- Find out device parameters
- Figure out initialization, if necessary
- Write a report descriptor
- Tweak input bits
- Tidy up event devices
- Contribute!
Find out device parameters
- Look at what tablet reports with usbhid-dump -es
- Find coordinate, pressure, tilt range
- Beware of required initialization
- Read seller/manufacturer specs, or a couple
- Find drawing area size
Huion (UC-Logic) Default Mode
001:003:000:STREAM 1375962321.017426
09 00 52 04 BA 04 00 00
001:003:000:STREAM 1375962321.021443
09 01 52 04 BA 04 05 00
001:003:000:STREAM 1375962321.025381
09 01 52 04 BA 04 07 00
001:003:000:STREAM 1375962321.029373
09 01 52 04 BA 04 0A 00
001:003:000:STREAM 1375962321.033402
09 01 52 04 BA 04 0C 00
001:003:000:STREAM 1375962321.045399
09 01 52 04 BA 04 08 00
001:003:000:STREAM 1375962321.049529
09 01 52 04 BA 04 04 00
001:003:000:STREAM 1375962321.053441
09 01 52 04 BA 04 01 00
001:003:000:STREAM 1375962321.057417
09 00 52 04 BA 04 00 00
Buttons, but no proximity bit?
Report ID 0x09
X coordinate
Y coordinate
Pressure
Little-endian!
Figure out initialization
- See if tablet already reports everything you need
- Check resolution, frame controls
- If not, try uclogic-probe
- If doesn't help, try Waltop and KYE methods
- Otherwise see Windows driver USB traffic
Huion (UC-Logic) Initialized
003:009:000:STREAM 1436696385.627237
07 80 4B 44 E3 25 00 00
003:009:000:STREAM 1436696385.643256
07 81 4F 44 D7 25 4D 00
003:009:000:STREAM 1436696385.709249
07 81 4A 44 C0 25 FB 01
003:009:000:STREAM 1436696385.775340
07 81 4A 44 C0 25 05 06
003:009:000:STREAM 1436696389.879212
07 81 38 44 94 25 FF 07
003:009:000:STREAM 1436696389.899233
07 81 02 44 A6 25 9C 03
003:009:000:STREAM 1436696389.907201
07 81 C4 43 B8 25 47 01
003:009:000:STREAM 1436696389.967255
07 80 71 43 06 26 00 00
003:009:000:STREAM 1436696389.969218
07 C0 71 43 06 26 00 00
Hey, buttons, and... inverted proximity bit?
Report ID 0x07!
X coordinate
Y coordinate
Pressure
Little-endian!
Huion (UC-Logic) Initialized V2
003:004:000:STREAM 1534321568.045283
08 80 AF 2C 1B 70 00 00 00 00 00 00
003:004:000:STREAM 1534321568.051237
08 81 E8 2B 1B 70 DF 06 00 00 00 00
003:004:000:STREAM 1534321568.059257
08 81 11 2B 1B 70 87 0C 00 00 00 00
003:004:000:STREAM 1534321568.065262
08 81 23 2A 1B 70 97 10 00 00 00 00
003:004:000:STREAM 1534321568.073265
08 81 3D 29 27 70 AF 0E 00 00 00 00
003:004:000:STREAM 1534321568.079278
08 81 16 28 48 70 4F 09 00 00 00 00
003:004:000:STREAM 1534321568.087291
08 81 E7 26 89 70 0F 05 00 00 00 00
003:004:000:STREAM 1534321568.091278
08 81 91 26 AC 70 3F 03 00 00 00 00
Buttons, but... no proximity bit, again?
Report ID 0x08!
X coordinate, two parts
Y coordinate, two parts
Pressure
Little-endian!
Buttons not released on proximity-out!
Write report descriptor
- If uclogic-probe worked, just extend hid-uclogic-*.c
- Otherwise... erm, learn report descriptor language
- Look at report descriptors in our tablets repo, kernel
- Use hidrd-convert or a similar tool to make one
- Feed it to the kernel in a .report_fixup handler
05 0D 09 02 A1 01 85 07 09 20 A1 00 09 42 09 44
09 45 09 3C 09 43 09 44 15 00 25 01 75 01 95 06
81 02 09 32 75 01 95 01 .. .. ..
<?xml version="1.0"?>
<descriptor>
<usage_page>digitizer<!-- Digitizer (0Dh) --></usage_page>
<usage>digitizer_pen<!-- Pen (02h, application collection) --></usage>
<COLLECTION type="application">
<report_id>7</report_id>
<usage>digitizer_stylus<!-- Stylus (20h, logical collection) --></usage>
<COLLECTION type="physical">
<usage>digitizer_tip_switch<!-- Tip switch (42h, momentary control) --></usage>
. . .
0x05, 0x0D, /* Usage Page (Digitizer), */
0x09, 0x02, /* Usage (Pen), */
0xA1, 0x01, /* Collection (Application), */
0x85, 0x07, /* Report ID (7), */
0x09, 0x20, /* Usage (Stylus), */
0xA0, /* Collection (Physical), */
0x14, /* Logical Minimum (0), */
. . .
usbhid-dump -ed
hidrd-convert -i hex -o xml
edit, edit, edit,
hidrd-convert -i xml -o code
Tweak input bits
If needed, add a .raw_event handler to e.g.:
- Mask out garbage data in certain conditions
- Divert some reports into another report ID
- Translate tilt reports
- Invert in-range bit
Tidy up event devices
- Return -ENODEV from .probe to hide interfaces
- Modify device names in .input_configured
UC-Logic WP8060U
UC-Logic WP8060U
UC-Logic WP8060U
UC-Logic WP8060U
UC-Logic WP8060U
UC-Logic WP8060U Pen
UC-Logic WP8060U Mouse
UC-Logic WP8060U Buttons
Eh? Which one is it?
Contribute!
- Get users faster with digimend-kernel-drivers
- Or contribute to the kernel directly
- In either case, follow kernel coding style
- And keep changes logically separate
Oh, and nevermind "shortcuts"
Those are
useless!
That's all!
Wait!
After the session is over, come by and get your free DIGImend stickers!
Thanks!
- To you for attending and listening
- To my Patreon supporters for keeping me going
- To all the Open-Source developers out there
- To makers of Font Awesome for the icons
- To Freepik for icons hosted on www.flaticon.com, and licensed under CC 3.0 BY
DIGImend
Generic Graphics Tablets in Linux
By Nikolai Kondrashov
Generic Graphics Tablets in Linux
- 3,626