From owner-freebsd-bugs Sun Feb 9 14: 0:38 2003 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 9890537B401 for ; Sun, 9 Feb 2003 14:00:28 -0800 (PST) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 5554943F85 for ; Sun, 9 Feb 2003 14:00:27 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.6/8.12.6) with ESMTP id h19M0RNS039150 for ; Sun, 9 Feb 2003 14:00:27 -0800 (PST) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.6/8.12.6/Submit) id h19M0RUJ039149; Sun, 9 Feb 2003 14:00:27 -0800 (PST) Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id E66E337B401 for ; Sun, 9 Feb 2003 13:56:18 -0800 (PST) Received: from albatross.mail.pas.earthlink.net (albatross.mail.pas.earthlink.net [207.217.120.120]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3D62A43F3F for ; Sun, 9 Feb 2003 13:56:18 -0800 (PST) (envelope-from rsidd@papagena.rockefeller.edu) Received: from user-0cev12u.cable.mindspring.com ([24.239.132.94] helo=bluerondo.a.la.turk) by albatross.mail.pas.earthlink.net with esmtp (Exim 3.33 #1) id 18hzQv-0002A7-00 for FreeBSD-gnats-submit@freebsd.org; Sun, 09 Feb 2003 13:56:17 -0800 Received: (qmail 23070 invoked by uid 1001); 9 Feb 2003 21:56:16 -0000 Message-Id: <20030209215616.23069.qmail@bluerondo.a.la.turk> Date: 9 Feb 2003 21:56:16 -0000 From: Rahul Siddharthan Reply-To: Rahul Siddharthan To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: kern/48116: Support for Synaptics touchpad Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >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