Support for Huion devices - linuxwacom/libwacom GitHub Wiki

Devices from Huion, Gaomon, and some other vendors use UCLogic-based hardware. These are supported by libwacom but have some quirks compared to Wacom devices, mostly around device identification. Note that Gaomon tablets are rebranded Huion hardware and use the same vendor ID (0x256c), so this page applies to both.

Firmware mode vs vendor mode

Most Huion devices expose three HID interfaces when plugged in: a vendor-specific device, a pen device, and a keyboard device.

In the default firmware mode, pen events come through the pen device and pad buttons are emulated as keyboard shortcuts (things like Ctrl+C or just Space). This works but means the pad buttons can't be individually configured -- they're just keyboard keys. The vendor device does not send events at all.

By reading a hidden USB string descriptor, the device can be switched into vendor mode. In vendor mode, all events (pen and buttons) go through the vendor device, and the pad buttons are reported as proper tablet buttons instead of keyboard shortcuts. The kernel then needs a driver that understands the vendor protocol.

There are two approaches to handling this:

The hid-uclogic kernel driver handles the switch and the protocol translation. It has been doing this for many years and supports a wide range of devices. However, it has been deprecated in favor of the approach below.

udev-hid-bpf uses eBPF programs to replace the HID report descriptors so the kernel can interpret the vendor protocol. It works with the generic hid-generic kernel driver. The companion tool huion-switcher handles the mode switch and exposes the firmware string.

The recommended setup is to install both udev-hid-bpf and huion-switcher. When the device is plugged in, the sequence is: huion-switcher reads the firmware string and switches to vendor mode; udev captures the firmware string; udev-hid-bpf loads the appropriate eBPF program; the kernel can now interpret the events through the standard hid-generic driver.

Identifying Huion devices

The main complication with Huion devices is that the vendor reuses USB product IDs across different tablet models. The known shared product IDs are 006d, 006e, 006f, and 0064 -- each of these is used by many different tablets. A simple DeviceMatch=usb|256c|006d would match a dozen different devices.

There are three levels of matching available, from simplest to most specific:

For devices with a unique product ID, a plain bus/vid/pid match is enough:

DeviceMatch=usb|256c|0191

Where the product ID is shared but the kernel device name differs, the name can be added as a fourth field. Note that the kernel creates separate suffixed devices for pen, pad, and touch, and all must be listed:

DeviceMatch=usb|256c|006d|HUION Huion Tablet_H640P Pen;usb|256c|006d|HUION Huion Tablet_H640P Pad

When even the device name is identical between different models, the UNIQ field can distinguish them. UNIQ is a firmware version prefix that is unique per device model. It can be appended as a fifth field (with the name left empty if needed):

DeviceMatch=usb|256c|006d||OEM02_T18e

or with both name and UNIQ:

DeviceMatch=usb|256c|006d|GAOMON Gaomon Tablet Pen|OEM02_T18e;usb|256c|006d|GAOMON Gaomon Tablet Pad|OEM02_T18e

Checking the UNIQ field

UNIQ matching requires libwacom 2.12 or later (June 2024). To find the UNIQ value for your device:

$ udevadm info /sys/class/input/event20 | grep UNIQ
E: UNIQ=OEM02_T18e_20191130

Replace event20 with your device's actual event node. The raw UNIQ value may have a date suffix (the _20191130 part) -- libwacom strips that automatically, so only the prefix (OEM02_T18e) goes in the DeviceMatch.

Where UNIQ comes from

For devices using the hid-uclogic kernel driver, the UNIQ field is set by the driver as of kernel v6.10. You can check which driver your device uses:

$ udevadm info /sys/class/input/event20/device/device | grep DRIVER
DRIVER=hid_uclogic

For devices using udev-hid-bpf with huion-switcher, the UNIQ value is read by huion-switcher and set as a udev property via a udev rule.