Bug 5555

Summary: Aiptek xinput driver fails to apply button events properly or pass events until patched.
Product: xorg Reporter: Adrian Winchell <adrian>
Component: Input/aiptekAssignee: Kevin E. Martin <kem>
Status: RESOLVED FIXED QA Contact: Xorg Project Team <xorg-team>
Severity: major    
Priority: highest CC: rene.vanpaassen, xorg-team
Version: 7.0.0Keywords: patch
Hardware: x86 (IA32)   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:
Attachments:
Description Flags
Patch with load of fixes, backported from aiptektablet.sourceforge.net none

Description Adrian Winchell 2006-01-09 17:31:07 UTC
The following patch is necessary to make input/aiptek module function correctly
on my system (the described changes also apply to previous versions, this diff
was created against module version 1.0.0.5 )

The main bug here is that the driver attempts to use a bitwise OR to turn the
tablet buttons both on and off (OR can only result in 1 if one side is set),
resulting in immediately stuck buttons. One or two other changes are required to
make the event list process correctly through the driver (otherwise no events
get passed to X - the tablet effectively doesn't work, although including the
module and setting its parameters doesn't kill X.)

### This is an edited diff created from a *fixed* older version of xf86Aiptek.c
- so some hunks include lines that will mangle your whitespace a bit. ###

--- ./xf86Aiptek.c	2004-04-23 15:54:02.000000000 -0400
+++ /root/xf86Aiptek.c	2004-09-30 17:47:27.000000000 -0400
@@ -309,7 +309,7 @@
 
     int bCorePointer, bAbsolute;
     int x, y, z, xTilt, yTilt;
-
+    
     if ((DEVICE_ID(device->flags) != common->currentValues.eventType))
     {
         DBG(7,ErrorF("xf86AiptekSendEvents: not the same device type (%u,%u)\n",
@@ -422,13 +422,11 @@
     }
 
     /* As the coordinates are ready, we can send events to X */
-    if (common->currentValues.proximity)
-    {
         if (!common->previousValues.proximity)
         {
             if (!bCorePointer)
             {
-                xf86PostProximityEvent(local->dev, 1, 0, 5,
+		xf86PostProximityEvent(local->dev, 1, 0, 5,
                     x, y, z, xTilt, yTilt);
             }
         }
@@ -442,7 +440,7 @@
         {
             if (bAbsolute || common->previousValues.proximity)
             {
-                xf86PostMotionEvent(local->dev, bAbsolute, 0, 5,
+		xf86PostMotionEvent(local->dev, bAbsolute, 0, 5,
                         x, y, z, xTilt, yTilt);
             }
         }
@@ -456,24 +454,11 @@
                 int id;
                 id = ffs(delta);
                 delta &= ~(1 << (id-1));
-                xf86PostButtonEvent(local->dev, bAbsolute, id,
+		xf86PostButtonEvent(local->dev, bAbsolute, id,
                         (common->currentValues.button & (1<<(id-1))), 0, 5,
                         x, y, z, xTilt, yTilt);
             }
         }
-    }
-    else
-    {
-        if (!bCorePointer)
-        {
-            if (common->previousValues.proximity)
-            {
-                xf86PostProximityEvent(local->dev, 0, 0, 5, x, y, z,
-                        xTilt, yTilt);
-            }
-        }
-        common->previousValues.proximity = 0;
-    }
 }
 
 /*
@@ -496,7 +481,7 @@
     double              d_zCapacity;
 
     SYSCALL(len = read(local->fd, eventbuf, sizeof(eventbuf)));
-
+    
     if (len <= 0)
     {
         ErrorF("Error reading Aiptek tablet: %s\n", strerror(errno));
@@ -524,7 +509,7 @@
         {
             case EV_ABS:
             {
-                switch (event->code)
+		    switch (event->code)
                 {
                     case ABS_X:
                     {
@@ -704,27 +689,48 @@
                      * as normal buttons.
                      */
                     case BTN_TOUCH:
-                    {
+		{
                         ++eventsInMessage;
-                        common->currentValues.button |= 
-                            (event->value > 0 ? 1 : 0) * BUTTONS_EVENT_TOUCH;
-                    }
+			    if (common->currentValues.eventType != STYLUS_ID)
+				    common->currentValues.eventType = STYLUS_ID;
+                        if ((event->value > 0) * BUTTONS_EVENT_TOUCH)
+			{
+				common->currentValues.button |= BUTTONS_EVENT_TOUCH;
+			}
+			else
+			{
+				common->currentValues.button &= ~BUTTONS_EVENT_TOUCH;
+			}
+		}
                     break;
+		
 
                     case BTN_STYLUS:
                     {
                         ++eventsInMessage;
-                        common->currentValues.button |= 
-                            (event->value > 0 ? 1 : 0) * BUTTONS_EVENT_STYLUS;
-                    }
+			if ((event->value > 0) * BUTTONS_EVENT_STYLUS)
+			{
+				common->currentValues.button |= BUTTONS_EVENT_STYLUS;
+			}
+			else
+			{
+				common->currentValues.button &= ~BUTTONS_EVENT_STYLUS;
+			}
+		}
                     break;
 
                     case BTN_STYLUS2:
                     {
                         ++eventsInMessage;
-                        common->currentValues.button |= 
-                            (event->value > 0 ? 1 : 0) * BUTTONS_EVENT_STYLUS2;
-                    }
+                	if ((event->value > 0) * BUTTONS_EVENT_STYLUS2)
+			{
+				common->currentValues.button |= BUTTONS_EVENT_STYLUS2;
+			}
+			else
+			{
+				common->currentValues.button &= ~BUTTONS_EVENT_STYLUS2;
+			}
+		}
                     break;
 
                     /*
@@ -737,41 +743,71 @@
                     case BTN_LEFT:
                     {
                         ++eventsInMessage;
-                        common->currentValues.button |= 
-                            (event->value > 0 ? 1 : 0) * BUTTONS_EVENT_MOUSE_LEFT;
-                    }
+                        if ((event->value > 0) * BUTTONS_EVENT_MOUSE_LEFT)
+			{
+				common->currentValues.button |= BUTTONS_EVENT_MOUSE_LEFT;
+			}
+			else
+			{
+				common->currentValues.button &= ~BUTTONS_EVENT_MOUSE_LEFT;
+			}
+		}
                     break;
 
                     case BTN_MIDDLE:
                     {
                         ++eventsInMessage;
-                        common->currentValues.button |= 
-                            (event->value > 0 ? 1 : 0) *
BUTTONS_EVENT_MOUSE_MIDDLE;
-                    }
+                        if ((event->value > 0) * BUTTONS_EVENT_MOUSE_MIDDLE)
+			{
+				common->currentValues.button |= BUTTONS_EVENT_MOUSE_MIDDLE;
+			}
+			else
+			{
+				common->currentValues.button &= ~BUTTONS_EVENT_MOUSE_MIDDLE;
+			}
+		}
                     break;
 
                     case BTN_RIGHT:
                     {
                         ++eventsInMessage;
-                        common->currentValues.button |= 
-                            (event->value > 0 ? 1 : 0) * BUTTONS_EVENT_MOUSE_RIGHT;
-                    }
+                        if ((event->value > 0) * BUTTONS_EVENT_MOUSE_RIGHT)
+			{
+				common->currentValues.button |= BUTTONS_EVENT_MOUSE_RIGHT;
+			}
+			else
+			{
+				common->currentValues.button &= ~BUTTONS_EVENT_MOUSE_RIGHT;
+			}
+		}
                     break;
 
                     case BTN_SIDE:
                     {
                         ++eventsInMessage;
-                        common->currentValues.button |= 
-                            (event->value > 0 ? 1 : 0) * BUTTONS_EVENT_SIDE_BTN;
-                    }
+                        if ((event->value > 0) * BUTTONS_EVENT_SIDE_BTN)
+			{
+				common->currentValues.button |= BUTTONS_EVENT_SIDE_BTN;
+			}
+			else
+			{
+				common->currentValues.button &= ~BUTTONS_EVENT_SIDE_BTN;
+			}
+		}
                     break;
 
                     case BTN_EXTRA:
                     {
                         ++eventsInMessage;
-                        common->currentValues.button |= 
-                            (event->value > 0 ? 1 : 0) * BUTTONS_EVENT_EXTRA_BTN;
-                    }
+                        if ((event->value > 0) * BUTTONS_EVENT_EXTRA_BTN)
+			{
+				common->currentValues.button |= BUTTONS_EVENT_EXTRA_BTN;
+			}
+			else
+			{
+				common->currentValues.button &= ~BUTTONS_EVENT_EXTRA_BTN;
+			}
+		}
                     break;
 
                     /*
@@ -812,7 +848,6 @@
         {
             continue;
         }
-
         /*
          * We've seen EV_MSCs in the incoming data trail with no
          * other message types in-between. We use 'eventsInMessage'
@@ -825,8 +860,6 @@
         {
             continue;
         }
-        eventsInMessage = 0;
-
         /* 
          * This filter throws out reports that do not meet minimum threshold
          * requirements for movement along that axis.
@@ -1851,10 +1884,10 @@
 xf86AiptekAllocateStylus(void)
 {
     LocalDevicePtr local = xf86AiptekAllocate(XI_STYLUS, STYLUS_ID);
-    
+	
     if (local)
     {
-        local->type_name = "Stylus";
+	local->type_name = "Stylus";
     }
     return local;
 }
@@ -1982,15 +2015,16 @@
     s = xf86FindOptionValue(fakeLocal->options, "Type");
     if (s && (xf86NameCmp(s, "stylus") == 0))
     {
-        local = xf86AiptekAllocateStylus();
+	local = xf86AiptekAllocate(XI_STYLUS, STYLUS_ID);
     }
     else if (s && (xf86NameCmp(s, "cursor") == 0))
     {
-        local = xf86AiptekAllocateCursor();
+	local = xf86AiptekAllocate(XI_CURSOR, CURSOR_ID);
     }
     else if (s && (xf86NameCmp(s, "eraser") == 0))
     {
-        local = xf86AiptekAllocateEraser();
+	local = xf86AiptekAllocate(XI_ERASER,
+            ABSOLUTE_FLAG|ERASER_ID);
     }
     else
     {
@@ -2004,7 +2038,6 @@
         xfree(fakeLocal);
         return NULL;
     }
-
     device = (AiptekDevicePtr) local->private;
 
     common              = device->common;
Comment 1 Daniel Stone 2007-02-27 01:29:52 UTC
Sorry about the phenomenal bug spam, guys.  Adding xorg-team@ to the QA contact so bugs don't get lost in future.
Comment 2 Rene van Paassen 2008-01-09 15:50:48 UTC
Created attachment 13625 [details] [review]
Patch with load of fixes, backported from aiptektablet.sourceforge.net

Tested with re-branded aiptek 12000U
Comment 3 Rene van Paassen 2008-01-09 15:53:56 UTC
Wow. This has been reported over a year ago (well, a year and 20 minutes). 

I am running Fedora 8 now, which is fitted with Xorg 7.2 . 

Let me introduce myself. I am the guy who fixed the aiptek kernel and
X drivers, several years ago. In those times, for optimal tablet
pleasure, one needed to download and compile at least the Linux kernel
driver. The aiptek driver that was in older Xfree/Xorg releases
worked, mostly.

By now, an updated kernel driver is in the linux kernel, so that part
progressed. However, the fixes/cleanups for this driver in Xorg 7
onwards introduced considerable bitrot in the xorg driver, so much
that it is unusable now, and everyone on the aiptek forums/lists is
complaining. I don't want to bitch, but this makes me somewhat
unhappy. Please, in the future when you plan to fix things, contact me
to check that you are not hurting functionality.

I produced a patch for the 1.0.1 version of the driver. I stuck as
much as possible to your formatting and structure, to get a clean
patch. I used the source from the fixed aiptek X driver as reference
(aiptektablet.sourceforge.net).

Please apply this patch ASAP. If you have a reason not to apply this
patch (and it better be a good one), clarify. I tested this on my
Medion (re-branded aiptek 12000U) tablet, and it works like a charm.

BTW Thanks Adrian, for reporting this and trying to fix the driver. I hope
this can be fixed soon.

Regards, 

	 Rene
Comment 4 Peter Hutterer 2008-01-09 17:11:18 UTC
(In reply to comment #3)
> By now, an updated kernel driver is in the linux kernel, so that part
> progressed. However, the fixes/cleanups for this driver in Xorg 7
> onwards introduced considerable bitrot in the xorg driver, so much
> that it is unusable now, and everyone on the aiptek forums/lists is
> complaining. I don't want to bitch, but this makes me somewhat
> unhappy. Please, in the future when you plan to fix things, contact me
> to check that you are not hurting functionality.

git://anongit.freedesktop.org/git/xorg/doc/xorg-docs, the MAINTAINERS file lists aiptek as unmaintained. 

AFAIK, there's exactly two ppl working on general input. so if stuff goes amiss, keep poking.

> I produced a patch for the 1.0.1 version of the driver. I stuck as
> much as possible to your formatting and structure, to get a clean
> patch. I used the source from the fixed aiptek X driver as reference
> (aiptektablet.sourceforge.net).
> 
> Please apply this patch ASAP. If you have a reason not to apply this
> patch (and it better be a good one), clarify. I tested this on my
> Medion (re-branded aiptek 12000U) tablet, and it works like a charm.

I took the liberty of removing the diff for the xf86Aiptek.c~ file from the diff :)

aside from that I fixed three things to make it work with git master, one compiler warning, one call to a deprecated function and - most importantly - one call to an unresolved function. 

so the current git head should work with 7.3 and beyond.

changing to fixed now, please reopen if problems occur.

do you want to take over maintainership and cut releases for 7.2 and 7.3?
Comment 5 Peter Hutterer 2008-01-09 17:13:12 UTC
I forgot:

patch was pushed as 3cb825cb4a633132de10df77e792fcbadf082385
Subsequent fixes for server 1.4 as
66e0fbb24377ac14b9cf8a80a55253cff13d7913
a88dafb63b0e0f3e4557ae75a3ee9a377ea4ef68
e34bc8e774d92bd81dcefbcd341ab3f040a7f144

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.