Recently I obtained an XP-Pen 4x3" Graphics Tablet for a very low price (about
$15).
The intended usage is to make handritten notes using Xournal, Xournalpp or
similar, rather than for illustration work.
I was not very hopeful of it being supported in OpenBSD, but I am pleased to
report that it is mostly functional and usable including Pressure Sensitivity.
The configuration discovery process was a little involved, so I am posting it
here in the hope the information will be useful to others trying to get a USB
tablet to work.
The tablet connects via USB and has a single-ended passive stylus.
I used OpenBSD 7.6-release. The kernel has been patched to make the (PS/2)
Touchpad work on this particular machine but I don't think that will change how
a USB tablet works.
In dmesg it attaches as:
uhidev0 at uhub0 port 4 configuration 1 interface 0 "UGTABLET 4 inch PenTablet"
rev 2.00/0.00 addr 2
uhidev0: iclass 3/1, 9 report ids
ukbd0 at uhidev0 reportid 6: 8 variable keys, 6 key codes
wskbd1 at ukbd0 mux 1
ums0 at uhidev0 reportid 9: 3 buttons
wsmouse1 at ums0 mux 0
uhidev1 at uhub0 port 4 configuration 1 interface 1 "UGTABLET 4 inch PenTablet"
rev 2.00/0.00 addr 2
uhidev1: iclass 3/1, 7 report ids
uhid0 at uhidev1 reportid 7: input=9, output=0, feature=0
uhidev2 at uhub0 port 4 configuration 1 interface 2 "UGTABLET 4 inch PenTablet"
rev 2.00/0.00 addr 2
uhidev2: iclass 3/0, 2 report ids
uhid1 at uhidev2 reportid 2: input=11, output=9, feature=0
That is, it appears as a secondary mouse with 3 buttons, and two uhid devices
uhid0 and uhid1.
Before the tablet is configured to be claimed by a driver such as usbtablet(4),
it is possible to dump the USB HID report descriptor for each of the uhid
devices:
usbhidctl -f 0 -r:
Report descriptor:
Collection page=Digitizer usage=Pen
Collection page=Digitizer usage=Stylus
Input size=1 count=1 page=Digitizer usage=Tip_Switch, logical range 0..1
Input size=1 count=1 page=Digitizer usage=Barrel_Switch, logical range 0..1
Input size=1 count=1 page=Digitizer usage=Eraser, logical range 0..1
Input size=1 count=1 page=Digitizer usage=Invert, logical range 0..1
Input size=1 count=1 page=Digitizer usage=In_Range, logical range 0..1
Input size=16 count=1 page=Generic_Desktop usage=X, logical range 0..32767,
physical range 0..4799, unit=
Input size=16 count=1 page=Generic_Desktop usage=Y, logical range 0..32767,
physical range 0..3000, unit=
Input size=16 count=1 page=Digitizer usage=Tip_Pressure, logical range 0..8191
Input size=8 count=1 page=Digitizer usage=X_Tilt, logical range -127..127
Input size=8 count=1 page=Digitizer usage=Y_Tilt, logical range -127..127
End collection
End collection
Total input size 9 bytes
Total output size 0 bytes
Total feature size 0 bytes
usbhidctl -f 1 -r:
Report descriptor:
Collection page=0xff0a usage=0x0001
Input size=8 count=1 page=0xff0a usage=0x0002, logical range 0..255
Input size=8 count=1 page=0xff0a usage=0x0002, logical range 0..255
Input size=8 count=1 page=0xff0a usage=0x0002, logical range 0..255
Input size=8 count=1 page=0xff0a usage=0x0002, logical range 0..255
Input size=8 count=1 page=0xff0a usage=0x0002, logical range 0..255
Input size=8 count=1 page=0xff0a usage=0x0002, logical range 0..255
Input size=8 count=1 page=0xff0a usage=0x0002, logical range 0..255
Input size=8 count=1 page=0xff0a usage=0x0002, logical range 0..255
Input size=8 count=1 page=0xff0a usage=0x0002, logical range 0..255
Input size=8 count=1 page=0xff0a usage=0x0002, logical range 0..255
Input size=8 count=1 page=0xff0a usage=0x0002, logical range 0..255
Output size=8 count=1 page=0xff0a usage=0x0003, logical range 0..255
Output size=8 count=1 page=0xff0a usage=0x0003, logical range 0..255
Output size=8 count=1 page=0xff0a usage=0x0003, logical range 0..255
Output size=8 count=1 page=0xff0a usage=0x0003, logical range 0..255
Output size=8 count=1 page=0xff0a usage=0x0003, logical range 0..255
Output size=8 count=1 page=0xff0a usage=0x0003, logical range 0..255
Output size=8 count=1 page=0xff0a usage=0x0003, logical range 0..255
Output size=8 count=1 page=0xff0a usage=0x0003, logical range 0..255
Output size=8 count=1 page=0xff0a usage=0x0003, logical range 0..255
End collection
Total input size 11 bytes
Total output size 9 bytes
Total feature size 0 bytes
The report for /dev/uhid1 seems to be a vendor custom page, which does not
appear in /usr/share/misc/usb_hid_usages (the default HID usage table), so I
was not able to make use of this interface.
The report for /dev/uhid0 includes capabilities which this unit does not in
fact have: the pen does not have an Eraser end, does not work inverted for
erasing, and doesn't support 'pen tilt'. I put this down to a vendor firmware
error, maybe using the same firmware as a more capable model in the range.
I created a minimal configuration file for Xenocara in
/etc/X11/xorg.conf.d/70-usbtablet.conf:
Section "InputDevice"
Identifier "stylus"
Driver "usbtablet"
Option "Device" "/dev/uhid0"
Option "Type" "stylus"
Option "Mode" "Absolute"
Option "AccelerationProfile" "-1" # no acceleration
Option "AdaptiveDeceleration" "2.0" # deceleration factor when moving
pointer slowly
# Option "DebugLevel" "0"
EndSection
# Available if the Tablet Pen has an 'Eraser" end
#Section "InputDevice"
# Identifier "eraser"
# Driver "usbtablet"
# Option "Device" "/dev/uhid0"
# Option "Type" "eraser"
# Option "Mode" "Absolute"
# Option "DebugLevel" "1"
#EndSection
Section "Serverlayout"
Identifier "Default Layout"
InputDevice "stylus"
# InputDevice "eraser"
EndSection
# required to avoid "No Screens found" error
Section "Screen"
Identifier "Default Screen"
EndSection
Section "ServerFlags"
# Option "DontZap" "true" # Prevent Ctrl-Alt-Backspace Xserver zap for
security
Option "AllowMouseOpenFail" "true" # Don't report failure to open a
Mouse device
EndSection
Notes:
1. It was not obvious from the usbtablet(4) Manpage that the ServerLayout and
Screen sections were necessary (to bind the InputDevice and to avoid a 'no
Screens found' error respectively).
I realise this is standard xorg.conf configuration procedure, but it took some
digging in the xorg.conf(5) Manpage to realise that.
2. The "eraser" InputDevice isn't necessary (doesn't appear to add any
functionality) for this particular device. But if the tablet used actually has
an Eraser function (rather than just reporting that it has it) then it may be
useful.
3. With this manual configuration, hotplugging doesn't work for the tablet,
though other USB devices such as mice can still be hotplugged. So it's
necessary to either 'pkill Xorg' or reboot to make the tablet work
4. ServerFlags AllowMouseOpenFail stops Xenocara from complaining if the tablet
isn't connected when it starts. DontZap is to prevent the screenlocker being
killed.
5. the DebugLevel option is useful to see what events the tablet actually
produces, rather than what it claims in the HID Report Descriptor. For example,
DebugLevel 1 shows pen pressure and driver default parameters. I didn't check
what Debug levels are valid, suspect anything >0 is 'on'.
5. The Threshold Option referred to in the usbtablet(4) Manpage, though an
integer, turns out to be a percentage of the maximum pressure parameter. So
with this tablet (pressure range 0-8191), the threshold is set to 419 by
default.
With the above configuration and 'XP-Pen Deco Fun XS' 4x3" tablet, I got the
following functionality:
xinput list:
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer
(2)]
⎜ ↳ Stylus id=6 [slave pointer
(2)]
⎜ ↳ /dev/wsmouse0 id=8 [slave pointer
(2)]
⎜ ↳ /dev/wsmouse1 id=9 [slave pointer
(2)]
⎜ ↳ /dev/wsmouse id=10 [slave pointer
(2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard
(3)]
↳ /dev/wskbd id=7 [slave keyboard
(3)]
xinput list 6:
Stylus id=6 [slave pointer (2)]
Reporting 6 classes:
Class originated from: 6. Type: XIButtonClass
Buttons supported: 4
Button labels: None None None None
Button state:
Class originated from: 6. Type: XIValuatorClass
Detail for Valuator 0:
Label: None
Range: 0.000000 - 1920.000000
Resolution: 393700 units/m
Mode: absolute
Current value: 1920.000000
Class originated from: 6. Type: XIValuatorClass
Detail for Valuator 1:
Label: None
Range: 0.000000 - 1200.000000
Resolution: 393700 units/m
Mode: absolute
Current value: 1200.000000
Class originated from: 6. Type: XIValuatorClass
Detail for Valuator 2:
Label: None
Range: 0.000000 - 8191.000000
Resolution: 393700 units/m
Mode: absolute
Current value: 0.000000
Class originated from: 6. Type: XIValuatorClass
Detail for Valuator 3:
Label: None
Range: 0.000000 - 0.000000
Resolution: 393700 units/m
Mode: absolute
Current value: 0.000000
Class originated from: 6. Type: XIValuatorClass
Detail for Valuator 4:
Label: None
Range: 0.000000 - 0.000000
Resolution: 393700 units/m
Mode: absolute
Current value: 0.000000
xinput list 9:
/dev/wsmouse1 id=9 [slave pointer (2)]
Reporting 7 classes:
Class originated from: 9. Type: XIButtonClass
Buttons supported: 7
Button labels: "Button Left" "Button Middle" "Button Right"
None None None None
Button state:
Class originated from: 9. Type: XIValuatorClass
Detail for Valuator 0:
Label: Abs X
Range: 0.000000 - 32767.000000
Resolution: 1 units/m
Mode: absolute
Current value: 960.000000
Class originated from: 9. Type: XIValuatorClass
Detail for Valuator 1:
Label: Abs Y
Range: 0.000000 - 32767.000000
Resolution: 1 units/m
Mode: absolute
Current value: 600.000000
Class originated from: 9. Type: XIValuatorClass
Detail for Valuator 2:
Label: Rel Horiz Scroll
Range: 0.000000 - -1.000000
Resolution: 0 units/m
Mode: relative
Class originated from: 9. Type: XIValuatorClass
Detail for Valuator 3:
Label: Rel Vert Scroll
Range: 0.000000 - -1.000000
Resolution: 0 units/m
Mode: relative
Class originated from: 9. Type: XIScrollClass
Scroll info for Valuator 2
type: 2 (horizontal)
increment: 4096.000000
flags: 0x0
Class originated from: 9. Type: XIScrollClass
Scroll info for Valuator 3
type: 1 (vertical)
increment: 4096.000000
flags: 0x0
- Drawing with pressure sensitivity works in Xournal, Inkscape and LibreOffice
Draw (and maybe other applications that use Xinput)
- Pressure sensitivity doesn't work in Xournal++. I tried adjusting the
pressure scaling but with no result. Maybe it doesn't use Xinput?
- Only one of the two 'barrel buttons' on the pen works. The tip is button1,
the lower button is button2. Button1 needs to be inactive (pen lifted out of
contact with the tablet a little) for button2 to be read. Button3 is absent.
This was tested using
'xev -event button'.
Perhaps the 70-usbtablet.conf above would be a candidate for inclusion in
/etc/examples?
Alternatively, a line could be added to the usbtablet(4) Manpage to say that
ServerLayout and Screen sections are necessary in the configuration file to
make the driver bind.
Comments and corrections to the above are welcome. Does anyone have any idea,
for example, why the second barrel button does not appear to work, while
/dev/wsmouse1 reports 3 buttons?
Chris Billington