tablets using evdev

Jimmy Hon honyuenkwun at
Wed May 18 19:30:11 PDT 2011

The Short:
I have a tablet and it didn't work with the evdev driver. So I hacked 
the evdev input driver to work with it. Hacks are bad, so how should I 
go about getting real fixes?

The Long:
I bought a tablet from MonoPrice (Item 6251, 

In lsusb, it identifies as:
5543:0064 UC-Logic Technology Corp. Aiptek HyperPen 10000U.

/proc/bus/input/devices says:
I: Bus=0003 Vendor=5543 Product=0064 Version=0110
N: Name="UC-LOGIC TWA60"
P: Phys=usb-0000:00:12.2-2.1.2/input0
U: Uniq=
H: Handlers=mouse5 event13
B: EV=1f
B: KEY=c03 3f0001 0 0 0 0
B: REL=303
B: ABS=100000f
B: MSC=10

The tablet didn't work correctly when evdev drove it. Playing with 
xinput test, it turns out the tablet was reporting the x/y coordinates 
on valuator 2 and 3, and not on 0 and 1. The pen sensitivity is reported 
as evaluator 4. So valuator 2, 3, and 4 were reporting data when I moved 
then pen around.

So I wanted evdev to ignore the first two valuators. I did this by 
cheating and changed the ABS initialization code in EvdevAddAbsClass() 
to start the for loop at ABS_Z instead for ABS_X when it's checking the 
abs_bitmask). So basically, if /proc/bus/input/devices reported 
ABS=100000c instead of ABS=100000f, I would have been fine.

To get the wheel emulation working, in EvdevWheelEmuFilterMotion(), I 
changed the switch statement to check pEvdev->axis_map[pEv->code] 
instead of just pEv->code. It's a similar idea as the ABS differential 
measurement code just above the switch statement. You want to check 
which axis the values will be eventually reported as.

This works fine for _me_, since the tablet is the only input device 
that's in absolute mode. My normal mouse and trackball use relative 
mode, and those code paths have not been modified.

So if I want this tablet to work for real what's the proper way to do it?
1. Should the kernel driver not report the two unused valuators? (Make 
it report ABS=100000c instead of ABS=100000f)
2. Does the evdev xorg driver have an ability to remap axes?
3. Can the evdev xorg driver have addditional options to blacklist some 
of the valuators?
4. Should any of this be done in the evdev xorg driver? Or is it more 
appropriate to have a specific tablet driver?

I know there is the wizardpen xorg driver, which supports this tablet. 
But it's not as featureful as evdev. There's no wheel emulation, and no 
Properties to changes at runtime. (I've been changing the Calibration 
property, when I switch between single monitor vs dual monitors)

If this type of support should be a tablet specific xorg driver, is 
there a master tablet driver? (i.e. like how evdev is the master driver 
for all mice and keyboards?)

I've seen the aiptek, hyperpen, wizardpen, and wacom drivers. Why are 
there so many tablet drivers? What makes each driver so special? (I 
tried google and also perusing the site, but I 
couldn't pinpoint the differences between the drivers). Having so many 
tablet drivers makes me think that there is going to be a lot of code 
duplication if they were all going to have a wheel emulation feature. Is 
there a way to put the wheel emulation logic into a library, and have 
all the drivers share that?


P.S. Should this be posted on xorg-devel too?

My hacks look like this:
diff -ur xf86-input-evdev-2.6.0/src/emuWheel.c 
--- xf86-input-evdev-2.6.0/src/emuWheel.c    2010-12-20 
19:19:16.000000000 -0500
+++ xf86-input-evdev-2.6.0-dev/src/emuWheel.c    2011-05-18 
04:14:18.207068902 -0400
@@ -125,7 +125,7 @@
          value -= oldValue; /* make value into a differential 
measurement */

-    switch(pEv->code) {
+    switch(pEvdev->axis_map[pEv->code]) {

      /* ABS_X has the same value as REL_X, so this case catches both */
      case REL_X:
diff -ur xf86-input-evdev-2.6.0/src/evdev.c 
--- xf86-input-evdev-2.6.0/src/evdev.c    2011-01-05 17:35:27.000000000 
+++ xf86-input-evdev-2.6.0-dev/src/evdev.c    2011-05-16 
00:52:41.485952421 -0400
@@ -1303,7 +1303,7 @@
      memset(pEvdev->old_vals, -1, num_axes * sizeof(int));
      atoms = malloc(pEvdev->num_vals * sizeof(Atom));

-    for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) {
+    for (axis = ABS_Z; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) {
          pEvdev->axis_map[axis] = -1;
          if (!TestBit(axis, pEvdev->abs_bitmask))

More information about the xorg mailing list