]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/input/tablet/aiptek.c
Pull bugzilla-7880 into release branch
[linux-2.6-omap-h63xx.git] / drivers / input / tablet / aiptek.c
index 7fb15af33c492847ee539ab14efaadd847b722ab..94683f58c9e18ec5b933d7721ab3b07467ae9a1c 100644 (file)
@@ -82,8 +82,8 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.5 (May-15-2004)"
-#define DRIVER_AUTHOR  "Bryan W. Headley/Chris Atenasio"
+#define DRIVER_VERSION "v2.3 (May 2, 2007)"
+#define DRIVER_AUTHOR  "Bryan W. Headley/Chris Atenasio/Cedric Brun/Rene van Paassen"
 #define DRIVER_DESC    "Aiptek HyperPen USB Tablet Driver (Linux 2.6.x)"
 
 /*
 #define AIPTEK_WHEEL_DISABLE                           (-10101)
 
        /* ToolCode values, which BTW are 0x140 .. 0x14f
-        * We have things set up such that if TOOL_BUTTON_FIRED_BIT is
-        * not set, we'll send one instance of AIPTEK_TOOL_BUTTON_xxx.
-        *
-        * Whenever the user resets the value, TOOL_BUTTON_FIRED_BIT will
-        * get reset.
+        * We have things set up such that if the tool button has changed,
+        * the tools get reset.
         */
-#define TOOL_BUTTON(x)                                 ((x) & 0x14f)
-#define TOOL_BUTTON_FIRED(x)                           ((x) & 0x200)
-#define TOOL_BUTTON_FIRED_BIT                          0x200
        /* toolMode codes
         */
 #define AIPTEK_TOOL_BUTTON_PEN_MODE                    BTN_TOOL_PEN
@@ -326,6 +320,9 @@ struct aiptek {
        int inDelay;                            /* jitter: in jitter delay?      */
        unsigned long endDelay;                 /* jitter: time when delay ends  */
        int previousJitterable;                 /* jitterable prev value     */
+
+       int lastMacro;                          /* macro key to reset            */
+       int previousToolMode;                   /* pen, pencil, brush, etc. tool */
        unsigned char *data;                    /* incoming packet data          */
 };
 
@@ -378,8 +375,11 @@ static int map_str_to_val(const struct aiptek_map *map, const char *str, size_t
 {
        const struct aiptek_map *p;
 
+       if (str[count - 1] == '\n')
+               count--;
+
        for (p = map; p->string; p++)
-               if (!strncmp(str, p->string, count))
+               if (!strncmp(str, p->string, count))
                        return p->value;
 
        return AIPTEK_INVALID_VALUE;
@@ -417,6 +417,9 @@ static const char *map_val_to_str(const struct aiptek_map *map, int val)
  * Proximity. Why two events? I thought it interesting to know if the
  * Proximity event occurred while the tablet was in absolute or relative
  * mode.
+ * Update: REL_MISC proved not to be such a good idea. With REL_MISC you
+ * get an event transmitted each time. ABS_MISC works better, since it
+ * can be set and re-set. Thus, only using ABS_MISC from now on.
  *
  * Other tablets use the notion of a certain minimum stylus pressure
  * to infer proximity. While that could have been done, that is yet
@@ -506,6 +509,11 @@ static void aiptek_irq(struct urb *urb)
                                                 aiptek->curSetting.wheel);
                                aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE;
                        }
+                       if (aiptek->lastMacro != -1) {
+                               input_report_key(inputdev,
+                                                macroKeyEvents[aiptek->lastMacro], 0);
+                               aiptek->lastMacro = -1;
+                       }
                        input_sync(inputdev);
                }
        }
@@ -539,16 +547,18 @@ static void aiptek_irq(struct urb *urb)
                         * all 'bad' reports...
                         */
                        if (dv != 0) {
-                               /* If we've not already sent a tool_button_?? code, do
-                                * so now. Then set FIRED_BIT so it won't be resent unless
-                                * the user forces FIRED_BIT off.
+                               /* If the selected tool changed, reset the old
+                                * tool key, and set the new one.
                                 */
-                               if (TOOL_BUTTON_FIRED
-                                   (aiptek->curSetting.toolMode) == 0) {
+                               if (aiptek->previousToolMode !=
+                                   aiptek->curSetting.toolMode) {
+                                       input_report_key(inputdev,
+                                                        aiptek->previousToolMode, 0);
                                        input_report_key(inputdev,
-                                                        TOOL_BUTTON(aiptek->curSetting.toolMode),
+                                                        aiptek->curSetting.toolMode,
                                                         1);
-                                       aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+                                       aiptek->previousToolMode =
+                                                 aiptek->curSetting.toolMode;
                                }
 
                                if (p != 0) {
@@ -584,6 +594,11 @@ static void aiptek_irq(struct urb *urb)
                                        }
                                }
                                input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_STYLUS);
