Index: psm.c =================================================================== --- psm.c (revision 244187) +++ psm.c (working copy) @@ -56,6 +56,10 @@ * - 5 March 1997. Defined driver configuration flags (PSM_CONFIG_XXX). * Improved sync check logic. * Vendor specific support routines. + * + * The latest Synaptics PS/2 TouchPad Interfacing guide that was + * used to write this driver was 511-000275-01_RevB, + * http://www.synaptics.com/sites/default/files/511-000275-01_RevB.pdf */ #include @@ -256,6 +260,10 @@ int in_vscroll; } synapticsaction_t; +/* Determine if we're running Synaptics firmware >= 7.5. */ +#define SYNAPTICS_POST_75_FW(hw) ((hw).infoMajor > 7 || \ + ((hw).infoMajor == 7 && (hw).infoMinor >= 5)) + /* driver control block */ struct psm_softc { /* Driver status information */ int unit; @@ -863,11 +871,15 @@ * A Reset (FF) or Set Defaults (F6) command would clear the * Absolute Mode bit. But a verbose boot or debug.psm.loglevel=5 * doesn't show any evidence of such a command. + * + * XXX: shouldn't we check (stat[2] & 0x80) instead of doing + * (stat[2] == 0x40)? */ if (sc->hw.model == MOUSE_MODEL_SYNAPTICS) { mouse_ext_command(sc->kbdc, 1); get_mouse_status(sc->kbdc, stat, 0, 3); - if (stat[1] == 0x47 && stat[2] == 0x40) { + if ((SYNAPTICS_POST_75_FW(sc->synhw) || stat[1] == 0x47) && + stat[2] == 0x40) { /* Set the mode byte -- request wmode where * available */ if (sc->synhw.capExtended) @@ -4315,6 +4327,7 @@ synapticshw_t synhw; int status[3]; int buttons; + uint16_t model = 0, model_sub = 0; VLOG(3, (LOG_DEBUG, "synaptics: BEGIN init\n")); @@ -4338,10 +4351,6 @@ synhw.infoMinor = status[0]; synhw.infoMajor = status[2] & 0x0f; - if (verbose >= 2) - printf("Synaptics Touchpad v%d.%d\n", synhw.infoMajor, - synhw.infoMinor); - if (synhw.infoMajor < 4) { printf(" Unsupported (pre-v4) Touchpad detected\n"); return (FALSE); @@ -4366,24 +4375,14 @@ synhw.infoSimplC = (status[2] & 0x20) != 0; synhw.infoGeometry = status[2] & 0x0f; - if (verbose >= 2) { - printf(" Model information:\n"); - printf(" infoRot180: %d\n", synhw.infoRot180); - printf(" infoPortrait: %d\n", synhw.infoPortrait); - printf(" infoSensor: %d\n", synhw.infoSensor); - printf(" infoHardware: %d\n", synhw.infoHardware); - printf(" infoNewAbs: %d\n", synhw.infoNewAbs); - printf(" capPen: %d\n", synhw.capPen); - printf(" infoSimplC: %d\n", synhw.infoSimplC); - printf(" infoGeometry: %d\n", 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) { + if (SYNAPTICS_POST_75_FW(synhw)) { + model_sub = status[1]; + } else if (status[1] != 0x47) { printf(" Failed to read extended capability bits\n"); return (FALSE); } @@ -4398,16 +4397,6 @@ synhw.capMultiFinger = (status[2] & 0x02) != 0; synhw.capPalmDetect = (status[2] & 0x01) != 0; - if (verbose >= 2) { - printf(" Extended capabilities:\n"); - printf(" capExtended: %d\n", synhw.capExtended); - printf(" capPassthrough: %d\n", synhw.capPassthrough); - printf(" capSleep: %d\n", synhw.capSleep); - printf(" capFourButtons: %d\n", synhw.capFourButtons); - printf(" capMultiFinger: %d\n", synhw.capMultiFinger); - printf(" capPalmDetect: %d\n", synhw.capPalmDetect); - } - /* * If we have bits set in status[0] & 0x70, then we can load * more information about buttons using query 0x09. @@ -4421,12 +4410,6 @@ } else buttons = synhw.capFourButtons ? 1 : 0; } - if (verbose >= 2) { - if (synhw.capExtended) - printf(" Additional Buttons: %d\n", buttons); - else - printf(" No extended capabilities\n"); - } /* * Read the mode byte. @@ -4434,12 +4417,19 @@ * 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. + * That's true only for firmware < 7.5, since for the newer + * firmware the lowest bit of the first byte tells us if guest + * devices are present or not. Don't know if this behaviour + * is strictly for firmware >= 7.5 or not, so omitting the + * check for 0x3b. */ if (mouse_ext_command(kbdc, 1) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); - if (status[1] != 0x47) { + if (SYNAPTICS_POST_75_FW(synhw)) { + model = status[1] + ((status[0] & 0xfc) >> 2); + } else if (status[1] != 0x47) { printf(" Failed to read mode byte\n"); return (FALSE); } @@ -4458,6 +4448,36 @@ buttons += 3; VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n", buttons)); + if (verbose >= 2) { + printf("Synaptics Touchpad v%d.%d\n", synhw.infoMajor, + synhw.infoMinor); + + printf(" Model information:\n"); + if (SYNAPTICS_POST_75_FW(synhw)) + printf(" model number: %d.%d\n", model, model_sub); + printf(" infoRot180: %d\n", synhw.infoRot180); + printf(" infoPortrait: %d\n", synhw.infoPortrait); + printf(" infoSensor: %d\n", synhw.infoSensor); + printf(" infoHardware: %d\n", synhw.infoHardware); + printf(" infoNewAbs: %d\n", synhw.infoNewAbs); + printf(" capPen: %d\n", synhw.capPen); + printf(" infoSimplC: %d\n", synhw.infoSimplC); + printf(" infoGeometry: %d\n", synhw.infoGeometry); + + if (synhw.capExtended) { + printf(" Extended capabilities:\n"); + printf(" capExtended: %d\n", synhw.capExtended); + printf(" capPassthrough: %d\n", synhw.capPassthrough); + printf(" capSleep: %d\n", synhw.capSleep); + printf(" capFourButtons: %d\n", synhw.capFourButtons); + printf(" capMultiFinger: %d\n", synhw.capMultiFinger); + printf(" capPalmDetect: %d\n", synhw.capPalmDetect); + printf(" Additional Buttons: %d\n", buttons); + } else { + printf(" No extended capabilities\n"); + } + } + if (sc != NULL) { /* Create sysctl tree. */ synaptics_sysctl_create_tree(sc);