]> Pileus Git - ~andy/linux/blobdiff - drivers/input/mouse/synaptics.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[~andy/linux] / drivers / input / mouse / synaptics.c
index 37033ade79d3c70881517f128d7a3d0141919099..12d12ca3fee030e0ab9ced706616c1160a1c584b 100644 (file)
 #define ABS_POS_BITS 13
 
 /*
- * Any position values from the hardware above the following limits are
- * treated as "wrapped around negative" values that have been truncated to
- * the 13-bit reporting range of the hardware. These are just reasonable
- * guesses and can be adjusted if hardware is found that operates outside
- * of these parameters.
+ * These values should represent the absolute maximum value that will
+ * be reported for a positive position value. Some Synaptics firmware
+ * uses this value to indicate a finger near the edge of the touchpad
+ * whose precise position cannot be determined.
+ *
+ * At least one touchpad is known to report positions in excess of this
+ * value which are actually negative values truncated to the 13-bit
+ * reporting range. These values have never been observed to be lower
+ * than 8184 (i.e. -8), so we treat all values greater than 8176 as
+ * negative and any other value as positive.
  */
-#define X_MAX_POSITIVE (((1 << ABS_POS_BITS) + XMAX) / 2)
-#define Y_MAX_POSITIVE (((1 << ABS_POS_BITS) + YMAX) / 2)
+#define X_MAX_POSITIVE 8176
+#define Y_MAX_POSITIVE 8176
 
 /*****************************************************************************
  *     Stuff we need even when we do not want native Synaptics support
@@ -604,11 +609,21 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
                hw->right = (buf[0] & 0x02) ? 1 : 0;
        }
 
-       /* Convert wrap-around values to negative */
+       /*
+        * Convert wrap-around values to negative. (X|Y)_MAX_POSITIVE
+        * is used by some firmware to indicate a finger at the edge of
+        * the touchpad whose precise position cannot be determined, so
+        * convert these values to the maximum axis value.
+        */
        if (hw->x > X_MAX_POSITIVE)
                hw->x -= 1 << ABS_POS_BITS;
+       else if (hw->x == X_MAX_POSITIVE)
+               hw->x = XMAX;
+
        if (hw->y > Y_MAX_POSITIVE)
                hw->y -= 1 << ABS_POS_BITS;
+       else if (hw->y == Y_MAX_POSITIVE)
+               hw->y = YMAX;
 
        return 0;
 }