+                               if (aiptek->lastMacro != -1) {
+                                       input_report_key(inputdev,
+                                                        macroKeyEvents[aiptek->lastMacro], 0);
+                                       aiptek->lastMacro = -1;
+                               }
                                input_sync(inputdev);
                        }
                }
@@ -609,16 +624,18 @@ static void aiptek_irq(struct urb *urb)
                        middle = (data[5] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
 
                        if (dv != 0) {
-                               /* If we've not already sent a tool_button_?? code, do
-                                * so now. Then set FIRED_BIT so it won't be resent unless
-                                * the user forces FIRED_BIT off.
+                               /* If the selected tool changed, reset the old
+                                * tool key, and set the new one.
                                 */
-                               if (TOOL_BUTTON_FIRED
-                                   (aiptek->curSetting.toolMode) == 0) {
+                               if (aiptek->previousToolMode !=
+                                   aiptek->curSetting.toolMode) {
+                                       input_report_key(inputdev,
+                                                        aiptek->previousToolMode, 0);
                                        input_report_key(inputdev,
-                                                        TOOL_BUTTON(aiptek->curSetting.toolMode),
+                                                        aiptek->curSetting.toolMode,
                                                         1);
-                                       aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+                                       aiptek->previousToolMode =
+                                                 aiptek->curSetting.toolMode;
                                }
 
                                if (p != 0) {
@@ -639,7 +656,12 @@ static void aiptek_irq(struct urb *urb)
                                                aiptek->curSetting.wheel = AIPTEK_WHEEL_DISABLE;
                                        }
                                }
-                               input_report_rel(inputdev, REL_MISC, p | AIPTEK_REPORT_TOOL_MOUSE);
+                               input_report_abs(inputdev, ABS_MISC, p | AIPTEK_REPORT_TOOL_MOUSE);
+                               if (aiptek->lastMacro != -1) {
+                                       input_report_key(inputdev,
+                                                        macroKeyEvents[aiptek->lastMacro], 0);
+                                       aiptek->lastMacro = -1;
+                               }
                                input_sync(inputdev);
                        }
                }
@@ -655,44 +677,37 @@ static void aiptek_irq(struct urb *urb)
                bs = (data[1] & aiptek->curSetting.stylusButtonLower) != 0 ? 1 : 0;
                pck = (data[1] & aiptek->curSetting.stylusButtonUpper) != 0 ? 1 : 0;
 
-               macro = data[3];
+               macro = dv && p && tip && !(data[3] & 1) ? (data[3] >> 1) : -1;
                z = le16_to_cpu(get_unaligned((__le16 *) (data + 4)));
 
-               if (dv != 0) {
-                       /* If we've not already sent a tool_button_?? code, do
-                        * so now. Then set FIRED_BIT so it won't be resent unless
-                        * the user forces FIRED_BIT off.
+               if (dv) {
+                       /* If the selected tool changed, reset the old
+                        * tool key, and set the new one.
                         */
-                       if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
+                       if (aiptek->previousToolMode !=
+                           aiptek->curSetting.toolMode) {
+                               input_report_key(inputdev,
+                                                aiptek->previousToolMode, 0);
                                input_report_key(inputdev,
-                                                TOOL_BUTTON(aiptek->curSetting.toolMode),
+                                                aiptek->curSetting.toolMode,
                                                 1);
-                               aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+                               aiptek->previousToolMode =
+                                       aiptek->curSetting.toolMode;
                        }
+               }
 
-                       if (p != 0) {
-                               input_report_key(inputdev, BTN_TOUCH, tip);
-                               input_report_key(inputdev, BTN_STYLUS, bs);
-                               input_report_key(inputdev, BTN_STYLUS2, pck);
-                               input_report_abs(inputdev, ABS_PRESSURE, z);
-                       }
+               if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) {
+                       input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0);
+                       aiptek->lastMacro = -1;
+               }
 
-                       /* For safety, we're sending key 'break' codes for the
-                        * neighboring macro keys.
-                        */
-                       if (macro > 0) {
-                               input_report_key(inputdev,
-                                                macroKeyEvents[macro - 1], 0);
-                       }
-                       if (macro < 25) {
-                               input_report_key(inputdev,
-                                                macroKeyEvents[macro + 1], 0);
-                       }
-                       input_report_key(inputdev, macroKeyEvents[macro], p);
-                       input_report_abs(inputdev, ABS_MISC,
-                                        p | AIPTEK_REPORT_TOOL_STYLUS);
-                       input_sync(inputdev);
+               if (macro != -1 && macro != aiptek->lastMacro) {
+                       input_report_key(inputdev, macroKeyEvents[macro], 1);
+                       aiptek->lastMacro = macro;
                }
