Date: 9 Feb 2003 21:56:16 -0000 From: Rahul Siddharthan <rsidd@online.fr> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/48116: Support for Synaptics touchpad Message-ID: <20030209215616.23069.qmail@bluerondo.a.la.turk>
next in thread | raw e-mail | index | archive | help
>Number: 48116
>Category: kern
>Synopsis: Support for Synaptics touchpad
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: change-request
>Submitter-Id: current-users
>Arrival-Date: Sun Feb 09 14:00:26 PST 2003
>Closed-Date:
>Last-Modified:
>Originator: Rahul Siddharthan
>Release: FreeBSD 5.0-CURRENT i386
>Organization:
>Environment:
System: FreeBSD bluerondo.a.la.turk 5.0-CURRENT FreeBSD 5.0-CURRENT #2: Tue Jan 21 19:29:39 EST 2003 root@bluerondo.a.la.turk:/usr/obj/usr/src/sys/BLUERONDO i386
>Description:
This is a patch from Marcin Dalecki for supporting the extra buttons on
the Synaptics touchpad, which comes with many laptops. He originally
posted this patch on -hackers on Jan 3, 2003. I have been using it for
a month and it works perfectly for me.
Marcin told me in private mail that he wasn't familiar with
FreeBSD development processes and didn't plan to send-pr it, but asked
me to feel free to post it wherever it should go. So here it is...
The diffs are against -current of Feb 9, 2002.
>How-To-Repeat:
>Fix:
--- src/sys/isa/psm.c.old Sun Feb 9 16:47:20 2003
+++ src/sys/isa/psm.c Sun Feb 9 16:47:37 2003
@@ -268,6 +268,7 @@
static probefunc_t enable_4dplus;
static probefunc_t enable_mmanplus;
static probefunc_t enable_versapad;
+static probefunc_t enable_synaptics;
static int tame_mouse(struct psm_softc *, mousestatus_t *, unsigned char *);
static struct {
@@ -300,6 +301,8 @@
0x80, MOUSE_PS2_PACKETSIZE, enable_kmouse, },
{ MOUSE_MODEL_VERSAPAD, /* Interlink electronics VersaPad */
0xe8, MOUSE_PS2VERSA_PACKETSIZE, enable_versapad, },
+ { MOUSE_MODEL_SYNAPTICS, /* Synaptics TouchPad */
+ 0xc0, MOUSE_PS2SYNAP_PACKETSIZE, enable_synaptics, },
{ MOUSE_MODEL_GENERIC,
0xc0, MOUSE_PS2_PACKETSIZE, NULL, },
};
@@ -561,6 +564,7 @@
{ MOUSE_MODEL_EXPLORER, "IntelliMouse Explorer" },
{ MOUSE_MODEL_4D, "4D Mouse" },
{ MOUSE_MODEL_4DPLUS, "4D+ Mouse" },
+ { MOUSE_MODEL_SYNAPTICS, "Synaptics TouchPad" },
{ MOUSE_MODEL_GENERIC, "Generic PS/2 mouse" },
{ MOUSE_MODEL_UNKNOWN, NULL },
};
@@ -1955,7 +1959,7 @@
* the table to turn PS/2 mouse button bits (MOUSE_PS2_BUTTON?DOWN)
* into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
*/
- static int butmap[8] = {
+ static const int butmap[8] = {
0,
MOUSE_BUTTON1DOWN,
MOUSE_BUTTON3DOWN,
@@ -1965,7 +1969,7 @@
MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN,
MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
};
- static int butmap_versapad[8] = {
+ static const int butmap_versapad[8] = {
0,
MOUSE_BUTTON3DOWN,
0,
@@ -1978,18 +1982,18 @@
register struct psm_softc *sc = arg;
mousestatus_t ms;
struct timeval tv;
- int x, y, z;
+ int x, y, z, w;
int c;
int l;
int x0, y0;
/* read until there is nothing to read */
while((c = read_aux_data_no_wait(sc->kbdc)) != -1) {
-
+
/* discard the byte if the device is not open */
if ((sc->state & PSM_OPEN) == 0)
continue;
-
+
getmicrouptime(&tv);
if ((sc->inputbytes > 0) && timevalcmp(&tv, &sc->inputtimeout, >)) {
log(LOG_DEBUG, "psmintr: delay too long; resetting byte count\n");
@@ -2005,9 +2009,9 @@
continue;
#if 0
- log(LOG_DEBUG, "psmintr: %02x %02x %02x %02x %02x %02x\n",
- sc->ipacket[0], sc->ipacket[1], sc->ipacket[2],
- sc->ipacket[3], sc->ipacket[4], sc->ipacket[5]);
+ log(LOG_DEBUG, "psmintr: %02x %02x %02x %02x %02x %02x\n",
+ sc->ipacket[0], sc->ipacket[1], sc->ipacket[2],
+ sc->ipacket[3], sc->ipacket[4], sc->ipacket[5]);
#endif
c = sc->ipacket[0];
@@ -2311,6 +2315,80 @@
}
break;
+ case MOUSE_MODEL_SYNAPTICS:
+ /* TouchPad PS/2 absolute mode message format
+ *
+ * Bits: 7 6 5 4 3 2 1 0 (LSB)
+ * ------------------------------------------------
+ * ipacket[0]: 1 0 W3 W2 0 W1 R L
+ * ipacket[1]: Yb Ya Y9 Y8 Xb Xa X9 X8
+ * ipacket[2]: Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0
+ * ipacket[3]: 1 1 Yc Xc 0 W0 D U
+ * ipacket[4]: X7 X6 X5 X4 X3 X2 X1 X0
+ * ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
+ *
+ * Legend:
+ * L: left physical mouse button
+ * R: right physical mouse button
+ * D: down button
+ * U: up button
+ * W: "wrist" value
+ * X: x position
+ * Y: x position
+ * Z: pressure
+ *
+ * Absolute reportable limits: 0 - 6143.
+ * Typical bezel limites: 1472 - 5472.
+ * Typical edge marings: 1632 - 5312.
+ */
+
+ /* Sanity check for out of sync packets. */
+ if ((sc->ipacket[0] & 0xc8) != 0x80 || (sc->ipacket[3] & 0xc8) != 0xc0)
+ continue;
+
+ ms.button = 0;
+ x = y = x0 = y0 = 0;
+
+ /* pressure */
+ z = sc->ipacket[2];
+ w = ((sc->ipacket[0] & 0x30) >> 2) |
+ ((sc->ipacket[0] & 0x04) >> 1) |
+ ((sc->ipacket[3] & 0x04) >> 2);
+
+ ms.button = 0;
+ if (sc->ipacket[0] & 0x01)
+ ms.button |= MOUSE_BUTTON1DOWN;
+ if (sc->ipacket[0] & 0x02)
+ ms.button |= MOUSE_BUTTON3DOWN;
+ if ((sc->ipacket[3] & 0x01) && !(sc->ipacket[0] & 0x01))
+ ms.button |= MOUSE_BUTTON2DOWN;
+ if ((sc->ipacket[3] & 0x02) && !(sc->ipacket[0] & 0x02))
+ ms.button |= MOUSE_BUTTON4DOWN;
+
+ /* There is a finger on the pad */
+ if ((w >= 4 && w <= 7) && (z >= 16 && z < 128) ) {
+ x0 = ((sc->ipacket[3] & 0x10) << 8) | ((sc->ipacket[1] & 0x0f) << 8) | sc->ipacket[4];
+ y0 = ((sc->ipacket[3] & 0x20) << 7) | ((sc->ipacket[1] & 0xf0) << 4) | sc->ipacket[5];
+
+ if (sc->flags & PSM_FLAGS_FINGERDOWN) {
+ x0 = (x0 + sc->xold * 3) / 4;
+ y0 = (y0 + sc->yold * 3) / 4;
+
+ x = (x0 - sc->xold) / 4;
+ y = (y0 - sc->yold) / 4;
+ } else {
+ sc->flags |= PSM_FLAGS_FINGERDOWN;
+ }
+
+ sc->xold = x0;
+ sc->yold = y0;
+ } else {
+ sc->flags &= ~PSM_FLAGS_FINGERDOWN;
+ }
+ z = 0;
+
+ break;
+
case MOUSE_MODEL_GENERIC:
default:
break;
@@ -2795,6 +2873,105 @@
return FALSE;
set_mouse_scaling(kbdc, 1); /* set scale 1:1 */
+ sc->config |= PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND;
+
+ return TRUE; /* PS/2 absolute mode */
+}
+
+/* Synaptics touch pad */
+static int
+enable_synaptics(struct psm_softc *sc)
+{
+ KBDC kbdc = sc->kbdc;
+ int res;
+ int data[4];
+ int info_rot180;
+ int info_portrait;
+ int info_sensor;
+ int info_hardware;
+ int info_new_abs;
+ int info_cap_pen;
+ int info_simple_cmd;
+ int info_geometry;
+
+ if (verbose >= 2)
+ log(LOG_DEBUG, "psm: ENABLE_SYNAPTICS\n");
+
+ /* Idenfity.
+ */
+ empty_aux_buffer(kbdc, 5);
+ mouse_ext_command(kbdc, 0x00);
+ if (get_mouse_status(kbdc, data, 0, 3) < 3)
+ return FALSE;
+ if (data[1] != 0x47)
+ return FALSE;
+
+ printf("Synaptics Touchpad:\n");
+ printf(" model: %d\n", (data[2] >> 4) & 0x0f);
+ printf(" firmware ver.: %d.%d\n", data[2] & 0x0f, data[0]);
+
+ /* Read Model ID.
+ */
+ empty_aux_buffer(kbdc, 5);
+ mouse_ext_command(kbdc, 0x03);
+ if (get_mouse_status(kbdc, data, 0, 3) < 3)
+ return FALSE;
+
+ info_rot180 = (data[0] & 0x80);
+ info_portrait = (data[0] & 0x40);
+ info_sensor = (data[0] & 0x003f);
+ info_hardware = (data[1] & 0xfe) >> 1;
+ info_new_abs = (data[2] & 0x80);
+ info_cap_pen = (data[2] & 0x40);
+ info_simple_cmd = (data[2] & 0x20);
+ info_geometry = (data[2] & 0x0f);
+
+ printf(" rot180: %s\n", info_rot180 ? "Yes" : "No");
+ printf(" portrait: %s\n", info_portrait ? "Yes" : "No");
+ printf(" sensor: %d\n", info_sensor);
+ printf(" hardware: %d\n", info_hardware);
+ printf(" newABS: %s\n", info_new_abs ? "Yes" : "No");
+ printf(" capPen: %s\n", info_cap_pen ? "Yes" : "No");
+ printf(" simpleCmd: %s\n", info_simple_cmd ? "Yes" : "No");
+ printf(" geometry: %d\n", info_geometry);
+
+ /* Read Capabilities.
+ */
+ empty_aux_buffer(kbdc, 5);
+ mouse_ext_command(kbdc, 0x02);
+ if (get_mouse_status(kbdc, data, 0, 3) < 3)
+ return FALSE;
+ if (data[1] != 0x47)
+ return FALSE;
+
+ printf(" capExtended: %s\n", (data[0] & 0x80) ? "Yes" : "No");
+ printf(" capSleep: %s\n", (data[2] & 0x10) ? "Yes" : "No");
+ printf(" capFourButtons: %s\n", (data[2] & 0x08) ? "Yes" : "No");
+ printf(" capMultiFinger: %s\n", (data[2] & 0x02) ? "Yes" : "No");
+ printf(" capPalmDetect: %s\n", (data[2] & 0x01) ? "Yes" : "No");
+
+ /* Now we set the operating mode to absolute.
+ */
+#define SYN_BIT_ABSOLUTE_MODE 0x80
+#define SYN_BIT_HIGH_RATE 0x40
+#define SYN_BIT_SLEEP_MODE 0x08
+#define SYN_BIT_DISABLE_GESTURE 0x04
+#define SYN_BIT_W_MODE 0x01
+
+ empty_aux_buffer(kbdc, 5);
+ mouse_ext_command(kbdc, SYN_BIT_ABSOLUTE_MODE |
+ SYN_BIT_HIGH_RATE |
+ SYN_BIT_DISABLE_GESTURE |
+ SYN_BIT_W_MODE);
+ res = send_aux_command_and_data(kbdc, PSMC_SET_SAMPLING_RATE, 0x14);
+ if (res != PSM_ACK) {
+ log(LOG_ERR, "psm: setting Synaptics TouchPad mode failed,\n");
+ return FALSE;
+ }
+
+ set_mouse_scaling(kbdc, 1); /* set scale 1:1 */
+
+ sc->hw.buttons = 4;
sc->config |= PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND;
return TRUE; /* PS/2 absolute mode */
--- src/sys/sys/mouse.h.old Sun Feb 9 16:47:33 2003
+++ src/sys/sys/mouse.h Sun Feb 9 16:47:37 2003
@@ -119,6 +119,7 @@
#define MOUSE_MODEL_EXPLORER 10
#define MOUSE_MODEL_4D 11
#define MOUSE_MODEL_4DPLUS 12
+#define MOUSE_MODEL_SYNAPTICS 13
typedef struct mousemode {
int protocol; /* MOUSE_PROTO_XXX */
@@ -139,7 +140,7 @@
* Bus mouse protocols:
* bus, InPort
* PS/2 mouse protocol:
- * PS/2
+ * PS/2, Synaptics TouchPad
*/
#define MOUSE_PROTO_UNKNOWN (-1)
#define MOUSE_PROTO_MS 0 /* Microsoft Serial, 3 bytes */
@@ -159,6 +160,7 @@
#define MOUSE_PROTO_KIDSPAD 14 /* Genius Kidspad */
#define MOUSE_PROTO_VERSAPAD 15 /* Interlink VersaPad, 6 bytes */
#define MOUSE_PROTO_JOGDIAL 16 /* Vaio's JogDial */
+#define MOUSE_PROTO_SYNAPTICS 17 /* Synaptics TouchPad, 6 bytes */
#define MOUSE_RES_UNKNOWN (-1)
#define MOUSE_RES_DEFAULT 0
@@ -293,12 +295,15 @@
#define MOUSE_PS2VERSA_BUTTON3DOWN 0x01 /* right */
#define MOUSE_PS2VERSA_TAP 0x02
+/* Synaptics TouchPad (PS/2 I/F) data packet */
+#define MOUSE_PS2SYNAP_PACKETSIZE 6
+
/* A4 Tech 4D Mouse (PS/2) data packet */
-#define MOUSE_4D_PACKETSIZE 3
+#define MOUSE_4D_PACKETSIZE 3
#define MOUSE_4D_WHEELBITS 0xf0
/* A4 Tech 4D+ Mouse (PS/2) data packet */
-#define MOUSE_4DPLUS_PACKETSIZE 3
+#define MOUSE_4DPLUS_PACKETSIZE 3
#define MOUSE_4DPLUS_ZNEG 0x04 /* sign bit */
#define MOUSE_4DPLUS_BUTTON4DOWN 0x08
>Release-Note:
>Audit-Trail:
>Unformatted:
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030209215616.23069.qmail>
