Lines Matching +full:rate +full:- +full:ati +full:- +full:ms

1 /*-
28 * Thanks are also due to Rick Macklem, rick@snowhite.cis.uoguelph.ca -
30 * of his "driver for the Logitech and ATI Inport Bus mice for use with
36 * Andrew Herbert <andrew@werple.apana.org.au> - 8 June 1993
39 * Andrew Herbert - 12 June 1993
42 * - 13 June 1993
44 * Modified for PS/2 AUX mouse by Shoji Yuen <yuen@nuie.nagoya-u.ac.jp>
45 * - 24 October 1993
48 * Kazutaka Yokota <yokota@zodiac.mech.utsunomiya-u.ac.jp>
49 * - 3, 14, 22 October 1996.
50 * - 12 November 1996. IOCTLs and rearranging `psmread', `psmioctl'...
51 * - 14, 30 November 1996. Uses `kbdio.c'.
52 * - 13 December 1996. Uses queuing version of `kbdio.c'.
53 * - January/February 1997. Tweaked probe logic for
55 * - 30 July 1997. Added APM support.
56 * - 5 March 1997. Defined driver configuration flags (PSM_CONFIG_XXX).
159 #define PSM_NOMUX (-1)
337 #define PSM_FINGER_IS_SET(f) ((f).x != -1 && (f).y != -1 && (f).p != 0)
339 (f) = (finger_t) { .x = -1, .y = -1, .p = 0, .w = 0, .flags = 0 }; \
386 .x = (((pb)->ipacket[1] & 0x0f) << 8) | (pb)->ipacket[2], \
387 .y = (((pb)->ipacket[4] & 0x0f) << 8) | (pb)->ipacket[5], \
388 .p = ((pb)->ipacket[1] & 0xf0) | (((pb)->ipacket[4] >> 4) & 0x0f), \
404 #define ELANTECH_PKT_IS_TRACKPOINT(pb) (((pb)->ipacket[3] & 0x0f) == 0x06)
406 (pb)->ipacket[0] == ((hwversion) == 2 ? 0x84 : 0xc4) && \
407 (pb)->ipacket[1] == 0xff && (pb)->ipacket[2] == 0xff && \
408 (pb)->ipacket[3] == 0x02 && (pb)->ipacket[4] == 0xff && \
409 (pb)->ipacket[5] == 0xff)
411 (((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0x0f) == 0x02)
413 ((pb)->ipacket[3] & 0x09) == 0x08 : \
414 ((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0xcf) == 0x02)
416 ((pb)->ipacket[3] & 0x09) == 0x09 : \
417 ((pb)->ipacket[0] & 0x0c) == 0x0c && ((pb)->ipacket[3] & 0xce) == 0x0c)
419 ((pb)->ipacket[3] & 0x08) == 0x00 : \
420 ((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0x1c) == 0x10)
477 u_char muxsave[3]; /* 3->6 byte proto conversion buffer */
523 #define ALWAYS_RESTORE_CONTROLLER(kbdc) !(kbdcp(kbdc)->quirks \
527 static int tap_enabled = -1;
532 static int mux_disabled = -1;
548 int rate; member
736 #define GENERIC_MOUSE_ENTRY (nitems(vendortype) - 1)
850 return (-1); in get_aux_id()
852 /* 10ms delay */ in get_aux_id()
862 set_mouse_sampling_rate(KBDC kbdc, int rate) in set_mouse_sampling_rate() argument
866 res = send_aux_command_and_data(kbdc, PSMC_SET_SAMPLING_RATE, rate); in set_mouse_sampling_rate()
867 VLOG(2, (LOG_DEBUG, "psm: SET_SAMPLING_RATE (%d) %04x\n", rate, res)); in set_mouse_sampling_rate()
869 return ((res == PSM_ACK) ? rate : -1); in set_mouse_sampling_rate()
902 return ((res == PSM_ACK) ? val : -1); in set_mouse_resolution()
907 * re-enabled by calling `enable_aux_dev()'
956 -1 /* end of table */ in is_a_mouse()
1042 * Re-initialize the aux port and device. The aux port must be enabled
1051 KBDC kbdc = sc->kbdc; in doinitialize()
1061 device_log(sc->dev, LOG_DEBUG, in doinitialize()
1066 case -1: /* time out */ in doinitialize()
1069 if (sc->config & PSM_CONFIG_IGNPORTERROR) in doinitialize()
1071 device_log(sc->dev, LOG_ERR, in doinitialize()
1076 if (sc->config & PSM_CONFIG_NORESET) { in doinitialize()
1088 device_log(sc->dev, LOG_ERR, in doinitialize()
1099 device_log(sc->dev, LOG_ERR, in doinitialize()
1105 /* Re-enable the mouse. */ in doinitialize()
1107 if (vendortype[i].model == sc->hw.model) in doinitialize()
1112 if (mode->rate > 0) in doinitialize()
1113 mode->rate = set_mouse_sampling_rate(kbdc, mode->rate); in doinitialize()
1114 if (mode->resolution >= 0) in doinitialize()
1115 mode->resolution = in doinitialize()
1116 set_mouse_resolution(kbdc, mode->resolution); in doinitialize()
1122 sc->flags |= PSM_NEED_SYNCBITS; in doinitialize()
1126 device_log(sc->dev, LOG_DEBUG, in doinitialize()
1150 if (sc->hw.model == MOUSE_MODEL_SYNAPTICS) {
1151 if (sc->muxport != PSM_NOMUX) {
1152 mux_enabled = enable_aux_mux(sc->kbdc) >= 0;
1154 set_active_aux_mux_port(sc->kbdc, sc->muxport);
1156 device_log(sc->dev, LOG_ERR, "failed to enable "
1159 mouse_ext_command(sc->kbdc, SYNAPTICS_READ_MODES);
1160 get_mouse_status(sc->kbdc, stat, 0, 3);
1161 if ((SYNAPTICS_VERSION_GE(sc->synhw, 7, 5) ||
1165 VDLOG(5, sc->dev, LOG_DEBUG, "Synaptis Absolute Mode "
1169 disable_aux_mux(sc->kbdc);
1176 if (sc->hw.model == MOUSE_MODEL_GENERIC) {
1178 VDLOG(2, sc->dev, LOG_DEBUG,
1182 VDLOG(2, sc->dev, LOG_DEBUG,
1189 if (!enable_aux_dev(sc->kbdc)) {
1196 recover_from_error(sc->kbdc);
1202 if (!doinitialize(sc, &sc->mode) || !enable_aux_dev(sc->kbdc)) {
1203 recover_from_error(sc->kbdc);
1207 restore_controller(sc->kbdc, command_byte);
1209 sc->state &= ~PSM_VALID;
1210 device_log(sc->dev, LOG_ERR,
1216 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
1217 device_log(sc->dev, LOG_DEBUG,
1221 if (!set_controller_command_byte(sc->kbdc,
1222 kbdc_get_device_mask(sc->kbdc),
1226 disable_aux_dev(sc->kbdc);
1227 restore_controller(sc->kbdc, command_byte);
1228 device_log(sc->dev, LOG_ERR,
1234 sc->watchdog = FALSE;
1235 callout_reset(&sc->callout, hz * 2, psmtimeout, sc);
1248 if (!kbdc_lock(sc->kbdc, TRUE))
1253 sc->watchdog = FALSE;
1254 callout_stop(&sc->callout);
1257 empty_both_buffers(sc->kbdc, 10);
1258 c = get_controller_command_byte(sc->kbdc);
1259 VDLOG(2, sc->dev, LOG_DEBUG,
1263 if ((c == -1) || !set_controller_command_byte(sc->kbdc,
1264 kbdc_get_device_mask(sc->kbdc),
1269 kbdc_lock(sc->kbdc, FALSE);
1270 device_log(sc->dev, LOG_ERR,
1276 if (sc->state & PSM_VALID) {
1278 disable_aux_dev(sc->kbdc);
1279 empty_aux_buffer(sc->kbdc, 10);
1282 sc->syncerrors = 0;
1283 sc->pkterrors = 0;
1284 memset(&sc->lastinputerr, 0, sizeof(sc->lastinputerr));
1289 if (doinitialize(sc, &sc->mode)) {
1291 sc->state |= PSM_VALID;
1294 restore_controller(sc->kbdc, c);
1295 sc->state &= ~PSM_VALID;
1296 device_log(sc->dev, LOG_ERR,
1304 if ((sc->state & (PSM_OPEN | PSM_EV_OPEN_R | PSM_EV_OPEN_A)) &&
1309 device_log(sc->dev, LOG_ERR,
1313 if (!set_controller_command_byte(sc->kbdc,
1314 kbdc_get_device_mask(sc->kbdc),
1318 device_log(sc->dev, LOG_ERR,
1324 kbdc_lock(sc->kbdc, FALSE);
1341 psm = BUS_ADD_CHILD(parent, KBDC_RID_AUX, driver->name, unit);
1367 --verbose; \
1368 kbdc_set_device_mask(sc->kbdc, mask); \
1369 kbdc_lock(sc->kbdc, FALSE); \
1389 sc->intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
1390 if (sc->intr == NULL) {
1395 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
1397 sc->dev = dev;
1398 sc->kbdc = atkbdc_open(device_get_unit(device_get_parent(dev)));
1399 if (sc->kbdc == NULL)
1401 sc->config = device_get_flags(dev) & PSM_CONFIG_FLAGS;
1404 sc->config |=
1411 sc->flags = 0;
1412 sc->muxport = PSM_NOMUX;
1418 if (!kbdc_lock(sc->kbdc, TRUE)) {
1421 --verbose;
1432 empty_both_buffers(sc->kbdc, 10);
1435 mask = kbdc_get_device_mask(sc->kbdc) & ~KBD_AUX_CONTROL_BITS;
1436 command_byte = get_controller_command_byte(sc->kbdc);
1439 if (command_byte == -1) {
1450 if (!set_controller_command_byte(sc->kbdc,
1458 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1459 restore_controller(sc->kbdc, command_byte);
1463 write_controller_command(sc->kbdc, KBDC_ENABLE_AUX_PORT);
1482 switch ((i = test_aux_port(sc->kbdc))) {
1493 case -1: /* time out */
1495 recover_from_error(sc->kbdc);
1496 if (sc->config & PSM_CONFIG_IGNPORTERROR)
1498 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1499 restore_controller(sc->kbdc, command_byte);
1506 if (sc->config & PSM_CONFIG_NORESET) {
1516 * Attempt to reset the controller twice -- this helps
1518 * is non-fatal.
1520 if (!reset_aux_dev(sc->kbdc)) {
1521 recover_from_error(sc->kbdc);
1522 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1523 restore_controller(sc->kbdc, command_byte);
1528 } else if (!reset_aux_dev(sc->kbdc)) {
1529 recover_from_error(sc->kbdc);
1542 if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) {
1544 recover_from_error(sc->kbdc);
1545 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1546 restore_controller(sc->kbdc, command_byte);
1553 if (get_mouse_status(sc->kbdc, stat, 0, 3) >= 3) {
1554 sc->dflt_mode.rate = sc->mode.rate = stat[2];
1555 sc->dflt_mode.resolution = sc->mode.resolution = stat[1];
1557 sc->dflt_mode.rate = sc->mode.rate = -1;
1558 sc->dflt_mode.resolution = sc->mode.resolution = -1;
1562 sc->hw.iftype = MOUSE_IF_PS2;
1565 sc->hw.hwid = get_aux_id(sc->kbdc);
1566 if (!is_a_mouse(sc->hw.hwid)) {
1567 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1568 restore_controller(sc->kbdc, command_byte);
1571 sc->hw.hwid);
1574 switch (sc->hw.hwid) {
1576 sc->hw.type = MOUSE_TRACKBALL;
1583 sc->hw.type = MOUSE_MOUSE;
1586 sc->hw.type = MOUSE_UNKNOWN;
1590 if (sc->config & PSM_CONFIG_NOIDPROBE) {
1591 sc->hw.buttons = 2;
1595 sc->hw.buttons = get_mouse_buttons(sc->kbdc);
1607 sc->hw.model = vendortype[i].model;
1609 sc->dflt_mode.level = PSM_LEVEL_BASE;
1610 sc->dflt_mode.packetsize = MOUSE_PS2_PACKETSIZE;
1611 sc->dflt_mode.accelfactor = (sc->config & PSM_CONFIG_ACCEL) >> 4;
1612 if (sc->config & PSM_CONFIG_NOCHECKSYNC)
1613 sc->dflt_mode.syncmask[0] = 0;
1615 sc->dflt_mode.syncmask[0] = vendortype[i].syncmask;
1616 if (sc->config & PSM_CONFIG_FORCETAP)
1617 sc->dflt_mode.syncmask[0] &= ~MOUSE_PS2_TAP;
1618 sc->dflt_mode.syncmask[1] = 0; /* syncbits */
1619 sc->mode = sc->dflt_mode;
1620 sc->mode.packetsize = vendortype[i].packetsize;
1629 i = send_aux_command(sc->kbdc, PSMC_SET_DEFAULTS);
1633 if (sc->config & PSM_CONFIG_RESOLUTION)
1634 sc->mode.resolution =
1635 set_mouse_resolution(sc->kbdc,
1636 (sc->config & PSM_CONFIG_RESOLUTION) - 1);
1637 else if (sc->mode.resolution >= 0)
1638 sc->mode.resolution =
1639 set_mouse_resolution(sc->kbdc, sc->dflt_mode.resolution);
1640 if (sc->mode.rate > 0)
1641 sc->mode.rate =
1642 set_mouse_sampling_rate(sc->kbdc, sc->dflt_mode.rate);
1643 set_mouse_scaling(sc->kbdc, 1);
1646 sc->flags |= PSM_NEED_SYNCBITS;
1654 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
1661 sc->dflt_mode.rate = sc->mode.rate = stat[2];
1662 sc->dflt_mode.resolution = sc->mode.resolution = stat[1];
1666 if (!set_controller_command_byte(sc->kbdc,
1674 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1675 restore_controller(sc->kbdc, command_byte);
1681 kbdc_set_device_mask(sc->kbdc, mask | KBD_AUX_CONTROL_BITS);
1682 kbdc_lock(sc->kbdc, FALSE);
1712 int y = sc->synhw.minimumYCoord + sc->synhw.maximumYCoord - f->y;
1714 evdev_push_abs(sc->evdev_a, ABS_MT_SLOT, id);
1715 evdev_push_abs(sc->evdev_a, ABS_MT_TRACKING_ID, id);
1716 evdev_push_abs(sc->evdev_a, ABS_MT_POSITION_X, f->x);
1717 evdev_push_abs(sc->evdev_a, ABS_MT_POSITION_Y, y);
1718 evdev_push_abs(sc->evdev_a, ABS_MT_PRESSURE, f->p);
1724 int y = sc->synhw.minimumYCoord + sc->synhw.maximumYCoord - f->y;
1726 evdev_push_abs(sc->evdev_a, ABS_X, f->x);
1727 evdev_push_abs(sc->evdev_a, ABS_Y, y);
1728 evdev_push_abs(sc->evdev_a, ABS_PRESSURE, f->p);
1729 if (sc->synhw.capPalmDetect)
1730 evdev_push_abs(sc->evdev_a, ABS_TOOL_WIDTH, f->w);
1743 nbuttons = sc->hw.buttons;
1805 sc->evdev_r = evdev_r;
1814 { ABS_X, sc->synhw.minimumXCoord,
1815 sc->synhw.maximumXCoord, sc->synhw.infoXupmm },
1816 { ABS_Y, sc->synhw.minimumYCoord,
1817 sc->synhw.maximumYCoord, sc->synhw.infoYupmm },
1822 { ABS_MT_SLOT, 0, PSM_FINGERS-1, 0},
1823 { ABS_MT_TRACKING_ID, -1, PSM_FINGERS-1, 0},
1824 { ABS_MT_POSITION_X, sc->synhw.minimumXCoord,
1825 sc->synhw.maximumXCoord, sc->synhw.infoXupmm },
1826 { ABS_MT_POSITION_Y, sc->synhw.minimumYCoord,
1827 sc->synhw.maximumYCoord, sc->synhw.infoYupmm },
1840 if (sc->synhw.capAdvancedGestures || sc->synhw.capReportsV)
1842 if (sc->synhw.capReportsV)
1849 if (sc->synhw.capAdvancedGestures)
1851 if (sc->synhw.capClickPad)
1853 if (sc->synhw.capClickPad && sc->synhw.topButtonPad)
1856 evdev_support_nfingers(evdev_a, sc->synhw.capReportsV ? 5 : 3);
1858 if (sc->synhw.capAdvancedGestures || sc->synhw.capReportsV)
1860 if (sc->synhw.capPalmDetect)
1863 if (!sc->synhw.capClickPad) {
1865 if (sc->synhw.capExtended && sc->synhw.capMiddle)
1868 if (sc->synhw.capExtended && sc->synhw.capFourButtons) {
1872 if (sc->synhw.capExtended && (sc->synhw.nExtendedButtons > 0))
1873 for (i = 0; i < sc->synhw.nExtendedButtons; i++)
1877 if (!error && (sc->synhw.capPassthrough || sc->muxport != PSM_NOMUX)) {
1878 guest_model = sc->tpinfo.sysctl_tree != NULL ?
1885 sc->evdev_a = evdev_a;
1894 { ABS_X, 0, sc->elanhw.sizex,
1895 sc->elanhw.dpmmx },
1896 { ABS_Y, 0, sc->elanhw.sizey,
1897 sc->elanhw.dpmmy },
1900 { ABS_MT_SLOT, 0, ELANTECH_MAX_FINGERS - 1, 0 },
1901 { ABS_MT_TRACKING_ID, -1, ELANTECH_MAX_FINGERS - 1, 0 },
1902 { ABS_MT_POSITION_X, 0, sc->elanhw.sizex,
1903 sc->elanhw.dpmmx },
1904 { ABS_MT_POSITION_Y, 0, sc->elanhw.sizey,
1905 sc->elanhw.dpmmy },
1908 sc->elanhw.dptracex, 0 },
1926 if (sc->elanhw.issemimt)
1928 if (sc->elanhw.isclickpad)
1933 if (!sc->elanhw.isclickpad)
1938 if (!error && sc->elanhw.hastrackpoint)
1943 sc->evdev_a = evdev_a;
1958 sc->state = PSM_VALID;
1959 callout_init(&sc->callout, 0);
1960 callout_init(&sc->softcallout, 0);
1961 knlist_init_mtx(&sc->rsel.si_note, &Giant);
1965 sc->intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
1966 if (sc->intr == NULL)
1968 error = bus_setup_intr(dev, sc->intr, INTR_TYPE_TTY, NULL, psmintr, sc,
1969 &sc->ih);
1979 if ((error = make_dev_s(&mda, &sc->cdev, "psm%d", unit)) != 0)
1981 if ((error = make_dev_s(&mda, &sc->bdev, "bpsm%d", unit)) != 0)
1985 switch (sc->hw.model) {
1995 error = psm_register(dev, sc->hw.model);
2003 switch (sc->hw.model) {
2008 sc->config |= PSM_CONFIG_INITAFTERSUSPEND;
2011 if (sc->synhw.infoMajor >= 4 || sc->tpinfo.sysctl_tree != NULL)
2012 sc->config |= PSM_CONFIG_INITAFTERSUSPEND;
2017 if (sc->hw.model == MOUSE_MODEL_ELANTECH &&
2018 (sc->elanhw.hascrc || sc->elanhw.hastrackpoint)) {
2019 sc->config |= PSM_CONFIG_NOCHECKSYNC;
2020 sc->flags &= ~PSM_NEED_SYNCBITS;
2025 model_name(sc->hw.model), sc->hw.hwid & 0x00ff);
2027 device_printf(dev, "model %s, device ID %d-%02x, %d buttons\n",
2028 model_name(sc->hw.model), sc->hw.hwid & 0x00ff,
2029 sc->hw.hwid >> 8, sc->hw.buttons);
2031 sc->config, sc->flags, sc->mode.packetsize);
2033 sc->mode.syncmask[0], sc->mode.syncmask[1],
2034 sc->config & PSM_CONFIG_NOCHECKSYNC ? " (sync not checked)" : "");
2038 --verbose;
2042 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
2043 if (sc->dev != NULL)
2044 destroy_dev(sc->cdev);
2045 if (sc->bdev != NULL)
2046 destroy_dev(sc->bdev);
2058 if (sc->state & PSM_OPEN)
2062 evdev_free(sc->evdev_r);
2063 evdev_free(sc->evdev_a);
2067 bus_teardown_intr(dev, sc->intr, sc->ih);
2068 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
2070 destroy_dev(sc->cdev);
2071 destroy_dev(sc->bdev);
2073 knlist_clear(&sc->rsel.si_note, 1);
2074 knlist_destroy(&sc->rsel.si_note);
2075 callout_drain(&sc->callout);
2076 callout_drain(&sc->softcallout);
2089 if ((sc->state & PSM_VALID) == 0) {
2094 if (!(sc->state & (PSM_OPEN | PSM_EV_OPEN_A)))
2098 sc->state |= PSM_EV_OPEN_R;
2109 sc->state &= ~PSM_EV_OPEN_R;
2111 if (sc->state & (PSM_OPEN | PSM_EV_OPEN_A))
2114 if (sc->state & PSM_VALID)
2127 if ((sc->state & PSM_VALID) == 0) {
2132 if (!(sc->state & (PSM_OPEN | PSM_EV_OPEN_R)))
2136 sc->state |= PSM_EV_OPEN_A;
2147 sc->state &= ~PSM_EV_OPEN_A;
2149 if (sc->state & (PSM_OPEN | PSM_EV_OPEN_R))
2152 if (sc->state & PSM_VALID)
2166 sc = dev->si_drv1;
2167 if ((sc == NULL) || (sc->state & PSM_VALID) == 0) {
2173 if (sc->state & PSM_OPEN)
2176 device_busy(sc->dev);
2180 if (!(sc->state & (PSM_EV_OPEN_R | PSM_EV_OPEN_A)))
2185 sc->state |= PSM_OPEN;
2187 device_unbusy(sc->dev);
2199 sc = dev->si_drv1;
2200 if ((sc == NULL) || (sc->state & PSM_VALID) == 0) {
2207 if (!(sc->state & (PSM_EV_OPEN_R | PSM_EV_OPEN_A)))
2212 sc->state &= ~PSM_OPEN;
2214 if (sc->async != NULL) {
2215 funsetown(&sc->async);
2216 sc->async = NULL;
2218 device_unbusy(sc->dev);
2232 sc->mode.level = sc->dflt_mode.level;
2233 sc->mode.protocol = sc->dflt_mode.protocol;
2234 sc->watchdog = FALSE;
2235 sc->async = NULL;
2238 sc->queue.count = 0;
2239 sc->queue.head = 0;
2240 sc->queue.tail = 0;
2241 sc->status.flags = 0;
2242 sc->status.button = 0;
2243 sc->status.obutton = 0;
2244 sc->status.dx = 0;
2245 sc->status.dy = 0;
2246 sc->status.dz = 0;
2247 sc->button = 0;
2248 sc->pqueue_start = 0;
2249 sc->pqueue_end = 0;
2253 sc->syncerrors = 0;
2254 sc->pkterrors = 0;
2257 if (!kbdc_lock(sc->kbdc, TRUE))
2262 command_byte = get_controller_command_byte(sc->kbdc);
2265 if (command_byte == -1 || !set_controller_command_byte(sc->kbdc,
2266 kbdc_get_device_mask(sc->kbdc),
2270 kbdc_lock(sc->kbdc, FALSE);
2272 device_log(sc->dev, LOG_ERR,
2289 kbdc_lock(sc->kbdc, FALSE);
2301 if (!kbdc_lock(sc->kbdc, TRUE))
2306 command_byte = get_controller_command_byte(sc->kbdc);
2307 if (command_byte == -1) {
2308 kbdc_lock(sc->kbdc, FALSE);
2314 if (!set_controller_command_byte(sc->kbdc,
2315 kbdc_get_device_mask(sc->kbdc),
2318 device_log(sc->dev, LOG_ERR,
2330 callout_stop(&sc->callout);
2333 empty_aux_buffer(sc->kbdc, 10);
2336 if (sc->state & PSM_VALID) {
2337 if (!disable_aux_dev(sc->kbdc)) {
2344 device_log(sc->dev, LOG_ERR,
2348 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
2349 device_log(sc->dev, LOG_DEBUG,
2353 if (!set_controller_command_byte(sc->kbdc,
2354 kbdc_get_device_mask(sc->kbdc),
2361 device_log(sc->dev, LOG_ERR,
2366 empty_aux_buffer(sc->kbdc, 10);
2369 kbdc_lock(sc->kbdc, FALSE);
2402 if (sc->mode.level == PSM_LEVEL_BASE) {
2403 mapped = status->button & ~MOUSE_BUTTON4DOWN;
2404 if (status->button & MOUSE_BUTTON4DOWN)
2406 status->button = mapped;
2408 i = imax(imin(status->dx, 255), -256);
2412 i = imax(imin(status->dy, 255), -256);
2417 } else if (sc->mode.level == PSM_LEVEL_STANDARD) {
2419 butmapmsc[status->button & MOUSE_STDBUTTONS];
2420 i = imax(imin(status->dx, 255), -256);
2422 buf[3] = i - buf[1];
2423 i = imax(imin(status->dy, 255), -256);
2425 buf[4] = i - buf[2];
2426 i = imax(imin(status->dz, 127), -128);
2428 buf[6] = (i - (i >> 1)) & 0x7f;
2429 buf[7] = (~status->button >> 3) & 0x7f;
2432 return (pb->inputbytes);
2438 struct psm_softc *sc = dev->si_drv1;
2444 if ((sc->state & PSM_VALID) == 0)
2449 while (sc->queue.count <= 0) {
2450 if (dev != sc->bdev) {
2454 sc->state |= PSM_ASLP;
2456 sc->state &= ~PSM_ASLP;
2460 } else if ((sc->state & PSM_VALID) == 0) {
2469 while ((sc->queue.count > 0) && (uio->uio_resid > 0)) {
2471 l = imin(sc->queue.count, uio->uio_resid);
2474 if (l > sizeof(sc->queue.buf) - sc->queue.head) {
2475 bcopy(&sc->queue.buf[sc->queue.head], &buf[0],
2476 sizeof(sc->queue.buf) - sc->queue.head);
2477 bcopy(&sc->queue.buf[0],
2478 &buf[sizeof(sc->queue.buf) - sc->queue.head],
2479 l - (sizeof(sc->queue.buf) - sc->queue.head));
2481 bcopy(&sc->queue.buf[sc->queue.head], &buf[0], l);
2482 sc->queue.count -= l;
2483 sc->queue.head = (sc->queue.head + l) % sizeof(sc->queue.buf);
2498 if (!kbdc_lock(sc->kbdc, TRUE))
2502 *c = get_controller_command_byte(sc->kbdc);
2503 if ((*c == -1) || !set_controller_command_byte(sc->kbdc,
2504 kbdc_get_device_mask(sc->kbdc),
2509 kbdc_lock(sc->kbdc, FALSE);
2525 empty_aux_buffer(sc->kbdc, 0); /* flush the queue */
2526 read_aux_data_no_wait(sc->kbdc); /* throw away data if any */
2537 sc->queue.count = 0;
2538 sc->queue.head = 0;
2539 sc->queue.tail = 0;
2540 if ((sc->state & PSM_SOFTARMED) != 0) {
2541 sc->state &= ~PSM_SOFTARMED;
2542 callout_stop(&sc->softcallout);
2544 sc->pqueue_start = sc->pqueue_end;
2552 bzero(&sc->pqueue, sizeof(sc->pqueue));
2564 empty_aux_buffer(sc->kbdc, 0);
2567 if (!set_controller_command_byte(sc->kbdc,
2568 kbdc_get_device_mask(sc->kbdc),
2578 kbdc_lock(sc->kbdc, FALSE);
2585 struct psm_softc *sc = dev->si_drv1;
2589 if ((sc->state & PSM_VALID) == 0)
2592 if (sc->mode.level < PSM_LEVEL_NATIVE)
2596 while (uio->uio_resid > 0) {
2597 l = imin(PSM_SMALLBUFSIZE, uio->uio_resid);
2602 VDLOG(4, sc->dev, LOG_DEBUG, "cmd 0x%x\n", buf[i]);
2603 if (!write_aux_command(sc->kbdc, buf[i])) {
2604 VDLOG(2, sc->dev, LOG_DEBUG,
2618 struct psm_softc *sc = dev->si_drv1;
2631 ((old_mousehw_t *)addr)->buttons = sc->hw.buttons;
2632 ((old_mousehw_t *)addr)->iftype = sc->hw.iftype;
2633 ((old_mousehw_t *)addr)->type = sc->hw.type;
2634 ((old_mousehw_t *)addr)->hwid = sc->hw.hwid & 0x00ff;
2640 *(mousehw_t *)addr = sc->hw;
2641 if (sc->mode.level == PSM_LEVEL_BASE)
2642 ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
2648 if (sc->synhw.infoMajor >= 4)
2649 *(synapticshw_t *)addr = sc->synhw;
2657 switch (sc->mode.level) {
2659 ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
2662 ((old_mousemode_t *)addr)->protocol =
2666 ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
2669 ((old_mousemode_t *)addr)->rate = sc->mode.rate;
2670 ((old_mousemode_t *)addr)->resolution = sc->mode.resolution;
2671 ((old_mousemode_t *)addr)->accelfactor = sc->mode.accelfactor;
2677 *(mousemode_t *)addr = sc->mode;
2678 if ((sc->flags & PSM_NEED_SYNCBITS) != 0) {
2679 ((mousemode_t *)addr)->syncmask[0] = 0;
2680 ((mousemode_t *)addr)->syncmask[1] = 0;
2682 ((mousemode_t *)addr)->resolution =
2683 MOUSE_RES_LOW - sc->mode.resolution;
2684 switch (sc->mode.level) {
2686 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
2687 ((mousemode_t *)addr)->packetsize =
2691 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
2692 ((mousemode_t *)addr)->packetsize =
2694 ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
2695 ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
2699 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
2708 mode.rate = ((old_mousemode_t *)addr)->rate;
2712 * low 1 -2
2713 * medium low 2 -3
2714 * medium high 3 -4
2715 * high 4 -5
2717 if (((old_mousemode_t *)addr)->resolution > 0)
2719 -((old_mousemode_t *)addr)->resolution - 1;
2723 ((old_mousemode_t *)addr)->accelfactor;
2724 mode.level = -1;
2729 if (mode.rate > UCHAR_MAX)
2731 if (mode.rate == 0)
2732 mode.rate = sc->dflt_mode.rate;
2733 else if (mode.rate == -1)
2736 else if (mode.rate < 0)
2749 mode.resolution = sc->dflt_mode.resolution;
2750 else if (mode.resolution == -1)
2754 mode.resolution = MOUSE_RES_LOW - mode.resolution;
2755 if (mode.level == -1)
2757 mode.level = sc->mode.level;
2761 if (mode.accelfactor == -1)
2763 mode.accelfactor = sc->mode.accelfactor;
2773 if (mode.rate > 0)
2774 mode.rate = set_mouse_sampling_rate(sc->kbdc,
2775 mode.rate);
2778 set_mouse_resolution(sc->kbdc, mode.resolution);
2779 set_mouse_scaling(sc->kbdc, 1);
2780 get_mouse_status(sc->kbdc, stat, 0, 3);
2783 sc->mode.rate = mode.rate;
2784 sc->mode.resolution = mode.resolution;
2785 sc->mode.accelfactor = mode.accelfactor;
2786 sc->mode.level = mode.level;
2793 *(int *)addr = sc->mode.level;
2800 sc->mode.level = *(int *)addr;
2805 status = sc->status;
2806 sc->status.flags = 0;
2807 sc->status.obutton = sc->status.button;
2808 sc->status.button = 0;
2809 sc->status.dx = 0;
2810 sc->status.dy = 0;
2811 sc->status.dz = 0;
2819 if (data->len > sizeof(data->buf)/sizeof(data->buf[0]))
2825 if ((data->len = get_mouse_status(sc->kbdc, data->buf,
2826 (cmd == MOUSE_READDATA) ? 1 : 0, data->len)) <= 0)
2845 mode.resolution = sc->dflt_mode.resolution;
2846 else if (mode.resolution == -1)
2847 mode.resolution = sc->mode.resolution;
2849 mode.resolution = MOUSE_RES_LOW - mode.resolution;
2854 sc->mode.resolution =
2855 set_mouse_resolution(sc->kbdc, mode.resolution);
2856 if (sc->mode.resolution != mode.resolution)
2864 mode.rate = *(int *)addr;
2865 if (mode.rate > UCHAR_MAX)
2867 if (mode.rate == 0)
2868 mode.rate = sc->dflt_mode.rate;
2869 else if (mode.rate < 0)
2870 mode.rate = sc->mode.rate;
2875 sc->mode.rate = set_mouse_sampling_rate(sc->kbdc, mode.rate);
2876 if (sc->mode.rate != mode.rate)
2890 if (!set_mouse_scaling(sc->kbdc, *(int *)addr))
2901 sc->hw.hwid &= ~0x00ff;
2902 sc->hw.hwid |= get_aux_id(sc->kbdc);
2903 *(int *)addr = sc->hw.hwid & 0x00ff;
2912 error = fsetown(*(int *)addr, &sc->async);
2915 *(int *) addr = fgetown(&sc->async);
2932 if (sc->watchdog && kbdc_lock(sc->kbdc, TRUE)) {
2933 VDLOG(6, sc->dev, LOG_DEBUG, "lost interrupt?\n");
2935 kbdc_lock(sc->kbdc, FALSE);
2937 sc->watchdog = TRUE;
2939 callout_reset(&sc->callout, hz, psmtimeout, sc);
3000 if (aux_mux_is_enabled(sc->kbdc))
3005 while((c = read_aux_data_no_wait(sc->kbdc)) != -1) {
3006 pb = &sc->pqueue[sc->pqueue_end];
3009 if (!(sc->state & (PSM_OPEN | PSM_EV_OPEN_R | PSM_EV_OPEN_A)))
3013 if ((pb->inputbytes > 0) &&
3014 timevalcmp(&now, &sc->inputtimeout, >)) {
3017 pb->inputbytes = 0;
3018 sc->syncerrors = 0;
3019 sc->pkterrors = 0;
3021 sc->inputtimeout.tv_sec = PSM_INPUT_TIMEOUT / 1000000;
3022 sc->inputtimeout.tv_usec = PSM_INPUT_TIMEOUT % 1000000;
3023 timevaladd(&sc->inputtimeout, &now);
3025 pb->ipacket[pb->inputbytes++] = c;
3027 if (sc->mode.level == PSM_LEVEL_NATIVE) {
3028 VLOG(4, (LOG_DEBUG, "psmintr: %02x\n", pb->ipacket[0]));
3029 sc->syncerrors = 0;
3030 sc->pkterrors = 0;
3033 if (pb->inputbytes < sc->mode.packetsize)
3038 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2],
3039 pb->ipacket[3], pb->ipacket[4], pb->ipacket[5]));
3042 c = pb->ipacket[0];
3044 if ((sc->flags & PSM_NEED_SYNCBITS) != 0) {
3045 sc->mode.syncmask[1] = (c & sc->mode.syncmask[0]);
3046 sc->flags &= ~PSM_NEED_SYNCBITS;
3049 sc->mode.syncmask[0], sc->mode.syncmask[1]));
3050 } else if ((sc->config & PSM_CONFIG_NOCHECKSYNC) == 0 &&
3051 (c & sc->mode.syncmask[0]) != sc->mode.syncmask[1]) {
3054 c & sc->mode.syncmask[0], sc->mode.syncmask[1],
3055 sc->cmdcount - sc->lasterr));
3056 sc->lasterr = sc->cmdcount;
3065 if (sc->syncerrors == 0)
3066 sc->pkterrors++;
3067 ++sc->syncerrors;
3068 sc->lastinputerr = now;
3069 if (sc->syncerrors >= sc->mode.packetsize * 2 ||
3070 sc->pkterrors >= pkterrthresh) {
3082 } else if (sc->syncerrors == sc->mode.packetsize) {
3088 "psmintr: re-enable the mouse.\n"));
3089 pb->inputbytes = 0;
3090 disable_aux_dev(sc->kbdc);
3091 enable_aux_dev(sc->kbdc);
3095 sc->syncerrors));
3096 pb->inputbytes--;
3097 bcopy(&pb->ipacket[1], &pb->ipacket[0],
3098 pb->inputbytes);
3107 sc->syncerrors = 0;
3116 if (!timeelapsed(&sc->lastinputerr, psmerrsecs, psmerrusecs,
3118 pb->inputbytes = 0;
3126 sc->pkterrors = 0;
3128 sc->cmdcount++;
3130 if (++sc->pqueue_end >= PSM_PACKETQUEUE)
3131 sc->pqueue_end = 0;
3138 if (sc->hw.model == MOUSE_MODEL_SYNAPTICS ||
3139 sc->hw.model == MOUSE_MODEL_ELANTECH ||
3140 !timeelapsed(&sc->lastsoftintr, psmsecs, psmusecs, &now) ||
3141 (sc->pqueue_end == sc->pqueue_start)) {
3142 if ((sc->state & PSM_SOFTARMED) != 0) {
3143 sc->state &= ~PSM_SOFTARMED;
3144 callout_stop(&sc->softcallout);
3147 } else if ((sc->state & PSM_SOFTARMED) == 0) {
3148 sc->state |= PSM_SOFTARMED;
3149 callout_reset(&sc->softcallout,
3156 proc_mmanplus(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, argument
3167 * p3-p0: packet type
3183 * d2-d0: roller data
3187 if (((pb->ipacket[0] & MOUSE_PS2PLUS_SYNCMASK) == MOUSE_PS2PLUS_SYNC) &&
3188 (abs(*x) > 191) && MOUSE_PS2PLUS_CHECKBITS(pb->ipacket)) {
3193 switch (MOUSE_PS2PLUS_PACKET_TYPE(pb->ipacket)) {
3197 if (pb->ipacket[2] & 0x80) {
3198 /* XXX horizontal roller count - ignore it */
3202 *z = (pb->ipacket[2] & MOUSE_PS2PLUS_ZNEG) ?
3203 (pb->ipacket[2] & 0x0f) - 16 :
3204 (pb->ipacket[2] & 0x0f);
3206 ms->button |= (pb->ipacket[2] &
3209 ms->button |= (pb->ipacket[2] &
3225 if (pb->ipacket[2] & 0x0f)
3226 *z = (pb->ipacket[2] & MOUSE_SPOINT_WNEG) ?
3227 -2 : 2;
3229 if (pb->ipacket[2] & 0xf0)
3230 *z = (pb->ipacket[2] & MOUSE_SPOINT_ZNEG) ?
3231 -1 : 1;
3234 /* device type packet - shouldn't happen */
3238 ms->button = ms->obutton;
3241 MOUSE_PS2PLUS_PACKET_TYPE(pb->ipacket),
3242 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2]));
3247 ms->button |= ms->obutton & MOUSE_EXTBUTTONS;
3252 proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, argument
3266 * ------------------------------------------------
3287 * ------------------------------------------------------
3295 * b1-b8: Extended mouse buttons
3299 * Absolute reportable limits: 0 - 6143.
3300 * Typical bezel limits: 1472 - 5472.
3301 * Typical edge marings: 1632 - 5312.
3312 if ((pb->ipacket[0] & 0xc8) != 0x80 ||
3313 (pb->ipacket[3] & 0xc8) != 0xc0)
3314 return (-1);
3317 ms->button = ms->obutton;
3330 *z = pb->ipacket[2];
3339 * w = 4-7 Finger of normal width (capPalmDetect needed)
3340 * w = 8-14 Very wide finger or palm (capPalmDetect needed)
3344 if (sc->synhw.capExtended)
3345 w = ((pb->ipacket[0] & 0x30) >> 2) |
3346 ((pb->ipacket[0] & 0x04) >> 1) |
3347 ((pb->ipacket[3] & 0x04) >> 2);
3359 if (sc->synhw.capPassthrough || sc->muxport != PSM_NOMUX) {
3360 *x = ((pb->ipacket[1] & 0x10) ?
3361 pb->ipacket[4] - 256 : pb->ipacket[4]);
3362 *y = ((pb->ipacket[1] & 0x20) ?
3363 pb->ipacket[5] - 256 : pb->ipacket[5]);
3367 if (pb->ipacket[1] & 0x01)
3369 if (pb->ipacket[1] & 0x04)
3371 if (pb->ipacket[1] & 0x02)
3375 evdev_push_rel(sc->evdev_r, REL_X, *x);
3376 evdev_push_rel(sc->evdev_r, REL_Y, -*y);
3377 evdev_push_mouse_btn(sc->evdev_r,
3378 guest_buttons | sc->extended_buttons);
3379 evdev_sync(sc->evdev_r);
3382 ms->button = touchpad_buttons | guest_buttons |
3383 sc->extended_buttons;
3389 ewcode = (pb->ipacket[5] & 0xf0) >> 4;
3394 if (sc->synhw.capAdvancedGestures)
3396 .x = (((pb->ipacket[4] & 0x0f) << 8) |
3397 pb->ipacket[1]) << 1,
3398 .y = (((pb->ipacket[4] & 0xf0) << 4) |
3399 pb->ipacket[2]) << 1,
3400 .p = ((pb->ipacket[3] & 0x30) |
3401 (pb->ipacket[5] & 0x0f)) << 1,
3405 else if (sc->synhw.capReportsV)
3407 .x = (((pb->ipacket[4] & 0x0f) << 8) |
3408 (pb->ipacket[1] & 0xfe)) << 1,
3409 .y = (((pb->ipacket[4] & 0xf0) << 4) |
3410 (pb->ipacket[2] & 0xfe)) << 1,
3411 .p = ((pb->ipacket[3] & 0x30) |
3412 (pb->ipacket[5] & 0x0e)) << 1,
3413 .w = (((pb->ipacket[5] & 0x01) << 2) |
3414 ((pb->ipacket[2] & 0x01) << 1) |
3415 (pb->ipacket[1] & 0x01)) + 8,
3420 ew_finger_count = pb->ipacket[1] & 0x0f;
3428 if (sc->synhw.capReportsV && ew_finger_count > 3) {
3441 if (sc->syninfo.touchpad_off)
3446 if (pb->ipacket[0] & 0x01)
3448 if (pb->ipacket[0] & 0x02)
3451 if (sc->synhw.capExtended && sc->synhw.capFourButtons) {
3452 if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x01)
3454 if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x02)
3456 } else if (sc->synhw.capExtended && sc->synhw.capMiddle &&
3457 !sc->synhw.capClickPad) {
3459 if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01)
3461 } else if (sc->synhw.capExtended && (sc->synhw.nExtendedButtons > 0)) {
3463 if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x02) {
3464 if (sc->syninfo.directional_scrolls) {
3465 if (pb->ipacket[4] & 0x01)
3467 if (pb->ipacket[5] & 0x01)
3469 if (pb->ipacket[4] & 0x02)
3471 if (pb->ipacket[5] & 0x02)
3474 if (pb->ipacket[4] & 0x01)
3476 if (pb->ipacket[5] & 0x01)
3478 if (pb->ipacket[4] & 0x02)
3480 sc->extended_buttons = extended_buttons;
3494 * (1 << n) - 1
3498 maskedbits = (sc->synhw.nExtendedButtons + 1) >> 1;
3499 mask = (1 << maskedbits) - 1;
3503 if (sc->synhw.capPassthrough) {
3504 evdev_push_mouse_btn(sc->evdev_r,
3506 evdev_sync(sc->evdev_r);
3509 evdev_push_key(sc->evdev_a,
3511 pb->ipacket[4] & (1 << i));
3512 evdev_push_key(sc->evdev_a,
3514 pb->ipacket[5] & (1 << i));
3518 pb->ipacket[4] &= ~(mask);
3519 pb->ipacket[5] &= ~(mask);
3520 } else if (!sc->syninfo.directional_scrolls &&
3521 !sc->gesture.in_vscroll) {
3526 extended_buttons |= sc->extended_buttons;
3530 if (sc->synhw.capReportsV && nfingers > 1)
3532 .x = ((pb->ipacket[3] & 0x10) << 8) |
3533 ((pb->ipacket[1] & 0x0f) << 8) |
3534 (pb->ipacket[4] & 0xfd),
3535 .y = ((pb->ipacket[3] & 0x20) << 7) |
3536 ((pb->ipacket[1] & 0xf0) << 4) |
3537 (pb->ipacket[5] & 0xfd),
3539 .w = (((pb->ipacket[2] & 0x01) << 2) |
3540 (pb->ipacket[5] & 0x02) |
3541 ((pb->ipacket[4] & 0x02) >> 1)) + 8,
3546 .x = ((pb->ipacket[3] & 0x10) << 8) |
3547 ((pb->ipacket[1] & 0x0f) << 8) |
3548 pb->ipacket[4],
3549 .y = ((pb->ipacket[3] & 0x20) << 7) |
3550 ((pb->ipacket[1] & 0xf0) << 4) |
3551 pb->ipacket[5],
3558 if (f[0].p < sc->syninfo.min_pressure || f[0].x < 2)
3562 if (sc->synhw.capClickPad) {
3563 clickpad_pressed = (pb->ipacket[0] ^ pb->ipacket[3]) & 0x01;
3564 if (sc->synhw.forcePad) {
3575 sc->fpcount = 0;
3578 if (clickpad_pressed && sc->fpcount < INT_MAX)
3579 ++sc->fpcount;
3583 sc->fpcount = 0;
3584 if (sc->fpcount >= sc->syninfo.window_min)
3600 evdev_push_key(sc->evdev_a, BTN_TOUCH, nfingers > 0);
3601 evdev_push_nfingers(sc->evdev_a, nfingers);
3605 evdev_push_abs(sc->evdev_a, ABS_PRESSURE, 0);
3606 evdev_push_mouse_btn(sc->evdev_a, touchpad_buttons);
3607 if (sc->synhw.capExtended && sc->synhw.capFourButtons) {
3608 evdev_push_key(sc->evdev_a, BTN_FORWARD,
3610 evdev_push_key(sc->evdev_a, BTN_BACK,
3613 evdev_sync(sc->evdev_a);
3617 ms->button = touchpad_buttons;
3623 psmgestures(sc, &f[0], nfingers, ms);
3626 psmsmoother(sc, &f[id], id, ms, x, y);
3630 ms->button = ms->obutton;
3634 ms->button |= extended_buttons | guest_buttons;
3644 * xf86-input-mouse needs therefore a small patch to
3651 if (ms->button & MOUSE_BUTTON4DOWN)
3652 *z = -1;
3653 else if (ms->button & MOUSE_BUTTON5DOWN)
3655 else if (ms->button & MOUSE_BUTTON6DOWN)
3656 *z = -2;
3657 else if (ms->button & MOUSE_BUTTON7DOWN)
3661 ms->button &= ~(MOUSE_BUTTON4DOWN | MOUSE_BUTTON5DOWN |
3673 * Convert 3-byte interleaved mixture of Synaptics and generic mouse
3674 * packets into plain 6-byte Synaptics packet protocol.
3682 switch (pb->ipacket[0] & 0xc0) {
3684 bcopy(pb->ipacket, sc->muxsave, 3);
3686 sc->muxmidtimeout.tv_sec = 0;
3687 sc->muxmidtimeout.tv_usec = 50000; /* ~2-3 ints */
3688 timevaladd(&sc->muxmidtimeout, &sc->lastsoftintr);
3692 /* Join two 3-bytes absolute packets */
3693 bcopy(pb->ipacket, pb->ipacket + 3, 3);
3694 bcopy(sc->muxsave, pb->ipacket, 3);
3696 pb->ipacket[0] &= ~(0x08 | sc->muxmsbuttons);
3697 pb->ipacket[3] &= ~(0x08 | sc->muxmsbuttons);
3698 butt = (pb->ipacket[3] & 0x03) << 2 | (pb->ipacket[0] & 0x03);
3700 if (butt != sc->muxtpbuttons && sc->fpcount < 1) {
3701 pb->ipacket[0] &= 0xfc;
3702 pb->ipacket[0] |= sc->muxtpbuttons & 0x03;
3703 pb->ipacket[3] &= 0xfc;
3704 pb->ipacket[3] |= sc->muxtpbuttons >> 2 & 0x03;
3705 ++sc->fpcount;
3707 sc->fpcount = 0;
3708 sc->muxtpbuttons = butt;
3711 if (sc->synhw.capExtended && !sc->synhw.capPassthrough &&
3712 (pb->ipacket[0] & 0x34) == 0x04 &&
3713 (pb->ipacket[3] & 0x04) == 0x04) {
3714 pb->ipacket[0] &= 0xfb;
3715 pb->ipacket[3] &= 0xfb;
3717 sc->muxsave[0] &= 0x30;
3722 if (sc->muxmsbuttons & 0x03 || pb->ipacket[0] & 0x03 ||
3723 (timevalcmp(&sc->lastsoftintr, &sc->muxmidtimeout, <=) &&
3724 (sc->muxsave[0] & 0x30 || sc->muxsave[2] > 8)))
3725 pb->ipacket[0] &= 0xfb;
3726 sc->muxmsbuttons = pb->ipacket[0] & 0x07;
3727 /* Convert to Synaptics pass-through protocol */
3728 pb->ipacket[4] = pb->ipacket[1];
3729 pb->ipacket[5] = pb->ipacket[2];
3730 pb->ipacket[1] = pb->ipacket[0];
3731 pb->ipacket[2] = 0;
3732 pb->ipacket[0] = 0x84 | (sc->muxtpbuttons & 0x03);
3733 pb->ipacket[3] = 0xc4 | (sc->muxtpbuttons >> 2 & 0x03);
3737 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2],
3738 pb->ipacket[3], pb->ipacket[4], pb->ipacket[5]));
3740 pb->inputbytes = MOUSE_SYNAPTICS_PACKETSIZE;
3748 ((sc->synhw.capMultiFinger || sc->synhw.capAdvancedGestures) &&
3749 !sc->synhw.capReportsV && nfingers > 1) ||
3750 (sc->synhw.capReportsV && nfingers > 2) ||
3751 (sc->synhw.capPalmDetect && f->w <= sc->syninfo.max_width) ||
3752 (!sc->synhw.capPalmDetect && f->p <= sc->syninfo.max_pressure) ||
3753 (sc->synhw.capPen && f->flags & PSM_FINGER_IS_PEN))) {
3757 * - the width isn't comprised in:
3759 * - the pressure isn't comprised in:
3761 * - pen aren't supported but PSM_FINGER_IS_PEN is set
3763 VLOG(2, (LOG_DEBUG, "synaptics: palm detected! (%d)\n", f->w));
3771 mousestatus_t *ms) argument
3779 smoother = &sc->smoother[0];
3780 gest = &sc->gesture;
3787 smoother = &sc->smoother[i];
3797 if (f->p >= sc->syninfo.min_pressure) {
3811 margin_top = sc->syninfo.margin_top;
3812 margin_right = sc->syninfo.margin_right;
3813 margin_bottom = sc->syninfo.margin_bottom;
3814 margin_left = sc->syninfo.margin_left;
3815 window_min = sc->syninfo.window_min;
3816 window_max = sc->syninfo.window_max;
3817 vscroll_hor_area = sc->syninfo.vscroll_hor_area;
3818 vscroll_ver_area = sc->syninfo.vscroll_ver_area;
3819 two_finger_scroll = sc->syninfo.two_finger_scroll;
3820 max_x = sc->syninfo.max_x;
3821 max_y = sc->syninfo.max_y;
3822 three_finger_drag = sc->syninfo.three_finger_drag;
3824 x0 = f->x;
3825 y0 = f->y;
3833 else if (x0 >= max_x - margin_right)
3834 x0 = max_x - margin_right;
3837 else if (y0 >= max_y - margin_top)
3838 y0 = max_y - margin_top;
3841 x0, y0, f->p, f->w));
3847 if (!(sc->flags & PSM_FLAGS_FINGERDOWN)) {
3848 VLOG(3, (LOG_DEBUG, "synaptics: ----\n"));
3851 gest->window_min = window_min;
3854 gest->zmax = 0;
3857 gest->fingers_nb = 0;
3860 gest->in_vscroll = 0;
3864 gest->taptimeout = (struct timeval) {
3869 &gest->taptimeout, &sc->lastsoftintr);
3871 timevalclear(&gest->taptimeout);
3873 sc->flags |= PSM_FLAGS_FINGERDOWN;
3880 queue_len = smoother->queue_len + 1;
3881 start_x = smoother->start_x;
3882 start_y = smoother->start_y;
3886 if (sc->synhw.capClickPad && ms->button & MOUSE_BUTTON1DOWN) {
3887 y_ok = sc->syninfo.softbuttons_y >= 0 ?
3888 start_y < sc->syninfo.softbuttons_y :
3889 start_y > max_y + sc->syninfo.softbuttons_y;
3892 center_x = sc->syninfo.softbutton2_x;
3894 right_x = sc->syninfo.softbutton3_x;
3898 center_x = sc->syninfo.softbutton3_x;
3900 right_x = sc->syninfo.softbutton2_x;
3904 ms->button = (ms->button &
3907 ms->button = (ms->button &
3911 /* If in tap-hold or three fingers, add the recorded button. */
3912 if (gest->in_taphold || (nfingers == 3 && three_finger_drag))
3913 ms->button |= gest->tap_button;
3921 gest->window_min = window_max;
3922 gest->fingers_nb = imax(nfingers, gest->fingers_nb);
3923 gest->zmax = imax(f->p, gest->zmax);
3926 if (queue_len < gest->window_min)
3929 dyp = -1;
3930 dxp = -1;
3933 if (!gest->in_taphold && !ms->button &&
3934 (!gest->in_vscroll || two_finger_scroll)) {
3939 * - the action in a configurable area
3940 * - one of the following:
3945 dxp = abs(x0 - start_x);
3946 dyp = abs(y0 - start_y);
3948 if (timevalcmp(&sc->lastsoftintr, &gest->taptimeout, >) ||
3949 dxp >= sc->syninfo.vscroll_min_delta ||
3950 dyp >= sc->syninfo.vscroll_min_delta) {
3958 gest->in_vscroll +=
3960 gest->in_vscroll +=
3970 gest->in_vscroll += 2;
3978 gest->in_vscroll += 1;
3982 if (gest->in_vscroll >= 3)
3983 gest->in_vscroll =
3991 if (two_finger_scroll && gest->in_vscroll != 0 &&
3992 (nfingers != 2 || ms->button))
3993 gest->in_vscroll = 0;
3998 gest->in_vscroll ? "YES" : "NO",
3999 gest->in_vscroll, dxp, dyp,
4000 gest->fingers_nb));
4002 } else if (sc->flags & PSM_FLAGS_FINGERDOWN) {
4009 dx = abs(smoother->queue[smoother->queue_cursor].x -
4010 smoother->start_x);
4011 dy = abs(smoother->queue[smoother->queue_cursor].y -
4012 smoother->start_y);
4014 /* Max delta is disabled for multi-fingers tap. */
4015 if (gest->fingers_nb > 1)
4018 tap_max_delta = sc->syninfo.tap_max_delta;
4020 sc->flags &= ~PSM_FLAGS_FINGERDOWN;
4026 gest->zmax, dx, dy, tap_max_delta, gest->fingers_nb,
4027 smoother->queue_len));
4028 if (!gest->in_vscroll && gest->zmax >= tap_threshold &&
4029 timevalcmp(&sc->lastsoftintr, &gest->taptimeout, <=) &&
4031 smoother->queue_len >= sc->syninfo.tap_min_queue) {
4034 * - the maximum pressure went over tap_threshold
4035 * - the action ended before tap_timeout
4037 * To handle tap-hold, we must delay any button push to
4040 if (gest->in_taphold) {
4043 * double tap action, not a tap-hold.
4045 gest->in_taphold = 0;
4048 * For double-tap to work:
4049 * - no button press is emitted (to
4051 * - PSM_FLAGS_FINGERDOWN is set to
4057 gest->tap_button));
4058 sc->flags |= PSM_FLAGS_FINGERDOWN;
4061 sc->idletimeout.tv_sec = psmhz > 1 ?
4063 sc->idletimeout.tv_usec = psmhz > 1 ?
4068 * tap-hold state and notify the button
4071 gest->in_taphold = 1;
4072 taphold_timeout = sc->syninfo.taphold_timeout;
4073 gest->taptimeout.tv_sec = taphold_timeout /
4075 gest->taptimeout.tv_usec = taphold_timeout %
4077 sc->idletimeout = gest->taptimeout;
4078 timevaladd(&gest->taptimeout,
4079 &sc->lastsoftintr);
4081 switch (gest->fingers_nb) {
4083 gest->tap_button =
4087 gest->tap_button =
4091 gest->tap_button =
4096 gest->tap_button));
4097 ms->button |= gest->tap_button;
4102 * tap-hold state.
4104 if (gest->in_taphold) {
4107 gest->tap_button));
4108 gest->in_taphold = 0;
4111 "synaptics: not a tap-hold\n"));
4114 } else if (!(sc->flags & PSM_FLAGS_FINGERDOWN) && gest->in_taphold) {
4116 * For a tap-hold to work, the button must remain down at
4120 if (timevalcmp(&sc->lastsoftintr, &gest->taptimeout, <=)) {
4121 ms->button |= gest->tap_button;
4124 gest->tap_button));
4125 gest->in_taphold = 0;
4134 mousestatus_t *ms, int *x, int *y) argument
4136 smoother_t *smoother = &sc->smoother[smoother_id];
4137 gesture_t *gest = &(sc->gesture);
4143 if (f->p >= sc->syninfo.min_pressure) {
4162 margin_top = sc->syninfo.margin_top;
4163 margin_right = sc->syninfo.margin_right;
4164 margin_bottom = sc->syninfo.margin_bottom;
4165 margin_left = sc->syninfo.margin_left;
4166 na_top = sc->syninfo.na_top;
4167 na_right = sc->syninfo.na_right;
4168 na_bottom = sc->syninfo.na_bottom;
4169 na_left = sc->syninfo.na_left;
4170 window_max = sc->syninfo.window_max;
4171 multiplicator = sc->syninfo.multiplicator;
4172 weight_current = sc->syninfo.weight_current;
4173 weight_previous = sc->syninfo.weight_previous;
4174 weight_len_squared = sc->syninfo.weight_len_squared;
4175 div_min = sc->syninfo.div_min;
4176 div_max = sc->syninfo.div_max;
4177 div_len = sc->syninfo.div_len;
4178 two_finger_scroll = sc->syninfo.two_finger_scroll;
4179 max_x = sc->syninfo.max_x;
4180 max_y = sc->syninfo.max_y;
4181 natural_scroll = sc->syninfo.natural_scroll;
4183 is_fuzzy = (f->flags & PSM_FINGER_FUZZY) != 0;
4186 x0 = f->x;
4187 y0 = f->y;
4195 else if (x0 >= max_x - margin_right)
4196 x0 = max_x - margin_right;
4199 else if (y0 >= max_y - margin_top)
4200 y0 = max_y - margin_top;
4203 if (smoother->active == 0) {
4204 VLOG(3, (LOG_DEBUG, "smoother%d: ---\n", smoother_id));
4207 smoother->start_x = x0;
4208 smoother->start_y = y0;
4212 smoother->queue_cursor = SYNAPTICS_PACKETQUEUE;
4213 smoother->queue_len = 0;
4216 smoother->avg_dx = 0;
4217 smoother->avg_dy = 0;
4220 smoother->squelch_x = 0;
4221 smoother->squelch_y = 0;
4224 smoother->active = 1;
4227 cursor = smoother->queue_cursor;
4228 dx = x0 - smoother->queue[cursor].x;
4229 dy = y0 - smoother->queue[cursor].y;
4233 smoother_id, x0, y0, f->p, f->w));
4236 cursor = SYNAPTICS_QUEUE_CURSOR(smoother->queue_cursor - 1);
4237 smoother->queue[cursor].x = x0;
4238 smoother->queue[cursor].y = y0;
4239 smoother->queue_cursor = cursor;
4240 if (smoother->queue_len < SYNAPTICS_PACKETQUEUE)
4241 smoother->queue_len++;
4247 if (smoother->queue_len < gest->window_min)
4253 if (gest->in_vscroll) {
4255 div_min = sc->syninfo.vscroll_div_min;
4256 div_max_x = div_max_y = sc->syninfo.vscroll_div_max;
4264 if (x0 <= na_left || x0 >= max_x - na_right) {
4265 weight_prev_x = sc->syninfo.weight_previous_na;
4266 div_max_x = sc->syninfo.div_max_na;
4269 if (y0 <= na_bottom || y0 >= max_y - na_top) {
4270 weight_prev_y = sc->syninfo.weight_previous_na;
4271 div_max_y = sc->syninfo.div_max_na;
4281 window = imin(smoother->queue_len, window_max);
4282 peer = SYNAPTICS_QUEUE_CURSOR(cursor + window - 1);
4283 dxp = abs(x0 - smoother->queue[peer].x) + 1;
4284 dyp = abs(y0 - smoother->queue[peer].y) + 1;
4305 smoother->avg_dx =
4307 weight_prev_x * smoother->avg_dx) /
4310 smoother->avg_dy =
4312 weight_prev_y * smoother->avg_dy) /
4317 smoother->avg_dx / multiplicator,
4318 smoother->avg_dy / multiplicator));
4321 smoother->squelch_x += smoother->avg_dx;
4322 dxp = smoother->squelch_x / (div_x * multiplicator);
4323 smoother->squelch_x = smoother->squelch_x %
4326 smoother->squelch_y += smoother->avg_dy;
4327 dyp = smoother->squelch_y / (div_y * multiplicator);
4328 smoother->squelch_y = smoother->squelch_y %
4331 switch(gest->in_vscroll) {
4333 /* On real<->fuzzy finger switch the x/y pos jumps */
4334 if (is_fuzzy == smoother->is_fuzzy) {
4339 VLOG(3, (LOG_DEBUG, "smoother%d: [%d, %d] -> [%d, %d]\n",
4345 ms->button |= (dyp > 0) ?
4348 ms->button |= (dyp > 0) ?
4355 ms->button |= (dxp > 0) ?
4358 ms->button |= (dxp > 0) ?
4364 smoother->is_fuzzy = is_fuzzy;
4372 smoother->active = 0;
4377 proc_elantech(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, argument
4388 if (ELANTECH_PKT_IS_DEBOUNCE(pb, sc->elanhw.hwversion))
4390 else if (sc->elanhw.hastrackpoint && ELANTECH_PKT_IS_TRACKPOINT(pb))
4393 switch (sc->elanhw.hwversion) {
4396 return (-1);
4398 pkt = (pb->ipacket[0] & 0xc0) == 0x80 ?
4402 if (!ELANTECH_PKT_IS_V3_HEAD(pb, sc->elanhw.hascrc) &&
4403 !ELANTECH_PKT_IS_V3_TAIL(pb, sc->elanhw.hascrc))
4404 return (-1);
4409 if (!ELANTECH_PKT_IS_V4(pb, sc->elanhw.hascrc))
4410 return (-1);
4412 switch (pb->ipacket[3] & 0x03) {
4423 return (-1);
4427 return (-1);
4436 ms->button = ms->obutton;
4438 if (sc->syninfo.touchpad_off && pkt != ELANTECH_PKT_TRACKPOINT)
4453 * -------------------------------------------
4460 * -------------------------------------------
4467 nfingers = (pb->ipacket[0] & 0xc0) >> 6;
4468 if (nfingers == 3 && (pb->ipacket[3] & 0x80))
4472 mask = (1 << nfingers) - 1; /* = 0x00 */
4476 /* Map 3-rd and 4-th fingers to first finger */
4477 mask = (1 << 1) - 1; /* = 0x01 */
4479 if (sc->elanhw.haspressure) {
4480 f[0].w = ((pb->ipacket[0] & 0x30) >> 2) |
4481 ((pb->ipacket[3] & 0x30) >> 4);
4498 * -------------------------------------------
4505 * -------------------------------------------
4506 * AX: lower-left finger absolute x value
4507 * AY: lower-left finger absolute y value
4508 * BX: upper-right finger absolute x value
4509 * BY: upper-right finger absolute y value
4512 mask = (1 << nfingers) - 1;
4516 .x = (((pb->ipacket[id * 3] & 0x10) << 4) |
4517 pb->ipacket[id * 3 + 1]) << 2,
4518 .y = (((pb->ipacket[id * 3] & 0x20) << 3) |
4519 pb->ipacket[id * 3 + 2]) << 2,
4529 * -------------------------------------------
4536 * -------------------------------------------
4538 nfingers = (pb->ipacket[0] & 0xc0) >> 6;
4539 /* Map 3-rd finger to first finger */
4540 id = nfingers > 2 ? 0 : nfingers - 1;
4541 mask = (1 << (id + 1)) - 1;
4547 fn.w = ((pb->ipacket[0] & 0x30) >> 2) |
4548 ((pb->ipacket[3] & 0x30) >> 4);
4558 if (ELANTECH_PKT_IS_V3_HEAD(pb, sc->elanhw.hascrc)) {
4559 sc->elanaction.fingers[0] = fn;
4562 f[0] = sc->elanaction.fingers[0];
4569 * -------------------------------------------
4576 * -------------------------------------------
4583 mask = pb->ipacket[1] & 0x1f;
4586 if (sc->elanaction.mask_v4wait != 0)
4591 sc->elanaction.mask_v4wait = mask & ~sc->elanaction.mask;
4594 if (sc->elanaction.mask_v4wait) {
4595 sc->elanaction.mask = mask;
4603 * -------------------------------------------
4610 * -------------------------------------------
4616 mask = sc->elanaction.mask;
4618 id = ((pb->ipacket[3] & 0xe0) >> 5) - 1;
4620 fn.w =(pb->ipacket[0] & 0xf0) >> 4;
4626 if (sc->elanaction.mask_v4wait == 0) {
4633 sc->elanaction.mask_v4wait &= ~(1 << id);
4635 sc->elanaction.fingers[id] = fn;
4638 if (sc->elanaction.mask_v4wait != 0)
4643 if (sc->elanaction.mask & (1 << id))
4644 f[id] = sc->elanaction.fingers[id];
4650 * -------------------------------------------
4657 * -------------------------------------------
4658 * OF: delta overflows (> 127 or < -128), in this case
4666 mask = sc->elanaction.mask;
4669 scale = (pb->ipacket[0] & 0x10) ? 5 : 1;
4671 id = ((pb->ipacket[i] & 0xe0) >> 5) - 1;
4675 if (PSM_FINGER_IS_SET(sc->elanaction.fingers[id])) {
4676 f[id] = sc->elanaction.fingers[id];
4677 f[id].x += imax(-f[id].x,
4678 (signed char)pb->ipacket[i+1] * scale);
4679 f[id].y += imax(-f[id].y,
4680 (signed char)pb->ipacket[i+2] * scale);
4691 * -------------------------------------------
4698 * -------------------------------------------
4703 if (!(pb->ipacket[0] & 0xC8) && !(pb->ipacket[1] & 0x7F) &&
4704 !(pb->ipacket[2] & 0x7F) && !(pb->ipacket[3] & 0xC9) &&
4705 !(pb->ipacket[0] & 0x10) != !(pb->ipacket[1] & 0x80) &&
4706 !(pb->ipacket[0] & 0x10) != !(pb->ipacket[3] & 0x10) &&
4707 !(pb->ipacket[0] & 0x20) != !(pb->ipacket[2] & 0x80) &&
4708 !(pb->ipacket[0] & 0x20) != !(pb->ipacket[3] & 0x20)) {
4709 *x = (pb->ipacket[0] & MOUSE_PS2_XNEG) ?
4710 pb->ipacket[4] - 256 : pb->ipacket[4];
4711 *y = (pb->ipacket[0] & MOUSE_PS2_YNEG) ?
4712 pb->ipacket[5] - 256 : pb->ipacket[5];
4715 ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) |
4716 ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0) |
4717 ((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0);
4719 evdev_push_rel(sc->evdev_r, REL_X, *x);
4720 evdev_push_rel(sc->evdev_r, REL_Y, -*y);
4721 evdev_push_mouse_btn(sc->evdev_r, trackpoint_button);
4722 evdev_sync(sc->evdev_r);
4724 ms->button = touchpad_button | trackpoint_button;
4734 return (-1);
4744 if (sc->elanhw.isclickpad) {
4746 ((pb->ipacket[0] & 0x03) ? MOUSE_BUTTON1DOWN : 0);
4749 ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) |
4750 ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0);
4759 evdev_push_abs(sc->evdev_a, ABS_MT_TOUCH_MAJOR,
4760 f[id].w * sc->elanhw.dptracex);
4763 evdev_push_key(sc->evdev_a, BTN_TOUCH, nfingers > 0);
4764 evdev_push_nfingers(sc->evdev_a, nfingers);
4769 evdev_push_abs(sc->evdev_a, ABS_PRESSURE, 0);
4770 evdev_push_mouse_btn(sc->evdev_a, touchpad_button);
4771 evdev_sync(sc->evdev_a);
4775 ms->button = touchpad_button | trackpoint_button;
4783 psmgestures(sc, &f[0], imin(nfingers, 3), ms);
4788 psmsmoother(sc, &f[id], id, ms, x, y);
4793 sc->elanaction.fingers[id] = f[id];
4794 if ((sc->elanaction.mask & (1 << id)) && !(mask & (1 << id)))
4795 PSM_FINGER_RESET(sc->elanaction.fingers[id]);
4797 sc->elanaction.mask = mask;
4801 ms->button = ms->obutton;
4806 if (ms->button & MOUSE_BUTTON4DOWN)
4807 *z = -1;
4808 else if (ms->button & MOUSE_BUTTON5DOWN)
4810 else if (ms->button & MOUSE_BUTTON6DOWN)
4811 *z = -2;
4812 else if (ms->button & MOUSE_BUTTON7DOWN)
4816 ms->button &= ~(MOUSE_BUTTON4DOWN | MOUSE_BUTTON5DOWN |
4823 proc_versapad(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, argument
4859 c = pb->ipacket[0];
4861 ms->button = butmap_versapad[c & MOUSE_PS2VERSA_BUTTONS];
4862 ms->button |= (c & MOUSE_PS2VERSA_TAP) ? MOUSE_BUTTON4DOWN : 0;
4864 x0 = pb->ipacket[1] | (((pb->ipacket[4]) & 0x0f) << 8);
4865 y0 = pb->ipacket[2] | (((pb->ipacket[4]) & 0xf0) << 4);
4867 x0 -= 0x1000;
4869 y0 -= 0x1000;
4870 if (sc->flags & PSM_FLAGS_FINGERDOWN) {
4871 *x = sc->xold - x0;
4872 *y = y0 - sc->yold;
4876 --*x;
4880 --*y;
4882 sc->flags |= PSM_FLAGS_FINGERDOWN;
4883 sc->xold = x0;
4884 sc->yold = y0;
4886 sc->flags &= ~PSM_FLAGS_FINGERDOWN;
4897 if (sc->pqueue_start == sc->pqueue_end &&
4898 sc->idlepacket.inputbytes > 0) {
4900 if (--sc->pqueue_start < 0)
4901 sc->pqueue_start = PSM_PACKETQUEUE - 1;
4903 pb = &sc->pqueue[sc->pqueue_start];
4904 memcpy(pb, &sc->idlepacket, sizeof(packetbuf_t));
4907 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2],
4908 pb->ipacket[3], pb->ipacket[4], pb->ipacket[5]));
4932 mousestatus_t ms; local
4936 getmicrouptime(&sc->lastsoftintr);
4941 pb = &sc->pqueue[sc->pqueue_start];
4943 if (sc->mode.level == PSM_LEVEL_NATIVE)
4946 c = pb->ipacket[0];
4952 if (sc->hw.model == MOUSE_MODEL_THINK)
4953 pb->ipacket[1] |= (c & MOUSE_PS2_XOVERFLOW) ? 0x80 : 0;
4957 pb->ipacket[1] - 256 : pb->ipacket[1];
4959 pb->ipacket[2] - 256 : pb->ipacket[2];
4961 ms.obutton = sc->button; /* previous button state */
4962 ms.button = butmap[c & MOUSE_PS2_BUTTONS];
4964 if (sc->config & PSM_CONFIG_FORCETAP)
4965 ms.button |= ((c & MOUSE_PS2_TAP)) ?
4967 timevalclear(&sc->idletimeout);
4968 sc->idlepacket.inputbytes = 0;
4970 switch (sc->hw.model) {
4981 * d2-d0: wheel data
4983 z = (pb->ipacket[3] & MOUSE_EXPLORER_ZNEG) ?
4984 (pb->ipacket[3] & 0x0f) - 16 :
4985 (pb->ipacket[3] & 0x0f);
4986 ms.button |=
4987 (pb->ipacket[3] & MOUSE_EXPLORER_BUTTON4DOWN) ?
4989 ms.button |=
4990 (pb->ipacket[3] & MOUSE_EXPLORER_BUTTON5DOWN) ?
4997 z = (char)pb->ipacket[3];
5000 if ((z >= 7) || (z <= -7))
5003 ms.button |= (c & MOUSE_PS2INTELLI_BUTTON4DOWN) ?
5005 ms.button |= (c & MOUSE_PS2INTELLI_BUTTON5DOWN) ?
5010 proc_mmanplus(sc, pb, &ms, &x, &y, &z);
5015 ms.button |= ((c & MOUSE_PS2_TAP)) ? 0 :
5024 ms.button |= (pb->ipacket[3] & MOUSE_PS2_BUTTON3DOWN) ?
5026 ms.button |= (pb->ipacket[3] & MOUSE_PS2_BUTTON1DOWN) ?
5028 z = (pb->ipacket[3] & MOUSE_PS2_XNEG) ?
5029 pb->ipacket[4] - 256 : pb->ipacket[4];
5034 ms.button |= (c & MOUSE_PS2_TAP) ?
5039 proc_versapad(sc, pb, &ms, &x, &y, &z);
5056 x = (pb->ipacket[1] & 0x80) ?
5057 pb->ipacket[1] - 256 : pb->ipacket[1];
5058 y = (pb->ipacket[2] & 0x80) ?
5059 pb->ipacket[2] - 256 : pb->ipacket[2];
5065 z = -1;
5071 z = -2;
5077 if ((x < 16 - 256) && (y < 16 - 256)) {
5087 * d1-d0: wheel data
5090 if (pb->ipacket[2] & MOUSE_4DPLUS_BUTTON4DOWN)
5091 ms.button |= MOUSE_BUTTON4DOWN;
5092 z = (pb->ipacket[2] & MOUSE_4DPLUS_ZNEG) ?
5093 ((pb->ipacket[2] & 0x07) - 8) :
5094 (pb->ipacket[2] & 0x07) ;
5097 ms.button |= ms.obutton & MOUSE_EXTBUTTONS;
5102 if (pb->inputbytes == MOUSE_PS2_PACKETSIZE)
5106 if (proc_synaptics(sc, pb, &ms, &x, &y, &z) != 0) {
5114 if (proc_elantech(sc, pb, &ms, &x, &y, &z) != 0) {
5128 if (timevalisset(&sc->idletimeout) && sc->idlepacket.inputbytes == 0)
5129 sc->idlepacket = *pb;
5133 sc->hw.model != MOUSE_MODEL_ELANTECH &&
5134 sc->hw.model != MOUSE_MODEL_SYNAPTICS) {
5135 evdev_push_rel(sc->evdev_r, REL_X, x);
5136 evdev_push_rel(sc->evdev_r, REL_Y, -y);
5138 switch (sc->hw.model) {
5144 evdev_push_rel(sc->evdev_r, REL_WHEEL, -z);
5150 case -1:
5151 evdev_push_rel(sc->evdev_r, REL_WHEEL, -z);
5154 case -2:
5155 evdev_push_rel(sc->evdev_r, REL_HWHEEL, z / 2);
5161 evdev_push_mouse_btn(sc->evdev_r, ms.button);
5162 evdev_sync(sc->evdev_r);
5165 if ((sc->evdev_a != NULL && evdev_is_grabbed(sc->evdev_a)) ||
5166 (sc->evdev_r != NULL && evdev_is_grabbed(sc->evdev_r)))
5171 if (sc->mode.accelfactor >= 1) {
5173 x = x * x / sc->mode.accelfactor;
5177 x = -x;
5180 y = y * y / sc->mode.accelfactor;
5184 y = -y;
5188 ms.dx = x;
5189 ms.dy = y;
5190 ms.dz = z;
5191 ms.flags = ((x || y || z) ? MOUSE_POSCHANGED : 0) |
5192 (ms.obutton ^ ms.button);
5194 pb->inputbytes = tame_mouse(sc, pb, &ms, pb->ipacket);
5196 sc->status.flags |= ms.flags;
5197 sc->status.dx += ms.dx;
5198 sc->status.dy += ms.dy;
5199 sc->status.dz += ms.dz;
5200 sc->status.button = ms.button;
5201 sc->button = ms.button;
5204 sc->watchdog = FALSE;
5207 if (sc->queue.count + pb->inputbytes < sizeof(sc->queue.buf)) {
5208 l = imin(pb->inputbytes,
5209 sizeof(sc->queue.buf) - sc->queue.tail);
5210 bcopy(&pb->ipacket[0], &sc->queue.buf[sc->queue.tail], l);
5211 if (pb->inputbytes > l)
5212 bcopy(&pb->ipacket[l], &sc->queue.buf[0],
5213 pb->inputbytes - l);
5214 sc->queue.tail = (sc->queue.tail + pb->inputbytes) %
5215 sizeof(sc->queue.buf);
5216 sc->queue.count += pb->inputbytes;
5220 pb->inputbytes = 0;
5221 if (++sc->pqueue_start >= PSM_PACKETQUEUE)
5222 sc->pqueue_start = 0;
5223 } while (sc->pqueue_start != sc->pqueue_end);
5225 if (sc->state & PSM_ASLP) {
5226 sc->state &= ~PSM_ASLP;
5229 selwakeuppri(&sc->rsel, PZERO);
5230 KNOTE_LOCKED(&sc->rsel.si_note, 0);
5231 if (sc->async != NULL) {
5232 pgsigio(&sc->async, SIGIO, 0);
5234 sc->state &= ~PSM_SOFTARMED;
5238 if (timevalisset(&sc->idletimeout)) {
5239 sc->state |= PSM_SOFTARMED;
5240 callout_reset(&sc->softcallout, tvtohz(&sc->idletimeout),
5243 tvtohz(&sc->idletimeout)));
5251 struct psm_softc *sc = dev->si_drv1;
5258 if (sc->queue.count > 0)
5261 selrecord(td, &sc->rsel);
5271 struct psm_softc *sc = kn->kn_hook;
5273 knlist_remove(&sc->rsel.si_note, kn, 0);
5279 struct psm_softc *sc = kn->kn_hook;
5283 return (sc->queue.count != 0 ? 1 : 0);
5295 struct psm_softc *sc = dev->si_drv1;
5297 if (kn->kn_filter != EVFILT_READ)
5300 kn->kn_fop = &psmfiltops;
5301 kn->kn_hook = sc;
5302 knlist_add(&sc->rsel.si_note, kn, 1);
5346 KBDC kbdc = sc->kbdc;
5354 ch = (status[0] & 0x07) - 1; /* channel # */
5359 * status[2]: battery status? (0-100)
5369 KBDC kbdc = sc->kbdc;
5388 * bit 0-2 button status
5390 * byte 3 report rate (?)
5399 sc->hw.buttons = 4;
5407 KBDC kbdc = sc->kbdc;
5431 KBDC kbdc = sc->kbdc;
5454 static u_char rate[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 }; local
5455 KBDC kbdc = sc->kbdc;
5475 /* at this point, resolution is LOW, sampling rate is 10/sec */
5484 for (i = 0; i < nitems(rate); ++i)
5485 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
5490 * sampling rate for the native mode.
5494 if ((status[1] == PSMD_RES_LOW) || (status[2] == rate[i - 1]))
5508 KBDC kbdc = sc->kbdc;
5532 * p3-p0: packet type: 0
5533 * m7-m0: model ID: MouseMan+:0x50,
5542 /* check d3-d0 in byte 2 */
5545 /* check p3-p0 */
5550 sc->hw.hwid &= 0x00ff;
5551 sc->hw.hwid |= data[2] << 8; /* save model ID */
5563 /* MS IntelliMouse Explorer */
5567 KBDC kbdc = sc->kbdc;
5574 * This is needed for at least A4Tech X-7xx mice - they do not go
5590 sc->hw.buttons = 5; /* IntelliMouse Explorer XXX */
5591 sc->hw.hwid = id;
5596 * which think they are clever enough to know the 4-byte IntelliMouse
5597 * protocol, and assume any other protocols use 3-byte packets.
5598 * They don't convey 4-byte data packets from the IntelliMouse Explorer
5613 * MS IntelliMouse
5620 KBDC kbdc = sc->kbdc;
5621 static u_char rate[] = { 200, 100, 80, }; local
5626 for (i = 0; i < nitems(rate); ++i)
5627 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
5635 sc->hw.buttons = 3;
5636 sc->hw.hwid = id;
5649 static u_char rate[] = { 200, 100, 80, 60, 40, 20 }; local
5650 KBDC kbdc = sc->kbdc;
5654 for (i = 0; i < nitems(rate); ++i)
5655 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
5660 * Cable-Free 4D: 8 (4DPLUS)
5667 sc->hw.buttons = 3; /* XXX some 4D mice have 4? */
5668 sc->hw.hwid = id;
5682 KBDC kbdc = sc->kbdc;
5687 static u_char rate[] = { 200, 100, 80, 60, 40, 20 };
5690 for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i)
5691 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
5706 sc->hw.buttons = (id == PSM_4DPLUS_ID) ? 4 : 3;
5707 sc->hw.hwid = id;
5720 if (oidp->oid_arg1 == NULL || oidp->oid_arg2 < 0 ||
5721 oidp->oid_arg2 > SYNAPTICS_SYSCTL_LAST)
5724 sc = oidp->oid_arg1;
5727 arg = *(int *)((char *)sc + oidp->oid_arg2);
5731 if (error || !req->newptr)
5738 switch (oidp->oid_arg2) {
5752 if (arg < 0 || arg > sc->synhw.maximumYCoord)
5758 if (!sc->synhw.capClickPad && arg != 0)
5765 if (arg < 0 || arg > sc->synhw.maximumXCoord)
5795 if (arg < -sc->synhw.maximumXCoord ||
5796 arg > sc->synhw.maximumXCoord)
5801 if (!sc->synhw.capClickPad && arg != 0)
5805 if (arg < -sc->synhw.maximumYCoord ||
5806 arg > sc->synhw.maximumYCoord)
5820 *(int *)((char *)sc + oidp->oid_arg2) = arg;
5835 sc->syninfo.softbuttons_y = sc->synhw.topButtonPad ? -1700 : 1700;
5836 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5837 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5845 sc->syninfo.softbutton2_x = 3100;
5846 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5847 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5852 "Horisontal position of 2-nd softbutton left edge (0-disable)");
5855 sc->syninfo.softbutton3_x = 3900;
5856 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5857 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5862 "Horisontal position of 3-rd softbutton left edge (0-disable)");
5870 if (sc->syninfo.sysctl_tree != NULL)
5874 sysctl_ctx_init(&sc->syninfo.sysctl_ctx);
5875 sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx,
5880 sc->syninfo.directional_scrolls = 0;
5881 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx,
5882 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5884 &sc->syninfo.directional_scrolls, 0,
5885 "Enable hardware scrolling pad (if non-zero) or register it as "
5889 sc->syninfo.max_x = 6143;
5890 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx,
5891 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5893 &sc->syninfo.max_x, 0,
5897 sc->syninfo.max_y = 6143;
5898 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx,
5899 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5901 &sc->syninfo.max_y, 0,
5909 if (sc->synhw.verticalScroll || (sc->synhw.capMultiFinger == 0 &&
5910 sc->synhw.capAdvancedGestures == 0))
5911 sc->syninfo.two_finger_scroll = 0;
5913 sc->syninfo.two_finger_scroll = 1;
5915 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx,
5916 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5918 &sc->syninfo.two_finger_scroll, 0,
5922 sc->syninfo.min_pressure = 32;
5923 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5924 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5932 sc->syninfo.max_pressure = 220;
5933 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5934 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5942 sc->syninfo.max_width = 10;
5943 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5944 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5952 sc->syninfo.margin_top = 200;
5953 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5954 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5962 sc->syninfo.margin_right = 200;
5963 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5964 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5972 sc->syninfo.margin_bottom = 200;
5973 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5974 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5982 sc->syninfo.margin_left = 200;
5983 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5984 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5992 sc->syninfo.na_top = 1783;
5993 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5994 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6003 sc->syninfo.na_right = 563;
6004 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6005 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6014 sc->syninfo.na_bottom = 1408;
6015 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6016 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6025 sc->syninfo.na_left = 1600;
6026 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6027 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6036 sc->syninfo.window_min = 4;
6037 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6038 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6046 sc->syninfo.window_max = 10;
6047 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6048 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6056 sc->syninfo.multiplicator = 10000;
6057 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6058 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6066 sc->syninfo.weight_current = 3;
6067 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6068 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6076 sc->syninfo.weight_previous = 6;
6077 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6078 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6086 sc->syninfo.weight_previous_na = 20;
6087 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6088 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6096 sc->syninfo.weight_len_squared = 2000;
6097 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6098 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6107 sc->syninfo.div_min = 9;
6108 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6109 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6117 sc->syninfo.div_max = 17;
6118 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6119 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6127 sc->syninfo.div_max_na = 30;
6128 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6129 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6137 sc->syninfo.div_len = 100;
6138 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6139 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6147 sc->syninfo.tap_max_delta = 80;
6148 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6149 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6157 sc->syninfo.tap_min_queue = 2;
6158 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6159 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6167 sc->gesture.in_taphold = 0;
6168 sc->syninfo.taphold_timeout = tap_timeout;
6169 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6170 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6175 "Maximum elapsed time between two taps to consider a tap-hold "
6179 sc->syninfo.vscroll_hor_area = 0; /* 1300 */
6180 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6181 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6189 sc->syninfo.vscroll_ver_area = -400 - sc->syninfo.margin_right;
6190 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6191 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6199 sc->syninfo.vscroll_min_delta = 50;
6200 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6201 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6209 sc->syninfo.vscroll_div_min = 100;
6210 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6211 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6219 sc->syninfo.vscroll_div_max = 150;
6220 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6221 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6229 sc->syninfo.touchpad_off = 0;
6230 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6231 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6238 sc->syninfo.three_finger_drag = 0;
6239 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6240 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6248 sc->syninfo.natural_scroll = 0;
6249 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6250 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6257 sc->syninfo.softbuttons_y = 0;
6258 sc->syninfo.softbutton2_x = 0;
6259 sc->syninfo.softbutton3_x = 0;
6262 if (sc->synhw.capClickPad)
6271 if (sc->hw.model != MOUSE_MODEL_SYNAPTICS) {
6291 if (sc->synhw.capExtended)
6299 mouse_ext_command(sc->kbdc, mode_byte);
6302 set_mouse_sampling_rate(sc->kbdc, 20);
6308 if ((sc->synhw.capAdvancedGestures || sc->synhw.capReportsV) &&
6309 sc->hw.model == MOUSE_MODEL_SYNAPTICS && !(mode_byte & (1 << 5))) {
6310 mouse_ext_command(sc->kbdc, SYNAPTICS_READ_MODEL_ID);
6311 set_mouse_sampling_rate(sc->kbdc, 0xc8);
6317 * at least before 4-byte protocol mouse probes e.g. MS IntelliMouse probe as
6323 KBDC kbdc = sc->kbdc;
6329 sc->muxsinglesyna = FALSE;
6331 if (mux_disabled == 1 || (mux_disabled == -1 &&
6332 (kbdc->quirks & KBDC_QUIRK_DISABLE_MUX_PROBE) != 0))
6336 if (version == -1)
6362 sc->muxport = port;
6378 device_printf(sc->dev, "AUX MUX hang detected!\n");
6387 sc->muxsinglesyna = probe;
6395 return (sc->muxsinglesyna);
6403 KBDC kbdc = sc->kbdc;
6435 printf(" Unsupported (pre-v4) Touchpad detected\n");
6490 device_get_unit(sc->dev));
6642 switch (psmcpnp_sc->type) {
6732 sc->synhw = synhw;
6737 sc->hw.model = MOUSE_MODEL_SYNAPTICS;
6751 sc->hw.buttons = buttons;
6760 VLOG(2, (LOG_NOTICE, "psm: setting pass-through mode.\n"));
6767 VLOG(2, (LOG_NOTICE, "psm: turning pass-through mode off.\n"));
6768 set_mouse_scaling(sc->kbdc, 2);
6769 set_mouse_scaling(sc->kbdc, 1);
6780 if (sc->synhw.capPassthrough)
6784 if (sc->synhw.capPassthrough &&
6786 if (send_aux_command(sc->kbdc, 0xe7) != PSM_ACK) {
6790 if (send_aux_command(sc->kbdc, seq[i]) != PSM_ACK) {
6791 if (sc->synhw.capPassthrough)
6797 if (sc->synhw.capPassthrough)
6855 if (sc->tpinfo.sysctl_tree != NULL)
6859 sysctl_ctx_init(&sc->tpinfo.sysctl_ctx);
6860 sc->tpinfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->tpinfo.sysctl_ctx,
6865 sc->tpinfo.sensitivity = 0x80;
6866 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6867 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6875 sc->tpinfo.inertia = 0x06;
6876 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6877 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6885 sc->tpinfo.uplateau = 0x61;
6886 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6887 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6895 sc->tpinfo.reach = 0x0a;
6896 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6897 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6905 sc->tpinfo.draghys = 0xff;
6906 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6907 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6915 sc->tpinfo.mindrag = 0x14;
6916 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6917 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6925 sc->tpinfo.upthresh = 0xff;
6926 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6927 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6935 sc->tpinfo.threshold = 0x08;
6936 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6937 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6945 sc->tpinfo.jenks = 0x87;
6946 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6947 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6955 sc->tpinfo.ztime = 0x26;
6956 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6957 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6965 sc->tpinfo.pts = 0x00;
6966 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6967 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6975 sc->tpinfo.skipback = 0x00;
6976 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6977 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6988 trackpoint_command(sc, 0x81, 0x4a, sc->tpinfo.sensitivity);
6989 trackpoint_command(sc, 0x81, 0x60, sc->tpinfo.uplateau);
6990 trackpoint_command(sc, 0x81, 0x4d, sc->tpinfo.inertia);
6991 trackpoint_command(sc, 0x81, 0x57, sc->tpinfo.reach);
6992 trackpoint_command(sc, 0x81, 0x58, sc->tpinfo.draghys);
6993 trackpoint_command(sc, 0x81, 0x59, sc->tpinfo.mindrag);
6994 trackpoint_command(sc, 0x81, 0x5a, sc->tpinfo.upthresh);
6995 trackpoint_command(sc, 0x81, 0x5c, sc->tpinfo.threshold);
6996 trackpoint_command(sc, 0x81, 0x5d, sc->tpinfo.jenks);
6997 trackpoint_command(sc, 0x81, 0x5e, sc->tpinfo.ztime);
6998 if (sc->tpinfo.pts == 0x01)
7000 if (sc->tpinfo.skipback == 0x01)
7007 KBDC kbdc = sc->kbdc;
7017 if (sc->synhw.capPassthrough)
7031 if (sc->synhw.capPassthrough)
7040 if (!sc->synhw.capPassthrough) {
7041 sc->hw.hwid = firmware;
7042 sc->hw.buttons = 3;
7044 VDLOG(2, sc->dev, LOG_NOTICE, "Trackpoint v=0x%x f=0x%x",
7046 sc->tpinfo.vendor = vendor;
7047 sc->tpinfo.firmware = firmware;
7055 if (sc->synhw.capPassthrough)
7065 KBDC kbdc = sc->kbdc;
7069 set_mouse_sampling_rate(kbdc, 100); /* set rate 100 */
7076 if (data[2] != 0xa || data[1] != 0 ) /* rate == 0xa && res. == 0 */
7150 hwversion = elanhw->hwversion;
7151 reg10 = -1;
7154 reg10 = elanhw->fwversion == 0x020030 ? 0x54 : 0xc4;
7193 sc->synhw.infoMajor = sc->elanhw.hwversion;
7194 sc->synhw.infoMinor = sc->elanhw.fwversion;
7195 sc->synhw.infoXupmm = sc->elanhw.dpmmx;
7196 sc->synhw.infoYupmm = sc->elanhw.dpmmy;
7197 sc->synhw.verticalScroll = 0;
7198 sc->synhw.nExtendedQueries = 4;
7199 sc->synhw.capExtended = 1;
7200 sc->synhw.capPassthrough = sc->elanhw.hastrackpoint;
7201 sc->synhw.capClickPad = sc->elanhw.isclickpad;
7202 sc->synhw.capMultiFinger = 1;
7203 if (sc->elanhw.issemimt)
7204 sc->synhw.capAdvancedGestures = 1;
7206 sc->synhw.capReportsV = 1;
7207 sc->synhw.capPalmDetect = 1;
7208 sc->synhw.capPen = 0;
7209 sc->synhw.capReportsMax = 1;
7210 sc->synhw.maximumXCoord = sc->elanhw.sizex;
7211 sc->synhw.maximumYCoord = sc->elanhw.sizey;
7212 sc->synhw.capReportsMin = 1;
7213 sc->synhw.minimumXCoord = 0;
7214 sc->synhw.minimumYCoord = 0;
7216 if (sc->syninfo.sysctl_tree == NULL) {
7227 * 4. For clickpads set bottom quarter as 42% - 16% - 42% sized
7234 sc->syninfo.max_x = sc->elanhw.sizex;
7235 sc->syninfo.max_y = sc->elanhw.sizey;
7238 sc->syninfo.min_pressure = 1;
7241 sc->syninfo.max_width = 7;
7244 sc->syninfo.tap_min_queue = 1;
7247 sc->syninfo.margin_top = 0;
7248 sc->syninfo.margin_right = 0;
7249 sc->syninfo.margin_bottom = 0;
7250 sc->syninfo.margin_left = 0;
7253 sc->syninfo.na_top = 0;
7254 sc->syninfo.na_right = 0;
7255 sc->syninfo.na_bottom = 0;
7256 sc->syninfo.na_left = 0;
7259 sc->syninfo.weight_len_squared = 200;
7260 sc->syninfo.div_min = 3;
7261 sc->syninfo.div_max = 6;
7262 sc->syninfo.div_max_na = 10;
7263 sc->syninfo.div_len = 30;
7264 sc->syninfo.tap_max_delta = 25;
7267 sc->syninfo.vscroll_hor_area = 0;
7268 sc->syninfo.vscroll_ver_area = 0;
7269 sc->syninfo.vscroll_min_delta = 15;
7270 sc->syninfo.vscroll_div_min = 30;
7271 sc->syninfo.vscroll_div_max = 50;
7273 /* Set bottom quarter as 42% - 16% - 42% sized softbuttons */
7274 if (sc->elanhw.isclickpad) {
7275 sc->syninfo.softbuttons_y = sc->elanhw.sizey / 4;
7276 sc->syninfo.softbutton2_x = sc->elanhw.sizex * 11 / 25;
7277 sc->syninfo.softbutton3_x = sc->elanhw.sizex * 14 / 25;
7301 KBDC kbdc = sc->kbdc;
7405 elanhw.sizex = (elanhw.ntracesx - xtr) * elanhw.dptracex;
7406 elanhw.sizey = (elanhw.ntracesy - xtr) * elanhw.dptracey;
7410 xtr = (elanhw.sizex % (elanhw.ntracesx - 2) == 0) ? 2 : 1;
7411 elanhw.dptracex = elanhw.sizex / (elanhw.ntracesx - xtr);
7412 elanhw.dptracey = elanhw.sizey / (elanhw.ntracesy - xtr);
7435 sc->elanhw = elanhw;
7436 sc->hw.buttons = 3;
7442 PSM_FINGER_RESET(sc->elanaction.fingers[id]);
7480 if ((sc->config &
7484 err = reinitialize(sc, sc->config & PSM_CONFIG_INITAFTERSUSPEND);
7486 if ((sc->state & PSM_ASLP) && !(sc->state & PSM_VALID)) {
7491 sc->state &= ~PSM_ASLP;
7630 sc->type = PSMCPNP_FORCEPAD;
7632 sc->type = PSMCPNP_TOPBUTTONPAD;
7634 sc->type = PSMCPNP_GENERIC;