summaryrefslogtreecommitdiffstats
path: root/sys/dev/atkbdc
diff options
context:
space:
mode:
authordumbbell <dumbbell@FreeBSD.org>2013-09-02 19:15:20 +0000
committerdumbbell <dumbbell@FreeBSD.org>2013-09-02 19:15:20 +0000
commitbc5fd7560b59fdb8569673b4c54ba5910c96327c (patch)
tree61fe8dd6fdc81945e75d6ea024247e3648a5fda2 /sys/dev/atkbdc
parent8f00835b6506e9ac2956e621e2f6e9c5ccd7c906 (diff)
downloadFreeBSD-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.c131
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) {
OpenPOWER on IntegriCloud