summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Osterlund <petero2@telia.com>2003-09-25 01:37:13 +0200
committerPeter Osterlund <petero2@telia.com>2006-04-09 04:01:12 +0200
commita37a1239a79d0147dbd76e7346108d4b7a836864 (patch)
tree507aa7a47fa006d5ec858eed039fe98497bdb6c8
parentfe3d1e6d2bae13264eb85d2466d1e8c78686d993 (diff)
Added support for the new 2.6 kernel events ABS_TOOL_WIDTH,
BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP and BTN_TOOL_TRIPLETAP. Note that this swaps the direction of the Y axis internally to match X and the linux input subsystem. Because of this, the TopEdge and BottomEdge parameters must be modified in the config file. There is some backwards compatibility code for old 2.5/2.6 kernels that will probably be deleted later.
-rw-r--r--INSTALL4
-rw-r--r--linux_input.h4
-rw-r--r--synaptics.c150
-rw-r--r--synaptics.h14
-rw-r--r--synclient.c22
5 files changed, 141 insertions, 53 deletions
diff --git a/INSTALL b/INSTALL
index bbbd0e7..375b1b2 100644
--- a/INSTALL
+++ b/INSTALL
@@ -31,8 +31,8 @@ Section "InputDevice"
Option "Protocol" "auto-dev"
Option "LeftEdge" "1900"
Option "RightEdge" "5400"
- Option "TopEdge" "3900"
- Option "BottomEdge" "1800"
+ Option "TopEdge" "1900"
+ Option "BottomEdge" "4000"
Option "FingerLow" "25"
Option "FingerHigh" "30"
Option "MaxTapTime" "180"
diff --git a/linux_input.h b/linux_input.h
index 39762d5..9e8c487 100644
--- a/linux_input.h
+++ b/linux_input.h
@@ -47,10 +47,14 @@ struct input_id {
#define BTN_5 0x105
#define BTN_6 0x106
#define BTN_7 0x107
+#define BTN_TOOL_FINGER 0x145
+#define BTN_TOOL_DOUBLETAP 0x14d
+#define BTN_TOOL_TRIPLETAP 0x14e
#define ABS_X 0x00
#define ABS_Y 0x01
#define ABS_PRESSURE 0x18
+#define ABS_TOOL_WIDTH 0x1c
#define MSC_GESTURE 0x02
diff --git a/synaptics.c b/synaptics.c
index feaf2d4..522633c 100644
--- a/synaptics.c
+++ b/synaptics.c
@@ -75,6 +75,16 @@
* Local Variables and Types
****************************************************************************/
+/*
+ * The x/y limits are taken from the Synaptics TouchPad interfacing Guide,
+ * section 2.3.2, which says that they should be valid regardless of the
+ * actual size of the sensor.
+ */
+#define XMIN_NOMINAL 1472
+#define XMAX_NOMINAL 5472
+#define YMIN_NOMINAL 1408
+#define YMAX_NOMINAL 4448
+
#define MAX_UNSYNC_PACKETS 10 /* i.e. 10 to 60 bytes */
typedef enum {
@@ -541,9 +551,9 @@ edge_detection(SynapticsPrivatePtr priv, int x, int y)
else if (x < priv->synpara->left_edge)
edge |= LEFT_EDGE;
- if (y > priv->synpara->top_edge)
+ if (y < priv->synpara->top_edge)
edge |= TOP_EDGE;
- else if (y < priv->synpara->bottom_edge)
+ else if (y > priv->synpara->bottom_edge)
edge |= BOTTOM_EDGE;
return edge;
@@ -700,30 +710,30 @@ SynapticsDetectFinger(SynapticsPrivatePtr priv, struct SynapticsHwState* hw)
/* palm detection */
if (finger) {
- if ((hw->z > 200) && (hw->w > 10))
+ if ((hw->z > 200) && (hw->fingerWidth > 10))
priv->palm = TRUE;
} else {
priv->palm = FALSE;
}
if (hw->x == 0)
- priv->avg_w = 0;
+ priv->avg_width = 0;
else
- priv->avg_w += (hw->w - priv->avg_w + 1) / 2;
+ priv->avg_width += (hw->fingerWidth - priv->avg_width + 1) / 2;
if (finger && !priv->finger_flag) {
- int safe_w = MAX(hw->w, priv->avg_w);
- if (hw->w < 2)
- finger = TRUE; /* more than one finger -> not a palm */
- else if ((safe_w < 6) && (priv->prev_z < para->finger_high))
- finger = TRUE; /* thin finger, distinct touch -> not a palm */
- else if ((safe_w < 7) && (priv->prev_z < para->finger_high / 2))
- finger = TRUE; /* thin finger, distinct touch -> not a palm */
- else if (hw->z > priv->prev_z + 1) /* z not stable, may be a palm */
+ int safe_width = MAX(hw->fingerWidth, priv->avg_width);
+ if (hw->twoFingers || hw->threeFingers)
+ finger = TRUE; /* more than one finger -> not a palm */
+ else if ((safe_width < 6) && (priv->prev_z < para->finger_high))
+ finger = TRUE; /* thin finger, distinct touch -> not a palm */
+ else if ((safe_width < 7) && (priv->prev_z < para->finger_high / 2))
+ finger = TRUE; /* thin finger, distinct touch -> not a palm */
+ else if (hw->z > priv->prev_z + 1) /* z not stable, may be a palm */
finger = FALSE;
- else if (hw->z < priv->prev_z - 5) /* z not stable, may be a palm */
+ else if (hw->z < priv->prev_z - 5) /* z not stable, may be a palm */
finger = FALSE;
else if (hw->z > 200) /* z too large -> probably palm */
finger = FALSE;
- else if (hw->w > 10) /* w too large -> probably palm */
+ else if (hw->fingerWidth > 10) /* finger width too large -> probably palm */
finger = FALSE;
}
priv->prev_z = hw->z;
@@ -765,7 +775,15 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState* hw)
para->x = hw->x;
para->y = hw->y;
para->z = hw->z;
- para->w = hw->w;
+ if (hw->oneFinger)
+ para->numFingers = 1;
+ else if (hw->twoFingers)
+ para->numFingers = 2;
+ else if (hw->threeFingers)
+ para->numFingers = 3;
+ else
+ para->numFingers = 0;
+ para->fingerWidth = hw->fingerWidth;
para->left = hw->left;
para->right = hw->right;
para->up = hw->up;
@@ -875,9 +893,9 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState* hw)
if (finger && /* finger is on the surface */
(timeleft > 0)) /* tap time is not succeeded */
{ /* count fingers when reported */
- if ((hw->w == 0) && (priv->finger_count == 0))
+ if (hw->twoFingers && (priv->finger_count == 0))
priv->finger_count = 2;
- if (hw->w == 1)
+ if (hw->threeFingers)
priv->finger_count = 3;
}
else
@@ -943,13 +961,13 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState* hw)
scroll_up = 0;
scroll_down = 0;
if (priv->vert_scroll_on) {
- /* + = up, - = down */
+ /* + = down, - = up */
while (hw->y - priv->scroll_y > para->scroll_dist_vert) {
- scroll_up++;
+ scroll_down++;
priv->scroll_y += para->scroll_dist_vert;
}
while (hw->y - priv->scroll_y < -para->scroll_dist_vert) {
- scroll_down++;
+ scroll_up++;
priv->scroll_y -= para->scroll_dist_vert;
}
}
@@ -972,12 +990,8 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState* hw)
!priv->finger_count && !priv->palm) {
delay = MIN(delay, 13);
if (priv->count_packet_finger > 3) { /* min. 3 packets */
- dy = (1 *
- (((MOVE_HIST(1).y + MOVE_HIST(2).y) / 2) -
- ((hw->y + MOVE_HIST(1).y) / 2)));
- dx = (-1 *
- (((MOVE_HIST(1).x + MOVE_HIST(2).x) / 2) -
- ((hw->x + MOVE_HIST(1).x) / 2)));
+ dx = (hw->x - MOVE_HIST(2).x) / 2;
+ dy = (hw->y - MOVE_HIST(2).y) / 2;
if (priv->drag) {
if (edge & RIGHT_EDGE) {
@@ -1270,6 +1284,15 @@ SynapticsParseEventData(LocalDevicePtr local, SynapticsPrivatePtr priv,
case BTN_3: /* multi-btn-3 */
priv->hwState.cbRight = (ev.value ? TRUE : FALSE);
break;
+ case BTN_TOOL_FINGER:
+ priv->hwState.oneFinger = (ev.value ? TRUE : FALSE);
+ break;
+ case BTN_TOOL_DOUBLETAP:
+ priv->hwState.twoFingers = (ev.value ? TRUE : FALSE);
+ break;
+ case BTN_TOOL_TRIPLETAP:
+ priv->hwState.threeFingers = (ev.value ? TRUE : FALSE);
+ break;
}
break;
case EV_ABS:
@@ -1278,17 +1301,44 @@ SynapticsParseEventData(LocalDevicePtr local, SynapticsPrivatePtr priv,
priv->hwState.x = ev.value;
break;
case ABS_Y:
- priv->hwState.y = ev.value;
+ if (priv->swapY) {
+ priv->hwState.y = YMAX_NOMINAL + YMIN_NOMINAL - ev.value;
+ } else {
+ priv->hwState.y = ev.value;
+ }
break;
case ABS_PRESSURE:
priv->hwState.z = ev.value;
break;
+ case ABS_TOOL_WIDTH:
+ priv->hwState.fingerWidth = ev.value;
+ break;
}
break;
case EV_MSC:
switch (ev.code) {
case MSC_GESTURE:
- priv->hwState.w = ev.value;
+ priv->swapY = TRUE;
+ switch (ev.value) {
+ case 0:
+ priv->hwState.oneFinger = FALSE;
+ priv->hwState.twoFingers = TRUE;
+ priv->hwState.threeFingers = FALSE;
+ priv->hwState.fingerWidth = 5;
+ break;
+ case 1:
+ priv->hwState.oneFinger = FALSE;
+ priv->hwState.twoFingers = FALSE;
+ priv->hwState.threeFingers = TRUE;
+ priv->hwState.fingerWidth = 5;
+ break;
+ default:
+ priv->hwState.oneFinger = TRUE;
+ priv->hwState.twoFingers = FALSE;
+ priv->hwState.threeFingers = FALSE;
+ priv->hwState.fingerWidth = ev.value;
+ break;
+ }
break;
}
break;
@@ -1320,6 +1370,7 @@ SynapticsParseRawPacket(LocalDevicePtr local, SynapticsPrivatePtr priv,
Bool ret = SynapticsGetPacket(local, priv);
int newabs = SYN_MODEL_NEWABS(priv->model_id);
unsigned char *buf;
+ int w;
if (ret != Success)
return ret;
@@ -1335,9 +1386,9 @@ SynapticsParseRawPacket(LocalDevicePtr local, SynapticsPrivatePtr priv,
buf[5]);
hw->z = buf[2];
- hw->w = (((buf[0] & 0x30) >> 2) |
- ((buf[0] & 0x04) >> 1) |
- ((buf[3] & 0x04) >> 2));
+ w = (((buf[0] & 0x30) >> 2) |
+ ((buf[0] & 0x04) >> 1) |
+ ((buf[3] & 0x04) >> 2));
hw->left = (buf[0] & 0x01) ? 1 : 0;
hw->right = (buf[0] & 0x02) ? 1 : 0;
@@ -1376,8 +1427,8 @@ SynapticsParseRawPacket(LocalDevicePtr local, SynapticsPrivatePtr priv,
hw->z = (((buf[0] & 0x30) << 2) |
(buf[3] & 0x3F));
- hw->w = (((buf[1] & 0x80) >> 4) |
- ((buf[0] & 0x04) >> 1));
+ w = (((buf[1] & 0x80) >> 4) |
+ ((buf[0] & 0x04) >> 1));
hw->left = (buf[0] & 0x01) ? 1 : 0;
hw->right = (buf[0] & 0x02) ? 1 : 0;
@@ -1385,6 +1436,14 @@ SynapticsParseRawPacket(LocalDevicePtr local, SynapticsPrivatePtr priv,
hw->down = 0;
hw->cbLeft = hw->cbRight = hw->up = hw->down = FALSE;
}
+
+ hw->y = YMAX_NOMINAL + YMIN_NOMINAL - hw->y;
+
+ hw->oneFinger = FALSE;
+ hw->twoFingers = FALSE;
+ hw->threeFingers = FALSE;
+ hw->fingerWidth = 0;
+
if (hw->z > 0) {
int w_ok = 0;
/*
@@ -1393,16 +1452,31 @@ SynapticsParseRawPacket(LocalDevicePtr local, SynapticsPrivatePtr priv,
* normal width.
*/
if (SYN_CAP_EXTENDED(priv->capabilities)) {
- if ((hw->w >= 0) && (hw->w <= 1)) {
+ if ((w >= 0) && (w <= 1)) {
w_ok = SYN_CAP_MULTIFINGER(priv->capabilities);
- } else if (hw->w == 2) {
+ } else if (w == 2) {
w_ok = SYN_MODEL_PEN(priv->model_id);
- } else if ((hw->w >= 4) && (hw->w <= 15)) {
+ } else if ((w >= 4) && (w <= 15)) {
w_ok = SYN_CAP_PALMDETECT(priv->capabilities);
}
}
if (!w_ok)
- hw->w = 5;
+ w = 5;
+
+ switch (w) {
+ case 0:
+ hw->twoFingers = TRUE;
+ hw->fingerWidth = 5;
+ break;
+ case 1:
+ hw->threeFingers = TRUE;
+ hw->fingerWidth = 5;
+ break;
+ default:
+ hw->oneFinger = TRUE;
+ hw->fingerWidth = w;
+ break;
+ }
}
priv->hwState = *hw;
diff --git a/synaptics.h b/synaptics.h
index 468f22b..dca94d9 100644
--- a/synaptics.h
+++ b/synaptics.h
@@ -13,7 +13,8 @@ typedef struct _SynapticsSHM
/* Current device state */
int x, y; /* actual x, y coordinates */
int z; /* pressure value */
- int w; /* finger width value */
+ int numFingers; /* number of fingers */
+ int fingerWidth; /* finger width value */
int left, right, up, down; /* left/right/up/down buttons */
/* Probed hardware properties */
@@ -54,7 +55,11 @@ struct SynapticsHwState {
int x; /* X position of finger */
int y; /* Y position of finger */
int z; /* Finger pressure */
- int w; /* Finger width/finger count */
+ Bool oneFinger;
+ Bool twoFingers;
+ Bool threeFingers;
+ int fingerWidth;
+
Bool left;
Bool right;
Bool up;
@@ -138,7 +143,10 @@ typedef struct _SynapticsPrivateRec
int palm; /* Set to true when palm detected, reset to false when
palm/finger contact disappears */
int prev_z; /* previous z value, for palm detection */
- int avg_w; /* weighted average of previous w values */
+ int avg_width; /* weighted average of previous fingerWidth values */
+
+ Bool swapY; /* Swap Y coordinate direction. For compatibility
+ with old 2.5/2.6 kernels. Will be removed. */
}
SynapticsPrivateRec, *SynapticsPrivatePtr;
diff --git a/synclient.c b/synclient.c
index e9f40fe..2aacacf 100644
--- a/synclient.c
+++ b/synclient.c
@@ -133,14 +133,15 @@ static void set_variables(SynapticsSHM* synshm, int argc, char* argv[], int firs
static int is_equal(SynapticsSHM* s1, SynapticsSHM* s2)
{
- return ((s1->x == s2->x) &&
- (s1->y == s2->y) &&
- (s1->z == s2->z) &&
- (s1->w == s2->w) &&
- (s1->left == s2->left) &&
- (s1->right == s2->right) &&
- (s1->up == s2->up) &&
- (s1->down == s2->down));
+ return ((s1->x == s2->x) &&
+ (s1->y == s2->y) &&
+ (s1->z == s2->z) &&
+ (s1->numFingers == s2->numFingers) &&
+ (s1->fingerWidth == s2->fingerWidth) &&
+ (s1->left == s2->left) &&
+ (s1->right == s2->right) &&
+ (s1->up == s2->up) &&
+ (s1->down == s2->down));
}
static void monitor(SynapticsSHM* synshm, int delay)
@@ -152,8 +153,9 @@ static void monitor(SynapticsSHM* synshm, int delay)
while(1) {
SynapticsSHM cur = *synshm;
if (!is_equal(&old, &cur)) {
- printf("x:%4d y:%4d z:%3d w:%2d left:%d right:%d up:%d down:%d\n",
- cur.x, cur.y, cur.z, cur.w, cur.left, cur.right, cur.up, cur.down);
+ printf("x:%4d y:%4d z:%3d f:%1d w:%2d left:%d right:%d up:%d down:%d\n",
+ cur.x, cur.y, cur.z, cur.numFingers, cur.fingerWidth,
+ cur.left, cur.right, cur.up, cur.down);
old = cur;
}
usleep(delay * 1000);