diff options
author | Peter Osterlund <petero2@telia.com> | 2003-12-15 22:44:08 +0100 |
---|---|---|
committer | Peter Osterlund <petero2@telia.com> | 2006-04-09 04:01:30 +0200 |
commit | e6d92b0e4399ead8d24e043857d3120b87ecc1ef (patch) | |
tree | 2c7d980e65d9f46d1a36f325216149bc5ad82e48 | |
parent | 13e1f68ac2c43e448bd012139bba5278a29f874c (diff) |
Added pass through support. From David Kennedy and Fred
Hucht.
-rw-r--r-- | ps2comm.c | 84 | ||||
-rw-r--r-- | ps2comm.h | 7 | ||||
-rw-r--r-- | synaptics.c | 50 | ||||
-rw-r--r-- | synaptics.h | 9 | ||||
-rw-r--r-- | synclient.c | 24 | ||||
-rw-r--r-- | syndaemon.c | 4 |
6 files changed, 173 insertions, 5 deletions
@@ -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 @@ -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)) |