The following reply was made to PR kern/147237; it has been noted by GNATS.

From: Lars Engels <[email protected]>
To: [email protected]
Cc: Tamas Szakaly <[email protected]>
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--
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "[email protected]"

Reply via email to