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!

  1. Find out device parameters
  2. Figure out initialization, if necessary
  3. Write a report descriptor
  4. Tweak input bits
  5. Tidy up event devices
  6. Contribute!

Find out device parameters

  1. Look at what tablet reports with usbhid-dump -es
  2. Find coordinate, pressure, tilt range
  3. Beware of required initialization
  4. Read seller/manufacturer specs, or a couple
  5. 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

  1. See if tablet already reports everything you need
  2. Check resolution, frame controls
  3. If not, try uclogic-probe
  4. If doesn't help, try Waltop and KYE methods
  5. 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!

Pledge $5+ support at

www.patreon.com/spbnick

and get your supporter stickers too!

Thanks!

DIGImend

Made with Slides.com