Lines Matching +full:aux +full:- +full:output +full:- +full:enable

1 /*-
28 * Thanks are also due to Rick Macklem, rick@snowhite.cis.uoguelph.ca -
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).
158 #define PSM_NOMUX (-1)
336 #define PSM_FINGER_IS_SET(f) ((f).x != -1 && (f).y != -1 && (f).p != 0)
338 (f) = (finger_t) { .x = -1, .y = -1, .p = 0, .w = 0, .flags = 0 }; \
385 .x = (((pb)->ipacket[1] & 0x0f) << 8) | (pb)->ipacket[2], \
386 .y = (((pb)->ipacket[4] & 0x0f) << 8) | (pb)->ipacket[5], \
387 .p = ((pb)->ipacket[1] & 0xf0) | (((pb)->ipacket[4] >> 4) & 0x0f), \
403 #define ELANTECH_PKT_IS_TRACKPOINT(pb) (((pb)->ipacket[3] & 0x0f) == 0x06)
405 (pb)->ipacket[0] == ((hwversion) == 2 ? 0x84 : 0xc4) && \
406 (pb)->ipacket[1] == 0xff && (pb)->ipacket[2] == 0xff && \
407 (pb)->ipacket[3] == 0x02 && (pb)->ipacket[4] == 0xff && \
408 (pb)->ipacket[5] == 0xff)
410 (((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0x0f) == 0x02)
412 ((pb)->ipacket[3] & 0x09) == 0x08 : \
413 ((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0xcf) == 0x02)
415 ((pb)->ipacket[3] & 0x09) == 0x09 : \
416 ((pb)->ipacket[0] & 0x0c) == 0x0c && ((pb)->ipacket[3] & 0xce) == 0x0c)
418 ((pb)->ipacket[3] & 0x08) == 0x00 : \
419 ((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0x1c) == 0x10)
476 u_char muxsave[3]; /* 3->6 byte proto conversion buffer */
503 #define PSM_CONFIG_IGNPORTERROR 0x1000 /* ignore error in aux port test */
522 #define ALWAYS_RESTORE_CONTROLLER(kbdc) !(kbdcp(kbdc)->quirks \
526 static int tap_enabled = -1;
531 static int mux_disabled = -1;
734 #define GENERIC_MOUSE_ENTRY (nitems(vendortype) - 1)
847 return (-1); in get_aux_id()
866 return ((res == PSM_ACK) ? rate : -1); in set_mouse_sampling_rate()
899 return ((res == PSM_ACK) ? val : -1); in set_mouse_resolution()
904 * re-enabled by calling `enable_aux_dev()'
953 -1 /* end of table */ in is_a_mouse()
1000 /* discard anything left in the output buffer */ in recover_from_error()
1039 * Re-initialize the aux port and device. The aux port must be enabled
1041 * The aux device will be disabled before returning.
1048 KBDC kbdc = sc->kbdc; in doinitialize()
1058 device_log(sc->dev, LOG_DEBUG, in doinitialize()
1059 "strange result for test aux port (%d).\n", i); in doinitialize()
1063 case -1: /* time out */ in doinitialize()
1066 if (sc->config & PSM_CONFIG_IGNPORTERROR) in doinitialize()
1068 device_log(sc->dev, LOG_ERR, in doinitialize()
1069 "the aux port is not functioning (%d).\n", i); in doinitialize()
1073 if (sc->config & PSM_CONFIG_NORESET) { in doinitialize()
1081 * the aux port doesn't exist and `PSMC_RESET_DEV' is issued. in doinitialize()
1085 device_log(sc->dev, LOG_ERR, in doinitialize()
1086 "failed to reset the aux device.\n"); in doinitialize()
1092 * both the aux port and the aux device is functioning, see in doinitialize()
1096 device_log(sc->dev, LOG_ERR, in doinitialize()
1097 "failed to enable the aux device.\n"); in doinitialize()
1102 /* Re-enable the mouse. */ in doinitialize()
1104 if (vendortype[i].model == sc->hw.model) in doinitialize()
1109 if (mode->rate > 0) in doinitialize()
1110 mode->rate = set_mouse_sampling_rate(kbdc, mode->rate); in doinitialize()
1111 if (mode->resolution >= 0) in doinitialize()
1112 mode->resolution = in doinitialize()
1113 set_mouse_resolution(kbdc, mode->resolution); in doinitialize()
1119 sc->flags |= PSM_NEED_SYNCBITS; in doinitialize()
1123 device_log(sc->dev, LOG_DEBUG, in doinitialize()
1147 if (sc->hw.model == MOUSE_MODEL_SYNAPTICS) {
1148 if (sc->muxport != PSM_NOMUX) {
1149 mux_enabled = enable_aux_mux(sc->kbdc) >= 0;
1151 set_active_aux_mux_port(sc->kbdc, sc->muxport);
1153 device_log(sc->dev, LOG_ERR, "failed to enable "
1156 mouse_ext_command(sc->kbdc, SYNAPTICS_READ_MODES);
1157 get_mouse_status(sc->kbdc, stat, 0, 3);
1158 if ((SYNAPTICS_VERSION_GE(sc->synhw, 7, 5) ||
1162 VDLOG(5, sc->dev, LOG_DEBUG, "Synaptis Absolute Mode "
1166 disable_aux_mux(sc->kbdc);
1173 if (sc->hw.model == MOUSE_MODEL_GENERIC) {
1175 VDLOG(2, sc->dev, LOG_DEBUG,
1176 "enable tap and drag gestures\n");
1179 VDLOG(2, sc->dev, LOG_DEBUG,
1185 /* enable the mouse device */
1186 if (!enable_aux_dev(sc->kbdc)) {
1187 /* MOUSE ERROR: failed to enable the mouse because:
1193 recover_from_error(sc->kbdc);
1195 /* FIXME: we could reset the mouse here and try to enable
1199 if (!doinitialize(sc, &sc->mode) || !enable_aux_dev(sc->kbdc)) {
1200 recover_from_error(sc->kbdc);
1204 restore_controller(sc->kbdc, command_byte);
1206 sc->state &= ~PSM_VALID;
1207 device_log(sc->dev, LOG_ERR,
1208 "failed to enable the device (doopen).\n");
1213 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
1214 device_log(sc->dev, LOG_DEBUG,
1217 /* enable the aux port and interrupt */
1218 if (!set_controller_command_byte(sc->kbdc,
1219 kbdc_get_device_mask(sc->kbdc),
1223 disable_aux_dev(sc->kbdc);
1224 restore_controller(sc->kbdc, command_byte);
1225 device_log(sc->dev, LOG_ERR,
1226 "failed to enable the aux interrupt (doopen).\n");
1231 sc->watchdog = FALSE;
1232 callout_reset(&sc->callout, hz * 2, psmtimeout, sc);
1244 /* don't let anybody mess with the aux device */
1245 if (!kbdc_lock(sc->kbdc, TRUE))
1250 sc->watchdog = FALSE;
1251 callout_stop(&sc->callout);
1254 empty_both_buffers(sc->kbdc, 10);
1255 c = get_controller_command_byte(sc->kbdc);
1256 VDLOG(2, sc->dev, LOG_DEBUG,
1259 /* enable the aux port but disable the aux interrupt and the keyboard */
1260 if ((c == -1) || !set_controller_command_byte(sc->kbdc,
1261 kbdc_get_device_mask(sc->kbdc),
1266 kbdc_lock(sc->kbdc, FALSE);
1267 device_log(sc->dev, LOG_ERR,
1273 if (sc->state & PSM_VALID) {
1275 disable_aux_dev(sc->kbdc);
1276 empty_aux_buffer(sc->kbdc, 10);
1279 sc->syncerrors = 0;
1280 sc->pkterrors = 0;
1281 memset(&sc->lastinputerr, 0, sizeof(sc->lastinputerr));
1283 /* try to detect the aux device; are you still there? */
1286 if (doinitialize(sc, &sc->mode)) {
1288 sc->state |= PSM_VALID;
1291 restore_controller(sc->kbdc, c);
1292 sc->state &= ~PSM_VALID;
1293 device_log(sc->dev, LOG_ERR,
1294 "the aux device has gone! (reinitialize).\n");
1301 if ((sc->state & (PSM_OPEN | PSM_EV_OPEN_R | PSM_EV_OPEN_A)) &&
1303 /* enable the aux device and the port again */
1306 device_log(sc->dev, LOG_ERR,
1307 "failed to enable the device (reinitialize).\n");
1309 /* restore the keyboard port and disable the aux port */
1310 if (!set_controller_command_byte(sc->kbdc,
1311 kbdc_get_device_mask(sc->kbdc),
1315 device_log(sc->dev, LOG_ERR,
1316 "failed to disable the aux port (reinitialize).\n");
1321 kbdc_lock(sc->kbdc, FALSE);
1338 psm = BUS_ADD_CHILD(parent, KBDC_RID_AUX, driver->name, unit);
1364 --verbose; \
1365 kbdc_set_device_mask(sc->kbdc, mask); \
1366 kbdc_lock(sc->kbdc, FALSE); \
1386 sc->intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
1387 if (sc->intr == NULL) {
1392 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
1394 sc->dev = dev;
1395 sc->kbdc = atkbdc_open(device_get_unit(device_get_parent(dev)));
1396 if (sc->kbdc == NULL)
1398 sc->config = device_get_flags(dev) & PSM_CONFIG_FLAGS;
1401 sc->config |=
1408 sc->flags = 0;
1409 sc->muxport = PSM_NOMUX;
1415 if (!kbdc_lock(sc->kbdc, TRUE)) {
1418 --verbose;
1424 * aux port (mouse port): the aux port disable bit (bit 5) and the aux
1425 * port interrupt (IRQ 12) enable bit (bit 2).
1429 empty_both_buffers(sc->kbdc, 10);
1432 mask = kbdc_get_device_mask(sc->kbdc) & ~KBD_AUX_CONTROL_BITS;
1433 command_byte = get_controller_command_byte(sc->kbdc);
1436 if (command_byte == -1) {
1444 * disable the keyboard port while probing the aux port, which must be
1447 if (!set_controller_command_byte(sc->kbdc,
1455 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1456 restore_controller(sc->kbdc, command_byte);
1460 write_controller_command(sc->kbdc, KBDC_ENABLE_AUX_PORT);
1463 * NOTE: `test_aux_port()' is designed to return with zero if the aux
1465 * to respond with zero even when the aux port doesn't exist. (It may
1466 * be that this is only the case when the controller DOES have the aux
1474 * when it has a perfectly functional aux port. We have to ignore
1475 * this error code. Even if the controller HAS error with the aux
1479 switch ((i = test_aux_port(sc->kbdc))) {
1485 device_printf(dev, "strange result for test aux port "
1490 case -1: /* time out */
1492 recover_from_error(sc->kbdc);
1493 if (sc->config & PSM_CONFIG_IGNPORTERROR)
1495 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1496 restore_controller(sc->kbdc, command_byte);
1499 "the aux port is not functioning (%d).\n", i);
1503 if (sc->config & PSM_CONFIG_NORESET) {
1511 * the aux port doesn't exist and `PSMC_RESET_DEV' is issued.
1513 * Attempt to reset the controller twice -- this helps
1515 * is non-fatal.
1517 if (!reset_aux_dev(sc->kbdc)) {
1518 recover_from_error(sc->kbdc);
1519 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1520 restore_controller(sc->kbdc, command_byte);
1522 device_printf(dev, "failed to reset the aux "
1525 } else if (!reset_aux_dev(sc->kbdc)) {
1526 recover_from_error(sc->kbdc);
1528 device_printf(dev, "failed to reset the aux "
1534 * both the aux port and the aux device are functioning, see if the
1539 if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) {
1541 recover_from_error(sc->kbdc);
1542 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1543 restore_controller(sc->kbdc, command_byte);
1545 device_printf(dev, "failed to enable the aux device.\n");
1550 if (get_mouse_status(sc->kbdc, stat, 0, 3) >= 3) {
1551 sc->dflt_mode.rate = sc->mode.rate = stat[2];
1552 sc->dflt_mode.resolution = sc->mode.resolution = stat[1];
1554 sc->dflt_mode.rate = sc->mode.rate = -1;
1555 sc->dflt_mode.resolution = sc->mode.resolution = -1;
1559 sc->hw.iftype = MOUSE_IF_PS2;
1562 sc->hw.hwid = get_aux_id(sc->kbdc);
1563 if (!is_a_mouse(sc->hw.hwid)) {
1564 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1565 restore_controller(sc->kbdc, command_byte);
1568 sc->hw.hwid);
1571 switch (sc->hw.hwid) {
1573 sc->hw.type = MOUSE_TRACKBALL;
1580 sc->hw.type = MOUSE_MOUSE;
1583 sc->hw.type = MOUSE_UNKNOWN;
1587 if (sc->config & PSM_CONFIG_NOIDPROBE) {
1588 sc->hw.buttons = 2;
1592 sc->hw.buttons = get_mouse_buttons(sc->kbdc);
1604 sc->hw.model = vendortype[i].model;
1606 sc->dflt_mode.level = PSM_LEVEL_BASE;
1607 sc->dflt_mode.packetsize = MOUSE_PS2_PACKETSIZE;
1608 sc->dflt_mode.accelfactor = (sc->config & PSM_CONFIG_ACCEL) >> 4;
1609 if (sc->config & PSM_CONFIG_NOCHECKSYNC)
1610 sc->dflt_mode.syncmask[0] = 0;
1612 sc->dflt_mode.syncmask[0] = vendortype[i].syncmask;
1613 if (sc->config & PSM_CONFIG_FORCETAP)
1614 sc->dflt_mode.syncmask[0] &= ~MOUSE_PS2_TAP;
1615 sc->dflt_mode.syncmask[1] = 0; /* syncbits */
1616 sc->mode = sc->dflt_mode;
1617 sc->mode.packetsize = vendortype[i].packetsize;
1626 i = send_aux_command(sc->kbdc, PSMC_SET_DEFAULTS);
1630 if (sc->config & PSM_CONFIG_RESOLUTION)
1631 sc->mode.resolution =
1632 set_mouse_resolution(sc->kbdc,
1633 (sc->config & PSM_CONFIG_RESOLUTION) - 1);
1634 else if (sc->mode.resolution >= 0)
1635 sc->mode.resolution =
1636 set_mouse_resolution(sc->kbdc, sc->dflt_mode.resolution);
1637 if (sc->mode.rate > 0)
1638 sc->mode.rate =
1639 set_mouse_sampling_rate(sc->kbdc, sc->dflt_mode.rate);
1640 set_mouse_scaling(sc->kbdc, 1);
1643 sc->flags |= PSM_NEED_SYNCBITS;
1651 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
1658 sc->dflt_mode.rate = sc->mode.rate = stat[2];
1659 sc->dflt_mode.resolution = sc->mode.resolution = stat[1];
1662 /* disable the aux port for now... */
1663 if (!set_controller_command_byte(sc->kbdc,
1671 if (ALWAYS_RESTORE_CONTROLLER(sc->kbdc))
1672 restore_controller(sc->kbdc, command_byte);
1678 kbdc_set_device_mask(sc->kbdc, mask | KBD_AUX_CONTROL_BITS);
1679 kbdc_lock(sc->kbdc, FALSE);
1709 int y = sc->synhw.minimumYCoord + sc->synhw.maximumYCoord - f->y;
1711 evdev_push_abs(sc->evdev_a, ABS_MT_SLOT, id);
1712 evdev_push_abs(sc->evdev_a, ABS_MT_TRACKING_ID, id);
1713 evdev_push_abs(sc->evdev_a, ABS_MT_POSITION_X, f->x);
1714 evdev_push_abs(sc->evdev_a, ABS_MT_POSITION_Y, y);
1715 evdev_push_abs(sc->evdev_a, ABS_MT_PRESSURE, f->p);
1721 int y = sc->synhw.minimumYCoord + sc->synhw.maximumYCoord - f->y;
1723 evdev_push_abs(sc->evdev_a, ABS_X, f->x);
1724 evdev_push_abs(sc->evdev_a, ABS_Y, y);
1725 evdev_push_abs(sc->evdev_a, ABS_PRESSURE, f->p);
1726 if (sc->synhw.capPalmDetect)
1727 evdev_push_abs(sc->evdev_a, ABS_TOOL_WIDTH, f->w);
1740 nbuttons = sc->hw.buttons;
1802 sc->evdev_r = evdev_r;
1811 { ABS_X, sc->synhw.minimumXCoord,
1812 sc->synhw.maximumXCoord, sc->synhw.infoXupmm },
1813 { ABS_Y, sc->synhw.minimumYCoord,
1814 sc->synhw.maximumYCoord, sc->synhw.infoYupmm },
1819 { ABS_MT_SLOT, 0, PSM_FINGERS-1, 0},
1820 { ABS_MT_TRACKING_ID, -1, PSM_FINGERS-1, 0},
1821 { ABS_MT_POSITION_X, sc->synhw.minimumXCoord,
1822 sc->synhw.maximumXCoord, sc->synhw.infoXupmm },
1823 { ABS_MT_POSITION_Y, sc->synhw.minimumYCoord,
1824 sc->synhw.maximumYCoord, sc->synhw.infoYupmm },
1837 if (sc->synhw.capAdvancedGestures || sc->synhw.capReportsV)
1839 if (sc->synhw.capReportsV)
1846 if (sc->synhw.capAdvancedGestures)
1848 if (sc->synhw.capClickPad)
1850 if (sc->synhw.capClickPad && sc->synhw.topButtonPad)
1853 evdev_support_nfingers(evdev_a, sc->synhw.capReportsV ? 5 : 3);
1855 if (sc->synhw.capAdvancedGestures || sc->synhw.capReportsV)
1857 if (sc->synhw.capPalmDetect)
1860 if (!sc->synhw.capClickPad) {
1862 if (sc->synhw.capExtended && sc->synhw.capMiddle)
1865 if (sc->synhw.capExtended && sc->synhw.capFourButtons) {
1869 if (sc->synhw.capExtended && (sc->synhw.nExtendedButtons > 0))
1870 for (i = 0; i < sc->synhw.nExtendedButtons; i++)
1874 if (!error && (sc->synhw.capPassthrough || sc->muxport != PSM_NOMUX)) {
1875 guest_model = sc->tpinfo.sysctl_tree != NULL ?
1882 sc->evdev_a = evdev_a;
1891 { ABS_X, 0, sc->elanhw.sizex,
1892 sc->elanhw.dpmmx },
1893 { ABS_Y, 0, sc->elanhw.sizey,
1894 sc->elanhw.dpmmy },
1897 { ABS_MT_SLOT, 0, ELANTECH_MAX_FINGERS - 1, 0 },
1898 { ABS_MT_TRACKING_ID, -1, ELANTECH_MAX_FINGERS - 1, 0 },
1899 { ABS_MT_POSITION_X, 0, sc->elanhw.sizex,
1900 sc->elanhw.dpmmx },
1901 { ABS_MT_POSITION_Y, 0, sc->elanhw.sizey,
1902 sc->elanhw.dpmmy },
1905 sc->elanhw.dptracex, 0 },
1923 if (sc->elanhw.issemimt)
1925 if (sc->elanhw.isclickpad)
1930 if (!sc->elanhw.isclickpad)
1935 if (!error && sc->elanhw.hastrackpoint)
1940 sc->evdev_a = evdev_a;
1955 sc->state = PSM_VALID;
1956 callout_init(&sc->callout, 0);
1957 callout_init(&sc->softcallout, 0);
1961 sc->intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
1962 if (sc->intr == NULL)
1964 error = bus_setup_intr(dev, sc->intr, INTR_TYPE_TTY, NULL, psmintr, sc,
1965 &sc->ih);
1975 if ((error = make_dev_s(&mda, &sc->cdev, "psm%d", unit)) != 0)
1977 if ((error = make_dev_s(&mda, &sc->bdev, "bpsm%d", unit)) != 0)
1981 switch (sc->hw.model) {
1991 error = psm_register(dev, sc->hw.model);
1999 switch (sc->hw.model) {
2004 sc->config |= PSM_CONFIG_INITAFTERSUSPEND;
2007 if (sc->synhw.infoMajor >= 4 || sc->tpinfo.sysctl_tree != NULL)
2008 sc->config |= PSM_CONFIG_INITAFTERSUSPEND;
2013 if (sc->hw.model == MOUSE_MODEL_ELANTECH &&
2014 (sc->elanhw.hascrc || sc->elanhw.hastrackpoint)) {
2015 sc->config |= PSM_CONFIG_NOCHECKSYNC;
2016 sc->flags &= ~PSM_NEED_SYNCBITS;
2021 model_name(sc->hw.model), sc->hw.hwid & 0x00ff);
2023 device_printf(dev, "model %s, device ID %d-%02x, %d buttons\n",
2024 model_name(sc->hw.model), sc->hw.hwid & 0x00ff,
2025 sc->hw.hwid >> 8, sc->hw.buttons);
2027 sc->config, sc->flags, sc->mode.packetsize);
2029 sc->mode.syncmask[0], sc->mode.syncmask[1],
2030 sc->config & PSM_CONFIG_NOCHECKSYNC ? " (sync not checked)" : "");
2034 --verbose;
2038 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
2039 if (sc->dev != NULL)
2040 destroy_dev(sc->cdev);
2041 if (sc->bdev != NULL)
2042 destroy_dev(sc->bdev);
2054 if (sc->state & PSM_OPEN)
2058 evdev_free(sc->evdev_r);
2059 evdev_free(sc->evdev_a);
2063 bus_teardown_intr(dev, sc->intr, sc->ih);
2064 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
2066 destroy_dev(sc->cdev);
2067 destroy_dev(sc->bdev);
2069 callout_drain(&sc->callout);
2070 callout_drain(&sc->softcallout);
2083 if ((sc->state & PSM_VALID) == 0) {
2088 if (!(sc->state & (PSM_OPEN | PSM_EV_OPEN_A)))
2092 sc->state |= PSM_EV_OPEN_R;
2103 sc->state &= ~PSM_EV_OPEN_R;
2105 if (sc->state & (PSM_OPEN | PSM_EV_OPEN_A))
2108 if (sc->state & PSM_VALID)
2121 if ((sc->state & PSM_VALID) == 0) {
2126 if (!(sc->state & (PSM_OPEN | PSM_EV_OPEN_R)))
2130 sc->state |= PSM_EV_OPEN_A;
2141 sc->state &= ~PSM_EV_OPEN_A;
2143 if (sc->state & (PSM_OPEN | PSM_EV_OPEN_R))
2146 if (sc->state & PSM_VALID)
2160 sc = dev->si_drv1;
2161 if ((sc == NULL) || (sc->state & PSM_VALID) == 0) {
2167 if (sc->state & PSM_OPEN)
2170 device_busy(sc->dev);
2174 if (!(sc->state & (PSM_EV_OPEN_R | PSM_EV_OPEN_A)))
2179 sc->state |= PSM_OPEN;
2181 device_unbusy(sc->dev);
2193 sc = dev->si_drv1;
2194 if ((sc == NULL) || (sc->state & PSM_VALID) == 0) {
2201 if (!(sc->state & (PSM_EV_OPEN_R | PSM_EV_OPEN_A)))
2206 sc->state &= ~PSM_OPEN;
2208 if (sc->async != NULL) {
2209 funsetown(&sc->async);
2210 sc->async = NULL;
2212 device_unbusy(sc->dev);
2226 sc->mode.level = sc->dflt_mode.level;
2227 sc->mode.protocol = sc->dflt_mode.protocol;
2228 sc->watchdog = FALSE;
2229 sc->async = NULL;
2232 sc->queue.count = 0;
2233 sc->queue.head = 0;
2234 sc->queue.tail = 0;
2235 sc->status.flags = 0;
2236 sc->status.button = 0;
2237 sc->status.obutton = 0;
2238 sc->status.dx = 0;
2239 sc->status.dy = 0;
2240 sc->status.dz = 0;
2241 sc->button = 0;
2242 sc->pqueue_start = 0;
2243 sc->pqueue_end = 0;
2247 sc->syncerrors = 0;
2248 sc->pkterrors = 0;
2251 if (!kbdc_lock(sc->kbdc, TRUE))
2256 command_byte = get_controller_command_byte(sc->kbdc);
2258 /* enable the aux port and temporalily disable the keyboard */
2259 if (command_byte == -1 || !set_controller_command_byte(sc->kbdc,
2260 kbdc_get_device_mask(sc->kbdc),
2264 kbdc_lock(sc->kbdc, FALSE);
2266 device_log(sc->dev, LOG_ERR,
2279 /* enable the mouse device */
2283 kbdc_lock(sc->kbdc, FALSE);
2295 if (!kbdc_lock(sc->kbdc, TRUE))
2300 command_byte = get_controller_command_byte(sc->kbdc);
2301 if (command_byte == -1) {
2302 kbdc_lock(sc->kbdc, FALSE);
2307 /* disable the aux interrupt and temporalily disable the keyboard */
2308 if (!set_controller_command_byte(sc->kbdc,
2309 kbdc_get_device_mask(sc->kbdc),
2312 device_log(sc->dev, LOG_ERR,
2313 "failed to disable the aux int (psmclose).\n");
2324 callout_stop(&sc->callout);
2326 /* remove anything left in the output buffer */
2327 empty_aux_buffer(sc->kbdc, 10);
2329 /* disable the aux device, port and interrupt */
2330 if (sc->state & PSM_VALID) {
2331 if (!disable_aux_dev(sc->kbdc)) {
2338 device_log(sc->dev, LOG_ERR,
2342 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
2343 device_log(sc->dev, LOG_DEBUG,
2347 if (!set_controller_command_byte(sc->kbdc,
2348 kbdc_get_device_mask(sc->kbdc),
2355 device_log(sc->dev, LOG_ERR,
2356 "failed to disable the aux port (psmclose).\n");
2359 /* remove anything left in the output buffer */
2360 empty_aux_buffer(sc->kbdc, 10);
2363 kbdc_lock(sc->kbdc, FALSE);
2396 if (sc->mode.level == PSM_LEVEL_BASE) {
2397 mapped = status->button & ~MOUSE_BUTTON4DOWN;
2398 if (status->button & MOUSE_BUTTON4DOWN)
2400 status->button = mapped;
2402 i = imax(imin(status->dx, 255), -256);
2406 i = imax(imin(status->dy, 255), -256);
2411 } else if (sc->mode.level == PSM_LEVEL_STANDARD) {
2413 butmapmsc[status->button & MOUSE_STDBUTTONS];
2414 i = imax(imin(status->dx, 255), -256);
2416 buf[3] = i - buf[1];
2417 i = imax(imin(status->dy, 255), -256);
2419 buf[4] = i - buf[2];
2420 i = imax(imin(status->dz, 127), -128);
2422 buf[6] = (i - (i >> 1)) & 0x7f;
2423 buf[7] = (~status->button >> 3) & 0x7f;
2426 return (pb->inputbytes);
2432 struct psm_softc *sc = dev->si_drv1;
2438 if ((sc->state & PSM_VALID) == 0)
2443 while (sc->queue.count <= 0) {
2444 if (dev != sc->bdev) {
2448 sc->state |= PSM_ASLP;
2450 sc->state &= ~PSM_ASLP;
2454 } else if ((sc->state & PSM_VALID) == 0) {
2463 while ((sc->queue.count > 0) && (uio->uio_resid > 0)) {
2465 l = imin(sc->queue.count, uio->uio_resid);
2468 if (l > sizeof(sc->queue.buf) - sc->queue.head) {
2469 bcopy(&sc->queue.buf[sc->queue.head], &buf[0],
2470 sizeof(sc->queue.buf) - sc->queue.head);
2471 bcopy(&sc->queue.buf[0],
2472 &buf[sizeof(sc->queue.buf) - sc->queue.head],
2473 l - (sizeof(sc->queue.buf) - sc->queue.head));
2475 bcopy(&sc->queue.buf[sc->queue.head], &buf[0], l);
2476 sc->queue.count -= l;
2477 sc->queue.head = (sc->queue.head + l) % sizeof(sc->queue.buf);
2492 if (!kbdc_lock(sc->kbdc, TRUE))
2496 *c = get_controller_command_byte(sc->kbdc);
2497 if ((*c == -1) || !set_controller_command_byte(sc->kbdc,
2498 kbdc_get_device_mask(sc->kbdc),
2503 kbdc_lock(sc->kbdc, FALSE);
2510 * data must be discarded. Although the aux interrupt is disabled
2511 * at the keyboard controller level, at most one aux interrupt
2513 * output buffer; throw it away. Note that the second argument
2519 empty_aux_buffer(sc->kbdc, 0); /* flush the queue */
2520 read_aux_data_no_wait(sc->kbdc); /* throw away data if any */
2531 sc->queue.count = 0;
2532 sc->queue.head = 0;
2533 sc->queue.tail = 0;
2534 if ((sc->state & PSM_SOFTARMED) != 0) {
2535 sc->state &= ~PSM_SOFTARMED;
2536 callout_stop(&sc->softcallout);
2538 sc->pqueue_start = sc->pqueue_end;
2546 bzero(&sc->pqueue, sizeof(sc->pqueue));
2558 empty_aux_buffer(sc->kbdc, 0);
2561 if (!set_controller_command_byte(sc->kbdc,
2562 kbdc_get_device_mask(sc->kbdc),
2572 kbdc_lock(sc->kbdc, FALSE);
2579 struct psm_softc *sc = dev->si_drv1;
2583 if ((sc->state & PSM_VALID) == 0)
2586 if (sc->mode.level < PSM_LEVEL_NATIVE)
2590 while (uio->uio_resid > 0) {
2591 l = imin(PSM_SMALLBUFSIZE, uio->uio_resid);
2596 VDLOG(4, sc->dev, LOG_DEBUG, "cmd 0x%x\n", buf[i]);
2597 if (!write_aux_command(sc->kbdc, buf[i])) {
2598 VDLOG(2, sc->dev, LOG_DEBUG,
2612 struct psm_softc *sc = dev->si_drv1;
2625 ((old_mousehw_t *)addr)->buttons = sc->hw.buttons;
2626 ((old_mousehw_t *)addr)->iftype = sc->hw.iftype;
2627 ((old_mousehw_t *)addr)->type = sc->hw.type;
2628 ((old_mousehw_t *)addr)->hwid = sc->hw.hwid & 0x00ff;
2634 *(mousehw_t *)addr = sc->hw;
2635 if (sc->mode.level == PSM_LEVEL_BASE)
2636 ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
2642 if (sc->synhw.infoMajor >= 4)
2643 *(synapticshw_t *)addr = sc->synhw;
2651 switch (sc->mode.level) {
2653 ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
2656 ((old_mousemode_t *)addr)->protocol =
2660 ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
2663 ((old_mousemode_t *)addr)->rate = sc->mode.rate;
2664 ((old_mousemode_t *)addr)->resolution = sc->mode.resolution;
2665 ((old_mousemode_t *)addr)->accelfactor = sc->mode.accelfactor;
2671 *(mousemode_t *)addr = sc->mode;
2672 if ((sc->flags & PSM_NEED_SYNCBITS) != 0) {
2673 ((mousemode_t *)addr)->syncmask[0] = 0;
2674 ((mousemode_t *)addr)->syncmask[1] = 0;
2676 ((mousemode_t *)addr)->resolution =
2677 MOUSE_RES_LOW - sc->mode.resolution;
2678 switch (sc->mode.level) {
2680 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
2681 ((mousemode_t *)addr)->packetsize =
2685 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
2686 ((mousemode_t *)addr)->packetsize =
2688 ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
2689 ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
2693 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
2702 mode.rate = ((old_mousemode_t *)addr)->rate;
2706 * low 1 -2
2707 * medium low 2 -3
2708 * medium high 3 -4
2709 * high 4 -5
2711 if (((old_mousemode_t *)addr)->resolution > 0)
2713 -((old_mousemode_t *)addr)->resolution - 1;
2717 ((old_mousemode_t *)addr)->accelfactor;
2718 mode.level = -1;
2726 mode.rate = sc->dflt_mode.rate;
2727 else if (mode.rate == -1)
2743 mode.resolution = sc->dflt_mode.resolution;
2744 else if (mode.resolution == -1)
2748 mode.resolution = MOUSE_RES_LOW - mode.resolution;
2749 if (mode.level == -1)
2751 mode.level = sc->mode.level;
2755 if (mode.accelfactor == -1)
2757 mode.accelfactor = sc->mode.accelfactor;
2768 mode.rate = set_mouse_sampling_rate(sc->kbdc,
2772 set_mouse_resolution(sc->kbdc, mode.resolution);
2773 set_mouse_scaling(sc->kbdc, 1);
2774 get_mouse_status(sc->kbdc, stat, 0, 3);
2777 sc->mode.rate = mode.rate;
2778 sc->mode.resolution = mode.resolution;
2779 sc->mode.accelfactor = mode.accelfactor;
2780 sc->mode.level = mode.level;
2787 *(int *)addr = sc->mode.level;
2794 sc->mode.level = *(int *)addr;
2799 status = sc->status;
2800 sc->status.flags = 0;
2801 sc->status.obutton = sc->status.button;
2802 sc->status.button = 0;
2803 sc->status.dx = 0;
2804 sc->status.dy = 0;
2805 sc->status.dz = 0;
2813 if (data->len > sizeof(data->buf)/sizeof(data->buf[0]))
2819 if ((data->len = get_mouse_status(sc->kbdc, data->buf,
2820 (cmd == MOUSE_READDATA) ? 1 : 0, data->len)) <= 0)
2839 mode.resolution = sc->dflt_mode.resolution;
2840 else if (mode.resolution == -1)
2841 mode.resolution = sc->mode.resolution;
2843 mode.resolution = MOUSE_RES_LOW - mode.resolution;
2848 sc->mode.resolution =
2849 set_mouse_resolution(sc->kbdc, mode.resolution);
2850 if (sc->mode.resolution != mode.resolution)
2862 mode.rate = sc->dflt_mode.rate;
2864 mode.rate = sc->mode.rate;
2869 sc->mode.rate = set_mouse_sampling_rate(sc->kbdc, mode.rate);
2870 if (sc->mode.rate != mode.rate)
2884 if (!set_mouse_scaling(sc->kbdc, *(int *)addr))
2895 sc->hw.hwid &= ~0x00ff;
2896 sc->hw.hwid |= get_aux_id(sc->kbdc);
2897 *(int *)addr = sc->hw.hwid & 0x00ff;
2906 error = fsetown(*(int *)addr, &sc->async);
2909 *(int *) addr = fgetown(&sc->async);
2926 if (sc->watchdog && kbdc_lock(sc->kbdc, TRUE)) {
2927 VDLOG(6, sc->dev, LOG_DEBUG, "lost interrupt?\n");
2929 kbdc_lock(sc->kbdc, FALSE);
2931 sc->watchdog = TRUE;
2933 callout_reset(&sc->callout, hz, psmtimeout, sc);
2965 "Enable tap and drag gestures");
2975 &synaptics_support, 0, "Enable support for Synaptics touchpads");
2978 &trackpoint_support, 0, "Enable support for IBM/Lenovo TrackPoint");
2981 &elantech_support, 0, "Enable support for Elantech touchpads");
2994 if (aux_mux_is_enabled(sc->kbdc))
2999 while((c = read_aux_data_no_wait(sc->kbdc)) != -1) {
3000 pb = &sc->pqueue[sc->pqueue_end];
3003 if (!(sc->state & (PSM_OPEN | PSM_EV_OPEN_R | PSM_EV_OPEN_A)))
3007 if ((pb->inputbytes > 0) &&
3008 timevalcmp(&now, &sc->inputtimeout, >)) {
3011 pb->inputbytes = 0;
3012 sc->syncerrors = 0;
3013 sc->pkterrors = 0;
3015 sc->inputtimeout.tv_sec = PSM_INPUT_TIMEOUT / 1000000;
3016 sc->inputtimeout.tv_usec = PSM_INPUT_TIMEOUT % 1000000;
3017 timevaladd(&sc->inputtimeout, &now);
3019 pb->ipacket[pb->inputbytes++] = c;
3021 if (sc->mode.level == PSM_LEVEL_NATIVE) {
3022 VLOG(4, (LOG_DEBUG, "psmintr: %02x\n", pb->ipacket[0]));
3023 sc->syncerrors = 0;
3024 sc->pkterrors = 0;
3027 if (pb->inputbytes < sc->mode.packetsize)
3032 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2],
3033 pb->ipacket[3], pb->ipacket[4], pb->ipacket[5]));
3036 c = pb->ipacket[0];
3038 if ((sc->flags & PSM_NEED_SYNCBITS) != 0) {
3039 sc->mode.syncmask[1] = (c & sc->mode.syncmask[0]);
3040 sc->flags &= ~PSM_NEED_SYNCBITS;
3043 sc->mode.syncmask[0], sc->mode.syncmask[1]));
3044 } else if ((sc->config & PSM_CONFIG_NOCHECKSYNC) == 0 &&
3045 (c & sc->mode.syncmask[0]) != sc->mode.syncmask[1]) {
3048 c & sc->mode.syncmask[0], sc->mode.syncmask[1],
3049 sc->cmdcount - sc->lasterr));
3050 sc->lasterr = sc->cmdcount;
3059 if (sc->syncerrors == 0)
3060 sc->pkterrors++;
3061 ++sc->syncerrors;
3062 sc->lastinputerr = now;
3063 if (sc->syncerrors >= sc->mode.packetsize * 2 ||
3064 sc->pkterrors >= pkterrthresh) {
3076 } else if (sc->syncerrors == sc->mode.packetsize) {
3082 "psmintr: re-enable the mouse.\n"));
3083 pb->inputbytes = 0;
3084 disable_aux_dev(sc->kbdc);
3085 enable_aux_dev(sc->kbdc);
3089 sc->syncerrors));
3090 pb->inputbytes--;
3091 bcopy(&pb->ipacket[1], &pb->ipacket[0],
3092 pb->inputbytes);
3101 sc->syncerrors = 0;
3110 if (!timeelapsed(&sc->lastinputerr, psmerrsecs, psmerrusecs,
3112 pb->inputbytes = 0;
3120 sc->pkterrors = 0;
3122 sc->cmdcount++;
3124 if (++sc->pqueue_end >= PSM_PACKETQUEUE)
3125 sc->pqueue_end = 0;
3132 if (sc->hw.model == MOUSE_MODEL_SYNAPTICS ||
3133 sc->hw.model == MOUSE_MODEL_ELANTECH ||
3134 !timeelapsed(&sc->lastsoftintr, psmsecs, psmusecs, &now) ||
3135 (sc->pqueue_end == sc->pqueue_start)) {
3136 if ((sc->state & PSM_SOFTARMED) != 0) {
3137 sc->state &= ~PSM_SOFTARMED;
3138 callout_stop(&sc->softcallout);
3141 } else if ((sc->state & PSM_SOFTARMED) == 0) {
3142 sc->state |= PSM_SOFTARMED;
3143 callout_reset(&sc->softcallout,
3161 * p3-p0: packet type
3177 * d2-d0: roller data
3181 if (((pb->ipacket[0] & MOUSE_PS2PLUS_SYNCMASK) == MOUSE_PS2PLUS_SYNC) &&
3182 (abs(*x) > 191) && MOUSE_PS2PLUS_CHECKBITS(pb->ipacket)) {
3187 switch (MOUSE_PS2PLUS_PACKET_TYPE(pb->ipacket)) {
3191 if (pb->ipacket[2] & 0x80) {
3192 /* XXX horizontal roller count - ignore it */
3196 *z = (pb->ipacket[2] & MOUSE_PS2PLUS_ZNEG) ?
3197 (pb->ipacket[2] & 0x0f) - 16 :
3198 (pb->ipacket[2] & 0x0f);
3200 ms->button |= (pb->ipacket[2] &
3203 ms->button |= (pb->ipacket[2] &
3219 if (pb->ipacket[2] & 0x0f)
3220 *z = (pb->ipacket[2] & MOUSE_SPOINT_WNEG) ?
3221 -2 : 2;
3223 if (pb->ipacket[2] & 0xf0)
3224 *z = (pb->ipacket[2] & MOUSE_SPOINT_ZNEG) ?
3225 -1 : 1;
3228 /* device type packet - shouldn't happen */
3232 ms->button = ms->obutton;
3235 MOUSE_PS2PLUS_PACKET_TYPE(pb->ipacket),
3236 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2]));
3241 ms->button |= ms->obutton & MOUSE_EXTBUTTONS;
3260 * ------------------------------------------------
3281 * ------------------------------------------------------
3289 * b1-b8: Extended mouse buttons
3293 * Absolute reportable limits: 0 - 6143.
3294 * Typical bezel limits: 1472 - 5472.
3295 * Typical edge marings: 1632 - 5312.
3306 if ((pb->ipacket[0] & 0xc8) != 0x80 ||
3307 (pb->ipacket[3] & 0xc8) != 0xc0)
3308 return (-1);
3311 ms->button = ms->obutton;
3324 *z = pb->ipacket[2];
3333 * w = 4-7 Finger of normal width (capPalmDetect needed)
3334 * w = 8-14 Very wide finger or palm (capPalmDetect needed)
3338 if (sc->synhw.capExtended)
3339 w = ((pb->ipacket[0] & 0x30) >> 2) |
3340 ((pb->ipacket[0] & 0x04) >> 1) |
3341 ((pb->ipacket[3] & 0x04) >> 2);
3353 if (sc->synhw.capPassthrough || sc->muxport != PSM_NOMUX) {
3354 *x = ((pb->ipacket[1] & 0x10) ?
3355 pb->ipacket[4] - 256 : pb->ipacket[4]);
3356 *y = ((pb->ipacket[1] & 0x20) ?
3357 pb->ipacket[5] - 256 : pb->ipacket[5]);
3361 if (pb->ipacket[1] & 0x01)
3363 if (pb->ipacket[1] & 0x04)
3365 if (pb->ipacket[1] & 0x02)
3369 evdev_push_rel(sc->evdev_r, REL_X, *x);
3370 evdev_push_rel(sc->evdev_r, REL_Y, -*y);
3371 evdev_push_mouse_btn(sc->evdev_r,
3372 guest_buttons | sc->extended_buttons);
3373 evdev_sync(sc->evdev_r);
3376 ms->button = touchpad_buttons | guest_buttons |
3377 sc->extended_buttons;
3383 ewcode = (pb->ipacket[5] & 0xf0) >> 4;
3388 if (sc->synhw.capAdvancedGestures)
3390 .x = (((pb->ipacket[4] & 0x0f) << 8) |
3391 pb->ipacket[1]) << 1,
3392 .y = (((pb->ipacket[4] & 0xf0) << 4) |
3393 pb->ipacket[2]) << 1,
3394 .p = ((pb->ipacket[3] & 0x30) |
3395 (pb->ipacket[5] & 0x0f)) << 1,
3399 else if (sc->synhw.capReportsV)
3401 .x = (((pb->ipacket[4] & 0x0f) << 8) |
3402 (pb->ipacket[1] & 0xfe)) << 1,
3403 .y = (((pb->ipacket[4] & 0xf0) << 4) |
3404 (pb->ipacket[2] & 0xfe)) << 1,
3405 .p = ((pb->ipacket[3] & 0x30) |
3406 (pb->ipacket[5] & 0x0e)) << 1,
3407 .w = (((pb->ipacket[5] & 0x01) << 2) |
3408 ((pb->ipacket[2] & 0x01) << 1) |
3409 (pb->ipacket[1] & 0x01)) + 8,
3414 ew_finger_count = pb->ipacket[1] & 0x0f;
3422 if (sc->synhw.capReportsV && ew_finger_count > 3) {
3435 if (sc->syninfo.touchpad_off)
3440 if (pb->ipacket[0] & 0x01)
3442 if (pb->ipacket[0] & 0x02)
3445 if (sc->synhw.capExtended && sc->synhw.capFourButtons) {
3446 if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x01)
3448 if ((pb->ipacket[3] ^ pb->ipacket[0]) & 0x02)
3450 } else if (sc->synhw.capExtended && sc->synhw.capMiddle &&
3451 !sc->synhw.capClickPad) {
3453 if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x01)
3455 } else if (sc->synhw.capExtended && (sc->synhw.nExtendedButtons > 0)) {
3457 if ((pb->ipacket[0] ^ pb->ipacket[3]) & 0x02) {
3458 if (sc->syninfo.directional_scrolls) {
3459 if (pb->ipacket[4] & 0x01)
3461 if (pb->ipacket[5] & 0x01)
3463 if (pb->ipacket[4] & 0x02)
3465 if (pb->ipacket[5] & 0x02)
3468 if (pb->ipacket[4] & 0x01)
3470 if (pb->ipacket[5] & 0x01)
3472 if (pb->ipacket[4] & 0x02)
3474 sc->extended_buttons = extended_buttons;
3488 * (1 << n) - 1
3492 maskedbits = (sc->synhw.nExtendedButtons + 1) >> 1;
3493 mask = (1 << maskedbits) - 1;
3497 if (sc->synhw.capPassthrough) {
3498 evdev_push_mouse_btn(sc->evdev_r,
3500 evdev_sync(sc->evdev_r);
3503 evdev_push_key(sc->evdev_a,
3505 pb->ipacket[4] & (1 << i));
3506 evdev_push_key(sc->evdev_a,
3508 pb->ipacket[5] & (1 << i));
3512 pb->ipacket[4] &= ~(mask);
3513 pb->ipacket[5] &= ~(mask);
3514 } else if (!sc->syninfo.directional_scrolls &&
3515 !sc->gesture.in_vscroll) {
3520 extended_buttons |= sc->extended_buttons;
3524 if (sc->synhw.capReportsV && nfingers > 1)
3526 .x = ((pb->ipacket[3] & 0x10) << 8) |
3527 ((pb->ipacket[1] & 0x0f) << 8) |
3528 (pb->ipacket[4] & 0xfd),
3529 .y = ((pb->ipacket[3] & 0x20) << 7) |
3530 ((pb->ipacket[1] & 0xf0) << 4) |
3531 (pb->ipacket[5] & 0xfd),
3533 .w = (((pb->ipacket[2] & 0x01) << 2) |
3534 (pb->ipacket[5] & 0x02) |
3535 ((pb->ipacket[4] & 0x02) >> 1)) + 8,
3540 .x = ((pb->ipacket[3] & 0x10) << 8) |
3541 ((pb->ipacket[1] & 0x0f) << 8) |
3542 pb->ipacket[4],
3543 .y = ((pb->ipacket[3] & 0x20) << 7) |
3544 ((pb->ipacket[1] & 0xf0) << 4) |
3545 pb->ipacket[5],
3552 if (f[0].p < sc->syninfo.min_pressure || f[0].x < 2)
3556 if (sc->synhw.capClickPad) {
3557 clickpad_pressed = (pb->ipacket[0] ^ pb->ipacket[3]) & 0x01;
3558 if (sc->synhw.forcePad) {
3569 sc->fpcount = 0;
3572 if (clickpad_pressed && sc->fpcount < INT_MAX)
3573 ++sc->fpcount;
3577 sc->fpcount = 0;
3578 if (sc->fpcount >= sc->syninfo.window_min)
3594 evdev_push_key(sc->evdev_a, BTN_TOUCH, nfingers > 0);
3595 evdev_push_nfingers(sc->evdev_a, nfingers);
3599 evdev_push_abs(sc->evdev_a, ABS_PRESSURE, 0);
3600 evdev_push_mouse_btn(sc->evdev_a, touchpad_buttons);
3601 if (sc->synhw.capExtended && sc->synhw.capFourButtons) {
3602 evdev_push_key(sc->evdev_a, BTN_FORWARD,
3604 evdev_push_key(sc->evdev_a, BTN_BACK,
3607 evdev_sync(sc->evdev_a);
3611 ms->button = touchpad_buttons;
3624 ms->button = ms->obutton;
3628 ms->button |= extended_buttons | guest_buttons;
3638 * xf86-input-mouse needs therefore a small patch to
3645 if (ms->button & MOUSE_BUTTON4DOWN)
3646 *z = -1;
3647 else if (ms->button & MOUSE_BUTTON5DOWN)
3649 else if (ms->button & MOUSE_BUTTON6DOWN)
3650 *z = -2;
3651 else if (ms->button & MOUSE_BUTTON7DOWN)
3655 ms->button &= ~(MOUSE_BUTTON4DOWN | MOUSE_BUTTON5DOWN |
3667 * Convert 3-byte interleaved mixture of Synaptics and generic mouse
3668 * packets into plain 6-byte Synaptics packet protocol.
3676 switch (pb->ipacket[0] & 0xc0) {
3678 bcopy(pb->ipacket, sc->muxsave, 3);
3680 sc->muxmidtimeout.tv_sec = 0;
3681 sc->muxmidtimeout.tv_usec = 50000; /* ~2-3 ints */
3682 timevaladd(&sc->muxmidtimeout, &sc->lastsoftintr);
3686 /* Join two 3-bytes absolute packets */
3687 bcopy(pb->ipacket, pb->ipacket + 3, 3);
3688 bcopy(sc->muxsave, pb->ipacket, 3);
3690 pb->ipacket[0] &= ~(0x08 | sc->muxmsbuttons);
3691 pb->ipacket[3] &= ~(0x08 | sc->muxmsbuttons);
3692 butt = (pb->ipacket[3] & 0x03) << 2 | (pb->ipacket[0] & 0x03);
3694 if (butt != sc->muxtpbuttons && sc->fpcount < 1) {
3695 pb->ipacket[0] &= 0xfc;
3696 pb->ipacket[0] |= sc->muxtpbuttons & 0x03;
3697 pb->ipacket[3] &= 0xfc;
3698 pb->ipacket[3] |= sc->muxtpbuttons >> 2 & 0x03;
3699 ++sc->fpcount;
3701 sc->fpcount = 0;
3702 sc->muxtpbuttons = butt;
3705 if (sc->synhw.capExtended && !sc->synhw.capPassthrough &&
3706 (pb->ipacket[0] & 0x34) == 0x04 &&
3707 (pb->ipacket[3] & 0x04) == 0x04) {
3708 pb->ipacket[0] &= 0xfb;
3709 pb->ipacket[3] &= 0xfb;
3711 sc->muxsave[0] &= 0x30;
3716 if (sc->muxmsbuttons & 0x03 || pb->ipacket[0] & 0x03 ||
3717 (timevalcmp(&sc->lastsoftintr, &sc->muxmidtimeout, <=) &&
3718 (sc->muxsave[0] & 0x30 || sc->muxsave[2] > 8)))
3719 pb->ipacket[0] &= 0xfb;
3720 sc->muxmsbuttons = pb->ipacket[0] & 0x07;
3721 /* Convert to Synaptics pass-through protocol */
3722 pb->ipacket[4] = pb->ipacket[1];
3723 pb->ipacket[5] = pb->ipacket[2];
3724 pb->ipacket[1] = pb->ipacket[0];
3725 pb->ipacket[2] = 0;
3726 pb->ipacket[0] = 0x84 | (sc->muxtpbuttons & 0x03);
3727 pb->ipacket[3] = 0xc4 | (sc->muxtpbuttons >> 2 & 0x03);
3731 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2],
3732 pb->ipacket[3], pb->ipacket[4], pb->ipacket[5]));
3734 pb->inputbytes = MOUSE_SYNAPTICS_PACKETSIZE;
3742 ((sc->synhw.capMultiFinger || sc->synhw.capAdvancedGestures) &&
3743 !sc->synhw.capReportsV && nfingers > 1) ||
3744 (sc->synhw.capReportsV && nfingers > 2) ||
3745 (sc->synhw.capPalmDetect && f->w <= sc->syninfo.max_width) ||
3746 (!sc->synhw.capPalmDetect && f->p <= sc->syninfo.max_pressure) ||
3747 (sc->synhw.capPen && f->flags & PSM_FINGER_IS_PEN))) {
3751 * - the width isn't comprised in:
3753 * - the pressure isn't comprised in:
3755 * - pen aren't supported but PSM_FINGER_IS_PEN is set
3757 VLOG(2, (LOG_DEBUG, "synaptics: palm detected! (%d)\n", f->w));
3773 smoother = &sc->smoother[0];
3774 gest = &sc->gesture;
3781 smoother = &sc->smoother[i];
3791 if (f->p >= sc->syninfo.min_pressure) {
3805 margin_top = sc->syninfo.margin_top;
3806 margin_right = sc->syninfo.margin_right;
3807 margin_bottom = sc->syninfo.margin_bottom;
3808 margin_left = sc->syninfo.margin_left;
3809 window_min = sc->syninfo.window_min;
3810 window_max = sc->syninfo.window_max;
3811 vscroll_hor_area = sc->syninfo.vscroll_hor_area;
3812 vscroll_ver_area = sc->syninfo.vscroll_ver_area;
3813 two_finger_scroll = sc->syninfo.two_finger_scroll;
3814 max_x = sc->syninfo.max_x;
3815 max_y = sc->syninfo.max_y;
3816 three_finger_drag = sc->syninfo.three_finger_drag;
3818 x0 = f->x;
3819 y0 = f->y;
3827 else if (x0 >= max_x - margin_right)
3828 x0 = max_x - margin_right;
3831 else if (y0 >= max_y - margin_top)
3832 y0 = max_y - margin_top;
3835 x0, y0, f->p, f->w));
3841 if (!(sc->flags & PSM_FLAGS_FINGERDOWN)) {
3842 VLOG(3, (LOG_DEBUG, "synaptics: ----\n"));
3845 gest->window_min = window_min;
3848 gest->zmax = 0;
3851 gest->fingers_nb = 0;
3854 gest->in_vscroll = 0;
3858 gest->taptimeout = (struct timeval) {
3863 &gest->taptimeout, &sc->lastsoftintr);
3865 timevalclear(&gest->taptimeout);
3867 sc->flags |= PSM_FLAGS_FINGERDOWN;
3874 queue_len = smoother->queue_len + 1;
3875 start_x = smoother->start_x;
3876 start_y = smoother->start_y;
3880 if (sc->synhw.capClickPad && ms->button & MOUSE_BUTTON1DOWN) {
3881 y_ok = sc->syninfo.softbuttons_y >= 0 ?
3882 start_y < sc->syninfo.softbuttons_y :
3883 start_y > max_y + sc->syninfo.softbuttons_y;
3886 center_x = sc->syninfo.softbutton2_x;
3888 right_x = sc->syninfo.softbutton3_x;
3892 center_x = sc->syninfo.softbutton3_x;
3894 right_x = sc->syninfo.softbutton2_x;
3898 ms->button = (ms->button &
3901 ms->button = (ms->button &
3905 /* If in tap-hold or three fingers, add the recorded button. */
3906 if (gest->in_taphold || (nfingers == 3 && three_finger_drag))
3907 ms->button |= gest->tap_button;
3915 gest->window_min = window_max;
3916 gest->fingers_nb = imax(nfingers, gest->fingers_nb);
3917 gest->zmax = imax(f->p, gest->zmax);
3920 if (queue_len < gest->window_min)
3923 dyp = -1;
3924 dxp = -1;
3927 if (!gest->in_taphold && !ms->button &&
3928 (!gest->in_vscroll || two_finger_scroll)) {
3933 * - the action in a configurable area
3934 * - one of the following:
3939 dxp = abs(x0 - start_x);
3940 dyp = abs(y0 - start_y);
3942 if (timevalcmp(&sc->lastsoftintr, &gest->taptimeout, >) ||
3943 dxp >= sc->syninfo.vscroll_min_delta ||
3944 dyp >= sc->syninfo.vscroll_min_delta) {
3952 gest->in_vscroll +=
3954 gest->in_vscroll +=
3964 gest->in_vscroll += 2;
3972 gest->in_vscroll += 1;
3976 if (gest->in_vscroll >= 3)
3977 gest->in_vscroll =
3985 if (two_finger_scroll && gest->in_vscroll != 0 &&
3986 (nfingers != 2 || ms->button))
3987 gest->in_vscroll = 0;
3992 gest->in_vscroll ? "YES" : "NO",
3993 gest->in_vscroll, dxp, dyp,
3994 gest->fingers_nb));
3996 } else if (sc->flags & PSM_FLAGS_FINGERDOWN) {
4003 dx = abs(smoother->queue[smoother->queue_cursor].x -
4004 smoother->start_x);
4005 dy = abs(smoother->queue[smoother->queue_cursor].y -
4006 smoother->start_y);
4008 /* Max delta is disabled for multi-fingers tap. */
4009 if (gest->fingers_nb > 1)
4012 tap_max_delta = sc->syninfo.tap_max_delta;
4014 sc->flags &= ~PSM_FLAGS_FINGERDOWN;
4020 gest->zmax, dx, dy, tap_max_delta, gest->fingers_nb,
4021 smoother->queue_len));
4022 if (!gest->in_vscroll && gest->zmax >= tap_threshold &&
4023 timevalcmp(&sc->lastsoftintr, &gest->taptimeout, <=) &&
4025 smoother->queue_len >= sc->syninfo.tap_min_queue) {
4028 * - the maximum pressure went over tap_threshold
4029 * - the action ended before tap_timeout
4031 * To handle tap-hold, we must delay any button push to
4034 if (gest->in_taphold) {
4037 * double tap action, not a tap-hold.
4039 gest->in_taphold = 0;
4042 * For double-tap to work:
4043 * - no button press is emitted (to
4045 * - PSM_FLAGS_FINGERDOWN is set to
4051 gest->tap_button));
4052 sc->flags |= PSM_FLAGS_FINGERDOWN;
4055 sc->idletimeout.tv_sec = psmhz > 1 ?
4057 sc->idletimeout.tv_usec = psmhz > 1 ?
4062 * tap-hold state and notify the button
4065 gest->in_taphold = 1;
4066 taphold_timeout = sc->syninfo.taphold_timeout;
4067 gest->taptimeout.tv_sec = taphold_timeout /
4069 gest->taptimeout.tv_usec = taphold_timeout %
4071 sc->idletimeout = gest->taptimeout;
4072 timevaladd(&gest->taptimeout,
4073 &sc->lastsoftintr);
4075 switch (gest->fingers_nb) {
4077 gest->tap_button =
4081 gest->tap_button =
4085 gest->tap_button =
4090 gest->tap_button));
4091 ms->button |= gest->tap_button;
4096 * tap-hold state.
4098 if (gest->in_taphold) {
4101 gest->tap_button));
4102 gest->in_taphold = 0;
4105 "synaptics: not a tap-hold\n"));
4108 } else if (!(sc->flags & PSM_FLAGS_FINGERDOWN) && gest->in_taphold) {
4110 * For a tap-hold to work, the button must remain down at
4114 if (timevalcmp(&sc->lastsoftintr, &gest->taptimeout, <=)) {
4115 ms->button |= gest->tap_button;
4118 gest->tap_button));
4119 gest->in_taphold = 0;
4130 smoother_t *smoother = &sc->smoother[smoother_id];
4131 gesture_t *gest = &(sc->gesture);
4137 if (f->p >= sc->syninfo.min_pressure) {
4156 margin_top = sc->syninfo.margin_top;
4157 margin_right = sc->syninfo.margin_right;
4158 margin_bottom = sc->syninfo.margin_bottom;
4159 margin_left = sc->syninfo.margin_left;
4160 na_top = sc->syninfo.na_top;
4161 na_right = sc->syninfo.na_right;
4162 na_bottom = sc->syninfo.na_bottom;
4163 na_left = sc->syninfo.na_left;
4164 window_max = sc->syninfo.window_max;
4165 multiplicator = sc->syninfo.multiplicator;
4166 weight_current = sc->syninfo.weight_current;
4167 weight_previous = sc->syninfo.weight_previous;
4168 weight_len_squared = sc->syninfo.weight_len_squared;
4169 div_min = sc->syninfo.div_min;
4170 div_max = sc->syninfo.div_max;
4171 div_len = sc->syninfo.div_len;
4172 two_finger_scroll = sc->syninfo.two_finger_scroll;
4173 max_x = sc->syninfo.max_x;
4174 max_y = sc->syninfo.max_y;
4175 natural_scroll = sc->syninfo.natural_scroll;
4177 is_fuzzy = (f->flags & PSM_FINGER_FUZZY) != 0;
4180 x0 = f->x;
4181 y0 = f->y;
4189 else if (x0 >= max_x - margin_right)
4190 x0 = max_x - margin_right;
4193 else if (y0 >= max_y - margin_top)
4194 y0 = max_y - margin_top;
4197 if (smoother->active == 0) {
4198 VLOG(3, (LOG_DEBUG, "smoother%d: ---\n", smoother_id));
4201 smoother->start_x = x0;
4202 smoother->start_y = y0;
4206 smoother->queue_cursor = SYNAPTICS_PACKETQUEUE;
4207 smoother->queue_len = 0;
4210 smoother->avg_dx = 0;
4211 smoother->avg_dy = 0;
4214 smoother->squelch_x = 0;
4215 smoother->squelch_y = 0;
4218 smoother->active = 1;
4221 cursor = smoother->queue_cursor;
4222 dx = x0 - smoother->queue[cursor].x;
4223 dy = y0 - smoother->queue[cursor].y;
4227 smoother_id, x0, y0, f->p, f->w));
4230 cursor = SYNAPTICS_QUEUE_CURSOR(smoother->queue_cursor - 1);
4231 smoother->queue[cursor].x = x0;
4232 smoother->queue[cursor].y = y0;
4233 smoother->queue_cursor = cursor;
4234 if (smoother->queue_len < SYNAPTICS_PACKETQUEUE)
4235 smoother->queue_len++;
4241 if (smoother->queue_len < gest->window_min)
4247 if (gest->in_vscroll) {
4249 div_min = sc->syninfo.vscroll_div_min;
4250 div_max_x = div_max_y = sc->syninfo.vscroll_div_max;
4258 if (x0 <= na_left || x0 >= max_x - na_right) {
4259 weight_prev_x = sc->syninfo.weight_previous_na;
4260 div_max_x = sc->syninfo.div_max_na;
4263 if (y0 <= na_bottom || y0 >= max_y - na_top) {
4264 weight_prev_y = sc->syninfo.weight_previous_na;
4265 div_max_y = sc->syninfo.div_max_na;
4275 window = imin(smoother->queue_len, window_max);
4276 peer = SYNAPTICS_QUEUE_CURSOR(cursor + window - 1);
4277 dxp = abs(x0 - smoother->queue[peer].x) + 1;
4278 dyp = abs(y0 - smoother->queue[peer].y) + 1;
4299 smoother->avg_dx =
4301 weight_prev_x * smoother->avg_dx) /
4304 smoother->avg_dy =
4306 weight_prev_y * smoother->avg_dy) /
4311 smoother->avg_dx / multiplicator,
4312 smoother->avg_dy / multiplicator));
4315 smoother->squelch_x += smoother->avg_dx;
4316 dxp = smoother->squelch_x / (div_x * multiplicator);
4317 smoother->squelch_x = smoother->squelch_x %
4320 smoother->squelch_y += smoother->avg_dy;
4321 dyp = smoother->squelch_y / (div_y * multiplicator);
4322 smoother->squelch_y = smoother->squelch_y %
4325 switch(gest->in_vscroll) {
4327 /* On real<->fuzzy finger switch the x/y pos jumps */
4328 if (is_fuzzy == smoother->is_fuzzy) {
4333 VLOG(3, (LOG_DEBUG, "smoother%d: [%d, %d] -> [%d, %d]\n",
4339 ms->button |= (dyp > 0) ?
4342 ms->button |= (dyp > 0) ?
4349 ms->button |= (dxp > 0) ?
4352 ms->button |= (dxp > 0) ?
4358 smoother->is_fuzzy = is_fuzzy;
4366 smoother->active = 0;
4382 if (ELANTECH_PKT_IS_DEBOUNCE(pb, sc->elanhw.hwversion))
4384 else if (sc->elanhw.hastrackpoint && ELANTECH_PKT_IS_TRACKPOINT(pb))
4387 switch (sc->elanhw.hwversion) {
4390 return (-1);
4392 pkt = (pb->ipacket[0] & 0xc0) == 0x80 ?
4396 if (!ELANTECH_PKT_IS_V3_HEAD(pb, sc->elanhw.hascrc) &&
4397 !ELANTECH_PKT_IS_V3_TAIL(pb, sc->elanhw.hascrc))
4398 return (-1);
4403 if (!ELANTECH_PKT_IS_V4(pb, sc->elanhw.hascrc))
4404 return (-1);
4406 switch (pb->ipacket[3] & 0x03) {
4417 return (-1);
4421 return (-1);
4430 ms->button = ms->obutton;
4432 if (sc->syninfo.touchpad_off && pkt != ELANTECH_PKT_TRACKPOINT)
4447 * -------------------------------------------
4454 * -------------------------------------------
4461 nfingers = (pb->ipacket[0] & 0xc0) >> 6;
4462 if (nfingers == 3 && (pb->ipacket[3] & 0x80))
4466 mask = (1 << nfingers) - 1; /* = 0x00 */
4470 /* Map 3-rd and 4-th fingers to first finger */
4471 mask = (1 << 1) - 1; /* = 0x01 */
4473 if (sc->elanhw.haspressure) {
4474 f[0].w = ((pb->ipacket[0] & 0x30) >> 2) |
4475 ((pb->ipacket[3] & 0x30) >> 4);
4492 * -------------------------------------------
4499 * -------------------------------------------
4500 * AX: lower-left finger absolute x value
4501 * AY: lower-left finger absolute y value
4502 * BX: upper-right finger absolute x value
4503 * BY: upper-right finger absolute y value
4506 mask = (1 << nfingers) - 1;
4510 .x = (((pb->ipacket[id * 3] & 0x10) << 4) |
4511 pb->ipacket[id * 3 + 1]) << 2,
4512 .y = (((pb->ipacket[id * 3] & 0x20) << 3) |
4513 pb->ipacket[id * 3 + 2]) << 2,
4523 * -------------------------------------------
4530 * -------------------------------------------
4532 nfingers = (pb->ipacket[0] & 0xc0) >> 6;
4533 /* Map 3-rd finger to first finger */
4534 id = nfingers > 2 ? 0 : nfingers - 1;
4535 mask = (1 << (id + 1)) - 1;
4541 fn.w = ((pb->ipacket[0] & 0x30) >> 2) |
4542 ((pb->ipacket[3] & 0x30) >> 4);
4552 if (ELANTECH_PKT_IS_V3_HEAD(pb, sc->elanhw.hascrc)) {
4553 sc->elanaction.fingers[0] = fn;
4556 f[0] = sc->elanaction.fingers[0];
4563 * -------------------------------------------
4570 * -------------------------------------------
4577 mask = pb->ipacket[1] & 0x1f;
4580 if (sc->elanaction.mask_v4wait != 0)
4585 sc->elanaction.mask_v4wait = mask & ~sc->elanaction.mask;
4588 if (sc->elanaction.mask_v4wait) {
4589 sc->elanaction.mask = mask;
4597 * -------------------------------------------
4604 * -------------------------------------------
4610 mask = sc->elanaction.mask;
4612 id = ((pb->ipacket[3] & 0xe0) >> 5) - 1;
4614 fn.w =(pb->ipacket[0] & 0xf0) >> 4;
4620 if (sc->elanaction.mask_v4wait == 0) {
4627 sc->elanaction.mask_v4wait &= ~(1 << id);
4629 sc->elanaction.fingers[id] = fn;
4632 if (sc->elanaction.mask_v4wait != 0)
4637 if (sc->elanaction.mask & (1 << id))
4638 f[id] = sc->elanaction.fingers[id];
4644 * -------------------------------------------
4651 * -------------------------------------------
4652 * OF: delta overflows (> 127 or < -128), in this case
4660 mask = sc->elanaction.mask;
4663 scale = (pb->ipacket[0] & 0x10) ? 5 : 1;
4665 id = ((pb->ipacket[i] & 0xe0) >> 5) - 1;
4669 if (PSM_FINGER_IS_SET(sc->elanaction.fingers[id])) {
4670 f[id] = sc->elanaction.fingers[id];
4671 f[id].x += imax(-f[id].x,
4672 (signed char)pb->ipacket[i+1] * scale);
4673 f[id].y += imax(-f[id].y,
4674 (signed char)pb->ipacket[i+2] * scale);
4685 * -------------------------------------------
4692 * -------------------------------------------
4697 if (!(pb->ipacket[0] & 0xC8) && !(pb->ipacket[1] & 0x7F) &&
4698 !(pb->ipacket[2] & 0x7F) && !(pb->ipacket[3] & 0xC9) &&
4699 !(pb->ipacket[0] & 0x10) != !(pb->ipacket[1] & 0x80) &&
4700 !(pb->ipacket[0] & 0x10) != !(pb->ipacket[3] & 0x10) &&
4701 !(pb->ipacket[0] & 0x20) != !(pb->ipacket[2] & 0x80) &&
4702 !(pb->ipacket[0] & 0x20) != !(pb->ipacket[3] & 0x20)) {
4703 *x = (pb->ipacket[0] & MOUSE_PS2_XNEG) ?
4704 pb->ipacket[4] - 256 : pb->ipacket[4];
4705 *y = (pb->ipacket[0] & MOUSE_PS2_YNEG) ?
4706 pb->ipacket[5] - 256 : pb->ipacket[5];
4709 ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) |
4710 ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0) |
4711 ((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0);
4713 evdev_push_rel(sc->evdev_r, REL_X, *x);
4714 evdev_push_rel(sc->evdev_r, REL_Y, -*y);
4715 evdev_push_mouse_btn(sc->evdev_r, trackpoint_button);
4716 evdev_sync(sc->evdev_r);
4718 ms->button = touchpad_button | trackpoint_button;
4728 return (-1);
4738 if (sc->elanhw.isclickpad) {
4740 ((pb->ipacket[0] & 0x03) ? MOUSE_BUTTON1DOWN : 0);
4743 ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) |
4744 ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0);
4753 evdev_push_abs(sc->evdev_a, ABS_MT_TOUCH_MAJOR,
4754 f[id].w * sc->elanhw.dptracex);
4757 evdev_push_key(sc->evdev_a, BTN_TOUCH, nfingers > 0);
4758 evdev_push_nfingers(sc->evdev_a, nfingers);
4763 evdev_push_abs(sc->evdev_a, ABS_PRESSURE, 0);
4764 evdev_push_mouse_btn(sc->evdev_a, touchpad_button);
4765 evdev_sync(sc->evdev_a);
4769 ms->button = touchpad_button | trackpoint_button;
4787 sc->elanaction.fingers[id] = f[id];
4788 if ((sc->elanaction.mask & (1 << id)) && !(mask & (1 << id)))
4789 PSM_FINGER_RESET(sc->elanaction.fingers[id]);
4791 sc->elanaction.mask = mask;
4795 ms->button = ms->obutton;
4800 if (ms->button & MOUSE_BUTTON4DOWN)
4801 *z = -1;
4802 else if (ms->button & MOUSE_BUTTON5DOWN)
4804 else if (ms->button & MOUSE_BUTTON6DOWN)
4805 *z = -2;
4806 else if (ms->button & MOUSE_BUTTON7DOWN)
4810 ms->button &= ~(MOUSE_BUTTON4DOWN | MOUSE_BUTTON5DOWN |
4853 c = pb->ipacket[0];
4855 ms->button = butmap_versapad[c & MOUSE_PS2VERSA_BUTTONS];
4856 ms->button |= (c & MOUSE_PS2VERSA_TAP) ? MOUSE_BUTTON4DOWN : 0;
4858 x0 = pb->ipacket[1] | (((pb->ipacket[4]) & 0x0f) << 8);
4859 y0 = pb->ipacket[2] | (((pb->ipacket[4]) & 0xf0) << 4);
4861 x0 -= 0x1000;
4863 y0 -= 0x1000;
4864 if (sc->flags & PSM_FLAGS_FINGERDOWN) {
4865 *x = sc->xold - x0;
4866 *y = y0 - sc->yold;
4870 --*x;
4874 --*y;
4876 sc->flags |= PSM_FLAGS_FINGERDOWN;
4877 sc->xold = x0;
4878 sc->yold = y0;
4880 sc->flags &= ~PSM_FLAGS_FINGERDOWN;
4891 if (sc->pqueue_start == sc->pqueue_end &&
4892 sc->idlepacket.inputbytes > 0) {
4894 if (--sc->pqueue_start < 0)
4895 sc->pqueue_start = PSM_PACKETQUEUE - 1;
4897 pb = &sc->pqueue[sc->pqueue_start];
4898 memcpy(pb, &sc->idlepacket, sizeof(packetbuf_t));
4901 pb->ipacket[0], pb->ipacket[1], pb->ipacket[2],
4902 pb->ipacket[3], pb->ipacket[4], pb->ipacket[5]));
4930 getmicrouptime(&sc->lastsoftintr);
4935 pb = &sc->pqueue[sc->pqueue_start];
4937 if (sc->mode.level == PSM_LEVEL_NATIVE)
4940 c = pb->ipacket[0];
4946 if (sc->hw.model == MOUSE_MODEL_THINK)
4947 pb->ipacket[1] |= (c & MOUSE_PS2_XOVERFLOW) ? 0x80 : 0;
4951 pb->ipacket[1] - 256 : pb->ipacket[1];
4953 pb->ipacket[2] - 256 : pb->ipacket[2];
4955 ms.obutton = sc->button; /* previous button state */
4958 if (sc->config & PSM_CONFIG_FORCETAP)
4961 timevalclear(&sc->idletimeout);
4962 sc->idlepacket.inputbytes = 0;
4964 switch (sc->hw.model) {
4975 * d2-d0: wheel data
4977 z = (pb->ipacket[3] & MOUSE_EXPLORER_ZNEG) ?
4978 (pb->ipacket[3] & 0x0f) - 16 :
4979 (pb->ipacket[3] & 0x0f);
4981 (pb->ipacket[3] & MOUSE_EXPLORER_BUTTON4DOWN) ?
4984 (pb->ipacket[3] & MOUSE_EXPLORER_BUTTON5DOWN) ?
4991 z = (char)pb->ipacket[3];
4994 if ((z >= 7) || (z <= -7))
5018 ms.button |= (pb->ipacket[3] & MOUSE_PS2_BUTTON3DOWN) ?
5020 ms.button |= (pb->ipacket[3] & MOUSE_PS2_BUTTON1DOWN) ?
5022 z = (pb->ipacket[3] & MOUSE_PS2_XNEG) ?
5023 pb->ipacket[4] - 256 : pb->ipacket[4];
5050 x = (pb->ipacket[1] & 0x80) ?
5051 pb->ipacket[1] - 256 : pb->ipacket[1];
5052 y = (pb->ipacket[2] & 0x80) ?
5053 pb->ipacket[2] - 256 : pb->ipacket[2];
5059 z = -1;
5065 z = -2;
5071 if ((x < 16 - 256) && (y < 16 - 256)) {
5081 * d1-d0: wheel data
5084 if (pb->ipacket[2] & MOUSE_4DPLUS_BUTTON4DOWN)
5086 z = (pb->ipacket[2] & MOUSE_4DPLUS_ZNEG) ?
5087 ((pb->ipacket[2] & 0x07) - 8) :
5088 (pb->ipacket[2] & 0x07) ;
5096 if (pb->inputbytes == MOUSE_PS2_PACKETSIZE)
5122 if (timevalisset(&sc->idletimeout) && sc->idlepacket.inputbytes == 0)
5123 sc->idlepacket = *pb;
5127 sc->hw.model != MOUSE_MODEL_ELANTECH &&
5128 sc->hw.model != MOUSE_MODEL_SYNAPTICS) {
5129 evdev_push_rel(sc->evdev_r, REL_X, x);
5130 evdev_push_rel(sc->evdev_r, REL_Y, -y);
5132 switch (sc->hw.model) {
5138 evdev_push_rel(sc->evdev_r, REL_WHEEL, -z);
5144 case -1:
5145 evdev_push_rel(sc->evdev_r, REL_WHEEL, -z);
5148 case -2:
5149 evdev_push_rel(sc->evdev_r, REL_HWHEEL, z / 2);
5155 evdev_push_mouse_btn(sc->evdev_r, ms.button);
5156 evdev_sync(sc->evdev_r);
5159 if ((sc->evdev_a != NULL && evdev_is_grabbed(sc->evdev_a)) ||
5160 (sc->evdev_r != NULL && evdev_is_grabbed(sc->evdev_r)))
5165 if (sc->mode.accelfactor >= 1) {
5167 x = x * x / sc->mode.accelfactor;
5171 x = -x;
5174 y = y * y / sc->mode.accelfactor;
5178 y = -y;
5188 pb->inputbytes = tame_mouse(sc, pb, &ms, pb->ipacket);
5190 sc->status.flags |= ms.flags;
5191 sc->status.dx += ms.dx;
5192 sc->status.dy += ms.dy;
5193 sc->status.dz += ms.dz;
5194 sc->status.button = ms.button;
5195 sc->button = ms.button;
5198 sc->watchdog = FALSE;
5201 if (sc->queue.count + pb->inputbytes < sizeof(sc->queue.buf)) {
5202 l = imin(pb->inputbytes,
5203 sizeof(sc->queue.buf) - sc->queue.tail);
5204 bcopy(&pb->ipacket[0], &sc->queue.buf[sc->queue.tail], l);
5205 if (pb->inputbytes > l)
5206 bcopy(&pb->ipacket[l], &sc->queue.buf[0],
5207 pb->inputbytes - l);
5208 sc->queue.tail = (sc->queue.tail + pb->inputbytes) %
5209 sizeof(sc->queue.buf);
5210 sc->queue.count += pb->inputbytes;
5214 pb->inputbytes = 0;
5215 if (++sc->pqueue_start >= PSM_PACKETQUEUE)
5216 sc->pqueue_start = 0;
5217 } while (sc->pqueue_start != sc->pqueue_end);
5219 if (sc->state & PSM_ASLP) {
5220 sc->state &= ~PSM_ASLP;
5223 selwakeuppri(&sc->rsel, PZERO);
5224 if (sc->async != NULL) {
5225 pgsigio(&sc->async, SIGIO, 0);
5227 sc->state &= ~PSM_SOFTARMED;
5231 if (timevalisset(&sc->idletimeout)) {
5232 sc->state |= PSM_SOFTARMED;
5233 callout_reset(&sc->softcallout, tvtohz(&sc->idletimeout),
5236 tvtohz(&sc->idletimeout)));
5244 struct psm_softc *sc = dev->si_drv1;
5251 if (sc->queue.count > 0)
5254 selrecord(td, &sc->rsel);
5300 KBDC kbdc = sc->kbdc;
5308 ch = (status[0] & 0x07) - 1; /* channel # */
5313 * status[2]: battery status? (0-100)
5323 KBDC kbdc = sc->kbdc;
5327 * The special sequence to enable the fourth button and the
5342 * bit 0-2 button status
5353 sc->hw.buttons = 4;
5361 KBDC kbdc = sc->kbdc;
5365 * The special sequence to enable the middle, "rubber" button.
5385 KBDC kbdc = sc->kbdc;
5409 KBDC kbdc = sc->kbdc;
5435 * The special sequence to enable the third and fourth buttons.
5448 if ((status[1] == PSMD_RES_LOW) || (status[2] == rate[i - 1]))
5462 KBDC kbdc = sc->kbdc;
5465 /* the special sequence to enable the fourth button and the roller. */
5486 * p3-p0: packet type: 0
5487 * m7-m0: model ID: MouseMan+:0x50,
5496 /* check d3-d0 in byte 2 */
5499 /* check p3-p0 */
5504 sc->hw.hwid &= 0x00ff;
5505 sc->hw.hwid |= data[2] << 8; /* save model ID */
5521 KBDC kbdc = sc->kbdc;
5528 * This is needed for at least A4Tech X-7xx mice - they do not go
5534 /* the special sequence to enable the extra buttons and the roller. */
5544 sc->hw.buttons = 5; /* IntelliMouse Explorer XXX */
5545 sc->hw.hwid = id;
5550 * which think they are clever enough to know the 4-byte IntelliMouse
5551 * protocol, and assume any other protocols use 3-byte packets.
5552 * They don't convey 4-byte data packets from the IntelliMouse Explorer
5574 KBDC kbdc = sc->kbdc;
5579 /* the special sequence to enable the third button and the roller. */
5589 sc->hw.buttons = 3;
5590 sc->hw.hwid = id;
5604 KBDC kbdc = sc->kbdc;
5614 * Cable-Free 4D: 8 (4DPLUS)
5621 sc->hw.buttons = 3; /* XXX some 4D mice have 4? */
5622 sc->hw.hwid = id;
5636 KBDC kbdc = sc->kbdc;
5660 sc->hw.buttons = (id == PSM_4DPLUS_ID) ? 4 : 3;
5661 sc->hw.hwid = id;
5674 if (oidp->oid_arg1 == NULL || oidp->oid_arg2 < 0 ||
5675 oidp->oid_arg2 > SYNAPTICS_SYSCTL_LAST)
5678 sc = oidp->oid_arg1;
5681 arg = *(int *)((char *)sc + oidp->oid_arg2);
5685 if (error || !req->newptr)
5692 switch (oidp->oid_arg2) {
5706 if (arg < 0 || arg > sc->synhw.maximumYCoord)
5712 if (!sc->synhw.capClickPad && arg != 0)
5719 if (arg < 0 || arg > sc->synhw.maximumXCoord)
5749 if (arg < -sc->synhw.maximumXCoord ||
5750 arg > sc->synhw.maximumXCoord)
5755 if (!sc->synhw.capClickPad && arg != 0)
5759 if (arg < -sc->synhw.maximumYCoord ||
5760 arg > sc->synhw.maximumYCoord)
5774 *(int *)((char *)sc + oidp->oid_arg2) = arg;
5789 sc->syninfo.softbuttons_y = sc->synhw.topButtonPad ? -1700 : 1700;
5790 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5791 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5799 sc->syninfo.softbutton2_x = 3100;
5800 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5801 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5806 "Horisontal position of 2-nd softbutton left edge (0-disable)");
5809 sc->syninfo.softbutton3_x = 3900;
5810 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5811 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5816 "Horisontal position of 3-rd softbutton left edge (0-disable)");
5824 if (sc->syninfo.sysctl_tree != NULL)
5828 sysctl_ctx_init(&sc->syninfo.sysctl_ctx);
5829 sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx,
5834 sc->syninfo.directional_scrolls = 0;
5835 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx,
5836 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5838 &sc->syninfo.directional_scrolls, 0,
5839 "Enable hardware scrolling pad (if non-zero) or register it as "
5843 sc->syninfo.max_x = 6143;
5844 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx,
5845 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5847 &sc->syninfo.max_x, 0,
5851 sc->syninfo.max_y = 6143;
5852 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx,
5853 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5855 &sc->syninfo.max_y, 0,
5863 if (sc->synhw.verticalScroll || (sc->synhw.capMultiFinger == 0 &&
5864 sc->synhw.capAdvancedGestures == 0))
5865 sc->syninfo.two_finger_scroll = 0;
5867 sc->syninfo.two_finger_scroll = 1;
5869 SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx,
5870 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5872 &sc->syninfo.two_finger_scroll, 0,
5873 "Enable two finger scrolling");
5876 sc->syninfo.min_pressure = 32;
5877 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5878 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5886 sc->syninfo.max_pressure = 220;
5887 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5888 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5896 sc->syninfo.max_width = 10;
5897 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5898 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5906 sc->syninfo.margin_top = 200;
5907 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5908 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5916 sc->syninfo.margin_right = 200;
5917 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5918 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5926 sc->syninfo.margin_bottom = 200;
5927 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5928 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5936 sc->syninfo.margin_left = 200;
5937 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5938 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5946 sc->syninfo.na_top = 1783;
5947 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5948 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5957 sc->syninfo.na_right = 563;
5958 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5959 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5968 sc->syninfo.na_bottom = 1408;
5969 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5970 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5979 sc->syninfo.na_left = 1600;
5980 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5981 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
5990 sc->syninfo.window_min = 4;
5991 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
5992 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6000 sc->syninfo.window_max = 10;
6001 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6002 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6010 sc->syninfo.multiplicator = 10000;
6011 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6012 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6020 sc->syninfo.weight_current = 3;
6021 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6022 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6030 sc->syninfo.weight_previous = 6;
6031 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6032 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6040 sc->syninfo.weight_previous_na = 20;
6041 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6042 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6050 sc->syninfo.weight_len_squared = 2000;
6051 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6052 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6061 sc->syninfo.div_min = 9;
6062 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6063 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6071 sc->syninfo.div_max = 17;
6072 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6073 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6081 sc->syninfo.div_max_na = 30;
6082 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6083 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6091 sc->syninfo.div_len = 100;
6092 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6093 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6101 sc->syninfo.tap_max_delta = 80;
6102 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6103 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6111 sc->syninfo.tap_min_queue = 2;
6112 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6113 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6121 sc->gesture.in_taphold = 0;
6122 sc->syninfo.taphold_timeout = tap_timeout;
6123 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6124 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6129 "Maximum elapsed time between two taps to consider a tap-hold "
6133 sc->syninfo.vscroll_hor_area = 0; /* 1300 */
6134 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6135 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6143 sc->syninfo.vscroll_ver_area = -400 - sc->syninfo.margin_right;
6144 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6145 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6153 sc->syninfo.vscroll_min_delta = 50;
6154 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6155 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6163 sc->syninfo.vscroll_div_min = 100;
6164 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6165 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6173 sc->syninfo.vscroll_div_max = 150;
6174 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6175 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6183 sc->syninfo.touchpad_off = 0;
6184 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6185 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6192 sc->syninfo.three_finger_drag = 0;
6193 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6194 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6199 "Enable dragging with three fingers");
6202 sc->syninfo.natural_scroll = 0;
6203 SYSCTL_ADD_PROC(&sc->syninfo.sysctl_ctx,
6204 SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
6209 "Enable natural scrolling");
6211 sc->syninfo.softbuttons_y = 0;
6212 sc->syninfo.softbutton2_x = 0;
6213 sc->syninfo.softbutton3_x = 0;
6216 if (sc->synhw.capClickPad)
6225 if (sc->hw.model != MOUSE_MODEL_SYNAPTICS) {
6235 * Enable tap & drag gestures. We use a Mode Byte
6245 if (sc->synhw.capExtended)
6253 mouse_ext_command(sc->kbdc, mode_byte);
6256 set_mouse_sampling_rate(sc->kbdc, 20);
6259 * Enable advanced gestures mode if supported and we are not entering
6262 if ((sc->synhw.capAdvancedGestures || sc->synhw.capReportsV) &&
6263 sc->hw.model == MOUSE_MODEL_SYNAPTICS && !(mode_byte & (1 << 5))) {
6264 mouse_ext_command(sc->kbdc, SYNAPTICS_READ_MODEL_ID);
6265 set_mouse_sampling_rate(sc->kbdc, 0xc8);
6270 * AUX MUX detection code should be placed at very beginning of probe sequence
6271 * at least before 4-byte protocol mouse probes e.g. MS IntelliMouse probe as
6277 KBDC kbdc = sc->kbdc;
6283 sc->muxsinglesyna = FALSE;
6285 if (mux_disabled == 1 || (mux_disabled == -1 &&
6286 (kbdc->quirks & KBDC_QUIRK_DISABLE_MUX_PROBE) != 0))
6290 if (version == -1)
6316 sc->muxport = port;
6327 * On some laptops e.g. Lenovo X121e dead AUX MUX can be
6332 device_printf(sc->dev, "AUX MUX hang detected!\n");
6341 sc->muxsinglesyna = probe;
6349 return (sc->muxsinglesyna);
6357 KBDC kbdc = sc->kbdc;
6389 printf(" Unsupported (pre-v4) Touchpad detected\n");
6444 device_get_unit(sc->dev));
6596 switch (psmcpnp_sc->type) {
6686 sc->synhw = synhw;
6691 sc->hw.model = MOUSE_MODEL_SYNAPTICS;
6705 sc->hw.buttons = buttons;
6714 VLOG(2, (LOG_NOTICE, "psm: setting pass-through mode.\n"));
6721 VLOG(2, (LOG_NOTICE, "psm: turning pass-through mode off.\n"));
6722 set_mouse_scaling(sc->kbdc, 2);
6723 set_mouse_scaling(sc->kbdc, 1);
6734 if (sc->synhw.capPassthrough)
6738 if (sc->synhw.capPassthrough &&
6740 if (send_aux_command(sc->kbdc, 0xe7) != PSM_ACK) {
6744 if (send_aux_command(sc->kbdc, seq[i]) != PSM_ACK) {
6745 if (sc->synhw.capPassthrough)
6751 if (sc->synhw.capPassthrough)
6809 if (sc->tpinfo.sysctl_tree != NULL)
6813 sysctl_ctx_init(&sc->tpinfo.sysctl_ctx);
6814 sc->tpinfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->tpinfo.sysctl_ctx,
6819 sc->tpinfo.sensitivity = 0x80;
6820 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6821 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6829 sc->tpinfo.inertia = 0x06;
6830 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6831 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6839 sc->tpinfo.uplateau = 0x61;
6840 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6841 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6849 sc->tpinfo.reach = 0x0a;
6850 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6851 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6859 sc->tpinfo.draghys = 0xff;
6860 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6861 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6869 sc->tpinfo.mindrag = 0x14;
6870 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6871 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6879 sc->tpinfo.upthresh = 0xff;
6880 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6881 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6889 sc->tpinfo.threshold = 0x08;
6890 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6891 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6899 sc->tpinfo.jenks = 0x87;
6900 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6901 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6909 sc->tpinfo.ztime = 0x26;
6910 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6911 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6919 sc->tpinfo.pts = 0x00;
6920 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6921 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6929 sc->tpinfo.skipback = 0x00;
6930 SYSCTL_ADD_PROC(&sc->tpinfo.sysctl_ctx,
6931 SYSCTL_CHILDREN(sc->tpinfo.sysctl_tree), OID_AUTO,
6942 trackpoint_command(sc, 0x81, 0x4a, sc->tpinfo.sensitivity);
6943 trackpoint_command(sc, 0x81, 0x60, sc->tpinfo.uplateau);
6944 trackpoint_command(sc, 0x81, 0x4d, sc->tpinfo.inertia);
6945 trackpoint_command(sc, 0x81, 0x57, sc->tpinfo.reach);
6946 trackpoint_command(sc, 0x81, 0x58, sc->tpinfo.draghys);
6947 trackpoint_command(sc, 0x81, 0x59, sc->tpinfo.mindrag);
6948 trackpoint_command(sc, 0x81, 0x5a, sc->tpinfo.upthresh);
6949 trackpoint_command(sc, 0x81, 0x5c, sc->tpinfo.threshold);
6950 trackpoint_command(sc, 0x81, 0x5d, sc->tpinfo.jenks);
6951 trackpoint_command(sc, 0x81, 0x5e, sc->tpinfo.ztime);
6952 if (sc->tpinfo.pts == 0x01)
6954 if (sc->tpinfo.skipback == 0x01)
6961 KBDC kbdc = sc->kbdc;
6971 if (sc->synhw.capPassthrough)
6985 if (sc->synhw.capPassthrough)
6994 if (!sc->synhw.capPassthrough) {
6995 sc->hw.hwid = firmware;
6996 sc->hw.buttons = 3;
6998 VDLOG(2, sc->dev, LOG_NOTICE, "Trackpoint v=0x%x f=0x%x",
7000 sc->tpinfo.vendor = vendor;
7001 sc->tpinfo.firmware = firmware;
7009 if (sc->synhw.capPassthrough)
7019 KBDC kbdc = sc->kbdc;
7104 hwversion = elanhw->hwversion;
7105 reg10 = -1;
7108 reg10 = elanhw->fwversion == 0x020030 ? 0x54 : 0xc4;
7147 sc->synhw.infoMajor = sc->elanhw.hwversion;
7148 sc->synhw.infoMinor = sc->elanhw.fwversion;
7149 sc->synhw.infoXupmm = sc->elanhw.dpmmx;
7150 sc->synhw.infoYupmm = sc->elanhw.dpmmy;
7151 sc->synhw.verticalScroll = 0;
7152 sc->synhw.nExtendedQueries = 4;
7153 sc->synhw.capExtended = 1;
7154 sc->synhw.capPassthrough = sc->elanhw.hastrackpoint;
7155 sc->synhw.capClickPad = sc->elanhw.isclickpad;
7156 sc->synhw.capMultiFinger = 1;
7157 if (sc->elanhw.issemimt)
7158 sc->synhw.capAdvancedGestures = 1;
7160 sc->synhw.capReportsV = 1;
7161 sc->synhw.capPalmDetect = 1;
7162 sc->synhw.capPen = 0;
7163 sc->synhw.capReportsMax = 1;
7164 sc->synhw.maximumXCoord = sc->elanhw.sizex;
7165 sc->synhw.maximumYCoord = sc->elanhw.sizey;
7166 sc->synhw.capReportsMin = 1;
7167 sc->synhw.minimumXCoord = 0;
7168 sc->synhw.minimumYCoord = 0;
7170 if (sc->syninfo.sysctl_tree == NULL) {
7181 * 4. For clickpads set bottom quarter as 42% - 16% - 42% sized
7188 sc->syninfo.max_x = sc->elanhw.sizex;
7189 sc->syninfo.max_y = sc->elanhw.sizey;
7192 sc->syninfo.min_pressure = 1;
7195 sc->syninfo.max_width = 7;
7198 sc->syninfo.tap_min_queue = 1;
7201 sc->syninfo.margin_top = 0;
7202 sc->syninfo.margin_right = 0;
7203 sc->syninfo.margin_bottom = 0;
7204 sc->syninfo.margin_left = 0;
7207 sc->syninfo.na_top = 0;
7208 sc->syninfo.na_right = 0;
7209 sc->syninfo.na_bottom = 0;
7210 sc->syninfo.na_left = 0;
7213 sc->syninfo.weight_len_squared = 200;
7214 sc->syninfo.div_min = 3;
7215 sc->syninfo.div_max = 6;
7216 sc->syninfo.div_max_na = 10;
7217 sc->syninfo.div_len = 30;
7218 sc->syninfo.tap_max_delta = 25;
7221 sc->syninfo.vscroll_hor_area = 0;
7222 sc->syninfo.vscroll_ver_area = 0;
7223 sc->syninfo.vscroll_min_delta = 15;
7224 sc->syninfo.vscroll_div_min = 30;
7225 sc->syninfo.vscroll_div_max = 50;
7227 /* Set bottom quarter as 42% - 16% - 42% sized softbuttons */
7228 if (sc->elanhw.isclickpad) {
7229 sc->syninfo.softbuttons_y = sc->elanhw.sizey / 4;
7230 sc->syninfo.softbutton2_x = sc->elanhw.sizex * 11 / 25;
7231 sc->syninfo.softbutton3_x = sc->elanhw.sizex * 14 / 25;
7255 KBDC kbdc = sc->kbdc;
7359 elanhw.sizex = (elanhw.ntracesx - xtr) * elanhw.dptracex;
7360 elanhw.sizey = (elanhw.ntracesy - xtr) * elanhw.dptracey;
7364 xtr = (elanhw.sizex % (elanhw.ntracesx - 2) == 0) ? 2 : 1;
7365 elanhw.dptracex = elanhw.sizex / (elanhw.ntracesx - xtr);
7366 elanhw.dptracey = elanhw.sizey / (elanhw.ntracesy - xtr);
7389 sc->elanhw = elanhw;
7390 sc->hw.buttons = 3;
7396 PSM_FINGER_RESET(sc->elanaction.fingers[id]);
7434 if ((sc->config &
7438 err = reinitialize(sc, sc->config & PSM_CONFIG_INITAFTERSUSPEND);
7440 if ((sc->state & PSM_ASLP) && !(sc->state & PSM_VALID)) {
7445 sc->state &= ~PSM_ASLP;
7584 sc->type = PSMCPNP_FORCEPAD;
7586 sc->type = PSMCPNP_TOPBUTTONPAD;
7588 sc->type = PSMCPNP_GENERIC;