diff options
author | dumbbell <dumbbell@FreeBSD.org> | 2013-09-02 19:15:20 +0000 |
---|---|---|
committer | dumbbell <dumbbell@FreeBSD.org> | 2013-09-02 19:15:20 +0000 |
commit | bc5fd7560b59fdb8569673b4c54ba5910c96327c (patch) | |
tree | 61fe8dd6fdc81945e75d6ea024247e3648a5fda2 /sys/dev/atkbdc | |
parent | 8f00835b6506e9ac2956e621e2f6e9c5ccd7c906 (diff) | |
download | FreeBSD-src-bc5fd7560b59fdb8569673b4c54ba5910c96327c.zip FreeBSD-src-bc5fd7560b59fdb8569673b4c54ba5910c96327c.tar.gz |
psm: Add support for middle and extended buttons on Synaptics touchpads
PR: kern/170834
Submitted by: Brandon Gooch <jamesbrandongooch@gmail.com>
Tested by: Artyom Mirgorodskiy <artyom.mirgorodsky@gmail.com>
MFC after: 1 month
Diffstat (limited to 'sys/dev/atkbdc')
-rw-r--r-- | sys/dev/atkbdc/psm.c | 131 |
1 files changed, 91 insertions, 40 deletions
diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c index 365b815..5a1fd37 100644 --- a/sys/dev/atkbdc/psm.c +++ b/sys/dev/atkbdc/psm.c @@ -2601,14 +2601,14 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, static int guest_buttons; int w, x0, y0; - /* TouchPad PS/2 absolute mode message format + /* TouchPad PS/2 absolute mode message format with capFourButtons: * * Bits: 7 6 5 4 3 2 1 0 (LSB) * ------------------------------------------------ * ipacket[0]: 1 0 W3 W2 0 W1 R L * ipacket[1]: Yb Ya Y9 Y8 Xb Xa X9 X8 * ipacket[2]: Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0 - * ipacket[3]: 1 1 Yc Xc 0 W0 D U + * ipacket[3]: 1 1 Yc Xc 0 W0 D^R U^L * ipacket[4]: X7 X6 X5 X4 X3 X2 X1 X0 * ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 * @@ -2622,6 +2622,21 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, * Y: y position * Z: pressure * + * Without capFourButtons but with nExtendeButtons and/or capMiddle + * + * Bits: 7 6 5 4 3 2 1 0 (LSB) + * ------------------------------------------------------ + * ipacket[3]: 1 1 Yc Xc 0 W0 E^R M^L + * ipacket[4]: X7 X6 X5 X4 X3|b7 X2|b5 X1|b3 X0|b1 + * ipacket[5]: Y7 Y6 Y5 Y4 Y3|b8 Y2|b6 Y1|b4 Y0|b2 + * + * Legend: + * M: Middle physical mouse button + * E: Extended mouse buttons reported instead of low bits of X and Y + * b1-b8: Extended mouse buttons + * Only ((nExtendedButtons + 1) >> 1) bits are used in packet + * 4 and 5, for reading X and Y value they should be zeroed. + * * Absolute reportable limits: 0 - 6143. * Typical bezel limits: 1472 - 5472. * Typical edge marings: 1632 - 5312. @@ -2675,8 +2690,10 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, w = 4; } - /* Handle packets from the guest device */ - /* XXX Documentation? */ + /* + * Handle packets from the guest device. See: + * Synaptics PS/2 TouchPad Interfacing Guide, Section 5.1 + */ if (w == 3 && sc->synhw.capPassthrough) { *x = ((pb->ipacket[1] & 0x10) ? pb->ipacket[4] - 256 : pb->ipacket[4]); @@ -2704,36 +2721,49 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, touchpad_buttons |= MOUSE_BUTTON3DOWN; if (sc->synhw.capExtended && sc->synhw.capFourButtons) { - if ((pb->ipacket[3] & 0x01) && (pb->ipacket[0] & 0x01) == 0) + if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x01) touchpad_buttons |= MOUSE_BUTTON4DOWN; - if ((pb->ipacket[3] & 0x02) && (pb->ipacket[0] & 0x02) == 0) + if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x02) touchpad_buttons |= MOUSE_BUTTON5DOWN; - } - - /* - * In newer pads - bit 0x02 in the third byte of - * the packet indicates that we have an extended - * button press. - */ - /* XXX Documentation? */ - if (pb->ipacket[3] & 0x02) { - /* - * if directional_scrolls is not 1, we treat any of - * the scrolling directions as middle-click. - */ - if (sc->syninfo.directional_scrolls) { - if (pb->ipacket[4] & 0x01) - touchpad_buttons |= MOUSE_BUTTON4DOWN; - if (pb->ipacket[5] & 0x01) - touchpad_buttons |= MOUSE_BUTTON5DOWN; - if (pb->ipacket[4] & 0x02) - touchpad_buttons |= MOUSE_BUTTON6DOWN; - if (pb->ipacket[5] & 0x02) - touchpad_buttons |= MOUSE_BUTTON7DOWN; - } else { - if ((pb->ipacket[4] & 0x0F) || - (pb->ipacket[5] & 0x0F)) + } else if (sc->synhw.capExtended && sc->synhw.capMiddle) { + /* Middle Button */ + if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01) + touchpad_buttons |= MOUSE_BUTTON2DOWN; + } else if (sc->synhw.capExtended && (sc->synhw.nExtendedButtons > 0)) { + /* Extended Buttons */ + if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x02) { + if (sc->syninfo.directional_scrolls) { + if (pb->ipacket[4] & 0x01) + touchpad_buttons |= MOUSE_BUTTON4DOWN; + if (pb->ipacket[5] & 0x01) + touchpad_buttons |= MOUSE_BUTTON5DOWN; + if (pb->ipacket[4] & 0x02) + touchpad_buttons |= MOUSE_BUTTON6DOWN; + if (pb->ipacket[5] & 0x02) + touchpad_buttons |= MOUSE_BUTTON7DOWN; + } else { touchpad_buttons |= MOUSE_BUTTON2DOWN; + } + + /* + * Zero out bits used by extended buttons to avoid + * misinterpretation of the data absolute position. + * + * The bits represented by + * + * (nExtendedButtons + 1) >> 1 + * + * will be masked out in both bytes. + * The mask for n bits is computed with the formula + * + * (1 << n) - 1 + */ + int maskedbits = 0; + int mask = 0; + maskedbits = (sc->synhw.nExtendedButtons + 1) >> 1; + mask = (1 << maskedbits) - 1; + pb->ipacket[4] &= ~(mask); + pb->ipacket[5] &= ~(mask); } } @@ -4440,15 +4470,20 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) buttons = 0; synhw.capExtended = (status[0] & 0x80) != 0; if (synhw.capExtended) { - synhw.capPassthrough = (status[2] & 0x80) != 0; - synhw.capSleep = (status[2] & 0x10) != 0; - synhw.capFourButtons = (status[2] & 0x08) != 0; - synhw.capMultiFinger = (status[2] & 0x02) != 0; - synhw.capPalmDetect = (status[2] & 0x01) != 0; + synhw.nExtendedQueries = (status[0] & 0x70) != 0; + synhw.capMiddle = (status[0] & 0x04) != 0; + synhw.capPassthrough = (status[2] & 0x80) != 0; + synhw.capSleep = (status[2] & 0x10) != 0; + synhw.capFourButtons = (status[2] & 0x08) != 0; + synhw.capMultiFinger = (status[2] & 0x02) != 0; + synhw.capPalmDetect = (status[2] & 0x01) != 0; if (verbose >= 2) { printf(" Extended capabilities:\n"); printf(" capExtended: %d\n", synhw.capExtended); + printf(" capMiddle: %d\n", synhw.capMiddle); + printf(" nExtendedQueries: %d\n", + synhw.nExtendedQueries); printf(" capPassthrough: %d\n", synhw.capPassthrough); printf(" capSleep: %d\n", synhw.capSleep); printf(" capFourButtons: %d\n", synhw.capFourButtons); @@ -4457,16 +4492,27 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) } /* - * If we have bits set in status[0] & 0x70, then we can load + * If nExtendedQueries is 1 or greater, then the TouchPad + * supports this number of extended queries. We can load * more information about buttons using query 0x09. */ - if ((status[0] & 0x70) != 0) { + if (synhw.capExtended && synhw.nExtendedQueries) { if (mouse_ext_command(kbdc, 0x09) == 0) return (FALSE); if (get_mouse_status(kbdc, status, 0, 3) != 3) return (FALSE); - buttons = (status[1] & 0xf0) >> 4; + synhw.nExtendedButtons = (status[1] & 0xf0) >> 4; + /* + * Add the number of extended buttons to the total + * button support count, including the middle button + * if capMiddle support bit is set. + */ + buttons = synhw.nExtendedButtons + synhw.capMiddle; } else + /* + * If the capFourButtons support bit is set, + * add a fourth button to the total button count. + */ buttons = synhw.capFourButtons ? 1 : 0; } if (verbose >= 2) { @@ -4477,6 +4523,12 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) } /* + * Add the default number of 3 buttons to the total + * count of supported buttons reported above. + */ + buttons += 3; + + /* * Read the mode byte. * * XXX: Note the Synaptics documentation also defines the first @@ -4503,7 +4555,6 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc) /* "Commit" the Set Mode Byte command sent above. */ set_mouse_sampling_rate(kbdc, 20); - buttons += 3; VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n", buttons)); if (sc != NULL) { |