diff options
author | Alexandr Shadchin <shadchin@cvs.openbsd.org> | 2012-03-05 18:42:56 +0000 |
---|---|---|
committer | Alexandr Shadchin <shadchin@cvs.openbsd.org> | 2012-03-05 18:42:56 +0000 |
commit | 5717648c0c43b1ce58d9b26ba930828353a58581 (patch) | |
tree | 6a0278cb4e5f1c26f2fca38edbe5359488376988 /sys | |
parent | 24ebfb7b4218c9cb8358de1710bbbd5fe3f6fba3 (diff) |
Adds support for a slightly different version of the ALPS protocol,
which send 'interleaved' PS2 packets in between absolute ALPS packets.
Dell laptops (E6xxx and E5500 at least) have this kind of touchpad.
ok and some rework mpi@, tested okan@.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pckbc/pms.c | 74 | ||||
-rw-r--r-- | sys/dev/pckbc/pmsreg.h | 21 |
2 files changed, 81 insertions, 14 deletions
diff --git a/sys/dev/pckbc/pms.c b/sys/dev/pckbc/pms.c index a04386bb3aa..5a026fc8639 100644 --- a/sys/dev/pckbc/pms.c +++ b/sys/dev/pckbc/pms.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pms.c,v 1.27 2012/01/28 21:00:48 mpi Exp $ */ +/* $OpenBSD: pms.c,v 1.28 2012/03/05 18:42:55 shadchin Exp $ */ /* $NetBSD: psm.c,v 1.11 2000/06/05 22:20:57 sommerfeld Exp $ */ /*- @@ -87,6 +87,11 @@ struct synaptics_softc { struct alps_softc { int model; +#define ALPS_GLIDEPOINT (1 << 1) +#define ALPS_DUALPOINT (1 << 2) +#define ALPS_PASSTHROUGH (1 << 3) +#define ALPS_INTERLEAVED (1 << 4) + int mask; int version; @@ -94,6 +99,8 @@ struct alps_softc { int max_x, max_y; int old_fin; + u_int sec_buttons; /* trackpoint */ + /* Compat mode */ int wsmode; int old_x, old_y; @@ -145,18 +152,15 @@ static const struct alps_model { int mask; int model; } alps_models[] = { -#if 0 - /* FIXME some clipads are not working yet */ - { 0x5212, 0xff, ALPS_DUALPOINT | ALPS_PASSTHROUGH }, - { 0x6222, 0xcf, ALPS_DUALPOINT | ALPS_PASSTHROUGH }, -#endif { 0x2021, 0xf8, ALPS_DUALPOINT | ALPS_PASSTHROUGH }, { 0x2221, 0xf8, ALPS_DUALPOINT | ALPS_PASSTHROUGH }, { 0x2222, 0xff, ALPS_DUALPOINT | ALPS_PASSTHROUGH }, { 0x3222, 0xf8, ALPS_DUALPOINT | ALPS_PASSTHROUGH }, + { 0x5212, 0xff, ALPS_DUALPOINT | ALPS_PASSTHROUGH | ALPS_INTERLEAVED }, { 0x5321, 0xf8, ALPS_GLIDEPOINT }, { 0x5322, 0xf8, ALPS_GLIDEPOINT }, { 0x603b, 0xf8, ALPS_GLIDEPOINT }, + { 0x6222, 0xcf, ALPS_DUALPOINT | ALPS_PASSTHROUGH | ALPS_INTERLEAVED }, { 0x6321, 0xf8, ALPS_GLIDEPOINT }, { 0x6322, 0xf8, ALPS_GLIDEPOINT }, { 0x6323, 0xf8, ALPS_GLIDEPOINT }, @@ -228,6 +232,7 @@ int synaptics_query(struct pms_softc *, int, int *); int synaptics_get_hwinfo(struct pms_softc *); void synaptics_sec_proc(struct pms_softc *); +int alps_sec_proc(struct pms_softc *); int alps_get_hwinfo(struct pms_softc *); struct cfattach pms_ca = { @@ -726,6 +731,7 @@ pmsinput(void *vsc, int data) return; } + sc->packet[sc->inputstate] = data; if (sc->protocol->sync(sc, data)) { #ifdef DIAGNOSTIC printf("%s: not in sync yet, discard input\n", DEVNAME(sc)); @@ -734,13 +740,13 @@ pmsinput(void *vsc, int data) return; } - sc->packet[sc->inputstate++] = data; + sc->inputstate++; if (sc->inputstate != sc->protocol->packetsize) return; - sc->protocol->proc(sc); sc->inputstate = 0; + sc->protocol->proc(sc); } int @@ -1050,6 +1056,40 @@ pms_disable_synaptics(struct pms_softc *sc) } int +alps_sec_proc(struct pms_softc *sc) +{ + struct alps_softc *alps = sc->alps; + int dx, dy, pos = 0; + + if ((sc->packet[0] & PMS_ALPS_PS2_MASK) == PMS_ALPS_PS2_VALID) { + /* + * We need to keep buttons states because interleaved + * packets only signalize x/y movements. + */ + alps->sec_buttons = butmap[sc->packet[0] & PMS_PS2_BUTTONSMASK]; + } else if ((sc->packet[3] & PMS_ALPS_INTERLEAVED_MASK) == + PMS_ALPS_INTERLEAVED_VALID) { + sc->inputstate = 3; + pos = 3; + } else { + return (0); + } + + if ((sc->sc_dev_enable & PMS_DEV_SECONDARY) == 0) + return (1); + + dx = (sc->packet[pos] & PMS_PS2_XNEG) ? + (int)sc->packet[pos + 1] - 256 : sc->packet[pos + 1]; + 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); + + return (1); +} + +int alps_get_hwinfo(struct pms_softc *sc) { struct alps_softc *alps = sc->alps; @@ -1161,6 +1201,8 @@ pms_enable_alps(struct pms_softc *sc) goto err; } + alps->sec_buttons = 0; + return (1); err: @@ -1205,6 +1247,13 @@ pms_sync_alps(struct pms_softc *sc, int data) { struct alps_softc *alps = sc->alps; + if ((alps->model & ALPS_DUALPOINT) && + (sc->packet[0] & PMS_ALPS_PS2_MASK) == PMS_ALPS_PS2_VALID) { + if (sc->inputstate == 2) + sc->inputstate += 3; + return (0); + } + switch (sc->inputstate) { case 0: if ((data & alps->mask) != alps->mask) @@ -1213,9 +1262,13 @@ pms_sync_alps(struct pms_softc *sc, int data) case 1: case 2: case 3: + if ((data & PMS_ALPS_MASK) != PMS_ALPS_VALID) + return (-1); + break; case 4: case 5: - if ((data & 0x80) != 0) + if ((alps->model & ALPS_INTERLEAVED) == 0 && + (data & PMS_ALPS_MASK) != PMS_ALPS_VALID) return (-1); break; } @@ -1231,6 +1284,9 @@ pms_proc_alps(struct pms_softc *sc) u_int buttons; int fin, ges; + if ((alps->model & ALPS_DUALPOINT) && alps_sec_proc(sc)) + return; + x = sc->packet[1] | ((sc->packet[2] & 0x78) << 4); y = sc->packet[4] | ((sc->packet[3] & 0x70) << 3); z = sc->packet[5]; diff --git a/sys/dev/pckbc/pmsreg.h b/sys/dev/pckbc/pmsreg.h index 5c124ff8a25..35c46b9ba35 100644 --- a/sys/dev/pckbc/pmsreg.h +++ b/sys/dev/pckbc/pmsreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pmsreg.h,v 1.6 2011/12/03 19:43:00 mpi Exp $ */ +/* $OpenBSD: pmsreg.h,v 1.7 2012/03/05 18:42:55 shadchin Exp $ */ /* $NetBSD: psmreg.h,v 1.1 1998/03/22 15:41:28 drochner Exp $ */ #ifndef SYS_DEV_PCKBC_PMSREG_H @@ -42,6 +42,21 @@ #define PMS_ALPS_MAGIC3_1 10 #define PMS_ALPS_MAGIC3_2 100 +/* + * Checking for almost-standard PS/2 packet + * Note: ALPS devices never signal overflow condition + */ +#define PMS_ALPS_PS2_MASK 0xc8 +#define PMS_ALPS_PS2_VALID 0x08 + +/* Checking for interleaved packet */ +#define PMS_ALPS_INTERLEAVED_MASK 0xcf +#define PMS_ALPS_INTERLEAVED_VALID 0x0f + +/* Checking for non first byte */ +#define PMS_ALPS_MASK 0x80 +#define PMS_ALPS_VALID 0x00 + /* Synaptics queries */ #define SYNAPTICS_QUE_IDENTIFY 0x00 #define SYNAPTICS_QUE_MODES 0x01 @@ -93,10 +108,6 @@ #define SYNAPTICS_MODEL_SIMPLC (1 << 5) #define SYNAPTICS_MODEL_GEOMETRY(m) ((m) & 0x0f) -#define ALPS_GLIDEPOINT (1 << 1) -#define ALPS_DUALPOINT (1 << 2) -#define ALPS_PASSTHROUGH (1 << 3) - /* Resolutions */ #define SYNAPTICS_RESOLUTION_X(r) (((r) >> 16) & 0xff) #define SYNAPTICS_RESOLUTION_Y(r) ((r) & 0xff) |