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
This commit is contained in:
parent
abcdcce124
commit
79d98ecd19
@ -2601,14 +2601,14 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
|
|||||||
static int guest_buttons;
|
static int guest_buttons;
|
||||||
int w, x0, y0;
|
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)
|
* Bits: 7 6 5 4 3 2 1 0 (LSB)
|
||||||
* ------------------------------------------------
|
* ------------------------------------------------
|
||||||
* ipacket[0]: 1 0 W3 W2 0 W1 R L
|
* ipacket[0]: 1 0 W3 W2 0 W1 R L
|
||||||
* ipacket[1]: Yb Ya Y9 Y8 Xb Xa X9 X8
|
* ipacket[1]: Yb Ya Y9 Y8 Xb Xa X9 X8
|
||||||
* ipacket[2]: Z7 Z6 Z5 Z4 Z3 Z2 Z1 Z0
|
* 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[4]: X7 X6 X5 X4 X3 X2 X1 X0
|
||||||
* ipacket[5]: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
|
* 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
|
* Y: y position
|
||||||
* Z: pressure
|
* 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.
|
* Absolute reportable limits: 0 - 6143.
|
||||||
* Typical bezel limits: 1472 - 5472.
|
* Typical bezel limits: 1472 - 5472.
|
||||||
* Typical edge marings: 1632 - 5312.
|
* Typical edge marings: 1632 - 5312.
|
||||||
@ -2675,8 +2690,10 @@ proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
|
|||||||
w = 4;
|
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) {
|
if (w == 3 && sc->synhw.capPassthrough) {
|
||||||
*x = ((pb->ipacket[1] & 0x10) ?
|
*x = ((pb->ipacket[1] & 0x10) ?
|
||||||
pb->ipacket[4] - 256 : pb->ipacket[4]);
|
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;
|
touchpad_buttons |= MOUSE_BUTTON3DOWN;
|
||||||
|
|
||||||
if (sc->synhw.capExtended && sc->synhw.capFourButtons) {
|
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;
|
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;
|
touchpad_buttons |= MOUSE_BUTTON5DOWN;
|
||||||
}
|
} else if (sc->synhw.capExtended && sc->synhw.capMiddle) {
|
||||||
|
/* Middle Button */
|
||||||
/*
|
if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01)
|
||||||
* In newer pads - bit 0x02 in the third byte of
|
touchpad_buttons |= MOUSE_BUTTON2DOWN;
|
||||||
* the packet indicates that we have an extended
|
} else if (sc->synhw.capExtended && (sc->synhw.nExtendedButtons > 0)) {
|
||||||
* button press.
|
/* Extended Buttons */
|
||||||
*/
|
if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x02) {
|
||||||
/* XXX Documentation? */
|
if (sc->syninfo.directional_scrolls) {
|
||||||
if (pb->ipacket[3] & 0x02) {
|
if (pb->ipacket[4] & 0x01)
|
||||||
/*
|
touchpad_buttons |= MOUSE_BUTTON4DOWN;
|
||||||
* if directional_scrolls is not 1, we treat any of
|
if (pb->ipacket[5] & 0x01)
|
||||||
* the scrolling directions as middle-click.
|
touchpad_buttons |= MOUSE_BUTTON5DOWN;
|
||||||
*/
|
if (pb->ipacket[4] & 0x02)
|
||||||
if (sc->syninfo.directional_scrolls) {
|
touchpad_buttons |= MOUSE_BUTTON6DOWN;
|
||||||
if (pb->ipacket[4] & 0x01)
|
if (pb->ipacket[5] & 0x02)
|
||||||
touchpad_buttons |= MOUSE_BUTTON4DOWN;
|
touchpad_buttons |= MOUSE_BUTTON7DOWN;
|
||||||
if (pb->ipacket[5] & 0x01)
|
} else {
|
||||||
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))
|
|
||||||
touchpad_buttons |= MOUSE_BUTTON2DOWN;
|
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;
|
buttons = 0;
|
||||||
synhw.capExtended = (status[0] & 0x80) != 0;
|
synhw.capExtended = (status[0] & 0x80) != 0;
|
||||||
if (synhw.capExtended) {
|
if (synhw.capExtended) {
|
||||||
synhw.capPassthrough = (status[2] & 0x80) != 0;
|
synhw.nExtendedQueries = (status[0] & 0x70) != 0;
|
||||||
synhw.capSleep = (status[2] & 0x10) != 0;
|
synhw.capMiddle = (status[0] & 0x04) != 0;
|
||||||
synhw.capFourButtons = (status[2] & 0x08) != 0;
|
synhw.capPassthrough = (status[2] & 0x80) != 0;
|
||||||
synhw.capMultiFinger = (status[2] & 0x02) != 0;
|
synhw.capSleep = (status[2] & 0x10) != 0;
|
||||||
synhw.capPalmDetect = (status[2] & 0x01) != 0;
|
synhw.capFourButtons = (status[2] & 0x08) != 0;
|
||||||
|
synhw.capMultiFinger = (status[2] & 0x02) != 0;
|
||||||
|
synhw.capPalmDetect = (status[2] & 0x01) != 0;
|
||||||
|
|
||||||
if (verbose >= 2) {
|
if (verbose >= 2) {
|
||||||
printf(" Extended capabilities:\n");
|
printf(" Extended capabilities:\n");
|
||||||
printf(" capExtended: %d\n", synhw.capExtended);
|
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(" capPassthrough: %d\n", synhw.capPassthrough);
|
||||||
printf(" capSleep: %d\n", synhw.capSleep);
|
printf(" capSleep: %d\n", synhw.capSleep);
|
||||||
printf(" capFourButtons: %d\n", synhw.capFourButtons);
|
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.
|
* more information about buttons using query 0x09.
|
||||||
*/
|
*/
|
||||||
if ((status[0] & 0x70) != 0) {
|
if (synhw.capExtended && synhw.nExtendedQueries) {
|
||||||
if (mouse_ext_command(kbdc, 0x09) == 0)
|
if (mouse_ext_command(kbdc, 0x09) == 0)
|
||||||
return (FALSE);
|
return (FALSE);
|
||||||
if (get_mouse_status(kbdc, status, 0, 3) != 3)
|
if (get_mouse_status(kbdc, status, 0, 3) != 3)
|
||||||
return (FALSE);
|
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
|
} else
|
||||||
|
/*
|
||||||
|
* If the capFourButtons support bit is set,
|
||||||
|
* add a fourth button to the total button count.
|
||||||
|
*/
|
||||||
buttons = synhw.capFourButtons ? 1 : 0;
|
buttons = synhw.capFourButtons ? 1 : 0;
|
||||||
}
|
}
|
||||||
if (verbose >= 2) {
|
if (verbose >= 2) {
|
||||||
@ -4476,6 +4522,12 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc)
|
|||||||
printf(" No extended capabilities\n");
|
printf(" No extended capabilities\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the default number of 3 buttons to the total
|
||||||
|
* count of supported buttons reported above.
|
||||||
|
*/
|
||||||
|
buttons += 3;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the mode byte.
|
* Read the mode byte.
|
||||||
*
|
*
|
||||||
@ -4503,7 +4555,6 @@ enable_synaptics(KBDC kbdc, struct psm_softc *sc)
|
|||||||
/* "Commit" the Set Mode Byte command sent above. */
|
/* "Commit" the Set Mode Byte command sent above. */
|
||||||
set_mouse_sampling_rate(kbdc, 20);
|
set_mouse_sampling_rate(kbdc, 20);
|
||||||
|
|
||||||
buttons += 3;
|
|
||||||
VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n", buttons));
|
VLOG(3, (LOG_DEBUG, "synaptics: END init (%d buttons)\n", buttons));
|
||||||
|
|
||||||
if (sc != NULL) {
|
if (sc != NULL) {
|
||||||
|
@ -101,12 +101,15 @@ typedef struct synapticshw {
|
|||||||
int capPen;
|
int capPen;
|
||||||
int infoSimplC;
|
int infoSimplC;
|
||||||
int infoGeometry;
|
int infoGeometry;
|
||||||
|
int nExtendedButtons;
|
||||||
int capExtended;
|
int capExtended;
|
||||||
|
int nExtendedQueries;
|
||||||
|
int capMiddle;
|
||||||
|
int capPassthrough;
|
||||||
int capSleep;
|
int capSleep;
|
||||||
int capFourButtons;
|
int capFourButtons;
|
||||||
int capMultiFinger;
|
int capMultiFinger;
|
||||||
int capPalmDetect;
|
int capPalmDetect;
|
||||||
int capPassthrough;
|
|
||||||
} synapticshw_t;
|
} synapticshw_t;
|
||||||
|
|
||||||
/* iftype */
|
/* iftype */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user