On Fri, Mar 10, 2017 at 12:47:37AM +0100, Ulf Brosziewski wrote: > This patch for ubcmtp makes it use the multitouch-input functions of > wsmouse. It's the first driver that would apply the "tracking" variant > (wsmouse_mtframe). > > No wonders will result from the change, but the two-finger gestures that > involve movement - scrolling and click-and-drag with two fingers on a > clickpad - should work without flaws. > > A quick way to check whether all touch positions are available and the > selection of the active touch works properly is two-finger-scrolling, > performed with only one finger moving, then switching to the other one. > > Please note that click-and-drag will still require that the "ClickPad" > attribute is set in the synaptics(4) configuration. > > The patch has been tested on a MacBookPro 8,2 (from 2011). It would be > nice to learn that it doesn't introduce regressions on older or newer > models. > > If you don't use a brand-new version of the synaptics driver, you may > encounter the following bug: If the X cursor is in a window with > scrollable content and you put two finger on the touchpad without moving > them, the window content may quickly scroll up and down by a small > distance. This bug is fixed in the latest version.
Tested and works fine MacBookAir6,2 with some slightly tweaked values: synclient ClickFinger2=3 synclient ClickFinger3=2 synclient ClickPad=1 synclient VertScrollDelta=-237 synclient HorizScrollDelta=-237 synclient HorizTwoFingerScroll=1 ClickPad/click-and-drag works, awesome! :) Diff reads fine. Thanks! OK jung@ > Index: dev/usb/ubcmtp.c > =================================================================== > RCS file: /cvs/src/sys/dev/usb/ubcmtp.c,v > retrieving revision 1.12 > diff -u -p -r1.12 ubcmtp.c > --- dev/usb/ubcmtp.c 30 Mar 2016 23:34:12 -0000 1.12 > +++ dev/usb/ubcmtp.c 9 Mar 2017 22:17:50 -0000 > @@ -125,6 +125,12 @@ struct ubcmtp_finger { > #define UBCMTP_SN_COORD 250 > #define UBCMTP_SN_ORIENT 10 > > +/* Identify clickpads in ubcmtp_configure. */ > +#define IS_CLICKPAD(ubcmtp_type) (ubcmtp_type != UBCMTP_TYPE1) > + > +/* Use a constant, synaptics-compatible pressure value for now. */ > +#define DEFAULT_PRESSURE 40 > + > struct ubcmtp_limit { > int limit; > int min; > @@ -316,17 +322,6 @@ static struct ubcmtp_dev ubcmtp_devices[ > }, > }; > > -/* coordinates for each tracked finger */ > -struct ubcmtp_pos { > - int down; > - int x; > - int y; > - int z; > - int w; > - int dx; > - int dy; > -}; > - > struct ubcmtp_softc { > struct device sc_dev; /* base device */ > > @@ -355,7 +350,8 @@ struct ubcmtp_softc { > uint32_t sc_status; > #define UBCMTP_ENABLED 1 > > - struct ubcmtp_pos pos[UBCMTP_MAX_FINGERS]; > + struct mtpoint frame[UBCMTP_MAX_FINGERS]; > + int contacts; > int btn; > }; > > @@ -519,6 +515,24 @@ ubcmtp_activate(struct device *self, int > } > > int > +ubcmtp_configure(struct ubcmtp_softc *sc) > +{ > + struct wsmousehw *hw = wsmouse_get_hw(sc->sc_wsmousedev); > + > + hw->type = WSMOUSE_TYPE_ELANTECH; /* see ubcmtp_ioctl */ > + hw->hw_type = (IS_CLICKPAD(sc->dev_type->type) > + ? WSMOUSEHW_CLICKPAD : WSMOUSEHW_TOUCHPAD); > + hw->x_min = sc->dev_type->l_x.min; > + hw->x_max = sc->dev_type->l_x.max; > + hw->y_min = sc->dev_type->l_y.min; > + hw->y_max = sc->dev_type->l_y.max; > + hw->mt_slots = UBCMTP_MAX_FINGERS; > + hw->flags = WSMOUSEHW_MT_TRACKING; > + > + return wsmouse_configure(sc->sc_wsmousedev, NULL, 0); > +} > + > +int > ubcmtp_enable(void *v) > { > struct ubcmtp_softc *sc = v; > @@ -534,6 +548,9 @@ ubcmtp_enable(void *v) > return (1); > } > > + if (ubcmtp_configure(sc)) > + return (1); > + > if (ubcmtp_setup_pipes(sc) == 0) { > sc->sc_status |= UBCMTP_ENABLED; > return (0); > @@ -608,6 +625,7 @@ ubcmtp_ioctl(void *v, unsigned long cmd, > wsmode); > return (EINVAL); > } > + wsmouse_set_mode(sc->sc_wsmousedev, wsmode); > > DPRINTF("%s: changing mode to %s\n", > sc->sc_dev.dv_xname, (wsmode == WSMOUSE_COMPAT ? "compat" : > @@ -779,7 +797,7 @@ ubcmtp_tp_intr(struct usbd_xfer *xfer, v > struct ubcmtp_softc *sc = priv; > struct ubcmtp_finger *pkt; > u_int32_t pktlen; > - int i, diff = 0, finger = 0, fingers = 0, s, t; > + int i, s, btn, contacts, fingers; > > if (usbd_is_dying(sc->sc_udev) || !(sc->sc_status & UBCMTP_ENABLED)) > return; > @@ -803,76 +821,30 @@ ubcmtp_tp_intr(struct usbd_xfer *xfer, v > pkt = (struct ubcmtp_finger *)(sc->tp_pkt + sc->tp_offset); > fingers = (pktlen - sc->tp_offset) / sizeof(struct ubcmtp_finger); > > + contacts = 0; > for (i = 0; i < fingers; i++) { > - if ((int16_t)letoh16(pkt[i].touch_major) == 0) { > - /* finger lifted */ > - sc->pos[i].down = 0; > - diff = 1; > - continue; > - } > - > - if (!sc->pos[finger].down) { > - sc->pos[finger].down = 1; > - diff = 1; > - } > - > - if ((t = (int16_t)letoh16(pkt[i].abs_x)) != sc->pos[finger].x) { > - sc->pos[finger].x = t; > - diff = 1; > - } > - > - if ((t = (int16_t)letoh16(pkt[i].abs_y)) != sc->pos[finger].y) { > - sc->pos[finger].y = t; > - diff = 1; > - } > - > - if ((t = (int16_t)letoh16(pkt[i].rel_x)) != sc->pos[finger].dx) > { > - sc->pos[finger].dx = t; > - diff = 1; > - } > - > - if ((t = (int16_t)letoh16(pkt[i].rel_y)) != sc->pos[finger].dy) > { > - sc->pos[finger].dy = t; > - diff = 1; > - } > - > - finger++; > - } > - > - if (sc->dev_type->type == UBCMTP_TYPE2 || > - sc->dev_type->type == UBCMTP_TYPE3 || > - sc->dev_type->type == UBCMTP_TYPE4) { > - if (sc->dev_type->type == UBCMTP_TYPE2) > - t = > !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE2_BTOFF])); > - else if (sc->dev_type->type == UBCMTP_TYPE3) > - t = > !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE3_BTOFF])); > - else if (sc->dev_type->type == UBCMTP_TYPE4) > - t = > !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE4_BTOFF])); > - > - if (sc->btn != t) { > - sc->btn = t; > - diff = 1; > - > - DPRINTF("%s: [button]\n", sc->sc_dev.dv_xname); > - } > - } > + if ((int16_t)letoh16(pkt[i].touch_major) == 0) > + continue; /* finger lifted */ > + sc->frame[contacts].x = (int16_t)letoh16(pkt[i].abs_x); > + sc->frame[contacts].y = (int16_t)letoh16(pkt[i].abs_y); > + sc->frame[contacts].pressure = DEFAULT_PRESSURE; > + contacts++; > + } > + > + btn = sc->btn; > + if (sc->dev_type->type == UBCMTP_TYPE2) > + sc->btn = !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE2_BTOFF])); > + else if (sc->dev_type->type == UBCMTP_TYPE3) > + sc->btn = !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE3_BTOFF])); > + else if (sc->dev_type->type == UBCMTP_TYPE4) > + sc->btn = !!((int16_t)letoh16(sc->tp_pkt[UBCMTP_TYPE4_BTOFF])); > > - if (diff) { > + if (contacts || sc->contacts || sc->btn != btn) { > + sc->contacts = contacts; > s = spltty(); > - > - DPRINTF("%s: ", sc->sc_dev.dv_xname); > - > - if (sc->wsmode == WSMOUSE_NATIVE) { > - DPRINTF("absolute input %d, %d (finger %d, button > %d)\n", > - sc->pos[0].x, sc->pos[0].y, finger, sc->btn); > - WSMOUSE_TOUCH(sc->sc_wsmousedev, sc->btn, sc->pos[0].x, > - sc->pos[0].y, (finger ? 50 : 0), finger); > - } else { > - DPRINTF("relative input %d, %d (button %d)\n", > - sc->pos[0].dx, sc->pos[0].dy, sc->btn); > - WSMOUSE_INPUT(sc->sc_wsmousedev, sc->btn, > - sc->pos[0].dx, sc->pos[0].dy, 0, 0); > - } > + wsmouse_buttons(sc->sc_wsmousedev, sc->btn); > + wsmouse_mtframe(sc->sc_wsmousedev, sc->frame, contacts); > + wsmouse_input_sync(sc->sc_wsmousedev); > splx(s); > } > } >