+               input_report_abs(inputdev, ABS_MISC,
+                                p | AIPTEK_REPORT_TOOL_STYLUS);
+               input_sync(inputdev);
        }
        /* Report 5s come from the macro keys when pressed by mouse
         */
@@ -704,43 +719,35 @@ static void aiptek_irq(struct urb *urb)
                left = (data[1]& aiptek->curSetting.mouseButtonLeft) != 0 ? 1 : 0;
                right = (data[1] & aiptek->curSetting.mouseButtonRight) != 0 ? 1 : 0;
                middle = (data[1] & aiptek->curSetting.mouseButtonMiddle) != 0 ? 1 : 0;
-               macro = data[3];
+               macro = dv && p && left && !(data[3] & 1) ? (data[3] >> 1) : 0;
 
-               if (dv != 0) {
-                       /* If we've not already sent a tool_button_?? code, do
-                        * so now. Then set FIRED_BIT so it won't be resent unless
-                        * the user forces FIRED_BIT off.
+               if (dv) {
+                       /* If the selected tool changed, reset the old
+                        * tool key, and set the new one.
                         */
-                       if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
-                               input_report_key(inputdev,
-                                                TOOL_BUTTON(aiptek->curSetting.toolMode),
-                                                1);
-                               aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
-                       }
-
-                       if (p != 0) {
-                               input_report_key(inputdev, BTN_LEFT, left);
-                               input_report_key(inputdev, BTN_MIDDLE, middle);
-                               input_report_key(inputdev, BTN_RIGHT, right);
+                       if (aiptek->previousToolMode !=
+                           aiptek->curSetting.toolMode) {
+                               input_report_key(inputdev,
+                                                aiptek->previousToolMode, 0);
+                               input_report_key(inputdev,
+                                                aiptek->curSetting.toolMode, 1);
+                               aiptek->previousToolMode = aiptek->curSetting.toolMode;
                        }
+               }
 
-                       /* For safety, we're sending key 'break' codes for the
-                        * neighboring macro keys.
-                        */
-                       if (macro > 0) {
-                               input_report_key(inputdev,
-                                                macroKeyEvents[macro - 1], 0);
-                       }
-                       if (macro < 25) {
-                               input_report_key(inputdev,
-                                                macroKeyEvents[macro + 1], 0);
-                       }
+               if (aiptek->lastMacro != -1 && aiptek->lastMacro != macro) {
+                       input_report_key(inputdev, macroKeyEvents[aiptek->lastMacro], 0);
+                       aiptek->lastMacro = -1;
+               }
 
+               if (macro != -1 && macro != aiptek->lastMacro) {
                        input_report_key(inputdev, macroKeyEvents[macro], 1);
-                       input_report_rel(inputdev, ABS_MISC,
-                                        p | AIPTEK_REPORT_TOOL_MOUSE);
-                       input_sync(inputdev);
+                       aiptek->lastMacro = macro;
                }
+
+               input_report_abs(inputdev, ABS_MISC,
+                                p | AIPTEK_REPORT_TOOL_MOUSE);
+               input_sync(inputdev);
        }
        /* We have no idea which tool can generate a report 6. Theoretically,
         * neither need to, having been given reports 4 & 5 for such use.
@@ -759,15 +766,18 @@ static void aiptek_irq(struct urb *urb)
                                         0);
                }
 
-               /* If we've not already sent a tool_button_?? code, do
-                * so now. Then set FIRED_BIT so it won't be resent unless
-                * the user forces FIRED_BIT off.
-                */
-               if (TOOL_BUTTON_FIRED(aiptek->curSetting.toolMode) == 0) {
+               /* If the selected tool changed, reset the old
+                  tool key, and set the new one.
+               */
+               if (aiptek->previousToolMode !=
+                   aiptek->curSetting.toolMode) {
+                       input_report_key(inputdev,
+                                        aiptek->previousToolMode, 0);
                        input_report_key(inputdev,
-                                        TOOL_BUTTON(aiptek->curSetting.
-                                                    toolMode), 1);
-                       aiptek->curSetting.toolMode |= TOOL_BUTTON_FIRED_BIT;
+                                        aiptek->curSetting.toolMode,
+                                        1);
+                       aiptek->previousToolMode =
+                               aiptek->curSetting.toolMode;
                }
 
                input_report_key(inputdev, macroKeyEvents[macro], 1);
@@ -1694,6 +1704,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
        aiptek->inDelay = 0;
        aiptek->endDelay = 0;
        aiptek->previousJitterable = 0;
+       aiptek->lastMacro = -1;
 
        /* Set up the curSettings struct. Said struct contains the current
         * programmable parameters. The newSetting struct contains changes