diff --git a/sys/dev/pckbport/files.pckbport b/sys/dev/pckbport/files.pckbport index 734fbc8..cb59fe3 100644 --- a/sys/dev/pckbport/files.pckbport +++ b/sys/dev/pckbport/files.pckbport @@ -15,9 +15,11 @@ defflag PCKBD_CNATTACH_MAY_FAIL defflag opt_pms.h PMS_DISABLE_POWERHOOK defflag opt_pms.h PMS_SYNAPTICS_TOUCHPAD -defflag opt_pms.h PMS_ELANTECH_TOUCHPAD +defflag opt_pms.h PMS_ELANTECH_TOUCHPAD +defflag opt_pms.h PMS_TRACKPOINT_STICK device pms: wsmousedev attach pms at pckbport file dev/pckbport/pms.c pms file dev/pckbport/synaptics.c pms & pms_synaptics_touchpad file dev/pckbport/elantech.c pms & pms_elantech_touchpad +file dev/pckbport/trackpoint.c pms & pms_trackpoint_stick diff --git a/sys/dev/pckbport/pms.c b/sys/dev/pckbport/pms.c index e95066c..c04be28 100644 --- a/sys/dev/pckbport/pms.c +++ b/sys/dev/pckbport/pms.c @@ -46,6 +46,9 @@ __KERNEL_RCSID(0, "$NetBSD: pms.c,v 1.26 2008/03/15 18:59:07 cube Exp $"); #ifdef PMS_ELANTECH_TOUCHPAD #include #endif +#ifdef PMS_TRACKPOINT_STICK +#include +#endif #include #include @@ -71,7 +74,8 @@ const struct pms_protocol pms_protocols[] = { { { 200, 100, 80 }, 3, "scroll wheel (3 buttons)" }, { { 200, 200, 80 }, 4, "scroll wheel (5 buttons)" }, { { 0, 0, 0 }, 0, "synaptics" }, - { { 0, 0, 0 }, 0, "elantech" } + { { 0, 0, 0 }, 0, "elantech" }, + { { 0, 0, 0 }, 0, "trackpoint" } }; @@ -208,6 +212,11 @@ pmsattach(device_t parent, device_t self, void *aux) sc->protocol = PMS_SYNAPTICS; } else #endif +#ifdef PMS_TRACKPOINT_STICK + if (pms_trackpoint_probe_init(sc) == 0) { + sc->protocol = PMS_TRACKPOINT; + } else +#endif #ifdef PMS_ELANTECH_TOUCHPAD if (pms_elantech_probe_init(sc) == 0) { sc->protocol = PMS_ELANTECH; @@ -264,6 +273,10 @@ do_enable(struct pms_softc *sc) if (sc->protocol == PMS_ELANTECH) pms_elantech_enable(sc); #endif +#ifdef PMS_TRACKPOINT_STICK + if (sc->protocol == PMS_TRACKPOINT) + pms_trackpoint_enable(sc); +#endif cmd[0] = PMS_DEV_ENABLE; res = pckbport_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, @@ -380,6 +393,14 @@ pms_resume(device_t dv PMF_FN_ARGS) } } else #endif +#ifdef PMS_TRACKPOINT_STICK + if (sc->protocol == PMS_TRACKPOINT) { + pms_trackpoint_resume(sc); + if (sc->sc_enabled) { + do_enable(sc); + } + } else +#endif if (sc->sc_enabled) { /* recheck protocol & init mouse */ sc->protocol = PMS_UNKNOWN; @@ -453,8 +474,12 @@ pms_reset_thread(void *arg) device_xname(sc->sc_dev), res)); } - /* For the synaptics and elantech case, leave the protocol alone. */ - if (sc->protocol != PMS_SYNAPTICS && sc->protocol != PMS_ELANTECH) + /* For the synaptics, trackpoint and elantech case, leave + * the protocol alone. + */ + if (sc->protocol != PMS_SYNAPTICS && \ + sc->protocol != PMS_ELANTECH && \ + sc->protocol != PMS_TRACKPOINT) sc->protocol = PMS_UNKNOWN; pms_enable(sc); diff --git a/sys/dev/pckbport/pmsvar.h b/sys/dev/pckbport/pmsvar.h index 849c331..05b7fd7 100644 --- a/sys/dev/pckbport/pmsvar.h +++ b/sys/dev/pckbport/pmsvar.h @@ -30,6 +30,7 @@ #include #include +#include enum pms_type { PMS_UNKNOWN, @@ -37,7 +38,8 @@ enum pms_type { PMS_SCROLL3, PMS_SCROLL5, PMS_SYNAPTICS, - PMS_ELANTECH + PMS_ELANTECH, + PMS_TRACKPOINT }; struct pms_protocol { @@ -66,7 +68,7 @@ struct pms_softc { /* driver status information */ device_t sc_wsmousedev; struct lwp *sc_event_thread; -#if defined(PMS_SYNAPTICS_TOUCHPAD) || defined(PMS_ELANTECH_TOUCHPAD) +#if defined(PMS_SYNAPTICS_TOUCHPAD) || defined(PMS_ELANTECH_TOUCHPAD) || defined(PMS_TRACKPOINT_STICK) union { #ifdef PMS_SYNAPTICS_TOUCHPAD struct synaptics_softc synaptics; @@ -74,6 +76,9 @@ struct pms_softc { /* driver status information */ #ifdef PMS_ELANTECH_TOUCHPAD struct elantech_softc elantech; #endif +#ifdef PMS_TRACKPOINT_STICK + struct trackpoint_softc trackpoint; +#endif } u; #endif }; diff --git a/sys/dev/pckbport/trackpoint.c b/sys/dev/pckbport/trackpoint.c new file mode 100644 index 0000000..8912b5b --- /dev/null +++ b/sys/dev/pckbport/trackpoint.c @@ -0,0 +1,590 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2010 Jerry Falkcrona + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Based on the documentation available at + * http://wwwcssrv.almaden.ibm.com/trackpoint/files/ykt3eext.pdf + */ + +#include "opt_pms.h" + +#include +__KERNEL_RCSID(0, "$NetBSD$"); + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +static void pms_trackpoint_input(void *, int); +static int pms_trackpoint_sysctl_handler(SYSCTLFN_PROTO); +static int pms_trackpoint_init(struct pms_softc *); +static int pms_trackpoint_read_reg(pckbport_tag_t, pckbport_slot_t, + uint8_t, uint8_t *); +static int pms_trackpoint_toggle_bit(pckbport_tag_t, pckbport_slot_t, + uint8_t, uint8_t); +static int pms_trackpoint_write_reg(pckbport_tag_t, pckbport_slot_t, + uint8_t, uint8_t); +static void pms_trackpoint_sysctl_attach(struct sysctllog **, + struct pms_softc *); + +static int trackpoint_ptson_nodenum; +static int trackpoint_inertia_nodenum; +static int trackpoint_snstvty_nodenum; +static int trackpoint_thr_nodenum; +static int trackpoint_uthr_nodenum; +static int trackpoint_jkcur_nodenum; +static int trackpoint_ztc_nodenum; +static int trackpoint_skipback_nodenum; +static int trackpoint_mcomdis_nodenum; + +int +pms_trackpoint_probe_init(void *opaque) +{ + struct pms_softc *psc = opaque; + struct trackpoint_softc *sc = &psc->u.trackpoint; + struct sysctllog *clog = NULL; + uint8_t cmd[1], resp[2]; + int res; + + pckbport_flush(psc->sc_kbctag, psc->sc_kbcslot); + + cmd[0] = TRACKPOINT_READ_EXT_ID; + if ((res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, + cmd, 1, 2, resp, 0)) != 0) { +#ifdef TRACKPOINT_DEBUG + aprint_normal_dev(psc->sc_dev, + "trackpoint_probe: Identify error\n"); +#endif + goto doreset; + } + + if (resp[0] != TRACKPOINT_MAGIC_BYTE) { +#ifdef TRACKPOINT_DEBUG + aprint_normal_dev(psc->sc_dev, + "trackpoint_probe: Not trackpoint\n"); +#endif + res = 1; + goto doreset; + } + + sc->version = resp[1]; + aprint_normal_dev(psc->sc_dev, "Trackpoint version 0x%X\n", + sc->version); + + /* Set default values of trackpoint settings */ + sc->ptson = 0; + sc->inertia = 6; + sc->thr = 8; + sc->uthr = 255; + sc->snstvty = 128; + sc->jkcur = 135; + sc->ztc = 38; + sc->skipback = 0; + sc->mcomdis = 0; + + pms_trackpoint_sysctl_attach(&clog, psc); + pckbport_set_inputhandler(psc->sc_kbctag, psc->sc_kbcslot, + pms_trackpoint_input, psc, device_xname(psc->sc_dev)); + + return 0; + +doreset: + cmd[0] = PMS_RESET; + (void) pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, + cmd, 1, 2, resp, 1); + return res; +} + +void +pms_trackpoint_enable(void *opaque) +{ + struct pms_softc *psc = opaque; + int res; + + res = pms_trackpoint_init(psc); + +#ifdef TRACKPOINT_DEBUG + if (res) + aprint_normal_dev(psc->sc_dev, + "trackpoint_enable: Error initializing\n"); +#endif +} + +int +pms_trackpoint_init(struct pms_softc *psc) +{ + struct trackpoint_softc *sc = &psc->u.trackpoint; + uint8_t val; + int res; + + /* Press to select */ + val = 0; + res = pms_trackpoint_read_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_TOGGLE_PTS, &val); + if ((val ^ sc->ptson) & TRACKPOINT_TOGGLE_PTS_MASK) + res |= pms_trackpoint_toggle_bit(psc->sc_kbctag, + psc->sc_kbcslot, TRACKPOINT_TOGGLE_PTS, + TRACKPOINT_TOGGLE_PTS_MASK); + + /* Negative inertia */ + val = 0; + res |= pms_trackpoint_read_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_INERTIA, &val); + if (val != sc->inertia) + res |= pms_trackpoint_write_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_INERTIA, sc->inertia); + + /* Sensitivity */ + val = 0; + res |= pms_trackpoint_read_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_SENSITIVITY, &val); + if (val != sc->snstvty) + res |= pms_trackpoint_write_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_SENSITIVITY, sc->snstvty); + + /* Z-axis threshold */ + val = 0; + res |= pms_trackpoint_read_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_THRESHOLD, &val); + if (val != sc->thr) + res |= pms_trackpoint_write_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_THRESHOLD, sc->thr); + + /* Z-axis up threshold */ + val = 0; + res |= pms_trackpoint_read_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_UP_THRESHOLD, &val); + if (val != sc->uthr) + res |= pms_trackpoint_write_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_UP_THRESHOLD, sc->uthr); + + /* Jenks curvature */ + val = 0; + res |= pms_trackpoint_read_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_JENKS_CURVATURE, &val); + if (val != sc->jkcur) + res |= pms_trackpoint_write_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_JENKS_CURVATURE, sc->jkcur); + + /* Z Time Constant */ + val = 0; + res |= pms_trackpoint_read_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_Z_TIME, &val); + if (val != sc->ztc) + res |= pms_trackpoint_write_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_Z_TIME, sc->ztc); + + /* Skipback */ + val = 0; + res |= pms_trackpoint_read_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_TOGGLE_SKIPBACK, &val); + if ((val ^ sc->ptson) & TRACKPOINT_TOGGLE_SKIPBACK_MASK) + res |= pms_trackpoint_toggle_bit(psc->sc_kbctag, + psc->sc_kbcslot, TRACKPOINT_TOGGLE_SKIPBACK, + TRACKPOINT_TOGGLE_SKIPBACK_MASK); + + /* External device disabled */ + val = 0; + res |= pms_trackpoint_read_reg(psc->sc_kbctag, psc->sc_kbcslot, + TRACKPOINT_TOGGLE_MCOMDIS, &val); + if ((val ^ sc->mcomdis) & TRACKPOINT_TOGGLE_MCOMDIS_MASK) + res |= pms_trackpoint_toggle_bit(psc->sc_kbctag, + psc->sc_kbcslot, TRACKPOINT_TOGGLE_MCOMDIS, + TRACKPOINT_TOGGLE_MCOMDIS_MASK); + + return res; +} + +void +pms_trackpoint_resume(void *opaque) +{ + struct pms_softc *psc = opaque; + uint8_t cmd[1], resp[2]; + int res; + + cmd[0] = PMS_RESET; + res = pckbport_poll_cmd(psc->sc_kbctag, psc->sc_kbcslot, + cmd, 1, 2, resp, 1); + if (res) + aprint_debug_dev(psc->sc_dev, + "trackpoint_resume: reset on resume failed\n"); +} + +static int +pms_trackpoint_read_reg(pckbport_tag_t tag, pckbport_slot_t slot, uint8_t reg, + uint8_t *val) +{ + int res; + uint8_t cmd[1], resp[1]; + + cmd[0] = TRACKPOINT_CUSTOM_CMD; + res = pckbport_enqueue_cmd(tag, slot, cmd, 1, 0, 1, NULL); + + cmd[0] = TRACKPOINT_READ_REG; + res |= pckbport_enqueue_cmd(tag, slot, cmd, 1, 0, 1, NULL); + + cmd[0] = reg; + res |= pckbport_enqueue_cmd(tag, slot, cmd, 1, 1, 1, resp); + + if (res == 0) + *val = resp[0]; + + return res; +} + +static int +pms_trackpoint_toggle_bit(pckbport_tag_t tag, pckbport_slot_t slot, uint8_t reg, + uint8_t val) +{ + int res; + uint8_t cmd[1]; + + /* Check that the register is within the "flag bits" range */ + if (reg < 0x20 || reg > 0x2F) + return EINVAL; + + cmd[0] = TRACKPOINT_CUSTOM_CMD; + res = pckbport_enqueue_cmd(tag, slot, cmd, 1, 0, 1, NULL); + + cmd[0] = TRACKPOINT_TOGGLE_BIT; + res |= pckbport_enqueue_cmd(tag, slot, cmd, 1, 0, 1, NULL); + + cmd[0] = reg; + res |= pckbport_enqueue_cmd(tag, slot, cmd, 1, 0, 1, NULL); + + cmd[0] = val; + res |= pckbport_enqueue_cmd(tag, slot, cmd, 1, 0, 1, NULL); + + return res; +} + +static int +pms_trackpoint_write_reg(pckbport_tag_t tag, pckbport_slot_t slot, uint8_t reg, + uint8_t val) +{ + int res; + uint8_t cmd[1]; + + cmd[0] = TRACKPOINT_CUSTOM_CMD; + res = pckbport_enqueue_cmd(tag, slot, cmd, 1, 0, 1, NULL); + + cmd[0] = TRACKPOINT_WRITE_REG; + res |= pckbport_enqueue_cmd(tag, slot, cmd, 1, 0, 1, NULL); + + cmd[0] = reg; + res |= pckbport_enqueue_cmd(tag, slot, cmd, 1, 0, 1, NULL); + + cmd[0] = val; + res |= pckbport_enqueue_cmd(tag, slot, cmd, 1, 0, 1, NULL); + + return res; +} + +static void +pms_trackpoint_input(void *opaque, int data) +{ + struct pms_softc *psc = opaque; + struct timeval diff; + int dx, dy; + int buttons; + int s; + + if (!psc->sc_enabled) + return; + + getmicrouptime(&psc->current); + + if (psc->inputstate > 0) { + timersub(&psc->current, &psc->last, &diff); + if (diff.tv_sec > 0 || diff.tv_usec >= 40000) { + psc->inputstate = 0; + psc->sc_enabled = 0; + wakeup(&psc->sc_enabled); + return; + } + } + psc->last = psc->current; + + if (psc->inputstate == 0 && (data & 0xc0) != 0) { + return; + } + + psc->packet[psc->inputstate++] = data & 0xff; + if (psc->inputstate == 3) { + buttons = psc->packet[0] & TRACKPOINT_LBUTMASK; + buttons |= (psc->packet[0] & TRACKPOINT_RBUTMASK) << 1; + buttons |= (psc->packet[0] & TRACKPOINT_MBUTMASK) >> 1; + + dx = psc->packet[1]; + if (dx >= 128) + dx -= 256; + if (dx == -128) + dx = -127; + + dy = psc->packet[2]; + if (dy >= 128) + dy -= 256; + if (dy == -128) + dy = -127; + + if (dx || dy || (psc->buttons ^ buttons)) { + s = spltty(); + wsmouse_input(psc->sc_wsmousedev, + buttons, dx, dy, 0, 0, + WSMOUSE_INPUT_DELTA); + splx(s); + } + + psc->inputstate = 0; + psc->buttons = buttons; + } +} + +static int +pms_trackpoint_sysctl_handler(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + struct pms_softc *psc; + struct trackpoint_softc *sc; + uint8_t cmd[1]; + int error, t, res; + + node = *rnode; + psc = (struct pms_softc *)node.sysctl_data; + sc = &psc->u.trackpoint; + + if (node.sysctl_num == trackpoint_ptson_nodenum) + t = sc->ptson; + else if (node.sysctl_num == trackpoint_inertia_nodenum) + t = sc->inertia; + else if (node.sysctl_num == trackpoint_snstvty_nodenum) + t = sc->snstvty; + else if (node.sysctl_num == trackpoint_thr_nodenum) + t = sc->thr; + else if (node.sysctl_num == trackpoint_uthr_nodenum) + t = sc->uthr; + else if (node.sysctl_num == trackpoint_jkcur_nodenum) + t = sc->jkcur; + else if (node.sysctl_num == trackpoint_skipback_nodenum) + t = sc->skipback; + else if (node.sysctl_num == trackpoint_ztc_nodenum) + t = sc->ztc; + else if (node.sysctl_num == trackpoint_mcomdis_nodenum) + t = sc->mcomdis; + else + return EINVAL; + + node.sysctl_data = &t; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return error; + + if (node.sysctl_num == trackpoint_ptson_nodenum) { + if (t < 0 || t > 1) + return EINVAL; + sc->ptson = t; + } else if (node.sysctl_num == trackpoint_inertia_nodenum) { + if (t < 0 || t > 255) + return EINVAL; + sc->inertia = t; + } else if (node.sysctl_num == trackpoint_snstvty_nodenum) { + if (t < 0 || t > 255) + return EINVAL; + sc->snstvty = t; + } else if (node.sysctl_num == trackpoint_thr_nodenum) { + if (t < 0 || t > 255) + return EINVAL; + sc->thr = t; + } else if (node.sysctl_num == trackpoint_uthr_nodenum) { + if (t < 0 || t > 255) + return EINVAL; + sc->uthr = t; + } else if (node.sysctl_num == trackpoint_jkcur_nodenum) { + if (t < 0 || t > 255) + return EINVAL; + sc->jkcur = t; + } else if (node.sysctl_num == trackpoint_skipback_nodenum) { + if (t < 0 || t > 1) + return EINVAL; + sc->skipback = t; + } else if (node.sysctl_num == trackpoint_ztc_nodenum) { + if (t < 0 || t > 255) + return EINVAL; + sc->ztc = t; + } else if (node.sysctl_num == trackpoint_mcomdis_nodenum) { + if (t < 0 || t > 1) + return EINVAL; + sc->mcomdis = t; + } + + /* Commit changes. + * Since the mouse most probably is in streaming mode, we disable + * data reporting while we send the trackpoint commands. + */ + cmd[0] = PMS_DEV_DISABLE; + res = pckbport_enqueue_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, + 1, 0, 1, NULL); + res |= pms_trackpoint_init(psc); + cmd[0] = PMS_DEV_ENABLE; + res |= pckbport_enqueue_cmd(psc->sc_kbctag, psc->sc_kbcslot, cmd, + 1, 0, 1, NULL); + if (res) { + aprint_normal_dev(psc->sc_dev, + "trackpoint: error commiting settings\n"); + return 1; + } + + return 0; +} + +static void +pms_trackpoint_sysctl_attach(struct sysctllog **clog, struct pms_softc *psc) +{ + const struct sysctlnode *node; + int rc, root_num; + + if ((rc = sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL, + NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) + goto err; + + if ((rc = sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT, CTLTYPE_NODE, "trackpoint", + SYSCTL_DESCR("Trackpoint controls"), + NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + root_num = node->sysctl_num; + + if ((rc = sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, "extdev_disable", + SYSCTL_DESCR("External device disable"), + pms_trackpoint_sysctl_handler, 0, + psc, 0, CTL_HW, root_num, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + trackpoint_mcomdis_nodenum = node->sysctl_num; + + if ((rc = sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, "jenks_curvature", + SYSCTL_DESCR("Double click sensitivity"), + pms_trackpoint_sysctl_handler, 0, + psc, 0, CTL_HW, root_num, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + trackpoint_jkcur_nodenum = node->sysctl_num; + + if ((rc = sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, "negative_inertia", + SYSCTL_DESCR("Negative inertia"), + pms_trackpoint_sysctl_handler, 0, + psc, 0, CTL_HW, root_num, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + trackpoint_inertia_nodenum = node->sysctl_num; + + if ((rc = sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, "press_to_select", + SYSCTL_DESCR("Press to select (1=Enable)"), + pms_trackpoint_sysctl_handler, 0, + psc, 0, CTL_HW, root_num, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + trackpoint_ptson_nodenum = node->sysctl_num; + + if ((rc = sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, "sensitivity", + SYSCTL_DESCR("Sensitivity"), + pms_trackpoint_sysctl_handler, 0, + psc, 0, CTL_HW, root_num, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + trackpoint_snstvty_nodenum = node->sysctl_num; + + if ((rc = sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, "skipback", + SYSCTL_DESCR("Suppress cursor movement on drag release"), + pms_trackpoint_sysctl_handler, 0, + psc, 0, CTL_HW, root_num, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + trackpoint_skipback_nodenum = node->sysctl_num; + + if ((rc = sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, "threshold", + SYSCTL_DESCR("Z axis force to trigger a press/release"), + pms_trackpoint_sysctl_handler, 0, + psc, 0, CTL_HW, root_num, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + trackpoint_thr_nodenum = node->sysctl_num; + + if ((rc = sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, "up_threshold", + SYSCTL_DESCR("Z axis force to trigger a click (255=Disable)"), + pms_trackpoint_sysctl_handler, 0, + psc, 0, CTL_HW, root_num, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + trackpoint_uthr_nodenum = node->sysctl_num; + + if ((rc = sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, "ztime", + SYSCTL_DESCR("Minimum sharpness of a press"), + pms_trackpoint_sysctl_handler, 0, + psc, 0, CTL_HW, root_num, CTL_CREATE, CTL_EOL)) != 0) + goto err; + + trackpoint_ztc_nodenum = node->sysctl_num; + + return; + +err: + aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); +} diff --git a/sys/dev/pckbport/trackpointreg.h b/sys/dev/pckbport/trackpointreg.h new file mode 100644 index 0000000..3499498 --- /dev/null +++ b/sys/dev/pckbport/trackpointreg.h @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2010 Jerry Falkcrona + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _DEV_PCKBCPORT_TRACKPOINTREG_H +#define _DEV_PCKBCPORT_TRACKPOINTREG_H + +/* Button masks */ +#define TRACKPOINT_LBUTMASK 0x01 +#define TRACKPOINT_RBUTMASK 0x02 +#define TRACKPOINT_MBUTMASK 0x04 + +/* Magic number */ +#define TRACKPOINT_MAGIC_BYTE 0x01 + +/* Commands */ +#define TRACKPOINT_CUSTOM_CMD 0xE2 +#define TRACKPOINT_READ_EXT_ID 0xE1 +#define TRACKPOINT_TOGGLE_BIT 0x47 +#define TRACKPOINT_READ_REG 0x80 +#define TRACKPOINT_WRITE_REG 0x81 + +/* Bit toggles */ +#define TRACKPOINT_TOGGLE_MCOMDIS 0x23 +#define TRACKPOINT_TOGGLE_MCOMDIS_MASK 0x02 +#define TRACKPOINT_TOGGLE_PTS 0x2C +#define TRACKPOINT_TOGGLE_PTS_MASK 0x01 +#define TRACKPOINT_TOGGLE_SKIPBACK 0x2D +#define TRACKPOINT_TOGGLE_SKIPBACK_MASK 0x08 + +/* Registers */ +#define TRACKPOINT_INERTIA 0x4D +#define TRACKPOINT_JENKS_CURVATURE 0x5D +#define TRACKPOINT_SENSITIVITY 0x4A +#define TRACKPOINT_THRESHOLD 0x5C +#define TRACKPOINT_UP_THRESHOLD 0x5A +#define TRACKPOINT_Z_TIME 0x5E + +#endif /* !_DEV_PCKBCPORT_TRACKPOINTREG_H */ diff --git a/sys/dev/pckbport/trackpointvar.h b/sys/dev/pckbport/trackpointvar.h new file mode 100644 index 0000000..1ac5e5f --- /dev/null +++ b/sys/dev/pckbport/trackpointvar.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2010 Jerry Falkcrona + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _DEV_PCKBCPORT_TRACKPOINTVAR_H +#define _DEV_PCKBCPORT_TRACKPOINTVAR_H + +struct trackpoint_softc { + u_char version; + int ptson; /* Press to Select */ + int inertia; /* Negative Inertia */ + int thr; /* Threshold */ + int uthr; /* Up Threshold */ + int snstvty; /* Sensitivity */ + int jkcur; /* Jenks Curvature */ + int ztc; /* Z Time Constant */ + int skipback; /* Skip backups on release */ + int mcomdis; /* External device disable */ +}; + +int pms_trackpoint_probe_init(void *); +void pms_trackpoint_enable(void *); +void pms_trackpoint_resume(void *); + +#endif /* !_DEV_PCKBCPORT_TRACKPOINTVAR_H */