diff options
author | Ulf Brosziewski <bru@cvs.openbsd.org> | 2016-03-30 23:34:13 +0000 |
---|---|---|
committer | Ulf Brosziewski <bru@cvs.openbsd.org> | 2016-03-30 23:34:13 +0000 |
commit | bb8a088342dbb8ce495fcdc306d2e2aafba86ce3 (patch) | |
tree | c6734c2df6aff4e3b257bec7d01b73f1a42d02bd /sys/dev/pckbc/pms.c | |
parent | 5a710a5f10a7c160b6aa76c992df11c4f29c2846 (diff) |
Add support for multitouch input to wsmouse.
This change adds new input-processing functions to wsmouse and
adapts the touchpad drivers.
ok mpi@, shadchin@
Diffstat (limited to 'sys/dev/pckbc/pms.c')
-rw-r--r-- | sys/dev/pckbc/pms.c | 206 |
1 files changed, 79 insertions, 127 deletions
diff --git a/sys/dev/pckbc/pms.c b/sys/dev/pckbc/pms.c index a4abfb20283..2bf2806dda8 100644 --- a/sys/dev/pckbc/pms.c +++ b/sys/dev/pckbc/pms.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pms.c,v 1.68 2016/02/27 22:01:58 mmcc Exp $ */ +/* $OpenBSD: pms.c,v 1.69 2016/03/30 23:34:12 bru Exp $ */ /* $NetBSD: psm.c,v 1.11 2000/06/05 22:20:57 sommerfeld Exp $ */ /*- @@ -143,17 +143,8 @@ struct elantech_softc { int min_x, min_y; int max_x, max_y; - struct { - unsigned int x; - unsigned int y; - unsigned int z; - } mt[ELANTECH_MAX_FINGERS]; - int mt_slots; - int mt_count; - int mt_filter; - int mt_lastid; - int mt_lastcount; - int mt_buttons; + + u_int mt_slots; int width; @@ -997,8 +988,7 @@ synaptics_sec_proc(struct pms_softc *sc) dy = (sc->packet[1] & PMS_PS2_YNEG) ? (int)sc->packet[5] - 256 : sc->packet[5]; - wsmouse_input(sc->sc_sec_wsmousedev, - buttons, dx, dy, 0, 0, WSMOUSE_INPUT_DELTA); + WSMOUSE_INPUT(sc->sc_sec_wsmousedev, buttons, dx, dy, 0, 0); } int @@ -1162,7 +1152,7 @@ pms_proc_synaptics(struct pms_softc *sc) { struct synaptics_softc *syn = sc->synaptics; u_int buttons; - int x, y, z, w, dx, dy; + int x, y, z, w, dx, dy, width; w = ((sc->packet[0] & 0x30) >> 2) | ((sc->packet[0] & 0x04) >> 1) | ((sc->packet[3] & 0x04) >> 2); @@ -1230,8 +1220,9 @@ pms_proc_synaptics(struct pms_softc *sc) (sc->packet[5] & 0x01) ? WSMOUSE_BUTTON(3) : 0; syn->sec_buttons |= (sc->packet[4] & 0x02) ? WSMOUSE_BUTTON(2) : 0; - wsmouse_input(sc->sc_sec_wsmousedev, - syn->sec_buttons, 0, 0, 0, 0, WSMOUSE_INPUT_DELTA); + wsmouse_buttons( + sc->sc_sec_wsmousedev, syn->sec_buttons); + wsmouse_input_sync(sc->sc_sec_wsmousedev); return; } @@ -1254,9 +1245,14 @@ pms_proc_synaptics(struct pms_softc *sc) } if (syn->wsmode == WSMOUSE_NATIVE) { - wsmouse_input(sc->sc_wsmousedev, buttons, x, y, z, w, - WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y | - WSMOUSE_INPUT_ABSOLUTE_Z | WSMOUSE_INPUT_ABSOLUTE_W); + if (z) { + width = imax(w, 4); + w = (w < 2 ? w + 2 : 1); + } else { + width = w = 0; + } + wsmouse_set(sc->sc_wsmousedev, WSMOUSE_TOUCH_WIDTH, width, 0); + WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, w); } else { dx = dy = 0; if (z > SYNAPTICS_PRESSURE) { @@ -1266,8 +1262,7 @@ pms_proc_synaptics(struct pms_softc *sc) dy /= SYNAPTICS_SCALE; } if (dx || dy || buttons != syn->old_buttons) - wsmouse_input(sc->sc_wsmousedev, buttons, dx, dy, 0, 0, - WSMOUSE_INPUT_DELTA); + WSMOUSE_INPUT(sc->sc_wsmousedev, buttons, dx, dy, 0, 0); syn->old_buttons = buttons; } @@ -1313,8 +1308,7 @@ alps_sec_proc(struct pms_softc *sc) dy = (sc->packet[pos] & PMS_PS2_YNEG) ? (int)sc->packet[pos + 2] - 256 : sc->packet[pos + 2]; - wsmouse_input(sc->sc_sec_wsmousedev, alps->sec_buttons, - dx, dy, 0, 0, WSMOUSE_INPUT_DELTA); + WSMOUSE_INPUT(sc->sc_sec_wsmousedev, alps->sec_buttons, dx, dy, 0, 0); return (1); } @@ -1514,7 +1508,7 @@ void pms_proc_alps(struct pms_softc *sc) { struct alps_softc *alps = sc->alps; - int x, y, z, w, dx, dy; + int x, y, z, dx, dy; u_int buttons, gesture; if ((alps->model & ALPS_DUALPOINT) && alps_sec_proc(sc)) @@ -1532,8 +1526,7 @@ pms_proc_alps(struct pms_softc *sc) dx = (x > ALPS_XSEC_BEZEL / 2) ? (x - ALPS_XSEC_BEZEL) : x; dy = (y > ALPS_YSEC_BEZEL / 2) ? (y - ALPS_YSEC_BEZEL) : y; - wsmouse_input(sc->sc_sec_wsmousedev, buttons, dx, dy, 0, 0, - WSMOUSE_INPUT_DELTA); + WSMOUSE_INPUT(sc->sc_sec_wsmousedev, buttons, dx, dy, 0, 0); return; } @@ -1552,35 +1545,21 @@ pms_proc_alps(struct pms_softc *sc) if (alps->wsmode == WSMOUSE_NATIVE) { if (alps->gesture == ALPS_TAP) { /* Report a touch with the tap coordinates. */ - wsmouse_input(sc->sc_wsmousedev, buttons, - alps->old_x, alps->old_y, ALPS_PRESSURE, 4, - WSMOUSE_INPUT_ABSOLUTE_X - | WSMOUSE_INPUT_ABSOLUTE_Y - | WSMOUSE_INPUT_ABSOLUTE_Z - | WSMOUSE_INPUT_ABSOLUTE_W); + WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, + alps->old_x, alps->old_y, ALPS_PRESSURE, 0); if (z > 0) { /* * The hardware doesn't send a null pressure * event when dragging starts. */ - wsmouse_input(sc->sc_wsmousedev, buttons, - alps->old_x, alps->old_y, 0, 0, - WSMOUSE_INPUT_ABSOLUTE_X - | WSMOUSE_INPUT_ABSOLUTE_Y - | WSMOUSE_INPUT_ABSOLUTE_Z - | WSMOUSE_INPUT_ABSOLUTE_W); + WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, + alps->old_x, alps->old_y, 0, 0); } } gesture = sc->packet[2] & 0x03; - if (gesture != ALPS_TAP) { - w = z ? 4 : 0; - wsmouse_input(sc->sc_wsmousedev, buttons, x, y, z, w, - WSMOUSE_INPUT_ABSOLUTE_X - | WSMOUSE_INPUT_ABSOLUTE_Y - | WSMOUSE_INPUT_ABSOLUTE_Z - | WSMOUSE_INPUT_ABSOLUTE_W); - } + if (gesture != ALPS_TAP) + WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, 0); if (alps->gesture != ALPS_DRAG || gesture != ALPS_TAP) alps->gesture = gesture; @@ -1600,8 +1579,7 @@ pms_proc_alps(struct pms_softc *sc) } if (dx || dy || buttons != alps->old_buttons) - wsmouse_input(sc->sc_wsmousedev, buttons, dx, dy, 0, 0, - WSMOUSE_INPUT_DELTA); + WSMOUSE_INPUT(sc->sc_wsmousedev, buttons, dx, dy, 0, 0); alps->old_x = x; alps->old_y = y; @@ -2045,6 +2023,18 @@ err: } int +pms_elantech_v4_configure(struct device *sc_wsmousedev, + struct elantech_softc *elantech) +{ + if (wsmouse_mt_init(sc_wsmousedev, ELANTECH_MAX_FINGERS, 0)) + return (-1); + + wsmouse_set_param(sc_wsmousedev, WSMPARAM_DX_DIV, SYNAPTICS_SCALE); + wsmouse_set_param(sc_wsmousedev, WSMPARAM_DY_DIV, SYNAPTICS_SCALE); + return (0); +} + +int pms_enable_elantech_v4(struct pms_softc *sc) { struct elantech_softc *elantech = sc->elantech; @@ -2068,6 +2058,15 @@ pms_enable_elantech_v4(struct pms_softc *sc) goto err; } + if (pms_elantech_v4_configure( + sc->sc_wsmousedev, sc->elantech)) { + free(sc->elantech, M_DEVBUF, 0); + sc->elantech = NULL; + printf("%s: setup failed\n", DEVNAME(sc)); + goto err; + } + wsmouse_set_mode(sc->sc_wsmousedev, WSMOUSE_COMPAT); + printf("%s: Elantech Clickpad, version %d, firmware 0x%x\n", DEVNAME(sc), 4, sc->elantech->fw_version); } else if (elantech_set_absolute_mode_v4(sc)) @@ -2107,6 +2106,8 @@ pms_ioctl_elantech(struct pms_softc *sc, u_long cmd, caddr_t data, int flag, if (wsmode != WSMOUSE_COMPAT && wsmode != WSMOUSE_NATIVE) return (EINVAL); elantech->wsmode = wsmode; + if (sc->protocol->type == PMS_ELANTECH_V4) + wsmouse_set_mode(sc->sc_wsmousedev, wsmode); break; default: return (-1); @@ -2352,41 +2353,29 @@ void pms_proc_elantech_v4(struct pms_softc *sc) { struct elantech_softc *elantech = sc->elantech; - int n, id, slots, weight, dx, dy; + struct device *sc_wsmousedev = sc->sc_wsmousedev; + int id, weight, n, x, y, z; + u_int buttons, slots; switch (sc->packet[3] & 0x1f) { case ELANTECH_V4_PKT_STATUS: - if (elantech->mt_slots == 0) - elantech->mt_lastid = -1; - slots = sc->packet[1] & 0x1f; - if (slots == 0 && elantech->mt_lastid > -1) - /* Notify that we lifted. */ - elantech_send_input(sc, - elantech->mt[elantech->mt_lastid].x, - elantech->mt[elantech->mt_lastid].y, 0, 0); - - elantech->mt_filter = elantech->mt_slots = slots; - - for (elantech->mt_count = 0; slots != 0; slots >>= 1) - elantech->mt_count += (1 & slots); - + slots = elantech->mt_slots; + elantech->mt_slots = sc->packet[1] & 0x1f; + slots &= ~elantech->mt_slots; + for (id = 0; slots; id++, slots >>= 1) { + if (slots & 1) + wsmouse_mtstate(sc_wsmousedev, id, 0, 0, 0); + } break; case ELANTECH_V4_PKT_HEAD: id = ((sc->packet[3] & 0xe0) >> 5) - 1; if (id > -1 && id < ELANTECH_MAX_FINGERS) { - elantech->mt[id].x = - ((sc->packet[1] & 0x0f) << 8) | sc->packet[2]; - elantech->mt[id].y = - ((sc->packet[4] & 0x0f) << 8) | sc->packet[5]; - elantech->mt[id].z = - (sc->packet[1] & 0xf0) + x = ((sc->packet[1] & 0x0f) << 8) | sc->packet[2]; + y = ((sc->packet[4] & 0x0f) << 8) | sc->packet[5]; + z = (sc->packet[1] & 0xf0) | ((sc->packet[4] & 0xf0) >> 4); - - if (elantech->mt_filter & (1 << id)) { - elantech_send_mt_input(sc, id); - elantech->mt_filter = (1 << id); - } + wsmouse_mtstate(sc_wsmousedev, id, x, y, z); } break; @@ -2396,22 +2385,12 @@ pms_proc_elantech_v4(struct pms_softc *sc) id = ((sc->packet[n] & 0xe0) >> 5) - 1; if (id < 0 || id >= ELANTECH_MAX_FINGERS) continue; - dx = weight * (signed char)sc->packet[n + 1]; - dy = weight * (signed char)sc->packet[n + 2]; - elantech->mt[id].x += dx; - elantech->mt[id].y += dy; - elantech->mt[id].z = 1; - if (elantech->mt_filter & (1 << id)) { - if ((dx | dy) - || elantech->mt_count != - elantech->mt_lastcount - || (sc->packet[0] & 3) != - elantech->mt_buttons) - elantech_send_mt_input(sc, id); - - elantech->mt_filter = (dx | dy) ? - (1 << id) : elantech->mt_slots; - } + x = weight * (signed char)sc->packet[n + 1]; + y = weight * (signed char)sc->packet[n + 2]; + z = WSMOUSE_DEFAULT_PRESSURE; + wsmouse_set(sc_wsmousedev, WSMOUSE_MT_REL_X, x, id); + wsmouse_set(sc_wsmousedev, WSMOUSE_MT_REL_Y, y, id); + wsmouse_set(sc_wsmousedev, WSMOUSE_MT_PRESSURE, z, id); } break; @@ -2421,37 +2400,15 @@ pms_proc_elantech_v4(struct pms_softc *sc) sc->packet[3] & 0x1f); return; } -} -void -elantech_send_mt_input(struct pms_softc *sc, int id) -{ - struct elantech_softc *elantech = sc->elantech; + buttons = 0; + if (sc->packet[0] & 0x01) + buttons |= WSMOUSE_BUTTON(1); + if (sc->packet[0] & 0x02) + buttons |= WSMOUSE_BUTTON(3); + wsmouse_buttons(sc_wsmousedev, buttons); - if (id != elantech->mt_lastid) { - /* Correct for compatibility mode, but not useful yet: */ - elantech->old_x = elantech->mt[id].x; - elantech->old_y = elantech->mt[id].y; - /* - * To avoid a jump of the cursor, simulate a change of the - * number of touches (without producing tapping gestures - * accidentally). It should suffice to do that only if - * mt_count hasn't changed, but we cannot rely on the - * synaptics driver, which alters its finger counts when - * handling click-and-drag actions (see HandleTapProcessing - * and ComputeDeltas in synaptics.c). - */ - if (elantech->mt_lastid > -1) - elantech_send_input(sc, - elantech->mt[id].x, elantech->mt[id].y, - elantech->mt[id].z, ELANTECH_MAX_FINGERS); - elantech->mt_lastid = id; - } - elantech->mt_lastcount = elantech->mt_count; - elantech->mt_buttons = sc->packet[0] & 3; - elantech_send_input(sc, - elantech->mt[id].x, elantech->mt[id].y, - elantech->mt[id].z, elantech->mt_count); + wsmouse_input_sync(sc_wsmousedev); } void @@ -2474,11 +2431,7 @@ elantech_send_input(struct pms_softc *sc, int x, int y, int z, int w) } if (elantech->wsmode == WSMOUSE_NATIVE) { - wsmouse_input(sc->sc_wsmousedev, buttons, x, y, z, w, - WSMOUSE_INPUT_ABSOLUTE_X | - WSMOUSE_INPUT_ABSOLUTE_Y | - WSMOUSE_INPUT_ABSOLUTE_Z | - WSMOUSE_INPUT_ABSOLUTE_W); + WSMOUSE_TOUCH(sc->sc_wsmousedev, buttons, x, y, z, w); } else { dx = dy = 0; @@ -2490,8 +2443,7 @@ elantech_send_input(struct pms_softc *sc, int x, int y, int z, int w) dy /= SYNAPTICS_SCALE; } if (dx || dy || buttons != elantech->old_buttons) - wsmouse_input(sc->sc_wsmousedev, buttons, dx, dy, 0, 0, - WSMOUSE_INPUT_DELTA); + WSMOUSE_INPUT(sc->sc_wsmousedev, buttons, dx, dy, 0, 0); elantech->old_buttons = buttons; } |