DIGImend / digimend-kernel-drivers

DIGImend graphics tablet drivers for the Linux kernel
GNU General Public License v2.0
1.17k stars 173 forks source link

XP-Pen Artist 15.6 Pro #286

Open Korvox opened 5 years ago

Korvox commented 5 years ago

Mostly works with usbhid out of the box, here are my observations poking around with this thing last night:

@spbnick Mentioned its running at half resolution on IRC.

descriptors.txt hid_report_descriptors.txt probe.txt pen_coords.txt pen_tilt.txt pen_pressure.txt pen_buttons.txt wheel-left.txt wheel-right.txt frame_buttons.txt

Update: Here is a Wireshark trace of how the Windows driver does init. Of relevance it ends init with a packet into the undocumented out interface 2 of 0x02b004 and gets a reply of 02b104.

Korvox commented 5 years ago

Finally got the Windows driver working properly in a VM and that magic packet is switching the device to output on Interface 2.

Heres another Wireshark trace testing all the buttons / doing a rectangle on the screen with the Windows driver.

Doesn't seem to totally fix the alignment issues I was seeing in standard hid mode so it will probably require calibration support as well. I'll be trying to figure out the packet format of Interface 2 this weekend - it doesn't follow the advertised report descriptors for the digitizer on interface 1. In case its relevant, heres the same routine as the first run without the driver installed on Windows, but the data is the same as on Linux since its just using generic hid.

Update: Slowly trying to figure out the packet format by hand from raw packets. Almost certainly totally irrelevant to anyone else but heres the script I'm using just to dump the data.

#! /usr/bin/env python

import usb.core
import usb.util

dev = usb.core.find(idVendor=0x28bd, idProduct=0x090d)

if dev.is_kernel_driver_active(2):
    dev.detach_kernel_driver(2)

cfg = dev.get_active_configuration()
intf = cfg[(2,0)]
ei = intf[0]
eo = intf[1]

eo.write(bytes.fromhex('02b0040000000000'))

while(True):
    print(''.join(format(x, '02x') for x in ei.read(10)))
Korvox commented 5 years ago

Interface 2 operating mode is pretty straightforward.

First byte stays interface id 02 so these aren't ever invalid hid packets.

Second byte is a mode byte - high order a means a pen event and f means button. Low order four bits are the pen buttons in a mode as a bitmap. So a0 is a hover event, a1 is a pen event (and will report pressure), a2 is the first barrel button, etc.

In pen mode, bytes 3+4 are x and 5+6 are y coords (lil endian, as per spec) with resolution 35689 x 20598 (0x8b69 x 0x5076). 7+8 are pressure (full 8192 levels), 9 and 10 are x and y tilt in range -61 to 60 as degrees of tilt from the perpendicular. In button mode, byte 3 has the 8 buttons in a bitmap (topmost button is 1, bottom is 8).The two wheel buttons are on byte 8 (left 1 right 2). The rest are always zeroed.

I tested all these ranges both with my script above on Linux and via the Windows XP-Pen driver, so unless this particular device is borked it seems the resolution is only 2641 LPI.

Update: Tangentially related String 0x64 (ie 100) has a value of 73 86 05 4c 08 00 ff 1f ec 09 which is the common params control string with the first two bytes being X resolution, second two being Y, two gap bytes, 2 bytes for pressure, and then the resolution (which it reports as 09ec aka 2540?).

Tested that string as well with and without the control packet to swing on interface 2 operation and nothing changes.