summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Osterlund <petero2@telia.com>2003-12-15 22:44:08 +0100
committerPeter Osterlund <petero2@telia.com>2006-04-09 04:01:30 +0200
commite6d92b0e4399ead8d24e043857d3120b87ecc1ef (patch)
tree2c7d980e65d9f46d1a36f325216149bc5ad82e48
parent13e1f68ac2c43e448bd012139bba5278a29f874c (diff)
Added pass through support. From David Kennedy and Fred
Hucht.
-rw-r--r--ps2comm.c84
-rw-r--r--ps2comm.h7
-rw-r--r--synaptics.c50
-rw-r--r--synaptics.h9
-rw-r--r--synclient.c24
-rw-r--r--syndaemon.c4
6 files changed, 173 insertions, 5 deletions
diff --git a/ps2comm.c b/ps2comm.c
index 50feeed..a93817e 100644
--- a/ps2comm.c
+++ b/ps2comm.c
@@ -4,6 +4,11 @@
* Copyright (c) 1998-2000 Bruce Kalk <kall@compass.com>
* code für the special synaptics commands (from the tpconfig-source)
*
+ * Synaptics Passthrough Support
+ * Copyright (c) 2002 Linuxcare Inc. David Kennedy <dkennedy@linuxcare.com>
+ * adapted to version 0.12.1
+ * Copyright (c) 2003 Fred Hucht <fred@thp.Uni-Duisburg.de>
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -157,6 +162,61 @@ ps2_send_cmd(int fd, byte c)
}
/*****************************************************************************
+ * Synaptics passthrough functions
+ ****************************************************************************/
+
+static Bool
+ps2_getbyte_passthrough(int fd, byte *response)
+{
+ byte ack;
+ int timeout_count;
+#define MAX_RETRY_COUNT 30
+
+ /* Getting a response back through the passthrough could take some time.
+ * Spin a little for the first byte */
+ for (timeout_count = 0;
+ (ps2_getbyte(fd, &ack) != Success) && timeout_count <= MAX_RETRY_COUNT;
+ timeout_count++)
+ ;
+ /* Do some sanity checking */
+ if ((ack & 0xfc) != 0x84) {
+ DBG(ErrorF("ps2_getbyte_passthrough: expected 0x84 and got: %02x\n",
+ (ack & 0xfc)));
+ return !Success;
+ }
+
+ ps2_getbyte(fd, response);
+ ps2_getbyte(fd, &ack);
+ ps2_getbyte(fd, &ack);
+ if ((ack & 0xcc) != 0xc4) {
+ DBG(ErrorF("ps2_getbyte_passthrough: expected 0xc4 and got: %02x\n",
+ (ack & 0xcc)));
+ return !Success;
+ }
+ ps2_getbyte(fd, &ack);
+ ps2_getbyte(fd, &ack);
+
+ return Success;
+}
+
+static Bool
+ps2_putbyte_passthrough(int fd, byte c)
+{
+ byte ack;
+
+ ps2_special_cmd(fd, c);
+ ps2_putbyte(fd, 0xF3);
+ ps2_putbyte(fd, 0x28);
+
+ ps2_getbyte_passthrough(fd, &ack);
+ if (ack != PS2_ACK) {
+ DBG(ErrorF("ps2_putbyte_passthrough: wrong acknowledge 0x%02x\n", ack));
+ return !Success;
+ }
+ return Success;
+}
+
+/*****************************************************************************
* Synaptics communications functions
****************************************************************************/
@@ -201,6 +261,30 @@ synaptics_reset(int fd)
return !Success;
}
+Bool
+SynapticsResetPassthrough(int fd)
+{
+ byte ack;
+
+ /* send reset */
+ ps2_putbyte_passthrough(fd, 0xff);
+ ps2_getbyte_passthrough(fd, &ack);
+ if (ack != 0xaa) {
+ DBG(ErrorF("SynapticsResetPassthrough: ack was %02x not 0xaa\n", ack));
+ return !Success;
+ }
+ ps2_getbyte_passthrough(fd, &ack);
+ if (ack != 0x00) {
+ DBG(ErrorF("SynapticsResetPassthrough: ack was %02x not 0x00\n", ack));
+ return !Success;
+ }
+
+ /* set defaults, turn on streaming, and enable the mouse */
+ return (ps2_putbyte_passthrough(fd, 0xf6) ||
+ ps2_putbyte_passthrough(fd, 0xea) ||
+ ps2_putbyte_passthrough(fd, 0xf4));
+}
+
/*
* Read the model-id bytes from the touchpad
* see also SYN_MODEL_* macros
diff --git a/ps2comm.h b/ps2comm.h
index b85bc1d..8450151 100644
--- a/ps2comm.h
+++ b/ps2comm.h
@@ -20,6 +20,7 @@
/* synaptics capability bits */
#define SYN_CAP_EXTENDED(c) ((c) & (1 << 23))
+#define SYN_CAP_PASSTHROUGH(c) ((c) & (1 << 7))
#define SYN_CAP_SLEEP(c) ((c) & (1 << 4))
#define SYN_CAP_FOUR_BUTTON(c) ((c) & (1 << 3))
#define SYN_CAP_MULTIFINGER(c) ((c) & (1 << 1))
@@ -64,9 +65,15 @@ Bool
synaptics_read_mode(int fd, unsigned char *mode);
Bool
+SynapticsDisableDevice(int fd);
+
+Bool
SynapticsEnableDevice(int fd);
Bool
QueryIsSynaptics(int fd);
+Bool
+SynapticsResetPassthrough(int fd);
+
#endif /* _PS2COMM_H_ */
diff --git a/synaptics.c b/synaptics.c
index ab134c0..c80ad5a 100644
--- a/synaptics.c
+++ b/synaptics.c
@@ -21,6 +21,11 @@
* absolute to relative translation code (from the gpm source)
* and some other ideas
*
+ * Synaptics Passthrough Support
+ * Copyright (c) 2002 Linuxcare Inc. David Kennedy <dkennedy@linuxcare.com>
+ * adapted to version 0.12.1
+ * Copyright (c) 2003 Fred Hucht <fred@thp.Uni-Duisburg.de>
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -281,6 +286,7 @@ SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
priv->tapping_millis = now;
priv->button_delay_millis = now;
priv->touch_on.millis = now;
+ priv->hasGuest = FALSE;
/* install shared memory or normal memory for parameter */
priv->shm_config = FALSE;
@@ -793,6 +799,11 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState* hw)
para->down = hw->down;
for (i = 0; i < 8; i++)
para->multi[i] = hw->multi[i];
+ para->guest_left = hw->guest_left;
+ para->guest_mid = hw->guest_mid;
+ para->guest_right = hw->guest_right;
+ para->guest_dx = hw->guest_dx;
+ para->guest_dy = hw->guest_dy;
/* If touchpad is switched off, we skip the whole thing and return delay */
if (para->touchpad_off == TRUE)
@@ -1044,6 +1055,9 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState* hw)
buttons = ((hw->left ? 0x01 : 0) |
(mid ? 0x02 : 0) |
(hw->right ? 0x04 : 0) |
+ (hw->guest_left ? 0x01 : 0) |
+ (hw->guest_mid ? 0x02 : 0) |
+ (hw->guest_right ? 0x04 : 0) |
(hw->up ? 0x08 : 0) |
(hw->down ? 0x10 : 0) |
(hw->multi[2] ? 0x20 : 0) |
@@ -1056,6 +1070,10 @@ HandleState(LocalDevicePtr local, struct SynapticsHwState* hw)
MOVE_HIST(0).y = hw->y;
MOVE_HIST(0).x = hw->x;
+ /* Add guest device movements */
+ dx += hw->guest_dx;
+ dy += hw->guest_dy;
+
/* Post events */
if (dx || dy)
xf86PostMotionEvent(local->dev, 0, 0, 2, dx, dy);
@@ -1230,6 +1248,21 @@ QueryHardware (LocalDevicePtr local)
if (synaptics_set_mode(local->fd, mode) != Success)
return !Success;
+ /* Check to see if the host mouse supports a guest */
+ if (SYN_CAP_PASSTHROUGH(priv->capabilities)) {
+ priv->hasGuest = TRUE;
+
+ /* Enable the guest mouse. Set it to relative mode, three byte
+ * packets */
+
+ /* Disable the host to talk to the guest */
+ SynapticsDisableDevice(local->fd);
+ /* Reset it, set defaults, streaming and enable it */
+ if ((SynapticsResetPassthrough(local->fd)) != Success) {
+ priv->hasGuest = FALSE;
+ }
+ }
+
SynapticsEnableDevice(local->fd);
PrintIdent(priv);
@@ -1422,6 +1455,21 @@ SynapticsParseRawPacket(LocalDevicePtr local, SynapticsPrivate *priv,
}
}
}
+
+ if (priv->hasGuest) {
+ static int guest_buttons = 0;
+ /* Check to see if w is 0x03. If it is, then it is a guest packet */
+ if (w == 0x03) {
+ guest_buttons = buf[1] & 0x07;
+ if (buf[4] != 0)
+ hw->guest_dx = buf[4] - ((buf[1] & 0x10) ? 256 : 0);
+ if (buf[5] != 0)
+ hw->guest_dy = -(buf[5] - ((buf[1] & 0x20) ? 256 : 0));
+ }
+ hw->guest_left = (guest_buttons & 0x01) ? TRUE : FALSE;
+ hw->guest_mid = (guest_buttons & 0x04) ? TRUE : FALSE;
+ hw->guest_right = (guest_buttons & 0x02) ? TRUE : FALSE;
+ }
} else { /* old proto...*/
DBG(7, ErrorF("using old protocol\n"));
hw->x = (((buf[1] & 0x1F) << 8) |
@@ -1610,5 +1658,7 @@ PrintIdent(SynapticsPrivate *priv)
xf86Msg(X_PROBED, " -> multifinger detection\n");
if (SYN_CAP_PALMDETECT(priv->capabilities))
xf86Msg(X_PROBED, " -> palm detection\n");
+ if (SYN_CAP_PASSTHROUGH(priv->capabilities))
+ xf86Msg(X_PROBED, " -> pass-through port\n");
}
}
diff --git a/synaptics.h b/synaptics.h
index 6538807..fa67c12 100644
--- a/synaptics.h
+++ b/synaptics.h
@@ -17,6 +17,8 @@ typedef struct _SynapticsSHM
int fingerWidth; /* finger width value */
int left, right, up, down; /* left/right/up/down buttons */
Bool multi[8];
+ int guest_left, guest_mid, guest_right; /* guest device buttons */
+ int guest_dx, guest_dy; /* guest device movement */
/* Probed hardware properties */
unsigned long int model_id; /* Model-ID */
@@ -66,6 +68,12 @@ struct SynapticsHwState {
Bool down;
Bool multi[8];
+
+ Bool guest_left; /* guest device */
+ Bool guest_mid;
+ Bool guest_right;
+ int guest_dx;
+ int guest_dy;
};
typedef struct _SynapticsTapRec
@@ -108,6 +116,7 @@ typedef struct _SynapticsPrivateRec
unsigned long int ext_cap; /* Extended Capabilities */
unsigned long int identity; /* Identification */
Bool isSynaptics; /* Synaptics touchpad active */
+ Bool hasGuest; /* Has a guest mouse */
Bool shm_config; /* True when shared memory area allocated */
OsTimerPtr timer; /* for up/down-button repeat, tap processing, etc */
diff --git a/synclient.c b/synclient.c
index 011199c..510bc66 100644
--- a/synclient.c
+++ b/synclient.c
@@ -142,11 +142,17 @@ static int is_equal(SynapticsSHM* s1, SynapticsSHM* s2)
(s1->left == s2->left) &&
(s1->right == s2->right) &&
(s1->up == s2->up) &&
- (s1->down == s2->down));
+ (s1->down == s2->down) &&
+ (s1->guest_left == s2->guest_left) &&
+ (s1->guest_mid == s2->guest_mid) &&
+ (s1->guest_right == s2->guest_right) &&
+ (s1->guest_dx == s2->guest_dx) &&
+ (s1->guest_dy == s2->guest_dy));
}
static void monitor(SynapticsSHM* synshm, int delay)
{
+ int header = 0;
SynapticsSHM old;
memset(&old, 0, sizeof(SynapticsSHM));
old.x = -1; /* Force first equality test to fail */
@@ -154,12 +160,22 @@ static void monitor(SynapticsSHM* synshm, int delay)
while(1) {
SynapticsSHM cur = *synshm;
if (!is_equal(&old, &cur)) {
- printf("x:%4d y:%4d z:%3d f:%1d w:%2d left:%d right:%d up:%d down:%d "
- "multi:%d %d %d %d %d %d %d %d\n",
+ if (!header) {
+ printf("%4s %4s %3s %s %2s %2s %s %s %s %8s "
+ "%2s %2s %2s %3s %3s\n",
+ "x", "y", "z", "f", "w", "l", "r", "u", "d", "multi",
+ "gl", "gm", "gr", "gdx", "gdy");
+ header = 20;
+ }
+ header--;
+ printf("%4d %4d %3d %d %2d %2d %d %d %d %d%d%d%d%d%d%d%d "
+ "%2d %2d %2d %3d %3d\n",
cur.x, cur.y, cur.z, cur.numFingers, cur.fingerWidth,
cur.left, cur.right, cur.up, cur.down,
cur.multi[0], cur.multi[1], cur.multi[2], cur.multi[3],
- cur.multi[4], cur.multi[5], cur.multi[6], cur.multi[7]);
+ cur.multi[4], cur.multi[5], cur.multi[6], cur.multi[7],
+ cur.guest_left, cur.guest_mid, cur.guest_right,
+ cur.guest_dx, cur.guest_dy);
fflush(stdout);
old = cur;
}
diff --git a/syndaemon.c b/syndaemon.c
index 93bdf6a..5647bcc 100644
--- a/syndaemon.c
+++ b/syndaemon.c
@@ -90,6 +90,8 @@ static int touchpad_buttons_active()
for (i = 0; i < 8; i++)
if (synshm->multi[i])
return 1;
+ if (synshm->guest_left || synshm->guest_mid || synshm->guest_right)
+ return 1;
return 0;
}
@@ -108,7 +110,7 @@ static void main_loop(Display *display, double idle_time)
pad_disabled = 0;
keyboard_activity(display);
-
+
for (;;) {
current_time = get_time();
if (keyboard_activity(display))