Update the wsp driver to support newer touch pads, like found in

MacBookPro11,4 and MacBook12,1. This update adds support for the
force touch parameter.

PR:		204420
MFC after:	1 week
This commit is contained in:
Hans Petter Selasky 2015-11-10 09:27:52 +00:00
parent 87101cb572
commit fcc75f06aa
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=290639
2 changed files with 282 additions and 107 deletions

View File

@ -94,8 +94,8 @@ static struct wsp_tuning {
.z_factor = 5,
.pressure_touch_threshold = 50,
.pressure_untouch_threshold = 10,
.pressure_tap_threshold = 100,
.scr_hor_threshold = 10,
.pressure_tap_threshold = 120,
.scr_hor_threshold = 20,
};
static void
@ -122,8 +122,6 @@ SYSCTL_INT(_hw_usb_wsp, OID_AUTO, pressure_tap_threshold, CTLFLAG_RWTUN,
SYSCTL_INT(_hw_usb_wsp, OID_AUTO, scr_hor_threshold, CTLFLAG_RWTUN,
&wsp_tuning.scr_hor_threshold, 0, "horizontal scrolling threshold");
#define WSP_IFACE_INDEX 1
/*
* Some tables, structures, definitions and constant values for the
* touchpad protocol has been copied from Linux's
@ -155,21 +153,30 @@ struct bt_data {
enum tp_type {
TYPE1, /* plain trackpad */
TYPE2, /* button integrated in trackpad */
TYPE3 /* additional header fields since June 2013 */
TYPE3, /* additional header fields since June 2013 */
TYPE4 /* additional header field for pressure data */
};
/* trackpad finger data offsets, le16-aligned */
#define FINGER_TYPE1 (13 * 2)
#define FINGER_TYPE2 (15 * 2)
#define FINGER_TYPE3 (19 * 2)
#define FINGER_TYPE4 (23 * 2)
/* trackpad button data offsets */
#define BUTTON_TYPE2 15
#define BUTTON_TYPE3 23
#define BUTTON_TYPE4 31
/* list of device capability bits */
#define HAS_INTEGRATED_BUTTON 1
/* trackpad finger data block size */
#define FSIZE_TYPE1 (14 * 2)
#define FSIZE_TYPE2 (14 * 2)
#define FSIZE_TYPE3 (14 * 2)
#define FSIZE_TYPE4 (15 * 2)
/* trackpad finger header - little endian */
struct tp_header {
uint8_t flag;
@ -197,9 +204,10 @@ struct tp_finger {
int16_t orientation; /* 16384 when point, else 15 bit angle */
int16_t touch_major; /* touch area, major axis */
int16_t touch_minor; /* touch area, minor axis */
int16_t unused[3]; /* zeros */
int16_t unused[2]; /* zeros */
int16_t pressure; /* pressure on forcetouch touchpad */
int16_t multi; /* one finger: varies, more fingers:
* constant */
* constant */
} __packed;
/* trackpad finger data size, empirically at least ten fingers */
@ -207,7 +215,7 @@ struct tp_finger {
#define SIZEOF_FINGER sizeof(struct tp_finger)
#define SIZEOF_ALL_FINGERS (MAX_FINGERS * SIZEOF_FINGER)
#if (WSP_BUFFER_MAX < ((MAX_FINGERS * 14 * 2) + FINGER_TYPE3))
#if (WSP_BUFFER_MAX < ((MAX_FINGERS * FSIZE_TYPE4) + FINGER_TYPE4))
#error "WSP_BUFFER_MAX is too small"
#endif
@ -224,6 +232,7 @@ enum {
WSP_FLAG_WELLSPRING7,
WSP_FLAG_WELLSPRING7A,
WSP_FLAG_WELLSPRING8,
WSP_FLAG_WELLSPRING9,
WSP_FLAG_MAX,
};
@ -231,69 +240,213 @@ enum {
struct wsp_dev_params {
uint8_t caps; /* device capability bitmask */
uint8_t tp_type; /* type of trackpad interface */
uint8_t tp_button; /* offset to button data */
uint8_t tp_offset; /* offset to trackpad finger data */
uint8_t tp_fsize; /* bytes in single finger block */
uint8_t tp_delta; /* offset from header to finger struct */
uint8_t iface_index;
uint8_t um_size; /* usb control message length */
uint8_t um_req_val; /* usb control message value */
uint8_t um_req_idx; /* usb control message index */
uint8_t um_switch_idx; /* usb control message mode switch index */
uint8_t um_switch_on; /* usb control message mode switch on */
uint8_t um_switch_off; /* usb control message mode switch off */
};
static const struct wsp_dev_params wsp_dev_params[WSP_FLAG_MAX] = {
[WSP_FLAG_WELLSPRING1] = {
.caps = 0,
.tp_type = TYPE1,
.tp_button = 0,
.tp_offset = FINGER_TYPE1,
.tp_fsize = FSIZE_TYPE1,
.tp_delta = 0,
.iface_index = 0,
.um_size = 8,
.um_req_val = 0x03,
.um_req_idx = 0x00,
.um_switch_idx = 0,
.um_switch_on = 0x01,
.um_switch_off = 0x08,
},
[WSP_FLAG_WELLSPRING2] = {
.caps = 0,
.tp_type = TYPE1,
.tp_button = 0,
.tp_offset = FINGER_TYPE1,
.tp_fsize = FSIZE_TYPE1,
.tp_delta = 0,
.iface_index = 0,
.um_size = 8,
.um_req_val = 0x03,
.um_req_idx = 0x00,
.um_switch_idx = 0,
.um_switch_on = 0x01,
.um_switch_off = 0x08,
},
[WSP_FLAG_WELLSPRING3] = {
.caps = HAS_INTEGRATED_BUTTON,
.tp_type = TYPE2,
.tp_button = BUTTON_TYPE2,
.tp_offset = FINGER_TYPE2,
.tp_fsize = FSIZE_TYPE2,
.tp_delta = 0,
.iface_index = 0,
.um_size = 8,
.um_req_val = 0x03,
.um_req_idx = 0x00,
.um_switch_idx = 0,
.um_switch_on = 0x01,
.um_switch_off = 0x08,
},
[WSP_FLAG_WELLSPRING4] = {
.caps = HAS_INTEGRATED_BUTTON,
.tp_type = TYPE2,
.tp_button = BUTTON_TYPE2,
.tp_offset = FINGER_TYPE2,
.tp_fsize = FSIZE_TYPE2,
.tp_delta = 0,
.iface_index = 0,
.um_size = 8,
.um_req_val = 0x03,
.um_req_idx = 0x00,
.um_switch_idx = 0,
.um_switch_on = 0x01,
.um_switch_off = 0x08,
},
[WSP_FLAG_WELLSPRING4A] = {
.caps = HAS_INTEGRATED_BUTTON,
.tp_type = TYPE2,
.tp_button = BUTTON_TYPE2,
.tp_offset = FINGER_TYPE2,
.tp_fsize = FSIZE_TYPE2,
.tp_delta = 0,
.iface_index = 0,
.um_size = 8,
.um_req_val = 0x03,
.um_req_idx = 0x00,
.um_switch_idx = 0,
.um_switch_on = 0x01,
.um_switch_off = 0x08,
},
[WSP_FLAG_WELLSPRING5] = {
.caps = HAS_INTEGRATED_BUTTON,
.tp_type = TYPE2,
.tp_button = BUTTON_TYPE2,
.tp_offset = FINGER_TYPE2,
.tp_fsize = FSIZE_TYPE2,
.tp_delta = 0,
.iface_index = 0,
.um_size = 8,
.um_req_val = 0x03,
.um_req_idx = 0x00,
.um_switch_idx = 0,
.um_switch_on = 0x01,
.um_switch_off = 0x08,
},
[WSP_FLAG_WELLSPRING6] = {
.caps = HAS_INTEGRATED_BUTTON,
.tp_type = TYPE2,
.tp_button = BUTTON_TYPE2,
.tp_offset = FINGER_TYPE2,
.tp_fsize = FSIZE_TYPE2,
.tp_delta = 0,
.iface_index = 0,
.um_size = 8,
.um_req_val = 0x03,
.um_req_idx = 0x00,
.um_switch_idx = 0,
.um_switch_on = 0x01,
.um_switch_off = 0x08,
},
[WSP_FLAG_WELLSPRING5A] = {
.caps = HAS_INTEGRATED_BUTTON,
.tp_type = TYPE2,
.tp_button = BUTTON_TYPE2,
.tp_offset = FINGER_TYPE2,
.tp_fsize = FSIZE_TYPE2,
.tp_delta = 0,
.iface_index = 0,
.um_size = 8,
.um_req_val = 0x03,
.um_req_idx = 0x00,
.um_switch_idx = 0,
.um_switch_on = 0x01,
.um_switch_off = 0x08,
},
[WSP_FLAG_WELLSPRING6A] = {
.caps = HAS_INTEGRATED_BUTTON,
.tp_type = TYPE2,
.tp_button = BUTTON_TYPE2,
.tp_offset = FINGER_TYPE2,
.tp_fsize = FSIZE_TYPE2,
.tp_delta = 0,
.um_size = 8,
.um_req_val = 0x03,
.um_req_idx = 0x00,
.um_switch_idx = 0,
.um_switch_on = 0x01,
.um_switch_off = 0x08,
},
[WSP_FLAG_WELLSPRING7] = {
.caps = HAS_INTEGRATED_BUTTON,
.tp_type = TYPE2,
.tp_button = BUTTON_TYPE2,
.tp_offset = FINGER_TYPE2,
.tp_fsize = FSIZE_TYPE2,
.tp_delta = 0,
.iface_index = 0,
.um_size = 8,
.um_req_val = 0x03,
.um_req_idx = 0x00,
.um_switch_idx = 0,
.um_switch_on = 0x01,
.um_switch_off = 0x08,
},
[WSP_FLAG_WELLSPRING7A] = {
.caps = HAS_INTEGRATED_BUTTON,
.tp_type = TYPE2,
.tp_button = BUTTON_TYPE2,
.tp_offset = FINGER_TYPE2,
.tp_fsize = FSIZE_TYPE2,
.tp_delta = 0,
.iface_index = 0,
.um_size = 8,
.um_req_val = 0x03,
.um_req_idx = 0x00,
.um_switch_idx = 0,
.um_switch_on = 0x01,
.um_switch_off = 0x08,
},
[WSP_FLAG_WELLSPRING8] = {
.caps = HAS_INTEGRATED_BUTTON,
.tp_type = TYPE3,
.tp_button = BUTTON_TYPE3,
.tp_offset = FINGER_TYPE3,
.tp_fsize = FSIZE_TYPE3,
.tp_delta = 0,
.iface_index = 0,
.um_size = 8,
.um_req_val = 0x03,
.um_req_idx = 0x00,
.um_switch_idx = 0,
.um_switch_on = 0x01,
.um_switch_off = 0x08,
},
[WSP_FLAG_WELLSPRING9] = {
.caps = HAS_INTEGRATED_BUTTON,
.tp_type = TYPE4,
.tp_button = BUTTON_TYPE4,
.tp_offset = FINGER_TYPE4,
.tp_fsize = FSIZE_TYPE4,
.tp_delta = 2,
.iface_index = 2,
.um_size = 2,
.um_req_val = 0x03,
.um_req_idx = 0x02,
.um_switch_idx = 1,
.um_switch_on = 0x01,
.um_switch_off = 0x00,
},
};
@ -346,7 +499,7 @@ static const STRUCT_USB_HOST_ID wsp_devs[] = {
WSP_DEV(APPLE, WELLSPRING5A_JIS, WSP_FLAG_WELLSPRING5A),
/* MacbookPro10,1 (unibody, June 2012) */
/* MacbookPro11,? (unibody, June 2013) */
/* MacbookPro11,1-3 (unibody, June 2013) */
WSP_DEV(APPLE, WELLSPRING7_ANSI, WSP_FLAG_WELLSPRING7),
WSP_DEV(APPLE, WELLSPRING7_ISO, WSP_FLAG_WELLSPRING7),
WSP_DEV(APPLE, WELLSPRING7_JIS, WSP_FLAG_WELLSPRING7),
@ -360,6 +513,11 @@ static const STRUCT_USB_HOST_ID wsp_devs[] = {
WSP_DEV(APPLE, WELLSPRING8_ANSI, WSP_FLAG_WELLSPRING8),
WSP_DEV(APPLE, WELLSPRING8_ISO, WSP_FLAG_WELLSPRING8),
WSP_DEV(APPLE, WELLSPRING8_JIS, WSP_FLAG_WELLSPRING8),
/* MacbookPro12,1 MacbookPro11,4 */
WSP_DEV(APPLE, WELLSPRING9_ANSI, WSP_FLAG_WELLSPRING9),
WSP_DEV(APPLE, WELLSPRING9_ISO, WSP_FLAG_WELLSPRING9),
WSP_DEV(APPLE, WELLSPRING9_JIS, WSP_FLAG_WELLSPRING9),
};
#define WSP_FIFO_BUF_SIZE 8 /* bytes */
@ -421,11 +579,6 @@ struct wsp_softc {
uint8_t tp_data[WSP_BUFFER_MAX] __aligned(4); /* trackpad transferred data */
};
typedef enum interface_mode {
RAW_SENSOR_MODE = 0x01,
HID_MODE = 0x08
} interface_mode;
/*
* function prototypes
*/
@ -473,14 +626,19 @@ static const struct usb_config wsp_config[WSP_N_TRANSFER] = {
};
static usb_error_t
wsp_set_device_mode(struct wsp_softc *sc, interface_mode mode)
wsp_set_device_mode(struct wsp_softc *sc, uint8_t on)
{
const struct wsp_dev_params *params = sc->sc_params;
uint8_t mode_bytes[8];
usb_error_t err;
/* Type 3 does not require a mode switch */
if (params->tp_type == TYPE3)
return 0;
err = usbd_req_get_report(sc->sc_usb_device, NULL,
mode_bytes, sizeof(mode_bytes), 0,
0x03, 0x00);
mode_bytes, params->um_size, params->iface_index,
params->um_req_val, params->um_req_idx);
if (err != USB_ERR_NORMAL_COMPLETION) {
DPRINTF("Failed to read device mode (%d)\n", err);
@ -495,11 +653,12 @@ wsp_set_device_mode(struct wsp_softc *sc, interface_mode mode)
*/
pause("WHW", hz / 4);
mode_bytes[0] = mode;
mode_bytes[params->um_switch_idx] =
on ? params->um_switch_on : params->um_switch_off;
return (usbd_req_set_report(sc->sc_usb_device, NULL,
mode_bytes, sizeof(mode_bytes), 0,
0x03, 0x00));
mode_bytes, params->um_size, params->iface_index,
params->um_req_val, params->um_req_idx));
}
static int
@ -524,17 +683,29 @@ static int
wsp_probe(device_t self)
{
struct usb_attach_arg *uaa = device_get_ivars(self);
struct usb_interface_descriptor *id;
struct usb_interface *iface;
uint8_t i;
if (uaa->usb_mode != USB_MODE_HOST)
return (ENXIO);
if (uaa->info.bIfaceIndex != WSP_IFACE_INDEX)
/* figure out first interface matching */
for (i = 1;; i++) {
iface = usbd_get_iface(uaa->device, i);
if (iface == NULL || i == 3)
return (ENXIO);
id = iface->idesc;
if ((id == NULL) ||
(id->bInterfaceClass != UICLASS_HID) ||
(id->bInterfaceProtocol != 0 &&
id->bInterfaceProtocol != UIPROTO_MOUSE))
continue;
break;
}
/* check if we are attaching to the first match */
if (uaa->info.bIfaceIndex != i)
return (ENXIO);
if ((uaa->info.bInterfaceClass != UICLASS_HID) ||
(uaa->info.bInterfaceProtocol != 0))
return (ENXIO);
return (usbd_lookup_id_by_uaa(wsp_devs, sizeof(wsp_devs), uaa));
}
@ -569,6 +740,9 @@ wsp_attach(device_t dev)
sc->sc_usb_device = uaa->device;
/* get device specific configuration */
sc->sc_params = wsp_dev_params + USB_GET_DRIVER_INFO(uaa);
/*
* By default the touchpad behaves like a HID device, sending
* packets with reportID = 8. Such reports contain only
@ -584,13 +758,13 @@ wsp_attach(device_t dev)
* device back into HID mode before switching it to RAW
* mode. Else the device does not work like expected.
*/
err = wsp_set_device_mode(sc, HID_MODE);
err = wsp_set_device_mode(sc, 0);
if (err != USB_ERR_NORMAL_COMPLETION) {
DPRINTF("Failed to set mode to HID MODE (%d)\n", err);
return (ENXIO);
}
err = wsp_set_device_mode(sc, RAW_SENSOR_MODE);
err = wsp_set_device_mode(sc, 1);
if (err != USB_ERR_NORMAL_COMPLETION) {
DPRINTF("failed to set mode to RAW MODE (%d)\n", err);
return (ENXIO);
@ -598,9 +772,6 @@ wsp_attach(device_t dev)
mtx_init(&sc->sc_mutex, "wspmtx", NULL, MTX_DEF | MTX_RECURSE);
/* get device specific configuration */
sc->sc_params = wsp_dev_params + USB_GET_DRIVER_INFO(uaa);
err = usbd_transfer_setup(uaa->device,
&uaa->info.bIfaceIndex, sc->sc_xfer, wsp_config,
WSP_N_TRANSFER, sc, &sc->sc_mutex);
@ -642,7 +813,7 @@ wsp_detach(device_t dev)
{
struct wsp_softc *sc = device_get_softc(dev);
(void) wsp_set_device_mode(sc, HID_MODE);
(void) wsp_set_device_mode(sc, 0);
mtx_lock(&sc->sc_mutex);
if (sc->sc_state & WSP_ENABLED)
@ -692,6 +863,13 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error)
pc = usbd_xfer_get_frame(xfer, 0);
usbd_copy_out(pc, 0, sc->tp_data, len);
if ((len < params->tp_offset + params->tp_fsize) ||
((len - params->tp_offset) % params->tp_fsize) != 0) {
DPRINTFN(WSP_LLEVEL_INFO, "Invalid length: %d, %x, %x\n",
len, sc->tp_data[0], sc->tp_data[1]);
goto tr_setup;
}
if (len < sc->tp_datalen) {
/* make sure we don't process old data */
memset(sc->tp_data + len, 0, sc->tp_datalen - len);
@ -699,12 +877,9 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error)
h = (struct tp_header *)(sc->tp_data);
if (params->tp_type == TYPE2) {
ibt = sc->tp_data[BUTTON_TYPE2];
ntouch = sc->tp_data[BUTTON_TYPE2 - 1];
} else if (params->tp_type == TYPE3) {
ibt = sc->tp_data[BUTTON_TYPE3];
ntouch = sc->tp_data[BUTTON_TYPE3 - 1];
if (params->tp_type >= TYPE2) {
ibt = sc->tp_data[params->tp_button];
ntouch = sc->tp_data[params->tp_button - 1];
}
/* range check */
if (ntouch < 0)
@ -712,33 +887,33 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error)
else if (ntouch > MAX_FINGERS)
ntouch = MAX_FINGERS;
f = (struct tp_finger *)(sc->tp_data + params->tp_offset);
for (i = 0; i != ntouch; i++) {
f = (struct tp_finger *)(sc->tp_data + params->tp_offset + params->tp_delta + i * params->tp_fsize);
/* swap endianness, if any */
if (le16toh(0x1234) != 0x1234) {
f[i].origin = le16toh((uint16_t)f[i].origin);
f[i].abs_x = le16toh((uint16_t)f[i].abs_x);
f[i].abs_y = le16toh((uint16_t)f[i].abs_y);
f[i].rel_x = le16toh((uint16_t)f[i].rel_x);
f[i].rel_y = le16toh((uint16_t)f[i].rel_y);
f[i].tool_major = le16toh((uint16_t)f[i].tool_major);
f[i].tool_minor = le16toh((uint16_t)f[i].tool_minor);
f[i].orientation = le16toh((uint16_t)f[i].orientation);
f[i].touch_major = le16toh((uint16_t)f[i].touch_major);
f[i].touch_minor = le16toh((uint16_t)f[i].touch_minor);
f[i].multi = le16toh((uint16_t)f[i].multi);
f->origin = le16toh((uint16_t)f->origin);
f->abs_x = le16toh((uint16_t)f->abs_x);
f->abs_y = le16toh((uint16_t)f->abs_y);
f->rel_x = le16toh((uint16_t)f->rel_x);
f->rel_y = le16toh((uint16_t)f->rel_y);
f->tool_major = le16toh((uint16_t)f->tool_major);
f->tool_minor = le16toh((uint16_t)f->tool_minor);
f->orientation = le16toh((uint16_t)f->orientation);
f->touch_major = le16toh((uint16_t)f->touch_major);
f->touch_minor = le16toh((uint16_t)f->touch_minor);
f->pressure = le16toh((uint16_t)f->pressure);
f->multi = le16toh((uint16_t)f->multi);
}
DPRINTFN(WSP_LLEVEL_INFO, "[%d]ibt=%d, taps=%d, u=%x, o=%4d, ax=%5d, ay=%5d, "
"rx=%5d, ry=%5d, tlmaj=%4d, tlmin=%4d, ot=%5d, tchmaj=%4d, tchmin=%4d, m=%4x\n",
i, ibt, ntouch, h->q2,
f[i].origin, f[i].abs_x, f[i].abs_y, f[i].rel_x, f[i].rel_y,
f[i].tool_major, f[i].tool_minor, f[i].orientation,
f[i].touch_major, f[i].touch_minor, f[i].multi);
sc->pos_x[i] = f[i].abs_x;
sc->pos_y[i] = -f[i].abs_y;
sc->index[i] = &f[i];
DPRINTFN(WSP_LLEVEL_INFO,
"[%d]ibt=%d, taps=%d, o=%4d, ax=%5d, ay=%5d, "
"rx=%5d, ry=%5d, tlmaj=%4d, tlmin=%4d, ot=%4x, "
"tchmaj=%4d, tchmin=%4d, presure=%4d, m=%4x\n",
i, ibt, ntouch, f->origin, f->abs_x, f->abs_y,
f->rel_x, f->rel_y, f->tool_major, f->tool_minor, f->orientation,
f->touch_major, f->touch_minor, f->pressure, f->multi);
sc->pos_x[i] = f->abs_x;
sc->pos_y[i] = -f->abs_y;
sc->index[i] = f;
}
sc->sc_status.flags &= ~MOUSE_POSCHANGED;
@ -750,24 +925,24 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error)
sc->sc_status.button |= MOUSE_BUTTON1DOWN;
sc->ibtn = 1;
}
if (h->q2 == 4)
sc->intr_count++;
sc->intr_count++;
if (sc->ntaps < ntouch) {
switch (ntouch) {
case 1:
if (f[0].touch_major > tun.pressure_tap_threshold)
if (sc->index[0]->touch_major > tun.pressure_tap_threshold &&
sc->index[0]->tool_major <= 1200)
sc->ntaps = 1;
break;
case 2:
if (f[0].touch_major > tun.pressure_tap_threshold &&
f[1].touch_major > tun.pressure_tap_threshold)
if (sc->index[0]->touch_major > tun.pressure_tap_threshold-30 &&
sc->index[1]->touch_major > tun.pressure_tap_threshold-30)
sc->ntaps = 2;
break;
case 3:
if (f[0].touch_major > tun.pressure_tap_threshold &&
f[1].touch_major > tun.pressure_tap_threshold &&
f[2].touch_major > tun.pressure_tap_threshold)
if (sc->index[0]->touch_major > tun.pressure_tap_threshold-40 &&
sc->index[1]->touch_major > tun.pressure_tap_threshold-40 &&
sc->index[2]->touch_major > tun.pressure_tap_threshold-40)
sc->ntaps = 3;
break;
default:
@ -779,7 +954,7 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error)
abs(sc->pos_x[0] - sc->pos_x[1]),
abs(sc->pos_y[0] - sc->pos_y[1])));
}
if (f[0].touch_major < tun.pressure_untouch_threshold &&
if (sc->index[0]->touch_major < tun.pressure_untouch_threshold &&
sc->sc_status.button == 0) {
sc->sc_touch = WSP_UNTOUCH;
if (sc->intr_count < WSP_TAP_MAX_COUNT &&
@ -840,10 +1015,10 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error)
sc->rdy = 0;
sc->rdz = 0;
sc->scr_mode = WSP_SCR_NONE;
} else if (f[0].touch_major >= tun.pressure_touch_threshold &&
} else if (sc->index[0]->touch_major >= tun.pressure_touch_threshold &&
sc->sc_touch == WSP_UNTOUCH) { /* ignore first touch */
sc->sc_touch = WSP_FIRST_TOUCH;
} else if (f[0].touch_major >= tun.pressure_touch_threshold &&
} else if (sc->index[0]->touch_major >= tun.pressure_touch_threshold &&
sc->sc_touch == WSP_FIRST_TOUCH) { /* ignore second touch */
sc->sc_touch = WSP_SECOND_TOUCH;
DPRINTFN(WSP_LLEVEL_INFO, "Fist pre_x=%5d, pre_y=%5d\n",
@ -853,22 +1028,26 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error)
sc->sc_touch = WSP_TOUCHING;
if (ntouch != 0 &&
h->q2 == 4 &&
f[0].touch_major >= tun.pressure_touch_threshold) {
sc->index[0]->touch_major >= tun.pressure_touch_threshold) {
dx = sc->pos_x[0] - sc->pre_pos_x;
dy = sc->pos_y[0] - sc->pre_pos_y;
/* Ignore movement from ibt=1 to ibt=0 */
if (sc->sc_status.obutton != 0 &&
sc->sc_status.button == 0) {
dx = 0;
dy = 0;
}
/* Ignore movement during button is releasing */
if (sc->ibtn != 0 && sc->sc_status.button == 0)
dx = dy = 0;
/* Ignore movement if ntouch changed */
if (sc->o_ntouch != ntouch) {
dx = 0;
dy = 0;
}
if (sc->o_ntouch != ntouch)
dx = dy = 0;
/* Ignore unexpeted movment when typing */
if (ntouch == 1 && sc->index[0]->tool_major > 1200)
dx = dy = 0;
if (sc->ibtn != 0 && ntouch == 1 &&
sc->intr_count < WSP_TAP_MAX_COUNT &&
abs(sc->dx_sum) < 1 && abs(sc->dy_sum) < 1 )
dx = dy = 0;
if (ntouch == 2 && sc->sc_status.button != 0) {
dx = sc->pos_x[sc->finger] - sc->pre_pos_x;
@ -878,26 +1057,23 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error)
* Ignore movement of switch finger or
* movement from ibt=0 to ibt=1
*/
if (f[0].origin == 0 || f[1].origin == 0 ||
if (sc->index[0]->origin == 0 || sc->index[1]->origin == 0 ||
sc->sc_status.obutton != sc->sc_status.button) {
dx = 0;
dy = 0;
dx = dy = 0;
sc->finger = 0;
}
if ((abs(f[0].rel_x) + abs(f[0].rel_y)) <
(abs(f[1].rel_x) + abs(f[1].rel_y)) &&
if ((abs(sc->index[0]->rel_x) + abs(sc->index[0]->rel_y)) <
(abs(sc->index[1]->rel_x) + abs(sc->index[1]->rel_y)) &&
sc->finger == 0) {
sc->sc_touch = WSP_SECOND_TOUCH;
dx = 0;
dy = 0;
dx = dy = 0;
sc->finger = 1;
}
if ((abs(f[0].rel_x) + abs(f[0].rel_y)) >=
(abs(f[1].rel_x) + abs(f[1].rel_y)) &&
if ((abs(sc->index[0]->rel_x) + abs(sc->index[0]->rel_y)) >=
(abs(sc->index[1]->rel_x) + abs(sc->index[1]->rel_y)) &&
sc->finger == 1) {
sc->sc_touch = WSP_SECOND_TOUCH;
dx = 0;
dy = 0;
dx = dy = 0;
sc->finger = 0;
}
DPRINTFN(WSP_LLEVEL_INFO, "dx=%5d, dy=%5d, mov=%5d\n",
@ -926,8 +1102,7 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error)
if (sc->scr_mode == WSP_SCR_NONE &&
abs(sc->dx_sum) + abs(sc->dy_sum) > tun.scr_hor_threshold)
sc->scr_mode = abs(sc->dx_sum) >
abs(sc->dy_sum) * 3 ? WSP_SCR_HOR :
WSP_SCR_VER;
abs(sc->dy_sum) * 2 ? WSP_SCR_HOR : WSP_SCR_VER;
DPRINTFN(WSP_LLEVEL_INFO, "scr_mode=%5d, count=%d, dx_sum=%d, dy_sum=%d\n",
sc->scr_mode, sc->intr_count, sc->dx_sum, sc->dy_sum);
if (sc->scr_mode == WSP_SCR_HOR)
@ -935,8 +1110,7 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error)
else
sc->dt_sum = 0;
dx = 0;
dy = 0;
dx = dy = 0;
if (sc->dz_count == 0)
dz = sc->dz_sum / tun.z_factor;
if (sc->scr_mode == WSP_SCR_HOR ||
@ -944,15 +1118,12 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error)
abs(sc->pos_y[0] - sc->pos_y[1]) > MAX_DISTANCE)
dz = 0;
}
if (ntouch == 3) {
dx = 0;
dy = 0;
dz = 0;
}
if (sc->intr_count < WSP_TAP_MAX_COUNT &&
abs(dx) < 3 && abs(dy) < 3 && abs(dz) < 3) {
if (ntouch == 3)
dx = dy = dz = 0;
} else
if (sc->intr_count < WSP_TAP_MAX_COUNT &&
abs(dx) < 3 && abs(dy) < 3 && abs(dz) < 3)
dx = dy = dz = 0;
else
sc->intr_count = WSP_TAP_MAX_COUNT;
if (dx || dy || dz)
sc->sc_status.flags |= MOUSE_POSCHANGED;

View File

@ -1131,6 +1131,10 @@ product APPLE WELLSPRING7A_JIS 0x025b Apple Internal Keyboard/Trackpad
product APPLE WELLSPRING8_ANSI 0x0290 Apple Internal Keyboard/Trackpad
product APPLE WELLSPRING8_ISO 0x0291 Apple Internal Keyboard/Trackpad
product APPLE WELLSPRING8_JIS 0x0292 Apple Internal Keyboard/Trackpad
/* MacbookPro12,1 */
product APPLE WELLSPRING9_ANSI 0x0272 Apple Internal Keyboard/Trackpad
product APPLE WELLSPRING9_ISO 0x0273 Apple Internal Keyboard/Trackpad
product APPLE WELLSPRING9_JIS 0x0274 Apple Internal Keyboard/Trackpad
product APPLE MOUSE 0x0301 Mouse M4848
product APPLE OPTMOUSE 0x0302 Optical mouse
product APPLE MIGHTYMOUSE 0x0304 Mighty Mouse