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