diff options
author | Joshua Stein <jcs@cvs.openbsd.org> | 2016-01-12 01:11:16 +0000 |
---|---|---|
committer | Joshua Stein <jcs@cvs.openbsd.org> | 2016-01-12 01:11:16 +0000 |
commit | aed4423c7d742eb53456cd5f7cfd25b67f684521 (patch) | |
tree | e4105dfd6022fcb1576a79fe91753fa8a5771aeb /sys/dev/i2c/ims.c | |
parent | 051eb318946cb49493d05cc3d8f3b20d33741552 (diff) |
Add dwiic, a driver for the Synopsys DesignWare i2c controller found
on the Samsung ATIV Book 9 laptop. This initial version only
supports ACPI config/attachment.
Add ihidev, a HID-over-i2c driver largely based on uhidev. dwiic
handles attaching ihidev devices found in ACPI.
Add ims, a HID-over-i2c mouse/trackpad driver to get basic cursor
and button functionality from HID-compliant i2c trackpads.
ok kettenis deraadt
Diffstat (limited to 'sys/dev/i2c/ims.c')
-rw-r--r-- | sys/dev/i2c/ims.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/sys/dev/i2c/ims.c b/sys/dev/i2c/ims.c new file mode 100644 index 00000000000..c3bc81ed84b --- /dev/null +++ b/sys/dev/i2c/ims.c @@ -0,0 +1,183 @@ +/* $OpenBSD: ims.c,v 1.1 2016/01/12 01:11:15 jcs Exp $ */ +/* + * HID-over-i2c mouse/trackpad driver + * + * Copyright (c) 2015, 2016 joshua stein <jcs@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/ioctl.h> + +#include <dev/i2c/i2cvar.h> +#include <dev/i2c/ihidev.h> + +#include <dev/wscons/wsconsio.h> +#include <dev/wscons/wsmousevar.h> + +#include <dev/hid/hid.h> +#include <dev/hid/hidmsvar.h> + +struct ims_softc { + struct ihidev sc_hdev; + struct hidms sc_ms; +}; + +void ims_intr(struct ihidev *addr, void *ibuf, u_int len); + +int ims_enable(void *); +void ims_disable(void *); +int ims_ioctl(void *, u_long, caddr_t, int, struct proc *); + +const struct wsmouse_accessops ims_accessops = { + ims_enable, + ims_ioctl, + ims_disable, +}; + +int ims_match(struct device *, void *, void *); +void ims_attach(struct device *, struct device *, void *); +int ims_detach(struct device *, int); + +struct cfdriver ims_cd = { + NULL, "ims", DV_DULL +}; + +const struct cfattach ims_ca = { + sizeof(struct ims_softc), + ims_match, + ims_attach, + ims_detach +}; + +int +ims_match(struct device *parent, void *match, void *aux) +{ + struct ihidev_attach_arg *iha = (struct ihidev_attach_arg *)aux; + int size; + void *desc; + + ihidev_get_report_desc(iha->parent, &desc, &size); + + if (hid_is_collection(desc, size, iha->reportid, + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_POINTER))) + return (IMATCH_IFACECLASS); + + if (hid_is_collection(desc, size, iha->reportid, + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) + return (IMATCH_IFACECLASS); + + if (hid_is_collection(desc, size, iha->reportid, + HID_USAGE2(HUP_DIGITIZERS, HUD_PEN))) + return (IMATCH_IFACECLASS); + + return (IMATCH_NONE); +} + +void +ims_attach(struct device *parent, struct device *self, void *aux) +{ + struct ims_softc *sc = (struct ims_softc *)self; + struct hidms *ms = &sc->sc_ms; + struct ihidev_attach_arg *iha = (struct ihidev_attach_arg *)aux; + int size, repid; + void *desc; + + sc->sc_hdev.sc_intr = ims_intr; + sc->sc_hdev.sc_parent = iha->parent; + sc->sc_hdev.sc_report_id = iha->reportid; + + ihidev_get_report_desc(iha->parent, &desc, &size); + repid = iha->reportid; + sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid); + sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid); + sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid); + + if (hidms_setup(self, ms, 0, iha->reportid, desc, size) != 0) + return; + + hidms_attach(ms, &ims_accessops); +} + +int +ims_detach(struct device *self, int flags) +{ + struct ims_softc *sc = (struct ims_softc *)self; + struct hidms *ms = &sc->sc_ms; + + return hidms_detach(ms, flags); +} + +void +ims_intr(struct ihidev *addr, void *buf, u_int len) +{ + struct ims_softc *sc = (struct ims_softc *)addr; + struct hidms *ms = &sc->sc_ms; + + if (ms->sc_enabled != 0) + hidms_input(ms, (uint8_t *)buf, len); +} + +int +ims_enable(void *v) +{ + struct ims_softc *sc = v; + struct hidms *ms = &sc->sc_ms; + int rv; + + if ((rv = hidms_enable(ms)) != 0) + return rv; + + return ihidev_open(&sc->sc_hdev); +} + +void +ims_disable(void *v) +{ + struct ims_softc *sc = v; + struct hidms *ms = &sc->sc_ms; + + hidms_disable(ms); + ihidev_close(&sc->sc_hdev); +} + +int +ims_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + struct ims_softc *sc = v; + struct hidms *ms = &sc->sc_ms; + int rc; + +#if 0 + rc = ihidev_ioctl(&sc->sc_hdev, cmd, data, flag, p); + if (rc != -1) + return rc; +#endif + + rc = hidms_ioctl(ms, cmd, data, flag, p); + if (rc != -1) + return rc; + + switch (cmd) { + case WSMOUSEIO_GTYPE: + /* XXX: should we set something else? */ + *(u_int *)data = WSMOUSE_TYPE_USB; + return 0; + default: + return -1; + } +} |