Folks, I have been bashing my head against a synaptics trackpad for a while now and I am convinced that I am missing something but I just cannot see what. My laptop has a synaptics "clickpad" which is, effectively, a one button trackpad. I have managed to emulate 3 buttons by checking the location of the click and returning the appropriate event. This actually has made the trackpad pretty much usable for me. I have enough wiggle room to navigate my menus. What I would really like is two finger support so I can hold a "button" down and use another finger to navigate. This does work on this trackpad in linux and windows. Below are my diffs for the synaptics drivers that _should_ do the job but no matter what I try the trackpad never returns the magic W value of 2 which is supposed to indicate a multi-touch event. I have tried poring over the linux driver but they seem to be doing the same as I am, I have also gone over the synaptics ps/2 protocol documentation a lot to no avail. Anyone have any ideas?
Here is what I have done: Index: synaptics.c =================================================================== RCS file: /cvsroot/src/sys/dev/pckbport/synaptics.c,v retrieving revision 1.33 diff -u -r1.33 synaptics.c --- synaptics.c 4 Mar 2015 22:58:35 -0000 1.33 +++ synaptics.c 5 Dec 2015 06:35:33 -0000 @@ -80,6 +80,10 @@ signed short sp_y; u_char sp_z; /* Z (pressure) */ u_char sp_w; /* W (contact patch width) */ + signed short sp_sx; /* Secondary finger unscaled absolute */ + /* X/Y coordinates */ + signed short sp_xy; + u_char sp_finger; /* 0 for primary, 1 for secondary */ char sp_left; /* Left mouse button status */ char sp_right; /* Right mouse button status */ char sp_middle; /* Middle button status (possibly emulated) */ @@ -93,6 +97,8 @@ static void pms_sysctl_synaptics(struct sysctllog **); static int pms_sysctl_synaptics_verify(SYSCTLFN_ARGS); +static short old_w = 256; + /* Controlled by sysctl. */ static int synaptics_up_down_emul = 2; static int synaptics_up_down_motion_delta = 1; @@ -105,6 +111,9 @@ static int synaptics_edge_motion_delta = 32; static u_int synaptics_finger_high = SYNAPTICS_FINGER_LIGHT + 5; static u_int synaptics_finger_low = SYNAPTICS_FINGER_LIGHT - 10; +static int synaptics_button_boundary = SYNAPTICS_EDGE_BOTTOM + 720; +static int synaptics_button2 = SYNAPTICS_EDGE_LEFT + (SYNAPTICS_EDGE_RIGHT - SYNAPTICS_EDGE_LEFT) / 3; +static int synaptics_button3 = SYNAPTICS_EDGE_LEFT + 2 * (SYNAPTICS_EDGE_RIGHT - SYNAPTICS_EDGE_LEFT) / 3; static int synaptics_two_fingers_emul = 0; static int synaptics_scale_x = 16; static int synaptics_scale_y = 16; @@ -113,6 +122,9 @@ static int synaptics_movement_threshold = 4; /* Sysctl nodes. */ +static int synaptics_button_boundary_nodenum; +static int synaptics_button2_nodenum; +static int synaptics_button3_nodenum; static int synaptics_up_down_emul_nodenum; static int synaptics_up_down_motion_delta_nodenum; static int synaptics_gesture_move_nodenum; @@ -385,8 +397,8 @@ { struct pms_softc *psc = vsc; struct synaptics_softc *sc = &psc->u.synaptics; - u_char cmd[2], resp[2]; - int res; + u_char cmd[2], resp[3], enable_modes; + int res, res2; if (sc->flags & SYN_FLAG_HAS_PASSTHROUGH) { /* @@ -399,15 +411,56 @@ } /* + * Synaptics documentation says to disable device before + * setting mode. + */ + cmd[0] = PMS_DEV_DISABLE; + res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 0, + NULL, 0); + if (res) + aprint_error("synaptics: disable error\n"); + + /* * Enable Absolute mode with W (width) reporting, and set - * the packet rate to maximum (80 packets per second). + * the packet rate to maximum (80 packets per second). Enable + * extended W mode if supported so we can report second finger + * position. */ - res = pms_sliced_command(psc->sc_kbctag, psc->sc_kbcslot, - SYNAPTICS_MODE_ABSOLUTE | SYNAPTICS_MODE_W | SYNAPTICS_MODE_RATE); + enable_modes = + SYNAPTICS_MODE_ABSOLUTE | SYNAPTICS_MODE_W | SYNAPTICS_MODE_RATE; + if (sc->flags & SYN_FLAG_HAS_EXTENDED_WMODE) + enable_modes |= SYNAPTICS_MODE_EXTENDED_W; +printf("synaptics: enable_mode = %x\n", enable_modes); + + + res = pms_sliced_command(psc->sc_kbctag, psc->sc_kbcslot, enable_modes); cmd[0] = PMS_SET_SAMPLE; cmd[1] = SYNAPTICS_CMD_SET_MODE2; res |= pckbport_enqueue_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 2, 0, 1, NULL); + + res2 = pms_sliced_command(psc->sc_kbctag, psc->sc_kbcslot, + SYNAPTICS_READ_MODE); + cmd[0] = PMS_SEND_DEV_STATUS; + res2 |= pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 3, + resp, 0); + if (res2) + aprint_error("synaptics: read mode error\n"); + +printf("synaptics: mode = 0x%x\n", resp[2]); + cmd[0] = PMS_SET_SAMPLE; + cmd[1] = 200; + res2 |= pckbport_enqueue_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 2, 0, + 1, NULL); + if (res2) + aprint_error("synaptics: set rate error\n"); + + cmd[0] = PMS_DEV_ENABLE; + res2 = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, 1, 0, + NULL, 0); + if (res2) + aprint_error("synaptics: enable error\n"); + sc->up_down = 0; sc->prev_fingers = 0; sc->gesture_start_x = sc->gesture_start_y = 0; @@ -415,8 +468,11 @@ sc->gesture_tap_packet = 0; sc->gesture_type = 0; sc->gesture_buttons = 0; - sc->rem_x = sc->rem_y = 0; - sc->movement_history = 0; + sc->rem_x[0] = sc->rem_y[0] = 0; + sc->rem_x[1] = sc->rem_y[1] = 0; + sc->movement_history[0] = 0; + sc->movement_history[1] = 0; + sc->button_history = 0; if (res) { aprint_error_dev(psc->sc_dev, "synaptics_enable: Error enabling device.\n"); @@ -655,6 +711,42 @@ goto err; synaptics_movement_threshold_nodenum = node->sysctl_num; + + if ((rc = sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, "button_boundary", + SYSCTL_DESCR("Top edge of button area"), + pms_sysctl_synaptics_verify, 0, + &synaptics_button_boundary, + 0, CTL_HW, root_num, CTL_CREATE, + CTL_EOL)) != 0) + goto err; + + synaptics_button_boundary_nodenum = node->sysctl_num; + + if ((rc = sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, "button2_edge", + SYSCTL_DESCR("Left edge of button 2 region"), + pms_sysctl_synaptics_verify, 0, + &synaptics_button2, + 0, CTL_HW, root_num, CTL_CREATE, + CTL_EOL)) != 0) + goto err; + + synaptics_button2_nodenum = node->sysctl_num; + + if ((rc = sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, "button3_edge", + SYSCTL_DESCR("Left edge of button 3 region"), + pms_sysctl_synaptics_verify, 0, + &synaptics_button3, + 0, CTL_HW, root_num, CTL_CREATE, + CTL_EOL)) != 0) + goto err; + + synaptics_button3_nodenum = node->sysctl_num; return; err: @@ -716,6 +808,16 @@ if (t < 0 || t > (SYNAPTICS_EDGE_MAX / 4)) return (EINVAL); } else + if (node.sysctl_num == synaptics_button_boundary) { + if (t < 0 || t < SYNAPTICS_EDGE_BOTTOM || + t > SYNAPTICS_EDGE_TOP) + return (EINVAL); + } else + if (node.sysctl_num == synaptics_button2 || + node.sysctl_num == synaptics_button3) { + if (t < SYNAPTICS_EDGE_LEFT || t > SYNAPTICS_EDGE_RIGHT) + return (EINVAL); + } else return (EINVAL); *(int *)rnode->sysctl_data = t; @@ -733,64 +835,153 @@ { struct synaptics_softc *sc = &psc->u.synaptics; struct synaptics_packet sp; + char new_buttons, ew_mode; memset(&sp, 0, sizeof(sp)); - /* Absolute X/Y coordinates of finger */ - sp.sp_x = psc->packet[4] + ((psc->packet[1] & 0x0f) << 8) + - ((psc->packet[3] & 0x10) << 8); - sp.sp_y = psc->packet[5] + ((psc->packet[1] & 0xf0) << 4) + - ((psc->packet[3] & 0x20) << 7); - - /* Pressure */ - sp.sp_z = psc->packet[2]; - /* Width of finger */ sp.sp_w = ((psc->packet[0] & 0x30) >> 2) + ((psc->packet[0] & 0x04) >> 1) + ((psc->packet[3] & 0x04) >> 2); + sp.sp_finger = 0; + if (sp.sp_w == SYNAPTICS_WIDTH_EXTENDED_W) { + ew_mode = psc->packet[5] >> 4; +printf("synaptics: extended w, mode = %d\n", ew_mode); + switch (ew_mode) + { + case SYNAPTICS_EW_WHEEL: + /* scroll wheel report, ignore for now */ + aprint_debug_dev(psc->sc_dev, "mouse wheel packet\n"); + return; + break; - /* Left/Right button handling. */ - sp.sp_left = psc->packet[0] & PMS_LBUTMASK; - sp.sp_right = psc->packet[0] & PMS_RBUTMASK; - - /* Up/Down buttons. */ - if (sc->flags & SYN_FLAG_HAS_BUTTONS_4_5) { - /* Old up/down buttons. */ - sp.sp_up = sp.sp_left ^ - (psc->packet[3] & PMS_LBUTMASK); - sp.sp_down = sp.sp_right ^ - (psc->packet[3] & PMS_RBUTMASK); - } else - if (sc->flags & SYN_FLAG_HAS_UP_DOWN_BUTTONS && - ((psc->packet[0] & PMS_RBUTMASK) ^ - (psc->packet[3] & PMS_RBUTMASK))) { - /* New up/down button. */ - sp.sp_up = psc->packet[4] & SYN_1BUTMASK; - sp.sp_down = psc->packet[5] & SYN_2BUTMASK; + case SYNAPTICS_EW_SECONDARY_FINGER: + /* parse the second finger report */ + + sp.sp_finger = 1; /* just one other finger for now */ + sp.sp_x = psc->packet[1] + + ((psc->packet[4] & 0x0f) << 8); + sp.sp_y = psc->packet[2] + + ((psc->packet[4] & 0xf0) << 4); + sp.sp_z = (psc->packet[3] & 0x30) + + (psc->packet[5] & 0x0f); + + /* keep same buttons down as primary */ + sp.sp_left = sc->button_history & PMS_LBUTMASK; + sp.sp_middle = sc->button_history & PMS_MBUTMASK; + sp.sp_right = sc->button_history & PMS_RBUTMASK; + break; + + case SYNAPTICS_EW_FINGER_STATUS: + /* reports which finger is primary/secondary + * ignore for now. + */ + return; + break; + + default: + aprint_error_dev(psc->sc_dev, + "invalid extended w mode %d\n", + ew_mode); + return; + break; + } } else { - sp.sp_up = 0; - sp.sp_down = 0; - } - if(sc->flags & SYN_FLAG_HAS_ONE_BUTTON_CLICKPAD) { - /* This is not correctly specified. Read this button press - * from L/U bit. - */ - sp.sp_left = ((psc->packet[0] ^ psc->packet[3]) & 0x01) ? 1 : 0; - } else - /* Middle button. */ - if (sc->flags & SYN_FLAG_HAS_MIDDLE_BUTTON) { - /* Old style Middle Button. */ - sp.sp_middle = (psc->packet[0] & PMS_LBUTMASK) ^ - (psc->packet[3] & PMS_LBUTMASK); - } else - if (synaptics_up_down_emul == 1) { - /* Do middle button emulation using up/down buttons */ - sp.sp_middle = sp.sp_up | sp.sp_down; - sp.sp_up = sp.sp_down = 0; - } else - sp.sp_middle = 0; + /* Absolute X/Y coordinates of finger */ + sp.sp_x = psc->packet[4] + ((psc->packet[1] & 0x0f) << 8) + + ((psc->packet[3] & 0x10) << 8); + sp.sp_y = psc->packet[5] + ((psc->packet[1] & 0xf0) << 4) + + ((psc->packet[3] & 0x20) << 7); + + /* Pressure */ + sp.sp_z = psc->packet[2]; + + /* Left/Right button handling. */ + sp.sp_left = psc->packet[0] & PMS_LBUTMASK; + sp.sp_right = psc->packet[0] & PMS_RBUTMASK; + + /* Up/Down buttons. */ + if (sc->flags & SYN_FLAG_HAS_BUTTONS_4_5) { + /* Old up/down buttons. */ + sp.sp_up = sp.sp_left ^ + (psc->packet[3] & PMS_LBUTMASK); + sp.sp_down = sp.sp_right ^ + (psc->packet[3] & PMS_RBUTMASK); + } else + if (sc->flags & SYN_FLAG_HAS_UP_DOWN_BUTTONS && + ((psc->packet[0] & PMS_RBUTMASK) ^ + (psc->packet[3] & PMS_RBUTMASK))) { + /* New up/down button. */ + sp.sp_up = psc->packet[4] & SYN_1BUTMASK; + sp.sp_down = psc->packet[5] & SYN_2BUTMASK; + } else { + sp.sp_up = 0; + sp.sp_down = 0; + } + + new_buttons = 0; + if(sc->flags & SYN_FLAG_HAS_ONE_BUTTON_CLICKPAD) { + /* This is not correctly specified. Read this button press + * from L/U bit. Emulate 3 buttons by checking the + * coordinates of the click and returning the appropriate + * button code. Outside the button region default to a + * left click. + */ + if (sp.sp_y < synaptics_button_boundary) { + if (sp.sp_x > synaptics_button3) { + sp.sp_right = + ((psc->packet[0] ^ psc->packet[3]) & 0x01) ? PMS_RBUTMASK : 0; + } else if (sp.sp_x > synaptics_button2) { + sp.sp_middle = + ((psc->packet[0] ^ psc->packet[3]) & 0x01) ? PMS_MBUTMASK : 0; + } else { + sp.sp_left = + ((psc->packet[0] ^ psc->packet[3]) & 0x01) ? PMS_LBUTMASK : 0; + } + } else + sp.sp_left = + ((psc->packet[0] ^ psc->packet[3]) & 0x01) ? 1 : 0; + new_buttons = sp.sp_left | sp.sp_middle | sp.sp_right; + if (new_buttons != sc->button_history) { + if (sc->button_history == 0) + sc->button_history = new_buttons; + else if (new_buttons == 0) { + sc->button_history = 0; + /* ensure all buttons are cleared just in + * case finger comes off in a different + * region. + */ + sp.sp_left = 0; + sp.sp_middle = 0; + sp.sp_right = 0; + } else { + /* make sure we keep the same button even + * if the finger moves to a different + * region. This precludes chording + * but, oh well. + */ + sp.sp_left = sc->button_history & PMS_LBUTMASK; + sp.sp_middle = sc->button_history + & PMS_MBUTMASK; + sp.sp_right = sc->button_history & PMS_RBUTMASK; + } + } + } else + /* Middle button. */ + if (sc->flags & SYN_FLAG_HAS_MIDDLE_BUTTON) { + /* Old style Middle Button. */ + sp.sp_middle = (psc->packet[0] & PMS_LBUTMASK) ^ + (psc->packet[3] & PMS_LBUTMASK); + } else + if (synaptics_up_down_emul == 1) { + /* Do middle button emulation using up/down buttons */ + sp.sp_middle = sp.sp_up | sp.sp_down; + sp.sp_up = sp.sp_down = 0; + } else + sp.sp_middle = 0; + + } pms_synaptics_process_packet(psc, &sp); } @@ -889,6 +1080,15 @@ */ psc->inputstate = 0; +short w; + w = ((psc->packet[0] & 0x30) >> 2) + + ((psc->packet[0] & 0x04) >> 1) + + ((psc->packet[3] & 0x04) >> 2); + +if (w != old_w) { +printf("synaptics: changed w = %d\n", w); +old_w = w; +} if ((psc->packet[0] & 0xfc) == 0x84 && (psc->packet[3] & 0xcc) == 0xc4) { /* W = SYNAPTICS_WIDTH_PASSTHROUGH, PS/2 passthrough */ @@ -948,7 +1148,8 @@ * fingers appear within the tap gesture time period. */ if (sc->flags & SYN_FLAG_HAS_MULTI_FINGER && - SYN_TIME(sc, sc->gesture_start_packet) < synaptics_gesture_length) { + SYN_TIME(sc, sc->gesture_start_packet, + sp->sp_finger) < synaptics_gesture_length) { switch (sp->sp_w) { case SYNAPTICS_WIDTH_TWO_FINGERS: fingers = 2; @@ -985,7 +1186,7 @@ int gesture_len, gesture_buttons; int set_buttons; - gesture_len = SYN_TIME(sc, sc->gesture_start_packet); + gesture_len = SYN_TIME(sc, sc->gesture_start_packet, sp->sp_finger); gesture_buttons = sc->gesture_buttons; if (fingers > 0 && (fingers == sc->prev_fingers)) { @@ -1010,7 +1211,7 @@ sc->gesture_start_y = abs(sp->sp_y); sc->gesture_move_x = 0; sc->gesture_move_y = 0; - sc->gesture_start_packet = sc->total_packets; + sc->gesture_start_packet = sc->total_packets[0]; #ifdef DIAGNOSTIC aprint_debug("Finger applied: gesture_start_x: %d gesture_start_y: %d\n", @@ -1053,7 +1254,7 @@ * Single tap gesture. Set the tap length timer * and flag a single-click. */ - sc->gesture_tap_packet = sc->total_packets; + sc->gesture_tap_packet = sc->total_packets[0]; sc->gesture_type |= SYN_GESTURE_SINGLE; /* @@ -1110,7 +1311,7 @@ * Activate the relevant button(s) until the * gesture tap timer has expired. */ - if (SYN_TIME(sc, sc->gesture_tap_packet) < + if (SYN_TIME(sc, sc->gesture_tap_packet, sp->sp_finger) < synaptics_gesture_length) set_buttons = 1; else @@ -1139,11 +1340,12 @@ } static inline int -synaptics_filter_policy(struct synaptics_softc *sc, int *history, int value) +synaptics_filter_policy(struct synaptics_softc *sc, int finger, int *history, + int value) { int a, b, rv, count; - count = sc->total_packets; + count = sc->total_packets[finger]; /* * Once we've accumulated at least SYN_HIST_SIZE values, combine @@ -1156,7 +1358,7 @@ * Using a rolling average helps to filter out jitter caused by * tiny finger movements. */ - if (sc->movement_history >= SYN_HIST_SIZE) { + if (sc->movement_history[finger] >= SYN_HIST_SIZE) { a = (history[(count + 0) % SYN_HIST_SIZE] + history[(count + 1) % SYN_HIST_SIZE]) / 2; @@ -1248,15 +1450,17 @@ static inline void synaptics_movement(struct synaptics_softc *sc, struct synaptics_packet *sp, - int *dxp, int *dyp) + int finger, int *dxp, int *dyp) { int dx, dy, edge; /* * Compute the next values of dx and dy */ - dx = synaptics_filter_policy(sc, sc->history_x, sp->sp_x); - dy = synaptics_filter_policy(sc, sc->history_y, sp->sp_y); + dx = synaptics_filter_policy(sc, finger, sc->history_x[finger], + sp->sp_x); + dy = synaptics_filter_policy(sc, finger, sc->history_y[finger], + sp->sp_y); /* * If we're dealing with a drag gesture, and the finger moves to @@ -1279,8 +1483,8 @@ /* * Apply scaling to both deltas */ - dx = synaptics_scale(dx, synaptics_scale_x, &sc->rem_x); - dy = synaptics_scale(dy, synaptics_scale_y, &sc->rem_y); + dx = synaptics_scale(dx, synaptics_scale_x, &sc->rem_x[finger]); + dy = synaptics_scale(dy, synaptics_scale_y, &sc->rem_y[finger]); /* * Clamp deltas to specified maximums. @@ -1293,7 +1497,7 @@ *dxp = dx; *dyp = dy; - sc->movement_history++; + sc->movement_history[finger]++; } static void @@ -1343,9 +1547,10 @@ fingers = synaptics_finger_detect(sc, sp, &palm); /* - * Do gesture processing only if we didn't detect a palm. + * Do gesture processing only if we didn't detect a palm and + * it is not the seondary finger. */ - if (palm == 0) + if ((sp->sp_finger == 0) && (palm == 0)) synaptics_gesture_detect(sc, sp, fingers); else sc->gesture_type = sc->gesture_buttons = 0; @@ -1362,19 +1567,31 @@ psc->buttons ^= changed; sc->prev_fingers = fingers; - sc->total_packets++; + sc->total_packets[sp->sp_finger]++; /* - * Do movement processing IFF we have a single finger and no palm. + * Do movement processing IFF we have a single finger and no palm or + * a secondary finger and no palm. */ - if (fingers == 1 && palm == 0) - synaptics_movement(sc, sp, &dx, &dy); - else { + if (palm == 0) { + if (fingers == 1) + synaptics_movement(sc, sp, 0, &dx, &dy); + else if (sp->sp_finger == 1) + synaptics_movement(sc, sp, 1, &dx, &dy); + else { + /* + * No valid finger. Therefore no movement. + */ + sc->movement_history[sp->sp_finger] = 0; + sc->rem_x[sp->sp_finger] = sc->rem_y[sp->sp_finger] = 0; + dx = dy = 0; + } + } else { /* * No valid finger. Therefore no movement. */ - sc->movement_history = 0; - sc->rem_x = sc->rem_y = 0; + sc->movement_history[0] = 0; + sc->rem_x[0] = sc->rem_y[0] = 0; dx = dy = 0; } Index: synapticsreg.h =================================================================== RCS file: /cvsroot/src/sys/dev/pckbport/synapticsreg.h,v retrieving revision 1.8 diff -u -r1.8 synapticsreg.h --- synapticsreg.h 23 May 2014 01:11:29 -0000 1.8 +++ synapticsreg.h 5 Dec 2015 06:35:33 -0000 @@ -69,6 +69,7 @@ #define SYNAPTICS_MODE_ABSOLUTE (1 << 7) #define SYNAPTICS_MODE_RATE (1 << 6) #define SYNAPTICS_MODE_SLEEP (1 << 3) +#define SYNAPTICS_MODE_EXTENDED_W (1 << 2) /* double meaning */ #define SYNAPTICS_MODE_GEST (1 << 2) #define SYNAPTICS_MODE_4BYTE_CLIENT (1 << 1) #define SYNAPTICS_MODE_W (1) @@ -97,6 +98,7 @@ #define SYNAPTICS_WIDTH_TWO_FINGERS 0 #define SYNAPTICS_WIDTH_THREE_OR_MORE 1 #define SYNAPTICS_WIDTH_PEN 2 +#define SYNAPTICS_WIDTH_EXTENDED_W 2 #define SYNAPTICS_WIDTH_ADVANCEDGESTURE 2 #define SYNAPTICS_WIDTH_PASSTHROUGH 3 #define SYNAPTICS_WIDTH_FINGER_MIN 4 @@ -106,4 +108,9 @@ #define SYNAPTICS_WIDTH_PALM_MAX 14 #define SYNAPTICS_WIDTH_MAX 15 +/* Extended W types */ +#define SYNAPTICS_EW_WHEEL 0 +#define SYNAPTICS_EW_SECONDARY_FINGER 1 +#define SYNAPTICS_EW_FINGER_STATUS 2 + #endif /* _DEV_PCKBCPORT_SYNAPTICSREG_H_ */ Index: synapticsvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/pckbport/synapticsvar.h,v retrieving revision 1.6 diff -u -r1.6 synapticsvar.h --- synapticsvar.h 23 May 2014 01:11:29 -0000 1.6 +++ synapticsvar.h 5 Dec 2015 06:35:33 -0000 @@ -55,10 +55,10 @@ #define SYN_FLAG_HAS_TWO_BUTTON_CLICKPAD (1 << 10) #define SYN_FLAG_HAS_EXTENDED_WMODE (1 << 11) - u_int total_packets; /* Total number of packets received */ -#define SYN_TIME(sc,c) (((sc)->total_packets >= (c)) ? \ - ((sc)->total_packets - (c)) : \ - ((c) - (sc)->total_packets)) + u_int total_packets[2]; /* Total number of packets received */ +#define SYN_TIME(sc,c,n) (((sc)->total_packets[(n)] >= (c)) ? \ + ((sc)->total_packets[(n)] - (c)) : \ + ((c) - (sc)->total_packets[(n)])) int up_down; int prev_fingers; @@ -78,9 +78,10 @@ #define SYN_IS_DRAG(t) ((t) & SYN_GESTURE_DRAG) #define SYN_HIST_SIZE 4 - int rem_x, rem_y; - u_int movement_history; - int history_x[SYN_HIST_SIZE], history_y[SYN_HIST_SIZE]; + char button_history; + int rem_x[2], rem_y[2]; + u_int movement_history[2]; + int history_x[2][SYN_HIST_SIZE], history_y[2][SYN_HIST_SIZE]; }; int pms_synaptics_probe_init(void *vsc); -- Brett Lymn Let go, or be dragged - Zen proverb.