64#include <sys/stdint.h>
65#include <sys/stddef.h>
69#include <sys/kernel.h>
71#include <sys/module.h>
74#include <sys/sysctl.h>
75#include <sys/malloc.h>
79#include <sys/selinfo.h>
82#include <dev/hid/hid.h>
91#define USB_DEBUG_VAR atp_debug
96#define ATP_DRIVER_NAME "atp"
104#ifndef ATP_SCALE_FACTOR
105#define ATP_SCALE_FACTOR 16
109#ifndef ATP_SMALL_MOVEMENT_THRESHOLD
110#define ATP_SMALL_MOVEMENT_THRESHOLD 30
114#ifndef ATP_FAST_MOVEMENT_TRESHOLD
115#define ATP_FAST_MOVEMENT_TRESHOLD 150
122#ifndef ATP_TOUCH_TIMEOUT
123#define ATP_TOUCH_TIMEOUT 125000
126#ifndef ATP_IDLENESS_THRESHOLD
127#define ATP_IDLENESS_THRESHOLD 10
130#ifndef FG_SENSOR_NOISE_THRESHOLD
131#define FG_SENSOR_NOISE_THRESHOLD 2
141#ifndef ATP_DOUBLE_TAP_N_DRAG_THRESHOLD
142#define ATP_DOUBLE_TAP_N_DRAG_THRESHOLD 200000
149#define ATP_ZOMBIE_STROKE_REAP_INTERVAL (hz / 20)
152#define FG_SCALE_FACTOR 380
159#define FG_MAX_DELTA_MICKEYS ((3 * (FG_SCALE_FACTOR)) >> 1)
162#ifndef WSP_MAX_ALLOWED_MATCH_DISTANCE_SQ
163#define WSP_MAX_ALLOWED_MATCH_DISTANCE_SQ 1000000
167#define FG_PSPAN_MIN_CUM_PRESSURE 10
170#define FG_PSPAN_MAX_WIDTH 4
175static SYSCTL_NODE(_hw_usb, OID_AUTO, atp, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
180 ATP_LLEVEL_DISABLED = 0,
185static int atp_debug = ATP_LLEVEL_ERROR;
187 &atp_debug, ATP_LLEVEL_ERROR,
"ATP debug level");
195SYSCTL_UINT(_hw_usb_atp, OID_AUTO, double_tap_threshold, CTLFLAG_RWTUN,
197 "maximum time in microseconds to allow association between a double-tap and "
203 CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
206 "movement scale factor");
211 "the small movement black-hole for filtering noise");
223SYSCTL_UINT(_hw_usb_atp, OID_AUTO, slide_min_movement, CTLFLAG_RWTUN,
225 "strokes with at least this amt. of movement are considered slides");
232SYSCTL_UINT(_hw_usb_atp, OID_AUTO, stroke_maturity_threshold, CTLFLAG_RWTUN,
234 "the minimum age of a stroke for it to be considered mature");
286#define ENCODE_DRIVER_INFO(FAMILY, PROD) \
287 (((FAMILY) << N_PROD_BITS) | (PROD))
288#define DECODE_FAMILY_FROM_DRIVER_INFO(INFO) ((INFO) >> N_PROD_BITS)
289#define DECODE_PRODUCT_FROM_DRIVER_INFO(INFO) \
290 ((INFO) & ((1 << N_PROD_BITS) - 1))
292#define FG_DRIVER_INFO(PRODUCT) \
293 ENCODE_DRIVER_INFO(TRACKPAD_FAMILY_FOUNTAIN_GEYSER, PRODUCT)
294#define WELLSPRING_DRIVER_INFO(PRODUCT) \
295 ENCODE_DRIVER_INFO(TRACKPAD_FAMILY_WELLSPRING, PRODUCT)
310#define FG_MAX_PSPANS_PER_AXIS 3
311#define FG_MAX_STROKES (2 * FG_MAX_PSPANS_PER_AXIS)
313#define WELLSPRING_INTERFACE_INDEX 1
316#define WSP_TYPE1_FINGER_DATA_OFFSET (13 * 2)
317#define WSP_TYPE2_FINGER_DATA_OFFSET (15 * 2)
318#define WSP_TYPE3_FINGER_DATA_OFFSET (19 * 2)
321#define WSP_TYPE2_BUTTON_DATA_OFFSET 15
322#define WSP_TYPE3_BUTTON_DATA_OFFSET 23
325#define HAS_INTEGRATED_BUTTON 1
352#define WSP_MAX_FINGERS 16
353#define WSP_SIZEOF_FINGER_SENSOR_DATA sizeof(struct wsp_finger_sensor_data)
354#define WSP_SIZEOF_ALL_FINGER_DATA (WSP_MAX_FINGERS * \
355 WSP_SIZEOF_FINGER_SENSOR_DATA)
356#define WSP_MAX_FINGER_ORIENTATION 16384
358#define ATP_SENSOR_DATA_BUF_MAX 1024
359#if (ATP_SENSOR_DATA_BUF_MAX < ((WSP_MAX_FINGERS * 14 * 2) + \
360 WSP_TYPE3_FINGER_DATA_OFFSET))
362#error "ATP_SENSOR_DATA_BUF_MAX is too small"
365#define ATP_MAX_STROKES MAX(WSP_MAX_FINGERS, FG_MAX_STROKES)
367#define FG_MAX_XSENSORS 26
368#define FG_MAX_YSENSORS 16
516#define ATP_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
593#define ATP_FIFO_BUF_SIZE 8
594#define ATP_FIFO_QUEUE_MAXLEN 50
621#define ATSF_ZOMBIE 0x1
624 struct timeval ctime;
639 int instantaneous_dx;
640 int instantaneous_dy;
677#define ATP_ENABLED 0x01
678#define ATP_ZOMBIES_EXIST 0x02
679#define ATP_DOUBLE_TAP_DRAG 0x04
680#define ATP_VALID 0x08
692 struct callout sc_callout;
706 struct timeval sc_touch_reap_time;
711 u_int sc_expected_sensor_data_len;
836 pstroke = TAILQ_FIRST(&sc->sc_stroke_free);
840 TAILQ_REMOVE(&sc->sc_stroke_free, pstroke, entry);
841 memset(pstroke, 0,
sizeof(*pstroke));
842 TAILQ_INSERT_TAIL(&sc->sc_stroke_used, pstroke, entry);
857 TAILQ_REMOVE(&sc->sc_stroke_used, pstroke, entry);
858 TAILQ_INSERT_TAIL(&sc->sc_stroke_free, pstroke, entry);
866 TAILQ_INIT(&sc->sc_stroke_free);
867 TAILQ_INIT(&sc->sc_stroke_used);
869 sc->sc_n_strokes = 0;
890 mode_value = (uint8_t)0x04;
892 mode_value = newMode;
898 DPRINTF(
"Failed to read device mode (%d)\n", err);
911 pause(
"WHW", hz / 4);
938 (uint8_t)0x03 , (uint8_t)0x00 );
972 DPRINTFN(ATP_LLEVEL_INFO,
"enabled atp\n");
980 DPRINTFN(ATP_LLEVEL_INFO,
"disabled atp\n");
994 sc->sc_cur_x, params->
prot);
996 sc->sc_cur_y, params->
prot);
1004 status_bits = sc->sc_sensor_data[params->
data_len - 1];
1009 memcpy(sc->sc_base_x, sc->sc_cur_x,
1010 params->
n_xsensors *
sizeof(*sc->sc_base_x));
1011 memcpy(sc->sc_base_y, sc->sc_cur_y,
1012 params->
n_ysensors *
sizeof(*sc->sc_base_y));
1029 if (
fg_update_strokes(sc, sc->sc_pspans_x, n_xpspans, sc->sc_pspans_y, n_ypspans))
1030 sc->
sc_status.flags |= MOUSE_POSCHANGED;
1042 if ((sc->
sc_status.flags == 0) && (sc->sc_n_strokes == 0)) {
1053 DPRINTFN(ATP_LLEVEL_INFO,
"idle\n");
1056 memcpy(sc->sc_base_x, sc->sc_cur_x,
1057 params->
n_xsensors *
sizeof(*(sc->sc_base_x)));
1058 memcpy(sc->sc_base_y, sc->sc_cur_y,
1059 params->
n_ysensors *
sizeof(*(sc->sc_base_y)));
1062 sc->sc_idlecount = 0;
1066 sc->sc_idlecount = 0;
1109 for (i = 0, di = (axis ==
Y) ? 1 : 2; i < 8; di += 5, i++) {
1110 arr[i] = sensor_data[di];
1111 arr[i+8] = sensor_data[di+2];
1112 if ((axis ==
X) && (num > 16))
1113 arr[i+16] = sensor_data[di+40];
1118 for (i = 0, di = (axis ==
Y) ? 1 : 19; i < num; ) {
1119 arr[i++] = sensor_data[di++];
1120 arr[i++] = sensor_data[di++];
1126 for (i = 0, di = (axis ==
Y) ? 2 : 20; i < num; ) {
1127 arr[i++] = sensor_data[di++];
1128 arr[i++] = sensor_data[di++];
1142 for (i = 0; i <
n; i++) {
1143 p[i] = cur[i] - base[i];
1171 u_int num_spans = 0;
1173 enum fg_pspan_state {
1175 ATP_PSPAN_INCREASING,
1176 ATP_PSPAN_DECREASING,
1183 memset(spans, 0, max_spans *
sizeof(
fg_pspan));
1185 state = ATP_PSPAN_INACTIVE;
1186 for (i = 0; i < num_sensors; i++) {
1187 if (num_spans >= max_spans)
1191 if (
state == ATP_PSPAN_INACTIVE) {
1198 state = ATP_PSPAN_INACTIVE;
1204 case ATP_PSPAN_INACTIVE:
1205 state = ATP_PSPAN_INCREASING;
1209 case ATP_PSPAN_INCREASING:
1212 else if (p[i] <= (maxp >> 1))
1213 state = ATP_PSPAN_DECREASING;
1216 case ATP_PSPAN_DECREASING:
1217 if (p[i] > p[i - 1]) {
1228 state = ATP_PSPAN_INACTIVE;
1237 spans[num_spans].
width++;
1238 spans[num_spans].
cum += p[i];
1239 spans[num_spans].
cog += p[i] * (i + 1);
1242 if (
state != ATP_PSPAN_INACTIVE)
1246 for (i = 0; i < num_spans; i++) {
1250 if ((i + 1) < num_spans) {
1251 memcpy(&spans[i], &spans[i + 1],
1252 (num_spans - i - 1) *
sizeof(
fg_pspan));
1266 *nspans_p = num_spans;
1275 u_int n_source_fingers;
1280 if ((data_len < params->finger_data_offset) ||
1297 for (i = 0; i < n_source_fingers; i++, source_fingerp++) {
1299 if (le16toh(0x1234) != 0x1234) {
1300 source_fingerp->
origin = le16toh((uint16_t)source_fingerp->
origin);
1301 source_fingerp->
abs_x = le16toh((uint16_t)source_fingerp->
abs_x);
1302 source_fingerp->
abs_y = le16toh((uint16_t)source_fingerp->
abs_y);
1303 source_fingerp->
rel_x = le16toh((uint16_t)source_fingerp->
rel_x);
1304 source_fingerp->
rel_y = le16toh((uint16_t)source_fingerp->
rel_y);
1310 source_fingerp->
multi = le16toh((uint16_t)source_fingerp->
multi);
1317 fingers[n_fingers].
matched =
false;
1318 fingers[n_fingers].
x = source_fingerp->
abs_x;
1319 fingers[n_fingers].
y = -source_fingerp->
abs_y;
1324 if ((sc->sc_n_strokes == 0) && (n_fingers == 0))
1328 sc->
sc_status.flags |= MOUSE_POSCHANGED;
1340 sc->
sc_status.button = sc->sc_ibtn ? MOUSE_BUTTON1DOWN : 0;
1354 delta_mickeys = pspan->
loc - component->
loc;
1359 component->
loc = pspan->
loc;
1394 fg_pspan *pspans, u_int n_pspans, u_int repeat_count)
1397 u_int repeat_index = 0;
1402 for (i = 0; i < n_pspans; i++) {
1403 if (pspans[i].cum > pspans[repeat_index].cum)
1408 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) {
1409 if (strokep->components[axis].matched)
1412 for (i = 0; i < n_pspans; i++) {
1413 if (pspans[i].matched)
1417 &strokep->components[axis], &pspans[i],
1420 strokep->components[axis].matched =
true;
1423 if ((repeat_count > 0) && (i == repeat_index))
1438 boolean_t movement =
false;
1443 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry)
1444 strokep->matched =
false;
1446 for (i = 0; i != n_fingers; i++) {
1450 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) {
1451 int instantaneous_dx;
1452 int instantaneous_dy;
1455 if (strokep->matched)
1458 instantaneous_dx = fingers[i].
x - strokep->x;
1459 instantaneous_dy = fingers[i].
y - strokep->y;
1463 (instantaneous_dx * instantaneous_dx) +
1464 (instantaneous_dy * instantaneous_dy);
1466 if (d_squared < least_distance_sq) {
1467 least_distance_sq = d_squared;
1468 strokep_best = strokep;
1472 strokep = strokep_best;
1474 if (strokep != NULL) {
1477 strokep->matched =
true;
1478 strokep->instantaneous_dx = fingers[i].
x - strokep->x;
1479 strokep->instantaneous_dy = fingers[i].
y - strokep->y;
1480 strokep->x = fingers[i].
x;
1481 strokep->y = fingers[i].
y;
1495 u_int n_xpspans,
fg_pspan *pspans_y, u_int n_ypspans)
1499 boolean_t movement =
false;
1500 u_int repeat_count = 0;
1505 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) {
1506 strokep->components[
X].matched =
false;
1507 strokep->components[
Y].matched =
false;
1544 repeat_count = abs(n_xpspans - n_ypspans);
1547 (((repeat_count != 0) && ((n_xpspans < n_ypspans))) ?
1550 (((repeat_count != 0) && (n_ypspans < n_xpspans)) ?
1554 TAILQ_FOREACH_SAFE(strokep, &sc->sc_stroke_used, entry, strokep_next) {
1555 if (strokep->components[
X].matched &&
1556 strokep->components[
Y].matched) {
1557 strokep->matched =
true;
1558 strokep->instantaneous_dx =
1559 strokep->components[
X].delta_mickeys;
1560 strokep->instantaneous_dy =
1561 strokep->components[
Y].delta_mickeys;
1574 for (i = 0; i < n_xpspans; i++) {
1575 if (pspans_x[i].matched ==
false)
break;
1577 for (j = 0; j < n_ypspans; j++) {
1578 if (pspans_y[j].matched ==
false)
break;
1580 if ((i < n_xpspans) && (j < n_ypspans)) {
1582 if (atp_debug >= ATP_LLEVEL_INFO) {
1583 printf(
"unmatched pspans:");
1584 for (; i < n_xpspans; i++) {
1585 if (pspans_x[i].matched)
1587 printf(
" X:[loc:%u,cum:%u]",
1588 pspans_x[i].loc, pspans_x[i].cum);
1590 for (; j < n_ypspans; j++) {
1591 if (pspans_y[j].matched)
1593 printf(
" Y:[loc:%u,cum:%u]",
1594 pspans_y[j].loc, pspans_y[j].cum);
1599 if ((n_xpspans == 1) && (n_ypspans == 1))
1604 pspans_y, n_ypspans);
1608 if (atp_debug >= ATP_LLEVEL_INFO) {
1609 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) {
1610 printf(
" %s%clc:%u,dm:%d,cum:%d,max:%d,%c"
1611 ",%clc:%u,dm:%d,cum:%d,max:%d,%c",
1614 strokep->components[
X].loc,
1615 strokep->components[
X].delta_mickeys,
1616 strokep->components[
X].cum_pressure,
1617 strokep->components[
X].max_cum_pressure,
1620 strokep->components[
Y].loc,
1621 strokep->components[
Y].delta_mickeys,
1622 strokep->components[
Y].cum_pressure,
1623 strokep->components[
Y].max_cum_pressure,
1626 if (TAILQ_FIRST(&sc->sc_stroke_used) != NULL)
1640 boolean_t movement =
false;
1645 if (sc->sc_n_strokes > 0) {
1647 sc, fingers, n_fingers);
1650 TAILQ_FOREACH_SAFE(strokep, &sc->sc_stroke_used, entry, strokep_next) {
1651 if (strokep->matched)
1658 for (i = 0; i != n_fingers; i++) {
1659 if (fingers[i].matched)
1675 if (strokep == NULL)
1684 strokep->matched =
false;
1685 microtime(&strokep->ctime);
1687 strokep->x = pspan_x->
loc;
1688 strokep->y = pspan_y->
loc;
1690 strokep->components[
X].loc = pspan_x->
loc;
1691 strokep->components[
X].cum_pressure = pspan_x->
cum;
1692 strokep->components[
X].max_cum_pressure = pspan_x->
cum;
1693 strokep->components[
X].matched =
true;
1695 strokep->components[
Y].loc = pspan_y->
loc;
1696 strokep->components[
Y].cum_pressure = pspan_y->
cum;
1697 strokep->components[
Y].max_cum_pressure = pspan_y->
cum;
1698 strokep->components[
Y].matched =
true;
1700 if (sc->sc_n_strokes > 1) {
1702 sc->
sc_state &= ~ATP_DOUBLE_TAP_DRAG;
1705 DPRINTFN(ATP_LLEVEL_INFO,
"[%u,%u], time: %u,%ld\n",
1706 strokep->components[
X].loc,
1707 strokep->components[
Y].loc,
1708 (u_int)strokep->ctime.tv_sec,
1709 (
unsigned long int)strokep->ctime.tv_usec);
1714 u_int n_xpspans,
fg_pspan *pspans_y, u_int n_ypspans)
1722 for (i = 0, nspans[
X] = 0; i < n_xpspans; i++) {
1723 if (pspans_x[i].matched ==
false) {
1724 spans[
X][nspans[
X]] = pspans_x[i];
1728 for (j = 0, nspans[
Y] = 0; j < n_ypspans; j++) {
1729 if (pspans_y[j].matched ==
false) {
1730 spans[
Y][nspans[
Y]] = pspans_y[j];
1735 if (nspans[
X] == nspans[
Y]) {
1737 for (i = 0, j = 0; (i < nspans[
X]) && (j < nspans[
Y]); i++, j++)
1743 u_int repeat_index = 0;
1745 repeat_axis = (nspans[
X] > nspans[
Y]) ?
Y :
X;
1746 repeat_count = abs(nspans[
X] - nspans[
Y]);
1747 for (i = 0; i < nspans[repeat_axis]; i++) {
1748 if (spans[repeat_axis][i].cum > cum) {
1750 cum = spans[repeat_axis][i].
cum;
1756 for (; (i < nspans[
X]) && (j < nspans[
Y]); i++, j++) {
1760 if (repeat_count > 0) {
1761 if ((repeat_axis ==
X) &&
1762 (repeat_index == i)) {
1765 }
else if ((repeat_axis ==
Y) &&
1766 (repeat_index == j)) {
1782 if (strokep == NULL)
1791 strokep->matched =
true;
1792 microtime(&strokep->ctime);
1794 strokep->x = fingerp->
x;
1795 strokep->y = fingerp->
y;
1798 if (sc->sc_n_strokes > 1)
1799 sc->
sc_state &= ~ATP_DOUBLE_TAP_DRAG;
1801 DPRINTFN(ATP_LLEVEL_INFO,
"[%d,%d]\n", strokep->x, strokep->y);
1806 boolean_t *movementp)
1810 strokep->flags &= ~ATSF_ZOMBIE;
1815 strokep->instantaneous_dx = 0;
1816 strokep->instantaneous_dy = 0;
1831 struct timeval tdiff;
1832 getmicrotime(&tdiff);
1833 if (timevalcmp(&tdiff, &strokep->ctime, >)) {
1834 timevalsub(&tdiff, &strokep->ctime);
1847 return (((u_int)abs(strokep->instantaneous_dx) <=
1849 ((u_int)abs(strokep->instantaneous_dy) <=
1862 strokep->pending_dx += strokep->instantaneous_dx;
1863 strokep->pending_dy += strokep->instantaneous_dy;
1865#define UPDATE_INSTANTANEOUS_AND_PENDING(I, P) \
1866 if (abs((P)) <= atp_small_movement_threshold) \
1876 (I) = (((I) + (atp_mickeys_scale_factor - 1)) / \
1877 atp_mickeys_scale_factor) * \
1878 atp_mickeys_scale_factor; \
1886 (P) -= ((I) << 1); \
1889 (P) = imax((P), 0); \
1897 (I) = (((I) - (atp_mickeys_scale_factor - 1)) / \
1898 atp_mickeys_scale_factor) * \
1899 atp_mickeys_scale_factor; \
1907 (P) -= ((I) << 1); \
1910 (P) = imin((P), 0); \
1915 strokep->pending_dx);
1917 strokep->pending_dy);
1937 strokep->pending_dx = 0;
1938 strokep->pending_dy = 0;
1942 strokep->movement_dx = (strokep->instantaneous_dx) /
1944 strokep->movement_dy = (strokep->instantaneous_dy) /
1949 strokep->movement_dx <<= 1;
1950 strokep->movement_dy <<= 1;
1953 strokep->cum_movement_x += strokep->movement_dx;
1954 strokep->cum_movement_y += strokep->movement_dy;
1956 return ((strokep->movement_dx != 0) || (strokep->movement_dy != 0));
1988 sc->
sc_state &= ~ATP_DOUBLE_TAP_DRAG;
1996 if (strokep->cum_movement_y == 0)
1998 return (abs(strokep->cum_movement_x / strokep->cum_movement_y) >= 4);
2006 if (strokep->cum_movement_x == 0)
2008 return (abs(strokep->cum_movement_y / strokep->cum_movement_x) >= 4);
2015 u_int8_t n_touches_reaped = 0;
2016 u_int8_t n_slides_reaped = 0;
2017 u_int8_t n_horizontal_scrolls = 0;
2018 u_int8_t n_vertical_scrolls = 0;
2019 int horizontal_scroll = 0;
2020 int vertical_scroll = 0;
2024 DPRINTFN(ATP_LLEVEL_INFO,
"\n");
2026 TAILQ_FOREACH_SAFE(strokep, &sc->sc_stroke_used, entry, strokep_next) {
2036 n_horizontal_scrolls++;
2037 horizontal_scroll += strokep->cum_movement_x;
2039 n_vertical_scrolls++;
2040 vertical_scroll += strokep->cum_movement_y;
2047 DPRINTFN(ATP_LLEVEL_INFO,
"reaped %u zombies\n",
2048 n_touches_reaped + n_slides_reaped);
2049 sc->
sc_state &= ~ATP_ZOMBIES_EXIST;
2052 if (sc->sc_ibtn != 0)
2055 if ((n_touches_reaped == 0) && (n_slides_reaped == 0))
2060 if (n_touches_reaped != 0) {
2064 switch (n_touches_reaped) {
2067 microtime(&sc->sc_touch_reap_time);
2081 }
else if ((n_slides_reaped == 2) && (n_horizontal_scrolls == 2)) {
2082 if (horizontal_scroll < 0)
2097 if ((sc->sc_n_strokes == 1) &&
2099 timevalcmp(&strokep->ctime, &sc->sc_touch_reap_time, >)) {
2100 struct timeval delta;
2101 struct timeval window = {
2106 delta = strokep->ctime;
2107 timevalsub(&delta, &sc->sc_touch_reap_time);
2108 if (timevalcmp(&delta, &window, <=))
2122 uint32_t buttons_in)
2124 uint32_t buttons_out;
2127 dx = imin(dx, 254); dx = imax(dx, -256);
2128 dy = imin(dy, 254); dy = imax(dy, -256);
2129 dz = imin(dz, 126); dz = imax(dz, -128);
2131 buttons_out = MOUSE_MSC_BUTTONS;
2132 if (buttons_in & MOUSE_BUTTON1DOWN)
2133 buttons_out &= ~MOUSE_MSC_BUTTON1UP;
2134 else if (buttons_in & MOUSE_BUTTON2DOWN)
2135 buttons_out &= ~MOUSE_MSC_BUTTON2UP;
2136 else if (buttons_in & MOUSE_BUTTON3DOWN)
2137 buttons_out &= ~MOUSE_MSC_BUTTON3UP;
2139 DPRINTFN(ATP_LLEVEL_INFO,
"dx=%d, dy=%d, buttons=%x\n",
2140 dx, dy, buttons_out);
2143 buf[0] = sc->
sc_mode.syncmask[1];
2144 buf[0] |= buttons_out;
2147 buf[3] = dx - (dx >> 1);
2148 buf[4] = dy - (dy >> 1);
2152 buf[6] = dz - (dz >> 1);
2153 buf[7] = (((~buttons_in) >> 3) & MOUSE_SYS_EXTBUTTONS);
2178 BUS_PROBE_DEFAULT : ENXIO);
2182 return (BUS_PROBE_DEFAULT);
2193 void *descriptor_ptr = NULL;
2194 uint16_t descriptor_len;
2197 DPRINTFN(ATP_LLEVEL_INFO,
"sc=%p\n", sc);
2209 sc->sc_expected_sensor_data_len = hid_report_size_max(descriptor_ptr,
2210 descriptor_len, hid_input, NULL);
2211 free(descriptor_ptr, M_TEMP);
2213 if ((sc->sc_expected_sensor_data_len <= 0) ||
2215 DPRINTF(
"atp_attach: datalength invalid or too large: %d\n",
2216 sc->sc_expected_sensor_data_len);
2236 DPRINTF(
"device mode switch skipped: Fountain device\n");
2238 DPRINTF(
"failed to set mode to 'RAW_SENSOR' (%d)\n", err);
2242 mtx_init(&sc->
sc_mutex,
"atpmtx", NULL, MTX_DEF | MTX_RECURSE);
2270 UID_ROOT, GID_OPERATOR, 0644)) {
2276 sc->
sc_hw.buttons = 3;
2277 sc->
sc_hw.iftype = MOUSE_IF_USB;
2278 sc->
sc_hw.type = MOUSE_PAD;
2279 sc->
sc_hw.model = MOUSE_MODEL_GENERIC;
2281 sc->
sc_mode.protocol = MOUSE_PROTO_MSC;
2284 sc->
sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
2285 sc->
sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
2286 sc->
sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
2293 callout_init_mtx(&sc->sc_callout, &sc->
sc_mutex, 0);
2307 sc = device_get_softc(dev);
2311 callout_drain(&sc->sc_callout);
2338 if (len < sc->sc_expected_sensor_data_len) {
2340 memset(sc->sc_sensor_data +
len, 0,
2341 sc->sc_expected_sensor_data_len -
len);
2344 sc->
sc_status.flags &= ~(MOUSE_STDBUTTONSCHANGED |
2352 sc->
sc_state &= ~ATP_DOUBLE_TAP_DRAG;
2355 sc->
sc_status.button = MOUSE_BUTTON1DOWN;
2360 if (sc->
sc_status.flags & MOUSE_STDBUTTONSCHANGED) {
2361 DPRINTFN(ATP_LLEVEL_INFO,
"button %s\n",
2362 ((sc->
sc_status.button & MOUSE_BUTTON1DOWN) ?
2363 "pressed" :
"released"));
2366 if (sc->
sc_status.flags & (MOUSE_POSCHANGED |
2367 MOUSE_STDBUTTONSCHANGED)) {
2369 u_int8_t n_movements = 0;
2374 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) {
2378 dx += strokep->movement_dx;
2379 dy += strokep->movement_dy;
2380 if (strokep->movement_dx ||
2381 strokep->movement_dy)
2386 if (n_movements > 1) {
2387 dx /= (int)n_movements;
2388 dy /= (int)n_movements;
2392 if (n_movements >= 2) {
2393 boolean_t all_vertical_scrolls =
true;
2394 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) {
2399 all_vertical_scrolls =
false;
2401 if (all_vertical_scrolls) {
2418 sc->sc_expected_sensor_data_len);
2480 if (fflags & FREAD) {
2487 sc->
sc_fflags |= (fflags & (FREAD | FWRITE));
2498 sc->
sc_fflags &= ~(fflags & (FREAD | FWRITE));
2514 case MOUSE_GETHWINFO:
2515 *(mousehw_t *)addr = sc->
sc_hw;
2521 mode = *(mousemode_t *)addr;
2523 if (mode.level == -1)
2526 else if ((mode.level < 0) || (mode.level > 1)) {
2530 sc->
sc_mode.level = mode.level;
2532 sc->
sc_hw.buttons = 3;
2535 sc->
sc_mode.protocol = MOUSE_PROTO_MSC;
2536 sc->
sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
2537 sc->
sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
2538 sc->
sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
2539 }
else if (sc->
sc_mode.level == 1) {
2540 sc->
sc_mode.protocol = MOUSE_PROTO_SYSMOUSE;
2541 sc->
sc_mode.packetsize = MOUSE_SYS_PACKETSIZE;
2542 sc->
sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK;
2543 sc->
sc_mode.syncmask[1] = MOUSE_SYS_SYNC;
2547 case MOUSE_GETLEVEL:
2548 *(
int *)addr = sc->
sc_mode.level;
2550 case MOUSE_SETLEVEL:
2551 if ((*(
int *)addr < 0) || (*(
int *)addr > 1)) {
2555 sc->
sc_mode.level = *(
int *)addr;
2556 sc->
sc_hw.buttons = 3;
2559 sc->
sc_mode.protocol = MOUSE_PROTO_MSC;
2560 sc->
sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
2561 sc->
sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
2562 sc->
sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
2563 }
else if (sc->
sc_mode.level == 1) {
2564 sc->
sc_mode.protocol = MOUSE_PROTO_SYSMOUSE;
2565 sc->
sc_mode.packetsize = MOUSE_SYS_PACKETSIZE;
2566 sc->
sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK;
2567 sc->
sc_mode.syncmask[1] = MOUSE_SYS_SYNC;
2571 case MOUSE_GETSTATUS: {
2572 mousestatus_t *
status = (mousestatus_t *)addr;
2582 status->flags |= MOUSE_POSCHANGED;
2584 status->flags |= MOUSE_BUTTONSCHANGED;
2604 error = sysctl_handle_int(oidp, &tmp, 0,
req);
2605 if (
error != 0 ||
req->newptr == NULL)
2614 DPRINTFN(ATP_LLEVEL_INFO,
"%s: resetting mickeys_scale_factor to %u\n",
struct wsp_finger wsp_finger_t
static u_int atp_double_tap_threshold
static SYSCTL_NODE(_hw_usb, OID_AUTO, atp, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "USB ATP")
static usb_fifo_close_t atp_close
static boolean_t wsp_match_strokes_against_fingers(struct atp_softc *, wsp_finger_t *, u_int)
static void atp_init_stroke_pool(struct atp_softc *sc)
static void fg_get_pressures(int *, const int *, const int *, int)
static void wsp_interpret_sensor_data(struct atp_softc *, u_int)
static device_method_t atp_methods[]
struct atp_stroke atp_stroke_t
#define ATP_ZOMBIE_STROKE_REAP_INTERVAL
#define ATP_TOUCH_TIMEOUT
void(* sensor_data_interpreter_t)(struct atp_softc *sc, u_int len)
static void atp_disable(struct atp_softc *)
#define FG_PSPAN_MIN_CUM_PRESSURE
static void atp_add_to_queue(struct atp_softc *, int, int, int, uint32_t)
static boolean_t atp_stroke_has_small_movement(const atp_stroke_t *)
#define WSP_MAX_ALLOWED_MATCH_DISTANCE_SQ
static void atp_terminate_stroke(struct atp_softc *, atp_stroke_t *)
enum atp_trackpad_family trackpad_family_t
#define WSP_SIZEOF_FINGER_SENSOR_DATA
static usb_error_t atp_set_device_mode(struct atp_softc *, interface_mode)
static const struct usb_config atp_xfer_config[ATP_N_TRANSFER]
static void fg_interpret_sensor_data(struct atp_softc *, u_int)
MODULE_DEPEND(atp, usb, 1, 1, 1)
@ TRACKPAD_FAMILY_FOUNTAIN_GEYSER
@ TRACKPAD_FAMILY_WELLSPRING
#define WELLSPRING_DRIVER_INFO(PRODUCT)
static void atp_advance_stroke_state(struct atp_softc *, atp_stroke_t *, boolean_t *)
#define FG_MAX_DELTA_MICKEYS
static device_detach_t atp_detach
struct wsp_finger_sensor_data __packed
#define ATP_DOUBLE_TAP_DRAG
#define ATP_ZOMBIES_EXIST
static const STRUCT_USB_HOST_ID fg_devs[]
#define ATP_FIFO_QUEUE_MAXLEN
fountain_geyser_trackpad_type
@ FG_TRACKPAD_TYPE_GEYSER1
@ FG_TRACKPAD_TYPE_GEYSER2
@ FG_TRACKPAD_TYPE_GEYSER4
@ FG_TRACKPAD_TYPE_GEYSER3
static usb_callback_t atp_intr
USB_PNP_HOST_INFO(fg_devs)
#define FG_MAX_PSPANS_PER_AXIS
#define ATP_FAST_MOVEMENT_TRESHOLD
#define ATP_IDLENESS_THRESHOLD
static atp_stroke_t * atp_alloc_stroke(struct atp_softc *sc)
static void atp_reset_buf(struct atp_softc *)
static void atp_update_pending_mickeys(atp_stroke_t *)
static u_int atp_small_movement_threshold
static usb_fifo_cmd_t atp_stop_read
#define DECODE_FAMILY_FROM_DRIVER_INFO(INFO)
static void fg_match_strokes_against_pspans(struct atp_softc *, atp_axis, fg_pspan *, u_int, u_int)
static usb_fifo_ioctl_t atp_ioctl
@ FOUNTAIN_GEYSER_PRODUCT_MAX
static void atp_reset_callback(struct usb_xfer *, usb_error_t)
static boolean_t fg_match_stroke_component(fg_stroke_component_t *, const fg_pspan *, atp_stroke_type)
static void fg_detect_pspans(int *, u_int, u_int, fg_pspan *, u_int *)
static int atp_enable(struct atp_softc *)
SYSCTL_UINT(_hw_usb_atp, OID_AUTO, touch_timeout, CTLFLAG_RWTUN, &atp_touch_timeout, 125000, "age threshold in microseconds for a touch")
#define FG_DRIVER_INFO(PRODUCT)
#define WELLSPRING_INTERFACE_INDEX
static const struct usb_device_id wsp_devs[]
static struct usb_fifo_methods atp_fifo_methods
static void wsp_add_stroke(struct atp_softc *, const wsp_finger_t *)
static boolean_t atp_is_vertical_scroll(const atp_stroke_t *)
static boolean_t wsp_update_strokes(struct atp_softc *, wsp_finger_t[WSP_MAX_FINGERS], u_int)
#define ATP_SENSOR_DATA_BUF_MAX
static boolean_t fg_update_strokes(struct atp_softc *, fg_pspan *, u_int, fg_pspan *, u_int)
SYSCTL_PROC(_hw_usb_atp, OID_AUTO, scale_factor, CTLTYPE_UINT|CTLFLAG_RWTUN|CTLFLAG_MPSAFE, &atp_mickeys_scale_factor, sizeof(atp_mickeys_scale_factor), atp_sysctl_scale_factor_handler, "IU", "movement scale factor")
static u_int atp_stroke_maturity_threshold
static void atp_free_stroke(struct atp_softc *sc, atp_stroke_t *pstroke)
static usb_fifo_cmd_t atp_start_read
#define DECODE_PRODUCT_FROM_DRIVER_INFO(INFO)
static void fg_extract_sensor_data(const int8_t *, u_int, atp_axis, int *, enum fountain_geyser_trackpad_type)
#define ATP_SMALL_MOVEMENT_THRESHOLD
#define ATP_DOUBLE_TAP_N_DRAG_THRESHOLD
static device_attach_t atp_attach
#define FG_PSPAN_MAX_WIDTH
static usb_fifo_open_t atp_open
static u_int atp_slide_min_movement
static boolean_t atp_compute_stroke_movement(atp_stroke_t *)
static device_probe_t atp_probe
static devclass_t atp_devclass
static driver_t atp_driver
static void atp_reap_sibling_zombies(void *)
#define HAS_INTEGRATED_BUTTON
static u_int atp_touch_timeout
#define WSP_TYPE1_FINGER_DATA_OFFSET
DRIVER_MODULE(atp, uhub, atp_driver, atp_devclass, NULL, 0)
static void fg_add_stroke(struct atp_softc *, const fg_pspan *, const fg_pspan *)
#define ATP_FIFO_BUF_SIZE
static boolean_t atp_is_horizontal_scroll(const atp_stroke_t *)
struct fg_stroke_component fg_stroke_component_t
#define UPDATE_INSTANTANEOUS_AND_PENDING(I, P)
#define WSP_TYPE3_BUTTON_DATA_OFFSET
static void atp_convert_to_slide(struct atp_softc *, atp_stroke_t *)
static u_int atp_mickeys_scale_factor
#define WSP_TYPE3_FINGER_DATA_OFFSET
static u_int atp_tap_minimum
#define FG_SENSOR_NOISE_THRESHOLD
static int atp_sysctl_scale_factor_handler(SYSCTL_HANDLER_ARGS)
#define WSP_TYPE2_BUTTON_DATA_OFFSET
#define WSP_TYPE2_FINGER_DATA_OFFSET
static void fg_add_new_strokes(struct atp_softc *, fg_pspan *, u_int, fg_pspan *, u_int)
SYSCTL_INT(_hw_usb_dwc_otg, OID_AUTO, phy_type, CTLFLAG_RDTUN, &dwc_otg_phy_type, 0, "DWC OTG PHY TYPE - 0/1/2/3 - ULPI/HSIC/INTERNAL/UTMI+")
struct ehci_hw_softc __aligned
trackpad_family_t sc_family
struct usb_xfer * sc_xfer[ATP_N_TRANSFER]
struct usb_device * sc_usb_device
char sc_mode_bytes[MODE_LENGTH]
struct usb_fifo_sc sc_fifo
atp_stroke_t sc_strokes_data[ATP_MAX_STROKES]
sensor_data_interpreter_t sensor_data_interpreter
enum fountain_geyser_trackpad_type prot
enum usb_hc_mode usb_mode
struct usbd_lookup_info info
struct usb_device * device
uint8_t bInterfaceProtocol
uint8_t finger_data_offset
#define UT_WRITE_CLASS_INTERFACE
void usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset, const void *ptr, usb_frlength_t len)
void usbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset, void *ptr, usb_frlength_t len)
TAILQ_HEAD(, urb) bsd_urb_list
#define USETW2(w, b1, b0)
const char * usbd_errstr(usb_error_t err)
usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, void **descp, uint16_t *sizep, struct malloc_type *mem, uint8_t iface_index)
int usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id, struct usb_attach_arg *uaa)
usb_error_t usbd_req_set_report(struct usb_device *udev, struct mtx *mtx, void *data, uint16_t len, uint8_t iface_index, uint8_t type, uint8_t id)
usb_error_t usbd_req_get_report(struct usb_device *udev, struct mtx *mtx, void *data, uint16_t len, uint8_t iface_index, uint8_t type, uint8_t id)
void usbd_transfer_submit(struct usb_xfer *xfer)
void usbd_xfer_set_frames(struct usb_xfer *xfer, usb_frcount_t n)
void usbd_transfer_unsetup(struct usb_xfer **pxfer, uint16_t n_setup)
void usbd_xfer_set_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex, usb_frlength_t len)
struct usb_page_cache * usbd_xfer_get_frame(struct usb_xfer *xfer, usb_frcount_t frindex)
usb_error_t usbd_transfer_setup(struct usb_device *udev, const uint8_t *ifaces, struct usb_xfer **ppxfer, const struct usb_config *setup_start, uint16_t n_setup, void *priv_sc, struct mtx *xfer_mtx)
void usbd_transfer_start(struct usb_xfer *xfer)
void * usbd_xfer_softc(struct usb_xfer *xfer)
void usbd_xfer_set_stall(struct usb_xfer *xfer)
void usbd_xfer_set_interval(struct usb_xfer *xfer, int i)
void usbd_transfer_stop(struct usb_xfer *xfer)
void usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen, int *aframes, int *nframes)
void device_set_usb_desc(device_t dev)
int usb_fifo_alloc_buffer(struct usb_fifo *f, uint32_t bufsize, uint16_t nbuf)
int() usb_fifo_ioctl_t(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
void * usb_fifo_softc(struct usb_fifo *fifo)
void() usb_fifo_close_t(struct usb_fifo *fifo, int fflags)
void usb_fifo_detach(struct usb_fifo_sc *f_sc)
void usb_fifo_put_data_linear(struct usb_fifo *fifo, void *ptr, usb_size_t len, uint8_t what)
int usb_fifo_attach(struct usb_device *udev, void *priv_sc, struct mtx *priv_mtx, struct usb_fifo_methods *pm, struct usb_fifo_sc *f_sc, uint16_t unit, int16_t subunit, uint8_t iface_index, uid_t uid, gid_t gid, int mode)
@ USB_ERR_NORMAL_COMPLETION
void() usb_fifo_cmd_t(struct usb_fifo *fifo)
void usb_fifo_free_buffer(struct usb_fifo *f)
void usb_fifo_reset(struct usb_fifo *f)
#define USB_ST_TRANSFERRED
void() usb_callback_t(struct usb_xfer *, usb_error_t)
int() usb_fifo_open_t(struct usb_fifo *fifo, int fflags)
#define USB_VPI(vend, prod, info)
#define STRUCT_USB_HOST_ID
#define USB_GET_DRIVER_INFO(did)
#define USB_GET_STATE(xfer)
uint32_t usb_fifo_put_bytes_max(struct usb_fifo *fifo)