Lines Matching +full:x +full:- +full:axis

1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
39 * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
42 * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
44 * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
56 * I'm grateful to Stephan Scheunig, Angela Naegele, and Nokia IT-support
132 * A double-tap followed by a single-finger slide is treated as a
134 * virtual button-press for the lifetime of the slide. The following
158 /* Distance-squared threshold for matching a finger with a known stroke */
166 /* Maximum allowed width for pressure-spans.*/
194 "maximum time in microseconds to allow association between a double-tap and "
208 "the small movement black-hole for filtering noise");
287 ((INFO) & ((1 << N_PROD_BITS) - 1))
296 * an axis. Each contact with the touchpad results in separate
312 /* trackpad finger data offsets, le16-aligned */
324 /* trackpad finger structure - little endian */
327 int16_t abs_x; /* absolute x coordinate */
329 int16_t rel_x; /* relative x coordinate */
331 int16_t tool_major; /* tool area, major axis */
332 int16_t tool_minor; /* tool area, minor axis */
334 int16_t touch_major; /* touch area, major axis */
335 int16_t touch_minor; /* touch area, minor axis */
345 int x; member
367 /* device-specific configuration */
585 X = 0, enumerator
600 /* Fields encapsulating the pressure-span. */
606 int delta_mickeys; /* change in location (un-smoothened movement)*/
611 * touchpad. A stroke comprises two p-span components and some state.
632 int x; member
636 int instantaneous_dx; /* curr. change in X location (un-smoothened) */
637 int instantaneous_dy; /* curr. change in Y location (un-smoothened) */
646 * The following member is relevant only for fountain-geyser trackpads.
647 * For these, there is the need to track pressure-spans and cumulative
692 * button status. Set to non-zero if the mouse-button is physically
701 * double-touch-n-drag.
707 /* Regarding the data transferred from t-pad in USB INTR packets. */
722 * The last byte of the fountain-geyser sensor data contains status bits; the
824 .interval = 0, /* no pre-delay */
833 pstroke = TAILQ_FIRST(&sc->sc_stroke_free); in atp_alloc_stroke()
837 TAILQ_REMOVE(&sc->sc_stroke_free, pstroke, entry); in atp_alloc_stroke()
839 TAILQ_INSERT_TAIL(&sc->sc_stroke_used, pstroke, entry); in atp_alloc_stroke()
841 sc->sc_n_strokes++; in atp_alloc_stroke()
852 sc->sc_n_strokes--; in atp_free_stroke()
854 TAILQ_REMOVE(&sc->sc_stroke_used, pstroke, entry); in atp_free_stroke()
855 TAILQ_INSERT_TAIL(&sc->sc_stroke_free, pstroke, entry); in atp_free_stroke()
861 u_int x; in atp_init_stroke_pool() local
863 TAILQ_INIT(&sc->sc_stroke_free); in atp_init_stroke_pool()
864 TAILQ_INIT(&sc->sc_stroke_used); in atp_init_stroke_pool()
866 sc->sc_n_strokes = 0; in atp_init_stroke_pool()
868 memset(&sc->sc_strokes_data, 0, sizeof(sc->sc_strokes_data)); in atp_init_stroke_pool()
870 for (x = 0; x != ATP_MAX_STROKES; x++) { in atp_init_stroke_pool()
871 TAILQ_INSERT_TAIL(&sc->sc_stroke_free, &sc->sc_strokes_data[x], in atp_init_stroke_pool()
886 (sc->sc_family == TRACKPAD_FAMILY_FOUNTAIN_GEYSER)) in atp_set_device_mode()
891 err = usbd_req_get_report(sc->sc_usb_device, NULL /* mutex */, in atp_set_device_mode()
892 sc->sc_mode_bytes, sizeof(sc->sc_mode_bytes), 0 /* interface idx */, in atp_set_device_mode()
899 if (sc->sc_mode_bytes[0] == mode_value) in atp_set_device_mode()
910 sc->sc_mode_bytes[0] = mode_value; in atp_set_device_mode()
911 return (usbd_req_set_report(sc->sc_usb_device, NULL /* mutex */, in atp_set_device_mode()
912 sc->sc_mode_bytes, sizeof(sc->sc_mode_bytes), 0 /* interface idx */, in atp_set_device_mode()
924 if (sc->sc_family == TRACKPAD_FAMILY_FOUNTAIN_GEYSER) in atp_reset_callback()
931 sc->sc_mode_bytes[0] = mode_value; in atp_reset_callback()
942 usbd_copy_in(pc, 0, sc->sc_mode_bytes, MODE_LENGTH); in atp_reset_callback()
959 if (sc->sc_state & ATP_ENABLED) in atp_enable()
963 memset(&sc->sc_status, 0, sizeof(sc->sc_status)); in atp_enable()
967 sc->sc_state |= ATP_ENABLED; in atp_enable()
976 sc->sc_state &= ~(ATP_ENABLED | ATP_VALID); in atp_disable()
988 (const struct fg_dev_params *)sc->sc_params; in fg_interpret_sensor_data()
990 fg_extract_sensor_data(sc->sc_sensor_data, params->n_xsensors, X, in fg_interpret_sensor_data()
991 sc->sc_cur_x, params->prot); in fg_interpret_sensor_data()
992 fg_extract_sensor_data(sc->sc_sensor_data, params->n_ysensors, Y, in fg_interpret_sensor_data()
993 sc->sc_cur_y, params->prot); in fg_interpret_sensor_data()
1001 status_bits = sc->sc_sensor_data[params->data_len - 1]; in fg_interpret_sensor_data()
1002 if (((params->prot == FG_TRACKPAD_TYPE_GEYSER3) || in fg_interpret_sensor_data()
1003 (params->prot == FG_TRACKPAD_TYPE_GEYSER4)) && in fg_interpret_sensor_data()
1004 ((sc->sc_state & ATP_VALID) == 0)) { in fg_interpret_sensor_data()
1006 memcpy(sc->sc_base_x, sc->sc_cur_x, in fg_interpret_sensor_data()
1007 params->n_xsensors * sizeof(*sc->sc_base_x)); in fg_interpret_sensor_data()
1008 memcpy(sc->sc_base_y, sc->sc_cur_y, in fg_interpret_sensor_data()
1009 params->n_ysensors * sizeof(*sc->sc_base_y)); in fg_interpret_sensor_data()
1010 sc->sc_state |= ATP_VALID; in fg_interpret_sensor_data()
1015 /* Get pressure readings and detect p-spans for both axes. */ in fg_interpret_sensor_data()
1016 fg_get_pressures(sc->sc_pressure_x, sc->sc_cur_x, sc->sc_base_x, in fg_interpret_sensor_data()
1017 params->n_xsensors); in fg_interpret_sensor_data()
1018 fg_detect_pspans(sc->sc_pressure_x, params->n_xsensors, in fg_interpret_sensor_data()
1019 FG_MAX_PSPANS_PER_AXIS, sc->sc_pspans_x, &n_xpspans); in fg_interpret_sensor_data()
1020 fg_get_pressures(sc->sc_pressure_y, sc->sc_cur_y, sc->sc_base_y, in fg_interpret_sensor_data()
1021 params->n_ysensors); in fg_interpret_sensor_data()
1022 fg_detect_pspans(sc->sc_pressure_y, params->n_ysensors, in fg_interpret_sensor_data()
1023 FG_MAX_PSPANS_PER_AXIS, sc->sc_pspans_y, &n_ypspans); in fg_interpret_sensor_data()
1026 if (fg_update_strokes(sc, sc->sc_pspans_x, n_xpspans, sc->sc_pspans_y, n_ypspans)) in fg_interpret_sensor_data()
1027 sc->sc_status.flags |= MOUSE_POSCHANGED; in fg_interpret_sensor_data()
1029 sc->sc_ibtn = (status_bits & FG_STATUS_BUTTON) ? MOUSE_BUTTON1DOWN : 0; in fg_interpret_sensor_data()
1030 sc->sc_status.button = sc->sc_ibtn; in fg_interpret_sensor_data()
1039 if ((sc->sc_status.flags == 0) && (sc->sc_n_strokes == 0)) { in fg_interpret_sensor_data()
1040 sc->sc_idlecount++; in fg_interpret_sensor_data()
1041 if (sc->sc_idlecount >= ATP_IDLENESS_THRESHOLD) { in fg_interpret_sensor_data()
1048 (const struct fg_dev_params *)sc->sc_params; in fg_interpret_sensor_data()
1052 if (params->prot < FG_TRACKPAD_TYPE_GEYSER3) { in fg_interpret_sensor_data()
1053 memcpy(sc->sc_base_x, sc->sc_cur_x, in fg_interpret_sensor_data()
1054 params->n_xsensors * sizeof(*(sc->sc_base_x))); in fg_interpret_sensor_data()
1055 memcpy(sc->sc_base_y, sc->sc_cur_y, in fg_interpret_sensor_data()
1056 params->n_ysensors * sizeof(*(sc->sc_base_y))); in fg_interpret_sensor_data()
1059 sc->sc_idlecount = 0; in fg_interpret_sensor_data()
1060 usbd_transfer_start(sc->sc_xfer[ATP_RESET]); in fg_interpret_sensor_data()
1063 sc->sc_idlecount = 0; in fg_interpret_sensor_data()
1068 * Interpret the data from the X and Y pressure sensors. This function
1069 * is called separately for the X and Y sensor arrays. The data in the
1073 * --,--,Y1,Y2,--,Y3,Y4,--,Y5,...,Y10, ... X1,X2,--,X3,X4
1076 * '--' (in the above) indicates that the value is unimportant.
1086 * axis
1087 * Axis of data to fetch
1094 fg_extract_sensor_data(const int8_t *sensor_data, u_int num, atp_axis axis, in fg_extract_sensor_data() argument
1106 for (i = 0, di = (axis == Y) ? 1 : 2; i < 8; di += 5, i++) { in fg_extract_sensor_data()
1109 if ((axis == X) && (num > 16)) in fg_extract_sensor_data()
1115 for (i = 0, di = (axis == Y) ? 1 : 19; i < num; /* empty */ ) { in fg_extract_sensor_data()
1123 for (i = 0, di = (axis == Y) ? 2 : 20; i < num; /* empty */ ) { in fg_extract_sensor_data()
1140 p[i] = cur[i] - base[i]; in fg_get_pressures()
1142 p[i] -= 256; in fg_get_pressures()
1143 if (p[i] < -127) in fg_get_pressures()
1149 * Shave off pressures below the noise-pressure in fg_get_pressures()
1156 p[i] -= FG_SENSOR_NOISE_THRESHOLD; in fg_get_pressures()
1214 if (p[i] > p[i - 1]) { in fg_detect_pspans()
1221 * re-process this reading in in fg_detect_pspans()
1227 i--; in fg_detect_pspans()
1242 /* post-process the spans */ in fg_detect_pspans()
1249 (num_spans - i - 1) * sizeof(fg_pspan)); in fg_detect_pspans()
1250 i--; in fg_detect_pspans()
1252 num_spans--; in fg_detect_pspans()
1269 const struct wsp_dev_params *params = sc->sc_params; in wsp_interpret_sensor_data()
1277 if ((data_len < params->finger_data_offset) || in wsp_interpret_sensor_data()
1278 ((data_len - params->finger_data_offset) % in wsp_interpret_sensor_data()
1283 n_source_fingers = (data_len - params->finger_data_offset) / in wsp_interpret_sensor_data()
1291 source_fingerp = (struct wsp_finger_sensor_data *)(sc->sc_sensor_data + in wsp_interpret_sensor_data()
1292 params->finger_data_offset); in wsp_interpret_sensor_data()
1297 source_fingerp->origin = le16toh((uint16_t)source_fingerp->origin); in wsp_interpret_sensor_data()
1298 source_fingerp->abs_x = le16toh((uint16_t)source_fingerp->abs_x); in wsp_interpret_sensor_data()
1299 source_fingerp->abs_y = le16toh((uint16_t)source_fingerp->abs_y); in wsp_interpret_sensor_data()
1300 source_fingerp->rel_x = le16toh((uint16_t)source_fingerp->rel_x); in wsp_interpret_sensor_data()
1301 source_fingerp->rel_y = le16toh((uint16_t)source_fingerp->rel_y); in wsp_interpret_sensor_data()
1302 source_fingerp->tool_major = le16toh((uint16_t)source_fingerp->tool_major); in wsp_interpret_sensor_data()
1303 source_fingerp->tool_minor = le16toh((uint16_t)source_fingerp->tool_minor); in wsp_interpret_sensor_data()
1304 source_fingerp->orientation = le16toh((uint16_t)source_fingerp->orientation); in wsp_interpret_sensor_data()
1305 source_fingerp->touch_major = le16toh((uint16_t)source_fingerp->touch_major); in wsp_interpret_sensor_data()
1306 source_fingerp->touch_minor = le16toh((uint16_t)source_fingerp->touch_minor); in wsp_interpret_sensor_data()
1307 source_fingerp->multi = le16toh((uint16_t)source_fingerp->multi); in wsp_interpret_sensor_data()
1311 if (source_fingerp->touch_major == 0) in wsp_interpret_sensor_data()
1315 fingers[n_fingers].x = source_fingerp->abs_x; in wsp_interpret_sensor_data()
1316 fingers[n_fingers].y = -source_fingerp->abs_y; in wsp_interpret_sensor_data()
1321 if ((sc->sc_n_strokes == 0) && (n_fingers == 0)) in wsp_interpret_sensor_data()
1325 sc->sc_status.flags |= MOUSE_POSCHANGED; in wsp_interpret_sensor_data()
1327 switch(params->tp_type) { in wsp_interpret_sensor_data()
1329 sc->sc_ibtn = sc->sc_sensor_data[WSP_TYPE2_BUTTON_DATA_OFFSET]; in wsp_interpret_sensor_data()
1332 sc->sc_ibtn = sc->sc_sensor_data[WSP_TYPE3_BUTTON_DATA_OFFSET]; in wsp_interpret_sensor_data()
1337 sc->sc_status.button = sc->sc_ibtn ? MOUSE_BUTTON1DOWN : 0; in wsp_interpret_sensor_data()
1341 * Match a pressure-span against a stroke-component. If there is a
1351 delta_mickeys = pspan->loc - component->loc; in fg_match_stroke_component()
1356 component->loc = pspan->loc; in fg_match_stroke_component()
1362 * centre-of-gravity, and hence the location of any/all in fg_match_stroke_component()
1366 if (pspan->cum > ((3 * component->cum_pressure) >> 1)) in fg_match_stroke_component()
1369 component->cum_pressure = pspan->cum; in fg_match_stroke_component()
1370 if (pspan->cum > component->max_cum_pressure) in fg_match_stroke_component()
1371 component->max_cum_pressure = pspan->cum; in fg_match_stroke_component()
1379 min_pressure = (3 * component->max_cum_pressure) >> 2; in fg_match_stroke_component()
1381 min_pressure = component->max_cum_pressure >> 2; in fg_match_stroke_component()
1382 if (component->cum_pressure < min_pressure) in fg_match_stroke_component()
1385 component->delta_mickeys = delta_mickeys; in fg_match_stroke_component()
1390 fg_match_strokes_against_pspans(struct atp_softc *sc, atp_axis axis, in fg_match_strokes_against_pspans() argument
1397 /* Determine the index of the multi-span. */ in fg_match_strokes_against_pspans()
1405 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) { in fg_match_strokes_against_pspans()
1406 if (strokep->components[axis].matched) in fg_match_strokes_against_pspans()
1414 &strokep->components[axis], &pspans[i], in fg_match_strokes_against_pspans()
1415 strokep->type)) { in fg_match_strokes_against_pspans()
1417 strokep->components[axis].matched = true; in fg_match_strokes_against_pspans()
1419 /* Take care to repeat at the multi-span. */ in fg_match_strokes_against_pspans()
1421 repeat_count--; in fg_match_strokes_against_pspans()
1440 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) in wsp_match_strokes_against_fingers()
1441 strokep->matched = false; in wsp_match_strokes_against_fingers()
1447 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) { in wsp_match_strokes_against_fingers()
1452 if (strokep->matched) in wsp_match_strokes_against_fingers()
1455 instantaneous_dx = fingers[i].x - strokep->x; in wsp_match_strokes_against_fingers()
1456 instantaneous_dy = fingers[i].y - strokep->y; in wsp_match_strokes_against_fingers()
1474 strokep->matched = true; in wsp_match_strokes_against_fingers()
1475 strokep->instantaneous_dx = fingers[i].x - strokep->x; in wsp_match_strokes_against_fingers()
1476 strokep->instantaneous_dy = fingers[i].y - strokep->y; in wsp_match_strokes_against_fingers()
1477 strokep->x = fingers[i].x; in wsp_match_strokes_against_fingers()
1478 strokep->y = fingers[i].y; in wsp_match_strokes_against_fingers()
1487 * Update strokes by matching against current pressure-spans.
1501 /* Reset X and Y components of all strokes as unmatched. */ in fg_update_strokes()
1502 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) { in fg_update_strokes()
1503 strokep->components[X].matched = false; in fg_update_strokes()
1504 strokep->components[Y].matched = false; in fg_update_strokes()
1508 * Usually, the X and Y pspans come in pairs (the common case in fg_update_strokes()
1511 * axis, as illustrated in the following: in fg_update_strokes()
1513 * F = finger-contact in fg_update_strokes()
1516 * +-----------------------+ in fg_update_strokes()
1525 * +-----------------------+ in fg_update_strokes()
1529 * number of X and Y pspans. When this happens, X and Y pspans in fg_update_strokes()
1532 * When X and Y pspans differ in number, the axis with the in fg_update_strokes()
1534 * pspan (or a multi-pspan)--in the above illustration, the in fg_update_strokes()
1535 * Y-axis has a repeating pspan. Our approach is to try to in fg_update_strokes()
1536 * match the multi-pspan repeatedly against strokes. The in fg_update_strokes()
1537 * difference between the number of X and Y pspans gives us a in fg_update_strokes()
1538 * crude repeat_count for matching multi-pspans--i.e. the in fg_update_strokes()
1539 * multi-pspan along the Y axis (above) has a repeat_count of 1. in fg_update_strokes()
1541 repeat_count = abs(n_xpspans - n_ypspans); in fg_update_strokes()
1543 fg_match_strokes_against_pspans(sc, X, pspans_x, n_xpspans, in fg_update_strokes()
1551 TAILQ_FOREACH_SAFE(strokep, &sc->sc_stroke_used, entry, strokep_next) { in fg_update_strokes()
1552 if (strokep->components[X].matched && in fg_update_strokes()
1553 strokep->components[Y].matched) { in fg_update_strokes()
1554 strokep->matched = true; in fg_update_strokes()
1555 strokep->instantaneous_dx = in fg_update_strokes()
1556 strokep->components[X].delta_mickeys; in fg_update_strokes()
1557 strokep->instantaneous_dy = in fg_update_strokes()
1558 strokep->components[Y].delta_mickeys; in fg_update_strokes()
1584 printf(" X:[loc:%u,cum:%u]", in fg_update_strokes()
1606 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) { in fg_update_strokes()
1609 (strokep->flags & ATSF_ZOMBIE) ? "zomb:" : "", in fg_update_strokes()
1610 (strokep->type == ATP_STROKE_TOUCH) ? '[' : '<', in fg_update_strokes()
1611 strokep->components[X].loc, in fg_update_strokes()
1612 strokep->components[X].delta_mickeys, in fg_update_strokes()
1613 strokep->components[X].cum_pressure, in fg_update_strokes()
1614 strokep->components[X].max_cum_pressure, in fg_update_strokes()
1615 (strokep->type == ATP_STROKE_TOUCH) ? ']' : '>', in fg_update_strokes()
1616 (strokep->type == ATP_STROKE_TOUCH) ? '[' : '<', in fg_update_strokes()
1617 strokep->components[Y].loc, in fg_update_strokes()
1618 strokep->components[Y].delta_mickeys, in fg_update_strokes()
1619 strokep->components[Y].cum_pressure, in fg_update_strokes()
1620 strokep->components[Y].max_cum_pressure, in fg_update_strokes()
1621 (strokep->type == ATP_STROKE_TOUCH) ? ']' : '>'); in fg_update_strokes()
1623 if (TAILQ_FIRST(&sc->sc_stroke_used) != NULL) in fg_update_strokes()
1631 * Update strokes by matching against current pressure-spans.
1643 if (sc->sc_n_strokes > 0) { in wsp_update_strokes()
1648 TAILQ_FOREACH_SAFE(strokep, &sc->sc_stroke_used, entry, strokep_next) { in wsp_update_strokes()
1649 if (strokep->matched) in wsp_update_strokes()
1665 /* Initialize a stroke using a pressure-span. */
1681 strokep->type = ATP_STROKE_TOUCH; in fg_add_stroke()
1682 strokep->matched = false; in fg_add_stroke()
1683 microtime(&strokep->ctime); in fg_add_stroke()
1684 strokep->age = 1; /* number of interrupts */ in fg_add_stroke()
1685 strokep->x = pspan_x->loc; in fg_add_stroke()
1686 strokep->y = pspan_y->loc; in fg_add_stroke()
1688 strokep->components[X].loc = pspan_x->loc; in fg_add_stroke()
1689 strokep->components[X].cum_pressure = pspan_x->cum; in fg_add_stroke()
1690 strokep->components[X].max_cum_pressure = pspan_x->cum; in fg_add_stroke()
1691 strokep->components[X].matched = true; in fg_add_stroke()
1693 strokep->components[Y].loc = pspan_y->loc; in fg_add_stroke()
1694 strokep->components[Y].cum_pressure = pspan_y->cum; in fg_add_stroke()
1695 strokep->components[Y].max_cum_pressure = pspan_y->cum; in fg_add_stroke()
1696 strokep->components[Y].matched = true; in fg_add_stroke()
1698 if (sc->sc_n_strokes > 1) { in fg_add_stroke()
1699 /* Reset double-tap-n-drag if we have more than one strokes. */ in fg_add_stroke()
1700 sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG; in fg_add_stroke()
1704 strokep->components[X].loc, in fg_add_stroke()
1705 strokep->components[Y].loc, in fg_add_stroke()
1706 (u_int)strokep->ctime.tv_sec, in fg_add_stroke()
1707 (unsigned long int)strokep->ctime.tv_usec); in fg_add_stroke()
1720 for (i = 0, nspans[X] = 0; i < n_xpspans; i++) { in fg_add_new_strokes()
1722 spans[X][nspans[X]] = pspans_x[i]; in fg_add_new_strokes()
1723 nspans[X]++; in fg_add_new_strokes()
1733 if (nspans[X] == nspans[Y]) { in fg_add_new_strokes()
1735 for (i = 0, j = 0; (i < nspans[X]) && (j < nspans[Y]); i++, j++) in fg_add_new_strokes()
1736 fg_add_stroke(sc, &spans[X][i], &spans[Y][j]); in fg_add_new_strokes()
1739 atp_axis repeat_axis; /* axis with multi-pspans */ in fg_add_new_strokes()
1740 u_int repeat_count; /* repeat count for the multi-pspan*/ in fg_add_new_strokes()
1741 u_int repeat_index = 0; /* index of the multi-span */ in fg_add_new_strokes()
1743 repeat_axis = (nspans[X] > nspans[Y]) ? Y : X; in fg_add_new_strokes()
1744 repeat_count = abs(nspans[X] - nspans[Y]); in fg_add_new_strokes()
1754 for (; (i < nspans[X]) && (j < nspans[Y]); i++, j++) { in fg_add_new_strokes()
1755 fg_add_stroke(sc, &spans[X][i], &spans[Y][j]); in fg_add_new_strokes()
1757 /* Take care to repeat at the multi-pspan. */ in fg_add_new_strokes()
1759 if ((repeat_axis == X) && in fg_add_new_strokes()
1761 i--; /* counter loop increment */ in fg_add_new_strokes()
1762 repeat_count--; in fg_add_new_strokes()
1765 j--; /* counter loop increment */ in fg_add_new_strokes()
1766 repeat_count--; in fg_add_new_strokes()
1788 strokep->type = ATP_STROKE_TOUCH; in wsp_add_stroke()
1789 strokep->matched = true; in wsp_add_stroke()
1790 microtime(&strokep->ctime); in wsp_add_stroke()
1791 strokep->age = 1; /* number of interrupts */ in wsp_add_stroke()
1792 strokep->x = fingerp->x; in wsp_add_stroke()
1793 strokep->y = fingerp->y; in wsp_add_stroke()
1795 /* Reset double-tap-n-drag if we have more than one strokes. */ in wsp_add_stroke()
1796 if (sc->sc_n_strokes > 1) in wsp_add_stroke()
1797 sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG; in wsp_add_stroke()
1799 DPRINTFN(ATP_LLEVEL_INFO, "[%d,%d]\n", strokep->x, strokep->y); in wsp_add_stroke()
1807 if (strokep->flags & ATSF_ZOMBIE) in atp_advance_stroke_state()
1808 strokep->flags &= ~ATSF_ZOMBIE; in atp_advance_stroke_state()
1810 strokep->age++; in atp_advance_stroke_state()
1811 if (strokep->age <= atp_stroke_maturity_threshold) { in atp_advance_stroke_state()
1813 strokep->instantaneous_dx = 0; in atp_advance_stroke_state()
1814 strokep->instantaneous_dy = 0; in atp_advance_stroke_state()
1820 if (strokep->type != ATP_STROKE_TOUCH) in atp_advance_stroke_state()
1824 if ((abs(strokep->cum_movement_x) > atp_slide_min_movement) || in atp_advance_stroke_state()
1825 (abs(strokep->cum_movement_y) > atp_slide_min_movement)) in atp_advance_stroke_state()
1831 if (timevalcmp(&tdiff, &strokep->ctime, >)) { in atp_advance_stroke_state()
1832 timevalsub(&tdiff, &strokep->ctime); in atp_advance_stroke_state()
1845 return (((u_int)abs(strokep->instantaneous_dx) <= in atp_stroke_has_small_movement()
1847 ((u_int)abs(strokep->instantaneous_dy) <= in atp_stroke_has_small_movement()
1860 strokep->pending_dx += strokep->instantaneous_dx; in atp_update_pending_mickeys()
1861 strokep->pending_dy += strokep->instantaneous_dy; in atp_update_pending_mickeys()
1874 (I) = (((I) + (atp_mickeys_scale_factor - 1)) / \ in atp_update_pending_mickeys()
1884 (P) -= ((I) << 1); \ in atp_update_pending_mickeys()
1895 (I) = (((I) - (atp_mickeys_scale_factor - 1)) / \ in atp_update_pending_mickeys()
1905 (P) -= ((I) << 1); \ in atp_update_pending_mickeys()
1912 UPDATE_INSTANTANEOUS_AND_PENDING(strokep->instantaneous_dx, in atp_update_pending_mickeys()
1913 strokep->pending_dx); in atp_update_pending_mickeys()
1914 UPDATE_INSTANTANEOUS_AND_PENDING(strokep->instantaneous_dy, in atp_update_pending_mickeys()
1915 strokep->pending_dy); in atp_update_pending_mickeys()
1920 * instantaneous changes in the X and Y components.
1935 strokep->pending_dx = 0; in atp_compute_stroke_movement()
1936 strokep->pending_dy = 0; in atp_compute_stroke_movement()
1940 strokep->movement_dx = (strokep->instantaneous_dx) / in atp_compute_stroke_movement()
1942 strokep->movement_dy = (strokep->instantaneous_dy) / in atp_compute_stroke_movement()
1945 if ((abs(strokep->instantaneous_dx) >= ATP_FAST_MOVEMENT_TRESHOLD) || in atp_compute_stroke_movement()
1946 (abs(strokep->instantaneous_dy) >= ATP_FAST_MOVEMENT_TRESHOLD)) { in atp_compute_stroke_movement()
1947 strokep->movement_dx <<= 1; in atp_compute_stroke_movement()
1948 strokep->movement_dy <<= 1; in atp_compute_stroke_movement()
1951 strokep->cum_movement_x += strokep->movement_dx; in atp_compute_stroke_movement()
1952 strokep->cum_movement_y += strokep->movement_dy; in atp_compute_stroke_movement()
1954 return ((strokep->movement_dx != 0) || (strokep->movement_dy != 0)); in atp_compute_stroke_movement()
1961 * end of a multi-touch gesture.
1966 if (strokep->flags & ATSF_ZOMBIE) in atp_terminate_stroke()
1970 if (strokep->age <= atp_stroke_maturity_threshold) { in atp_terminate_stroke()
1975 strokep->flags |= ATSF_ZOMBIE; in atp_terminate_stroke()
1976 sc->sc_state |= ATP_ZOMBIES_EXIST; in atp_terminate_stroke()
1978 callout_reset(&sc->sc_callout, ATP_ZOMBIE_STROKE_REAP_INTERVAL, in atp_terminate_stroke()
1982 * Reset the double-click-n-drag at the termination of any in atp_terminate_stroke()
1985 if (strokep->type == ATP_STROKE_SLIDE) in atp_terminate_stroke()
1986 sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG; in atp_terminate_stroke()
1992 if (abs(strokep->cum_movement_x) < atp_slide_min_movement) in atp_is_horizontal_scroll()
1994 if (strokep->cum_movement_y == 0) in atp_is_horizontal_scroll()
1996 return (abs(strokep->cum_movement_x / strokep->cum_movement_y) >= 4); in atp_is_horizontal_scroll()
2002 if (abs(strokep->cum_movement_y) < atp_slide_min_movement) in atp_is_vertical_scroll()
2004 if (strokep->cum_movement_x == 0) in atp_is_vertical_scroll()
2006 return (abs(strokep->cum_movement_y / strokep->cum_movement_x) >= 4); in atp_is_vertical_scroll()
2022 TAILQ_FOREACH_SAFE(strokep, &sc->sc_stroke_used, entry, strokep_next) { in atp_reap_sibling_zombies()
2023 if ((strokep->flags & ATSF_ZOMBIE) == 0) in atp_reap_sibling_zombies()
2026 if (strokep->type == ATP_STROKE_TOUCH) { in atp_reap_sibling_zombies()
2033 horizontal_scroll += strokep->cum_movement_x; in atp_reap_sibling_zombies()
2042 sc->sc_state &= ~ATP_ZOMBIES_EXIST; in atp_reap_sibling_zombies()
2045 if (sc->sc_ibtn != 0) in atp_reap_sibling_zombies()
2051 /* Add a pair of virtual button events (button-down and button-up) if in atp_reap_sibling_zombies()
2060 microtime(&sc->sc_touch_reap_time); /* remember this time */ in atp_reap_sibling_zombies()
2087 strokep->type = ATP_STROKE_SLIDE; in atp_convert_to_slide()
2089 /* Are we at the beginning of a double-click-n-drag? */ in atp_convert_to_slide()
2090 if ((sc->sc_n_strokes == 1) && in atp_convert_to_slide()
2091 ((sc->sc_state & ATP_ZOMBIES_EXIST) == 0) && in atp_convert_to_slide()
2092 timevalcmp(&strokep->ctime, &sc->sc_touch_reap_time, >)) { in atp_convert_to_slide()
2099 delta = strokep->ctime; in atp_convert_to_slide()
2100 timevalsub(&delta, &sc->sc_touch_reap_time); in atp_convert_to_slide()
2102 sc->sc_state |= ATP_DOUBLE_TAP_DRAG; in atp_convert_to_slide()
2110 usb_fifo_reset(sc->sc_fifo.fp[USB_FIFO_RX]); in atp_reset_buf()
2120 dx = imin(dx, 254); dx = imax(dx, -256); in atp_add_to_queue()
2121 dy = imin(dy, 254); dy = imax(dy, -256); in atp_add_to_queue()
2122 dz = imin(dz, 126); dz = imax(dz, -128); in atp_add_to_queue()
2132 DPRINTFN(ATP_LLEVEL_INFO, "dx=%d, dy=%d, buttons=%x\n", in atp_add_to_queue()
2136 buf[0] = sc->sc_mode.syncmask[1]; in atp_add_to_queue()
2140 buf[3] = dx - (dx >> 1); in atp_add_to_queue()
2141 buf[4] = dy - (dy >> 1); in atp_add_to_queue()
2143 if (sc->sc_mode.level == 1) { in atp_add_to_queue()
2145 buf[6] = dz - (dz >> 1); in atp_add_to_queue()
2149 usb_fifo_put_data_linear(sc->sc_fifo.fp[USB_FIFO_RX], buf, in atp_add_to_queue()
2150 sc->sc_mode.packetsize, 1); in atp_add_to_queue()
2158 if (uaa->usb_mode != USB_MODE_HOST) in atp_probe()
2161 if (uaa->info.bInterfaceClass != UICLASS_HID) in atp_probe()
2165 * (uaa->info.bInterfaceProtocol == UIPROTO_MOUSE) doesn't hold true in atp_probe()
2170 return ((uaa->info.bInterfaceProtocol == UIPROTO_MOUSE) ? in atp_probe()
2174 if (uaa->info.bIfaceIndex == WELLSPRING_INTERFACE_INDEX) in atp_probe()
2192 sc->sc_dev = dev; in atp_attach()
2193 sc->sc_usb_device = uaa->device; in atp_attach()
2196 if (usbd_req_get_hid_desc(uaa->device, NULL, &descriptor_ptr, in atp_attach()
2197 &descriptor_len, M_TEMP, uaa->info.bIfaceIndex) != in atp_attach()
2202 sc->sc_expected_sensor_data_len = hid_report_size_max(descriptor_ptr, in atp_attach()
2206 if ((sc->sc_expected_sensor_data_len <= 0) || in atp_attach()
2207 (sc->sc_expected_sensor_data_len > ATP_SENSOR_DATA_BUF_MAX)) { in atp_attach()
2209 sc->sc_expected_sensor_data_len); in atp_attach()
2214 sc->sc_family = DECODE_FAMILY_FROM_DRIVER_INFO(di); in atp_attach()
2219 * limited information--they encode movement deltas and button in atp_attach()
2220 * events,--but do not include data from the pressure in atp_attach()
2222 * reports to raw sensor data using vendor-specific USB in atp_attach()
2227 if ((sc->sc_family == TRACKPAD_FAMILY_FOUNTAIN_GEYSER) && in atp_attach()
2235 mtx_init(&sc->sc_mutex, "atpmtx", NULL, MTX_DEF | MTX_RECURSE); in atp_attach()
2237 switch(sc->sc_family) { in atp_attach()
2239 sc->sc_params = in atp_attach()
2241 sc->sensor_data_interpreter = fg_interpret_sensor_data; in atp_attach()
2244 sc->sc_params = in atp_attach()
2246 sc->sensor_data_interpreter = wsp_interpret_sensor_data; in atp_attach()
2252 err = usbd_transfer_setup(uaa->device, in atp_attach()
2253 &uaa->info.bIfaceIndex, sc->sc_xfer, atp_xfer_config, in atp_attach()
2254 ATP_N_TRANSFER, sc, &sc->sc_mutex); in atp_attach()
2260 if (usb_fifo_attach(sc->sc_usb_device, sc, &sc->sc_mutex, in atp_attach()
2261 &atp_fifo_methods, &sc->sc_fifo, in atp_attach()
2262 device_get_unit(dev), -1, uaa->info.bIfaceIndex, in atp_attach()
2269 sc->sc_hw.buttons = 3; in atp_attach()
2270 sc->sc_hw.iftype = MOUSE_IF_USB; in atp_attach()
2271 sc->sc_hw.type = MOUSE_PAD; in atp_attach()
2272 sc->sc_hw.model = MOUSE_MODEL_GENERIC; in atp_attach()
2273 sc->sc_hw.hwid = 0; in atp_attach()
2274 sc->sc_mode.protocol = MOUSE_PROTO_MSC; in atp_attach()
2275 sc->sc_mode.rate = -1; in atp_attach()
2276 sc->sc_mode.resolution = MOUSE_RES_UNKNOWN; in atp_attach()
2277 sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE; in atp_attach()
2278 sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK; in atp_attach()
2279 sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC; in atp_attach()
2280 sc->sc_mode.accelfactor = 0; in atp_attach()
2281 sc->sc_mode.level = 0; in atp_attach()
2283 sc->sc_state = 0; in atp_attach()
2284 sc->sc_ibtn = 0; in atp_attach()
2286 callout_init_mtx(&sc->sc_callout, &sc->sc_mutex, 0); in atp_attach()
2303 mtx_lock(&sc->sc_mutex); in atp_detach()
2304 callout_drain(&sc->sc_callout); in atp_detach()
2305 if (sc->sc_state & ATP_ENABLED) in atp_detach()
2307 mtx_unlock(&sc->sc_mutex); in atp_detach()
2309 usb_fifo_detach(&sc->sc_fifo); in atp_detach()
2311 usbd_transfer_unsetup(sc->sc_xfer, ATP_N_TRANSFER); in atp_detach()
2313 mtx_destroy(&sc->sc_mutex); in atp_detach()
2330 usbd_copy_out(pc, 0, sc->sc_sensor_data, len); in atp_intr()
2331 if (len < sc->sc_expected_sensor_data_len) { in atp_intr()
2333 memset(sc->sc_sensor_data + len, 0, in atp_intr()
2334 sc->sc_expected_sensor_data_len - len); in atp_intr()
2337 sc->sc_status.flags &= ~(MOUSE_STDBUTTONSCHANGED | in atp_intr()
2339 sc->sc_status.obutton = sc->sc_status.button; in atp_intr()
2341 (sc->sensor_data_interpreter)(sc, len); in atp_intr()
2343 if (sc->sc_status.button != 0) { in atp_intr()
2345 sc->sc_state &= ~ATP_DOUBLE_TAP_DRAG; in atp_intr()
2346 } else if (sc->sc_state & ATP_DOUBLE_TAP_DRAG) { in atp_intr()
2347 /* Assume a button-press with DOUBLE_TAP_N_DRAG. */ in atp_intr()
2348 sc->sc_status.button = MOUSE_BUTTON1DOWN; in atp_intr()
2351 sc->sc_status.flags |= in atp_intr()
2352 sc->sc_status.button ^ sc->sc_status.obutton; in atp_intr()
2353 if (sc->sc_status.flags & MOUSE_STDBUTTONSCHANGED) { in atp_intr()
2355 ((sc->sc_status.button & MOUSE_BUTTON1DOWN) ? in atp_intr()
2359 if (sc->sc_status.flags & (MOUSE_POSCHANGED | in atp_intr()
2367 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) { in atp_intr()
2368 if (strokep->flags & ATSF_ZOMBIE) in atp_intr()
2371 dx += strokep->movement_dx; in atp_intr()
2372 dy += strokep->movement_dy; in atp_intr()
2373 if (strokep->movement_dx || in atp_intr()
2374 strokep->movement_dy) in atp_intr()
2384 /* detect multi-finger vertical scrolls */ in atp_intr()
2387 TAILQ_FOREACH(strokep, &sc->sc_stroke_used, entry) { in atp_intr()
2388 if (strokep->flags & ATSF_ZOMBIE) in atp_intr()
2400 sc->sc_status.dx += dx; in atp_intr()
2401 sc->sc_status.dy += dy; in atp_intr()
2402 sc->sc_status.dz += dz; in atp_intr()
2403 atp_add_to_queue(sc, dx, -dy, -dz, sc->sc_status.button); in atp_intr()
2409 if (usb_fifo_put_bytes_max(sc->sc_fifo.fp[USB_FIFO_RX]) != 0) { in atp_intr()
2411 sc->sc_expected_sensor_data_len); in atp_intr()
2433 rate = sc->sc_pollrate; in atp_start_read()
2438 if ((rate > 0) && (sc->sc_xfer[ATP_INTR_DT] != NULL)) { in atp_start_read()
2440 usbd_transfer_stop(sc->sc_xfer[ATP_INTR_DT]); in atp_start_read()
2442 usbd_xfer_set_interval(sc->sc_xfer[ATP_INTR_DT], 1000 / rate); in atp_start_read()
2444 sc->sc_pollrate = 0; in atp_start_read()
2447 usbd_transfer_start(sc->sc_xfer[ATP_INTR_DT]); in atp_start_read()
2454 usbd_transfer_stop(sc->sc_xfer[ATP_INTR_DT]); in atp_stop_read()
2463 if (sc->sc_fflags & fflags) in atp_open()
2467 if (sc->sc_fflags == 0) { in atp_open()
2480 sc->sc_fflags |= (fflags & (FREAD | FWRITE)); in atp_open()
2491 sc->sc_fflags &= ~(fflags & (FREAD | FWRITE)); in atp_close()
2492 if (sc->sc_fflags == 0) { in atp_close()
2504 mtx_lock(&sc->sc_mutex); in atp_ioctl()
2508 *(mousehw_t *)addr = sc->sc_hw; in atp_ioctl()
2511 *(mousemode_t *)addr = sc->sc_mode; in atp_ioctl()
2516 if (mode.level == -1) in atp_ioctl()
2523 sc->sc_mode.level = mode.level; in atp_ioctl()
2524 sc->sc_pollrate = mode.rate; in atp_ioctl()
2525 sc->sc_hw.buttons = 3; in atp_ioctl()
2527 if (sc->sc_mode.level == 0) { in atp_ioctl()
2528 sc->sc_mode.protocol = MOUSE_PROTO_MSC; in atp_ioctl()
2529 sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE; in atp_ioctl()
2530 sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK; in atp_ioctl()
2531 sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC; in atp_ioctl()
2532 } else if (sc->sc_mode.level == 1) { in atp_ioctl()
2533 sc->sc_mode.protocol = MOUSE_PROTO_SYSMOUSE; in atp_ioctl()
2534 sc->sc_mode.packetsize = MOUSE_SYS_PACKETSIZE; in atp_ioctl()
2535 sc->sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK; in atp_ioctl()
2536 sc->sc_mode.syncmask[1] = MOUSE_SYS_SYNC; in atp_ioctl()
2541 *(int *)addr = sc->sc_mode.level; in atp_ioctl()
2548 sc->sc_mode.level = *(int *)addr; in atp_ioctl()
2549 sc->sc_hw.buttons = 3; in atp_ioctl()
2551 if (sc->sc_mode.level == 0) { in atp_ioctl()
2552 sc->sc_mode.protocol = MOUSE_PROTO_MSC; in atp_ioctl()
2553 sc->sc_mode.packetsize = MOUSE_MSC_PACKETSIZE; in atp_ioctl()
2554 sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK; in atp_ioctl()
2555 sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC; in atp_ioctl()
2556 } else if (sc->sc_mode.level == 1) { in atp_ioctl()
2557 sc->sc_mode.protocol = MOUSE_PROTO_SYSMOUSE; in atp_ioctl()
2558 sc->sc_mode.packetsize = MOUSE_SYS_PACKETSIZE; in atp_ioctl()
2559 sc->sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK; in atp_ioctl()
2560 sc->sc_mode.syncmask[1] = MOUSE_SYS_SYNC; in atp_ioctl()
2567 *status = sc->sc_status; in atp_ioctl()
2568 sc->sc_status.obutton = sc->sc_status.button; in atp_ioctl()
2569 sc->sc_status.button = 0; in atp_ioctl()
2570 sc->sc_status.dx = 0; in atp_ioctl()
2571 sc->sc_status.dy = 0; in atp_ioctl()
2572 sc->sc_status.dz = 0; in atp_ioctl()
2574 if (status->dx || status->dy || status->dz) in atp_ioctl()
2575 status->flags |= MOUSE_POSCHANGED; in atp_ioctl()
2576 if (status->button != status->obutton) in atp_ioctl()
2577 status->flags |= MOUSE_BUTTONSCHANGED; in atp_ioctl()
2586 mtx_unlock(&sc->sc_mutex); in atp_ioctl()
2598 if (error != 0 || req->newptr == NULL) in atp_sysctl_scale_factor_handler()