Index: psm.c =================================================================== RCS file: /home/fcvs/src/sys/isa/psm.c,v retrieving revision 1.71 diff -u -r1.71 psm.c --- psm.c 30 Jul 2004 00:59:40 -0000 1.71 +++ psm.c 6 Aug 2004 11:35:48 -0000 @@ -3029,37 +3029,33 @@ /* Just to be on the safe side */ set_mouse_scaling(kbdc, 1); + /* Identify the Touchpad version */ if (mouse_ext_command(kbdc, 0) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); - - /* If it is a Synaptics, byte 2 is 0x47. */ if (status[1] != 0x47) return (FALSE); - /* - * Identify the Touchpad version. The first byte contains the minor - * version number, the lower 4 bits of the third byte contain infoMajor, - * and the upper 4 bits contain the (obsolete) infoModelCode. - */ sc->synhw.infoMinor = status[0]; sc->synhw.infoMajor = status[2] & 0x0f; - if (verbose >= 2) { - printf("Synaptics Touchpad:\n"); - printf(" Version: %d.%d\n", sc->synhw.infoMajor, sc->synhw.infoMinor); - } + + if (verbose >= 2) + printf("Synaptics Touchpad v%d.%d\n", + sc->synhw.infoMajor, sc->synhw.infoMinor); + if (sc->synhw.infoMajor < 4) { - printf("Synaptics Version less than 4 detected, not yet supported\n"); + printf(" Unsupported (pre-v4) Touchpad detected\n"); return (FALSE); } + /* Get the Touchpad model information */ if (mouse_ext_command(kbdc, 3) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); if ((status[1] & 0x01) != 0) { - printf(" Could not read model id bytes from the Touchpad\n"); + printf(" Failed to read model information\n"); return (FALSE); } @@ -3071,67 +3067,81 @@ sc->synhw.capPen = (status[2] & 0x40) >> 6; sc->synhw.infoSimplC = (status[2] & 0x20) >> 5; sc->synhw.infoGeometry = status[2] & 0x0f; + if (verbose >= 2) { - printf(" Model id: %02x %02x %02x\n", status[0] , status[1] , - status[2]); - printf(" infoRot180: %d\n",sc->synhw.infoRot180); - printf(" infoPortrait: %d\n",sc->synhw.infoPortrait); - printf(" infoSensor: %d\n",sc->synhw.infoSensor); - printf(" infoHardware: %d\n",sc->synhw.infoHardware); - printf(" infoNewAbs: %d\n",sc->synhw.infoNewAbs); - printf(" capPen: %d\n",sc->synhw.capPen); - printf(" infoSimplC: %d\n",sc->synhw.infoSimplC); - printf(" infoGeometry: %d\n",sc->synhw.infoGeometry); + printf(" Model information:\n"); + printf(" infoRot180: %d\n", sc->synhw.infoRot180); + printf(" infoPortrait: %d\n", sc->synhw.infoPortrait); + printf(" infoSensor: %d\n", sc->synhw.infoSensor); + printf(" infoHardware: %d\n", sc->synhw.infoHardware); + printf(" infoNewAbs: %d\n", sc->synhw.infoNewAbs); + printf(" capPen: %d\n", sc->synhw.capPen); + printf(" infoSimplC: %d\n", sc->synhw.infoSimplC); + printf(" infoGeometry: %d\n", sc->synhw.infoGeometry); } + /* Read the extended capability bits */ if (mouse_ext_command(kbdc, 2) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); if (status[1] != 0x47) { - printf(" Could not read capabilities from the Touchpad\n"); + printf(" Failed to read extended capability bits\n"); return (FALSE); } - sc->synhw.capExtended = (status[0] & 0x80) >> 7; - sc->synhw.capPassthrough = (status[2] & 0x80) >> 7; - sc->synhw.capSleep = (status[2] & 0x10) >> 4; - sc->synhw.capFourButtons = (status[2] & 0x08) >> 3; - sc->synhw.capMultiFinger = (status[2] & 0x02) >> 1; - sc->synhw.capPalmDetect = (status[2] & 0x01); - if (verbose >= 2) - printf(" Capability Bytes: %02x %02x %02x\n", status[0], status[1], - status[2]); + if ((status[0] & 0x80) >> 7) { + sc->synhw.capExtended = (status[0] & 0x80) >> 7; + sc->synhw.capPassthrough = (status[2] & 0x80) >> 7; + sc->synhw.capSleep = (status[2] & 0x10) >> 4; + sc->synhw.capFourButtons = (status[2] & 0x08) >> 3; + sc->synhw.capMultiFinger = (status[2] & 0x02) >> 1; + sc->synhw.capPalmDetect = (status[2] & 0x01); + + if (verbose >= 2) { + printf(" Extended capabilities:\n"); + printf(" capExtended: %d\n", sc->synhw.capExtended); + printf(" capPassthrough: %d\n", sc->synhw.capPassthrough); + printf(" capSleep: %d\n", sc->synhw.capSleep); + printf(" capFourButtons: %d\n", sc->synhw.capFourButtons); + printf(" capMultiFinger: %d\n", sc->synhw.capMultiFinger); + printf(" capPalmDetect: %d\n", sc->synhw.capPalmDetect); + } + } else { + sc->synhw.capExtended = 0; + + if (verbose >= 2) + printf(" No extended capabilities\n"); + } + + /* + * Read the mode byte + * + * XXX: Note the Synaptics documentation also defines the first + * byte of the response to this query to be a constant 0x3b, this + * does not appear to be true for Touchpads with guest devices. + */ if (mouse_ext_command(kbdc, 1) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); - if (status[0] != 0x3b || status[1] != 0x47) { - printf(" Could not read mode byte from the Touchpad\n"); + if (status[1] != 0x47) { + printf(" Failed to read mode byte\n"); return (FALSE); } - if (verbose >= 2) - printf(" Mode byte set by BIOS: %02x\n", status[2]); - /* - * Mode byte values: - * 1 (absolute) - * 1 rate (0 = 40/1 = 80) - * 0 - * 0 (reserved) - * 0 (Sleep (Only buttons)) - * 0 DisGest (not for absolute Mode) - * 0 pktsize (0 for ps2) - * 1 wmode - */ - sc->hw.buttons = 3; + /* Set the mode byte -- request wmode where available */ + if (sc->synhw.capExtended) + mouse_ext_command(kbdc, 0xc1); + else + mouse_ext_command(kbdc, 0xc0); - /* Set encode mode byte and sampling rate. */ - mouse_ext_command(kbdc, 0xc1); + /* Reset the sampling rate */ set_mouse_sampling_rate(kbdc, 20); return (TRUE); } + /* Interlink electronics VersaPad */ static int enable_versapad(struct psm_softc *sc) --- psm.c.1 Fri Aug 6 13:35:56 2004 +++ psm.c Fri Aug 6 13:43:49 2004 @@ -2502,16 +2502,19 @@ ((pb->ipacket[0] & 0x04) >> 1) | ((pb->ipacket[3] & 0x04) >> 2); + /* Button presses */ ms.button = 0; if (pb->ipacket[0] & 0x01) ms.button |= MOUSE_BUTTON1DOWN; if (pb->ipacket[0] & 0x02) ms.button |= MOUSE_BUTTON3DOWN; - if ((pb->ipacket[3] & 0x01) && (pb->ipacket[0] & 0x01) == 0) - ms.button |= MOUSE_BUTTON2DOWN; - if ((pb->ipacket[3] & 0x02) && (pb->ipacket[0] & 0x02) == 0) - ms.button |= MOUSE_BUTTON4DOWN; + if (sc->synhw.capExtended && sc->synhw.capFourButtons) { + if ((pb->ipacket[3] & 0x01) && (pb->ipacket[0] & 0x01) == 0) + ms.button |= MOUSE_BUTTON4DOWN; + if ((pb->ipacket[3] & 0x02) && (pb->ipacket[0] & 0x02) == 0) + ms.button |= MOUSE_BUTTON5DOWN; + } /* There is a finger on the pad. */ if ((w >= 4 && w <= 7) && (z >= 16 && z < 200)) { @@ -2537,7 +2540,15 @@ } else { sc->flags &= ~PSM_FLAGS_FINGERDOWN; } - z = 0; + + /* Use the extra buttons as a scrollwheel */ + if (ms.button & MOUSE_BUTTON4DOWN) + z = -1; + else if (ms.button & MOUSE_BUTTON5DOWN) + z = 1; + else + z = 0; + break; case MOUSE_MODEL_GENERIC: @@ -3138,6 +3149,16 @@ /* Reset the sampling rate */ set_mouse_sampling_rate(kbdc, 20); + + /* + * Report the correct number of buttons + * + * XXX: I'm not sure this is used anywhere. + */ + if (sc->synhw.capExtended && sc->synhw.capFourButtons) + sc->hw.buttons = 4; + else + sc->hw.buttons = 3; return (TRUE); } --- psm.c.2 Fri Aug 6 13:44:38 2004 +++ psm.c Fri Aug 6 14:00:46 2004 @@ -103,6 +103,14 @@ #define PSM_INPUT_TIMEOUT 2000000 /* 2 sec */ #endif +#ifndef PSM_TAP_TIMEOUT +#define PSM_TAP_TIMEOUT 125000 +#endif + +#ifndef PSM_TAP_THRESHOLD +#define PSM_TAP_THRESHOLD 25 +#endif + /* end of driver specific options */ #define PSM_DRIVER_NAME "psm" @@ -170,10 +178,12 @@ int button; /* the latest button state */ int xold; /* previous absolute X position */ int yold; /* previous absolute Y position */ + int zmax; /* maximum pressure value for touchpads */ int syncerrors; /* XXX: KILL ME! */ struct timeval inputtimeout; struct timeval lastsoftintr; /* time of last soft interrupt */ struct timeval lastinputerr; /* time last sync error happened */ + struct timeval taptimeout; /* tap timeout for touchpads */ int watchdog; /* watchdog timer flag */ struct callout_handle callout; /* watchdog timer call out */ struct callout_handle softcallout; /* buffer timer call out */ @@ -2537,8 +2547,24 @@ sc->xold = x0; sc->yold = y0; + sc->zmax = imax(z, sc->zmax); } else { sc->flags &= ~PSM_FLAGS_FINGERDOWN; + + if (sc->zmax > PSM_TAP_THRESHOLD && + timevalcmp(&sc->lastsoftintr, &sc->taptimeout, <=)) { + if (w == 0) + ms.button |= MOUSE_BUTTON3DOWN; + else if (w == 1) + ms.button |= MOUSE_BUTTON2DOWN; + else + ms.button |= MOUSE_BUTTON1DOWN; + } + + sc->zmax = 0; + sc->taptimeout.tv_sec = PSM_TAP_TIMEOUT / 1000000; + sc->taptimeout.tv_usec = PSM_TAP_TIMEOUT % 1000000; + timevaladd(&sc->taptimeout, &sc->lastsoftintr); } /* Use the extra buttons as a scrollwheel */ --- psm.c.3 Fri Aug 6 15:43:51 2004 +++ psm.c Fri Aug 6 15:44:24 2004 @@ -2539,8 +2539,8 @@ x0 = (x0 + sc->xold * 3) / 4; y0 = (y0 + sc->yold * 3) / 4; - x = (x0 - sc->xold) / 4; - y = (y0 - sc->yold) / 4; + x = (x0 - sc->xold) / 8.5; + y = (y0 - sc->yold) / 8.5; } else { sc->flags |= PSM_FLAGS_FINGERDOWN; }