From owner-freebsd-bugs@FreeBSD.ORG Tue Aug 28 09:30:04 2012 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id C9190106566B for ; Tue, 28 Aug 2012 09:30:04 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id A59858FC0C for ; Tue, 28 Aug 2012 09:30:04 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.5/8.14.5) with ESMTP id q7S9U4hC047277 for ; Tue, 28 Aug 2012 09:30:04 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.5/8.14.5/Submit) id q7S9U48o047274; Tue, 28 Aug 2012 09:30:04 GMT (envelope-from gnats) Date: Tue, 28 Aug 2012 09:30:04 GMT Message-Id: <201208280930.q7S9U48o047274@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: Lars Engels Cc: Subject: Re: kern/147237: [psm] [patch] There is no IBM/Lenovo TrackPoint support in psm driver X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Lars Engels List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Aug 2012 09:30:04 -0000 The following reply was made to PR kern/147237; it has been noted by GNATS. From: Lars Engels To: bug-followup@FreeBSD.org Cc: Tamas Szakaly Subject: Re: kern/147237: [psm] [patch] There is no IBM/Lenovo TrackPoint support in psm driver Date: Tue, 28 Aug 2012 11:23:15 +0200 --NT59pYSnj1ZLVgEN Content-Type: multipart/mixed; boundary="lBqJz4CGKwlWe7/k" Content-Disposition: inline --lBqJz4CGKwlWe7/k Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Hi Tamas, thanks a lot for the patch. Attached is an updated version that works more or less for me. The problem is that when PSM_CONFIG_INITAFTERSUSPEND is added to sc->config my X200 hangs when I resume. Without INITAFTERSUSPEND resuming works, but the trackpoint's config is reset to its default values. Another issue I have on a T61 is that this one also has a Synaptics touchpad and I added hw.psm.synaptics_support=1 and hw.psm.trackpoint_support=1 to loader.conf. As the synaptics devices is matched first, it the trackpoint function is never run. --lBqJz4CGKwlWe7/k Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="psm_trackpoint.diff" Content-Transfer-Encoding: quoted-printable Index: sys/dev/atkbdc/psm.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- sys/dev/atkbdc/psm.c (revision 238992) +++ sys/dev/atkbdc/psm.c (working copy) @@ -256,6 +256,38 @@ int in_vscroll; } synapticsaction_t; =20 +enum { + TRACKPOINT_SYSCTL_SENSITIVITY, + TRACKPOINT_SYSCTL_NEGATIVE_INERTIA, + TRACKPOINT_SYSCTL_UPPER_PLATEAU, + TRACKPOINT_SYSCTL_BACKUP_RANGE, + TRACKPOINT_SYSCTL_DRAG_HYSTERESIS, + TRACKPOINT_SYSCTL_MINIMUM_DRAG, + TRACKPOINT_SYSCTL_UP_THRESHOLD, + TRACKPOINT_SYSCTL_THRESHOLD, + TRACKPOINT_SYSCTL_JENKS_CURVATURE, + TRACKPOINT_SYSCTL_Z_TIME, + TRACKPOINT_SYSCTL_PRESS_TO_SELECT, + TRACKPOINT_SYSCTL_SKIP_BACKUPS +}; + +typedef struct trackpointinfo { + struct sysctl_ctx_list sysctl_ctx; + struct sysctl_oid *sysctl_tree; + int sensitivity; + int inertia; + int uplateau; + int reach; + int draghys; + int mindrag; + int upthresh; + int threshold; + int jenks; + int ztime; + int pts; + int skipback; +} trackpointinfo_t; + /* driver control block */ struct psm_softc { /* Driver status information */ int unit; @@ -270,6 +302,7 @@ synapticshw_t synhw; /* Synaptics hardware information */ synapticsinfo_t syninfo; /* Synaptics configuration */ synapticsaction_t synaction; /* Synaptics action context */ + trackpointinfo_t tpinfo; /* IBM/Lenovo TrackPoint configuration*/ mousemode_t mode; /* operation mode */ mousemode_t dflt_mode; /* default operation mode */ mousestatus_t status; /* accumulated mouse movement */ @@ -340,6 +373,9 @@ static int synaptics_support =3D 0; TUNABLE_INT("hw.psm.synaptics_support", &synaptics_support); =20 +static int trackpoint_support =3D 0; +TUNABLE_INT("hw.psm.trackpoint_support", &trackpoint_support); + static int verbose =3D PSM_DEBUG; TUNABLE_INT("debug.psm.loglevel", &verbose); =20 @@ -429,6 +465,7 @@ static probefunc_t enable_mmanplus; static probefunc_t enable_synaptics; static probefunc_t enable_versapad; +static probefunc_t enable_trackpoint; =20 static struct { int model; @@ -462,6 +499,8 @@ 0x80, MOUSE_PS2_PACKETSIZE, enable_kmouse }, { MOUSE_MODEL_VERSAPAD, /* Interlink electronics VersaPad */ 0xe8, MOUSE_PS2VERSA_PACKETSIZE, enable_versapad }, + { MOUSE_MODEL_TRACKPOINT, /* IBM/Lenovo TrackPoint*/ + 0xc0, MOUSE_TRACKPOINT_PACKETSIZE, enable_trackpoint }, { MOUSE_MODEL_GENERIC, 0xc0, MOUSE_PS2_PACKETSIZE, NULL }, }; @@ -704,6 +743,7 @@ { MOUSE_MODEL_4DPLUS, "4D+ Mouse" }, { MOUSE_MODEL_SYNAPTICS, "Synaptics Touchpad" }, { MOUSE_MODEL_GENERIC, "Generic PS/2 mouse" }, + { MOUSE_MODEL_TRACKPOINT, "IBM/Lenovo TrackPoint" }, { MOUSE_MODEL_UNKNOWN, "Unknown" }, }; int i; @@ -3434,6 +3474,7 @@ goto next; break; =20 + case MOUSE_MODEL_TRACKPOINT: case MOUSE_MODEL_GENERIC: default: break; @@ -4487,6 +4528,285 @@ return (TRUE); /* PS/2 absolute mode */ } =20 +/* IBM/Lenovo TrackPoint */ +static int +trackpoint_command(KBDC kbdc, int cmd, int loc, int val) +{ + if (send_aux_command(kbdc, 0xe2) !=3D PSM_ACK || + send_aux_command(kbdc, cmd) !=3D PSM_ACK || + send_aux_command(kbdc, loc) !=3D PSM_ACK || + send_aux_command(kbdc, val) !=3D PSM_ACK) + return (EIO); + + return (0); +} + +static int +trackpoint_sysctl(SYSCTL_HANDLER_ARGS) +{ + int error, cmd, loc, mask, max, *oldvalp; + struct psm_softc *sc =3D arg1; + + loc =3D 0; + mask =3D 0; + oldvalp =3D NULL; + + /* + * The value of cmd and max will be 0x81 and 255 respectively for + * the majority of cases, so we set them outside the switch, and + * change them only when needed. + */ + cmd =3D 0x81; + max =3D 255; + + switch (arg2) { + case TRACKPOINT_SYSCTL_SENSITIVITY: + loc =3D 0x4a; + oldvalp =3D &sc->tpinfo.sensitivity; + break; + case TRACKPOINT_SYSCTL_NEGATIVE_INERTIA: + loc =3D 0x4d; + oldvalp =3D &sc->tpinfo.inertia; + break; + case TRACKPOINT_SYSCTL_UPPER_PLATEAU: + loc =3D 0x60; + oldvalp =3D &sc->tpinfo.uplateau; + break; + case TRACKPOINT_SYSCTL_BACKUP_RANGE: + loc =3D 0x57; + oldvalp =3D &sc->tpinfo.reach; + break; + case TRACKPOINT_SYSCTL_DRAG_HYSTERESIS: + loc =3D 0x58; + oldvalp =3D &sc->tpinfo.draghys; + break; + case TRACKPOINT_SYSCTL_MINIMUM_DRAG: + loc =3D 0x59; + oldvalp =3D &sc->tpinfo.mindrag; + break; + case TRACKPOINT_SYSCTL_UP_THRESHOLD: + loc =3D 0x5a; + oldvalp =3D &sc->tpinfo.upthresh; + break; + case TRACKPOINT_SYSCTL_THRESHOLD: + loc =3D 0x5c; + oldvalp =3D &sc->tpinfo.threshold; + break; + case TRACKPOINT_SYSCTL_JENKS_CURVATURE: + loc =3D 0x5d; + oldvalp =3D &sc->tpinfo.jenks; + break; + case TRACKPOINT_SYSCTL_Z_TIME: + loc =3D 0x5e; + oldvalp =3D &sc->tpinfo.ztime; + break; + case TRACKPOINT_SYSCTL_PRESS_TO_SELECT: + cmd =3D 0x47; + loc =3D 0x2c; + mask =3D 0x01; + max =3D 1; + oldvalp =3D &sc->tpinfo.pts; + break; + case TRACKPOINT_SYSCTL_SKIP_BACKUPS: + cmd =3D 0x47; + loc =3D 0x2d; + mask =3D 0x08; + max =3D 1; + oldvalp =3D &sc->tpinfo.skipback; + break; + default: + return (1); + /* NOTREACHED */ + } + + int newval =3D *oldvalp; + if ((error =3D sysctl_handle_int(oidp, &newval, 0, req)) !=3D 0) + return error; + + if (newval =3D=3D *oldvalp) + return (0); + + if (newval < 0 || newval > max) + return (EINVAL); + + if ((error =3D trackpoint_command(sc->kbdc, cmd, loc, + mask ? mask : newval)) !=3D 0) + return (error); + else + *oldvalp =3D newval; + + return (error); +} + +static void +trackpoint_sysctl_create_tree(struct psm_softc *sc) +{ + /* Attach extra trackpoint sysctl nodes under hw.psm.trackpoint */ + sysctl_ctx_init(&sc->tpinfo.sysctl_ctx); + sc->tpinfo.sysctl_tree =3D SYSCTL_ADD_NODE(&sc->tpinfo.sysctl_ctx, + SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, "trackpoint", CTLFLAG_RD, + 0, "IBM/Lenovo TrackPoint"); + + /* hw.psm.trackpoint.sensitivity */ + sc->tpinfo.sensitivity =3D 0x64; + SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, + SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, + "sensitivity", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, + sc, TRACKPOINT_SYSCTL_SENSITIVITY, + trackpoint_sysctl, "I", + "Sensitivity"); + + /* hw.psm.trackpoint.negative_inertia */ + sc->tpinfo.inertia =3D 0x06; + SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, + SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, + "negative_inertia", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, + sc, TRACKPOINT_SYSCTL_NEGATIVE_INERTIA, + trackpoint_sysctl, "I", + "Negative inertia factor"); + + /* hw.psm.trackpoint.upper_plateau */ + sc->tpinfo.uplateau =3D 0x61; + SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, + SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, + "upper_plateau", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, + sc, TRACKPOINT_SYSCTL_UPPER_PLATEAU, + trackpoint_sysctl, "I", + "Transfer function upper plateau speed"); + + /* hw.psm.trackpoint.backup_range */ + sc->tpinfo.reach =3D 0x0a; + SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, + SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, + "backup_range", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, + sc, TRACKPOINT_SYSCTL_BACKUP_RANGE, + trackpoint_sysctl, "I", + "Backup range"); + + /* hw.psm.trackpoint.drag_hysteresis */ + sc->tpinfo.draghys =3D 0xff; + SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, + SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, + "drag_hysteresis", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, + sc, TRACKPOINT_SYSCTL_DRAG_HYSTERESIS, + trackpoint_sysctl, "I", + "Drag hysteresis"); + + /* hw.psm.trackpoint.minimum_drag */ + sc->tpinfo.mindrag =3D 0x14; + SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, + SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, + "minimum_drag", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, + sc, TRACKPOINT_SYSCTL_MINIMUM_DRAG, + trackpoint_sysctl, "I", + "Minimum drag"); + + /* hw.psm.trackpoint.up_threshold */ + sc->tpinfo.upthresh =3D 0xff; + SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, + SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, + "up_threshold", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, + sc, TRACKPOINT_SYSCTL_UP_THRESHOLD, + trackpoint_sysctl, "I", + "Up threshold for release"); + + /* hw.psm.trackpoint.threshold */ + sc->tpinfo.threshold =3D 0x08; + SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, + SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, + "threshold", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, + sc, TRACKPOINT_SYSCTL_THRESHOLD, + trackpoint_sysctl, "I", + "Threshold"); + + /* hw.psm.trackpoint.jenks_curvature */ + sc->tpinfo.jenks =3D 0x87; + SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, + SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, + "jenks_curvature", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, + sc, TRACKPOINT_SYSCTL_JENKS_CURVATURE, + trackpoint_sysctl, "I", + "Jenks curvature"); + + /* hw.psm.trackpoint.z_time */ + sc->tpinfo.ztime =3D 0x26; + SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, + SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, + "z_time", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, + sc, TRACKPOINT_SYSCTL_Z_TIME, + trackpoint_sysctl, "I", + "Z time constant"); + + /* hw.psm.trackpoint.press_to_select */ + sc->tpinfo.pts =3D 0x00; + SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, + SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, + "press_to_select", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, + sc, TRACKPOINT_SYSCTL_PRESS_TO_SELECT, + trackpoint_sysctl, "I", + "Press to Select"); + + /* hw.psm.trackpoint.skip_backups */ + sc->tpinfo.skipback =3D 0x00; + SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx, + SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO, + "skip_backups", CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, + sc, TRACKPOINT_SYSCTL_SKIP_BACKUPS, + trackpoint_sysctl, "I", + "Skip backups from drags"); +} + +static int +enable_trackpoint(KBDC kbdc, struct psm_softc *sc) +{ + int id; + + if (!trackpoint_support) + return (FALSE); + + kbdc =3D sc->kbdc; + sc->hw.buttons =3D 3; + + if (send_aux_command(kbdc, 0xe1) !=3D PSM_ACK || + read_aux_data(kbdc) !=3D 0x01 || + (id =3D read_aux_data(kbdc)) < 0x01) + return (FALSE); + + sc->hw.hwid =3D id; + + if (sc->tpinfo.sysctl_tree =3D=3D NULL) { + trackpoint_sysctl_create_tree(sc); + } else {=20 + /* + * If the tree already exist, then we are after a suspend/resume + * cycle and the TrackPoint is reset to defaults. So we have to=20 + * set the stored values. + */ + trackpoint_command(kbdc, 0x81, 0x4a, sc->tpinfo.sensitivity); + trackpoint_command(kbdc, 0x81, 0x4d, sc->tpinfo.inertia); + trackpoint_command(kbdc, 0x81, 0x60, sc->tpinfo.uplateau); + trackpoint_command(kbdc, 0x81, 0x57, sc->tpinfo.reach); + trackpoint_command(kbdc, 0x81, 0x58, sc->tpinfo.draghys); + trackpoint_command(kbdc, 0x81, 0x59, sc->tpinfo.mindrag); + trackpoint_command(kbdc, 0x81, 0x5a, sc->tpinfo.upthresh); + trackpoint_command(kbdc, 0x81, 0x5c, sc->tpinfo.threshold); + trackpoint_command(kbdc, 0x81, 0x5d, sc->tpinfo.jenks); + trackpoint_command(kbdc, 0x81, 0x5e, sc->tpinfo.ztime); + if (sc->tpinfo.pts =3D=3D 0x01) + trackpoint_command(kbdc, 0x47, 0x2c, 0x01); + if (sc->tpinfo.skipback =3D=3D 0x01) + trackpoint_command(kbdc, 0x47, 0x2d, 0x08); + } + + /* + * TrackPoint will have to be reinitialized after + * suspend/resume. + */ + sc->config |=3D PSM_CONFIG_HOOKRESUME; + + return (TRUE); +} + /* * Return true if 'now' is earlier than (start + (secs.usecs)). * Now may be NULL and the function will fetch the current time from --lBqJz4CGKwlWe7/k-- --NT59pYSnj1ZLVgEN Content-Type: application/pgp-signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (FreeBSD) iEYEARECAAYFAlA8jgIACgkQKc512sD3afjPbQCghVNuvB5HKSY0YRVuGXI/9XxM z+cAn30fkkvBbk98kUuUeCqvWk6TkDf5 =w8rU -----END PGP SIGNATURE----- --NT59pYSnj1ZLVgEN--