Bringing XPPen Tablets to FreeBSD: Reverse Engineering a USB Protocol

06 Apr 2026 - tsp
Last update 06 Apr 2026
Reading time 9 mins

There is a certain kind of frustration that only appears when perfectly functional hardware refuses to cooperate with your operating system of choice. In my case, this happened with an XPPen graphics tablet.

XPPen tablets are, in many respects, surprisingly capable devices. The passive models in particular offer excellent value: precise pen input, good pressure sensitivity, and a solid overall build quality - at a fraction of the cost typically associated with professional drawing tablets. While the highly professional display-equipped variants can become quite expensive (in my personal opinion totally worth the price), the simpler models are almost irresistible for hobby and development setups.

Out of the box, the tablet was detected at the USB and HID level but none of the usual tooling - neither the base system utilities nor common open-source drivers - managed to produce usable input events. The root cause quickly became apparent: the device did not behave like a standard HID tablet. Instead, it required a vendor-specific initialization sequence and produced non-standard event packets that needed translation before they could be consumed by applications such as GIMP.

At that point, there were two options: abandon the device or solve the problem. Hating unresolved problems and having zero acceptance for unsupported hardware I choose the second route.

⚠️ TL;DR: This application is in no way associated with the official manufacturer and available on GitHub and installable via PyPi via pip install xppenfbsd. It solves my problem with the deco mini7.

Why Wacom Works (and XPPen does not)

To understand why this problem exists at all, it is useful to look at how Wacom devices are typically supported.

Most Wacom tablets implement (or at least closely emulate) pseudo-standard HID interfaces. On Unix-like systems, these devices are handled by the generic input stack and then enhanced by specialized drivers such as the X11 xf86-input-wacom driver. These drivers understand additional semantics like pressure, tilt, tool types, and button mappings—but crucially, they operate on top of a well-defined input abstraction.

In other words: Wacom devices speak a language the operating system and the X11 framework already understands.

XPPen devices, in contrast, often rely on vendor-specific extensions of the HID protocol, often requiring initialization sequences and custom report parsing on top of USBs HID device class. While they expose HID endpoints, they typically require an explicit activation or configuration sequence before they start producing any data. Even then, the reported data does not directly match standard input expectations and must be interpreted and transformed.

This difference explains why Wacom devices tend to work out of the box, while XPPen devices appear dead without proprietary applications.

Reverse Engineering the Protocol

The approach I chose was pragmatic: observe a working system and replicate its behavior.

A Windows test machine was set up with the official XPPen application performing the translation. Using USBPcap, I recorded the raw USB traffic generated while interacting with the tablet. This included device initialization, pen movement, pressure changes, and button events.

The resulting capture was then analyzed using Wireshark. By filtering out unrelated traffic and focusing on the relevant USB endpoints, it became possible to isolate the sequences responsible for device activation and continuous stylus data streaming.

To accelerate the decoding process, I first filtered the packets from the various phases (activation, data delivery, etc.) and used OpenAIs Codex to assist in identifying structural patterns and generating candidate parsers. While the initial suggestions required manual correction and validation, this significantly reduced the time required to move from raw captures to a working understanding of the protocol.

From USB Packets to Usable Input

Once the protocol was sufficiently understood, the next step was to reproduce the behavior on FreeBSD. Using libusb via a Python interface, I implemented a userspace daemon that performs three essential tasks:

First, it detects the tablet and performs the required initialization sequence. Without this step, the device remains silent.

Second, it continuously reads raw data packets from the stylus endpoint. These packets encode position, pressure, tilt, and button states in a vendor-specific format.

Third, it translates these packets into standard input events.

This translation layer is the core of the system. Instead of attempting to modify the kernel or introduce a custom driver, the daemon creates a virtual input device and re-injects events into the system again via an emulated HID device (uinput via the evdev compatibility layer). From the perspective of the operating system, this virtual device behaves like a normal stylus.

This design has several advantages. It keeps the implementation entirely in userspace and allows rapid iteration when refining the protocol understanding. It also makes the solution portable across systems that provide similar input injection mechanisms.

Integrating with X11

Once the virtual device is available, it can be consumed by the existing X11 driver stack.

