On 05/10/12(Fri) 20:40, Stefan Sperling wrote:
> On Fri, Oct 05, 2012 at 01:52:08PM +0200, Martin Pieuchot wrote:
> > My first impression at looking the code is that the v2 and v3 use
> > totally different packet formats and I don't see a real benefit of
> > having only one entry in the protocol table if you need to check
> > for the hardware version in every function.
> >
> > I would suggest to use 3 different entries in the protocol table and a
> > enable_elantech_common() function so you can get rid of the hw_version
> > check and the protocol->packetsize hack for the v1.
> >
> > I got the same feeling when you set the absolute mode: every version
> > use different magic ps2 commands with different magic values, I'm not
> > sure adding generic read/write functions help to understand nor save
> > some lines of code.
> >
> > Other than that, it looks to me that the flags ELANTECH_F_HW_V1_OLD and
> > ELANTECH_F_PARITY_REVERSED are redundant.
>
> All good points. And the parity flag was even wrongly defined...
>
> New version, hopefully better. Also fixes softc->elantech memory leak
> in error paths (which synaptics and alps have, too, btw.)
>
> Works for me with version 3, other versions still untested AFAIK.
I don't have any Elantech hardware to test but I can tell you that this
version doesn't introduce any regression with my ALPS touchpad. It could
be nice to hear from other touchpad owners too ;)
> +int
> +pms_ioctl_elantech(struct pms_softc *sc, u_long cmd, caddr_t data, int flag,
> + struct proc *p)
> +{
> + struct elantech_softc *elantech = sc->elantech;
> + struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
> + int wsmode;
> +
> + switch (cmd) {
> + case WSMOUSEIO_GTYPE:
> + *(u_int *)data = WSMOUSE_TYPE_SYNAPTICS;
Here you may want to define a WSMOUSE_TYPE_ELANTECH, it is used in the
synaptics(4) driver to describe which "features" are supported by this
touchpad, see xenocara/driver/xf86-input-synaptics/src/wsconscomm.c
But if you do so, you'll obviously need to rebuild the X driver too ;)
> +void
> +pms_proc_elantech_v3(struct pms_softc *sc)
> +{
> + const u_char debounce_pkt[] = { 0xc4, 0xff, 0xff, 0x02, 0xff, 0xff };
> + struct elantech_softc *elantech = sc->elantech;
> + u_int buttons;
> + int fingers, x, y, w, z;
> +
> + /* The hardware sends this packet when in debounce state.
> + * The packet should be ignored. */
> + if (!memcmp(sc->packet, debounce_pkt, sizeof(debounce_pkt)))
> + return;
> +
> + buttons = ((sc->packet[0] & 0x01 ? WSMOUSE_BUTTON(1) : 0) |
> + ((sc->packet[0] & 0x02) ? WSMOUSE_BUTTON(3): 0));
> + x = y = z = 0;
> + w = -1; /* corresponds to no finger, see synaptics */
> + fingers = (sc->packet[0] & 0xc0) >> 6;
> + if (fingers == 2) {
> + /* Two-finger touch causes two packets -- a head packet
> + * and a tail packet. */
> + if ((sc->packet[0] & 0x0c) == 0x04 &&
> + (sc->packet[3] & 0xfc) == 0x02) {
> + /* head packet */
> + x = ((sc->packet[1] & 0x0f) << 8 | sc->packet[2]);
> + y = ((sc->packet[4] & 0x0f) << 8 | sc->packet[5]);
> + } else if ((sc->packet[0] & 0x0c) == 0x0c &&
> + (sc->packet[3] & 0xce) == 0x0c) {
> + /* tail packet */
> + x = ((sc->packet[1] & 0x0f) << 8 | sc->packet[2]);
> + y = ((sc->packet[4] & 0x0f) << 8 | sc->packet[5]);
Is it a typo or the 'x' and 'y' calculation are the same in both cases?
> + }
> + w = 0; /* force 2 fingers in synaptics */
This isn't related to your diff, but we should add defines for
w = {-1, 0, 3, 4} because these values come from the synaptics devices.
> + } else if (fingers == 1 || fingers == 3) {
> + x = (sc->packet[1] & 0x0f) << 8 | sc->packet[2];
> + y = ((sc->packet[4] & 0x0f) << 8) | sc->packet[5];
> + w = (fingers == 3 ? 1 : 4); /* values for synaptics */
> + }
Same here for the 'x' and 'y', maybe you just need to convert the value
you call 'fingers' to the corresponding 'w' (synaptics finger value).
> +void
> +elantech_send_input(struct pms_softc *sc, u_int buttons, int x, int y, int z,
> + int w)
> + {
> + struct elantech_softc *elantech = sc->elantech;
> + int dx, dy;
> +
> + if (elantech->wsmode == WSMOUSE_NATIVE) {
> + if ((x > 0 && y > 0) || buttons)
I think this condition is always true, or does the elantech touchpads
generate packets without position nor buttons pressed? Plus in case of
the v3 if x or y are null you explicitly force them to their previous
know position.
> +/* Hardware version 1 has hard-coded axis range values.
> + * X axis range is 0 to 576, Y axis range is 0 to 384.
> + * Edge offset accounts for bezel around the touchpad. */
> +#define ELANTECH_V1_EDGE_OFFSET 32
> +#define ELANTECH_V1_X_MIN (0 + ELANTECH_V1_EDGE_OFFSET)
> +#define ELANTECH_V1_X_MAX (576 - ELANTECH_V1_EDGE_OFFSET)
> +#define ELANTECH_V1_Y_MIN (0 + ELANTECH_V1_EDGE_OFFSET)
> +#define ELANTECH_V1_Y_MAX (384 - ELANTECH_V1_EDGE_OFFSET)
Some nitpicking, can you use just one space after "#define" to be
coherent with the rest of the file ;)
Apart from that, does your touchpad respond to the ELANTECH_QUE_FW_ID
query before being in absolute mode? Because if it does you can remove
the set_absolute_mode_vN() call from get_hwinfo_vN() and turn the latter
into a version independent function.
This would allow you to simplify the enable_elantech_vN() by sharing
the get_hwinfo() code and merging the set_absolute_mode_vN() code in it.
Martin