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:
parent
87101cb572
commit
fcc75f06aa
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user