A minimal configuration binds the generated event device to the stylus driver, allowing applications to interpret the input correctly. The exact device node depends on the system’s input enumeration and should ideally be discovered dynamically, but even a static configuration is sufficient for initial setups.

In my case the input device always appeared as event7 leading to the following configuration placed in /usr/local/etc/X11/xorg.conf.d/11-wacom.conf:

Section "InputDevice"
       Identifier "XP-PEN"
       Driver "wacom"
       Option "Device" "/dev/input/event7"
       Option "Type" "stylus"
       Option "USB" "on"
EndSection

Section "ServerLayout"
        Identifier "Default Layout"
        InputDevice "XP-PEN" "SendCoreEvent"
EndSection

At this point, the entire pipeline is complete: vendor-specific USB HID protocol > userspace translation > standard input events > X11 driver > application.

Applications such as GIMP can use the tablet without modification, including pressure sensitivity and stylus buttons.

Design Considerations

One might consider implementing this functionality as a kernel driver. However, this would not be a natural fit for the problem.

The primary task here is not hardware access but protocol translation. The kernel already provides mechanisms for exposing input devices and injecting events, and duplicating this logic in kernel space would introduce unnecessary complexity.

More importantly, from a design perspective, the kernel should remain as small and minimal as possible due to its privileged nature. Moving complex parsing and translation logic into the kernel increases the risk surface and makes debugging significantly harder. By keeping this layer in userspace, failures are contained, iteration is faster, and the system remains more robust overall.

Separating this functionality into a dedicated userspace process is therefore the correct architectural choice - not only from a modularity standpoint but also from a security perspective. It allows the protocol handling to evolve independently while relying on the kernel only for what it does best: providing stable and well-defined interfaces.

Additionally, the solution integrates naturally with system facilities such as device event frameworks, allowing automatic discovery and activation when the tablet is connected.

Limitations and Future Work

The current implementation focuses on a single device and a specific model family. Extending it to support multiple tablets or additional models would require further protocol analysis.

There is also room for improvement in device discovery and configuration, particularly in dynamically resolving input device paths and integrating more tightly with desktop environments as well as optimizing the runtime (adding daemonization support, etc.).

Nevertheless, the core functionality is complete: the tablet behaves like a native input device and can be used in real-world applications without noticeable limitations.

Conclusion

What started as a simple compatibility issue turned into a small reverse engineering project spanning USB protocols, driver behavior, and input subsystems. Interestingly, the entire process - from capturing USB traffic to having a fully working implementation - took essentially one sleepless night. This alone highlights how little effort would actually be required for a manufacturer to provide proper cross-platform support by simply releasing documentation (the manufacturers themselves could not cover all available operating systems in a feasable way due to QA, support, device generations, etc. but rely on the community).

The key insight is that many unsupported devices are not inherently incompatible - they are simply undocumented. With the right tools and a structured approach, it is often possible to bridge that gap. However, it also raises the question why this gap exists in the first place.

In this case, the combination of USB traffic capture, protocol reconstruction, and userspace event translation resulted in a fully usable graphics tablet on FreeBSD without relying on proprietary drivers. The fact that this can be achieved so quickly strongly suggests that publicly available protocol documentation would make such integrations almost trivial.

It is therefore somewhat difficult to understand why manufacturers so often hesitate to document their hardware interfaces. Instead of enabling broad compatibility across platforms, effort is invested into maintaining proprietary applications for a limited set of operating systems (they can never by themselves span the whole ecosystem of operating systems in a sane way). From a technical standpoint, publishing protocol specifications would significantly reduce duplicated effort, empower the community, and improve the longevity and usability of the hardware.

For anyone encountering similar issues, this workflow provides a practical path forward: observe, decode, translate, and integrate.

References

My implementation is available on GitHub and directly installable via PyPi

This article is tagged:


Data protection policy

Dipl.-Ing. Thomas Spielauer, Wien (webcomplainsQu98equt9ewh@tspi.at)

This webpage is also available via TOR at http://rh6v563nt2dnxd5h2vhhqkudmyvjaevgiv77c62xflas52d5omtkxuid.onion/

Valid HTML 4.01 Strict Powered by FreeBSD IPv6 support