Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 28 Aug 2012 09:30:04 GMT
From:      Lars Engels <lars.engels@0x20.net>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: kern/147237: [psm] [patch] There is no IBM/Lenovo TrackPoint support in psm driver
Message-ID:  <201208280930.q7S9U48o047274@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/147237; it has been noted by GNATS.

From: Lars Engels <lars.engels@0x20.net>
To: bug-followup@FreeBSD.org
Cc: Tamas Szakaly <sghctoma@gmail.com>
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--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201208280930.q7S9U48o047274>