1117397Skan/* $OpenBSD: ims.c,v 1.3 2021/01/22 17:35:00 jcs Exp $ */ 2117397Skan/* 3169691Skan * HID-over-i2c mouse/trackpad driver 4117397Skan * 5117397Skan * Copyright (c) 2015, 2016 joshua stein <jcs@openbsd.org> 6117397Skan * 7117397Skan * Permission to use, copy, modify, and distribute this software for any 8117397Skan * purpose with or without fee is hereby granted, provided that the above 9117397Skan * copyright notice and this permission notice appear in all copies. 10117397Skan * 11117397Skan * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12117397Skan * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13117397Skan * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14117397Skan * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15117397Skan * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16117397Skan * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17117397Skan * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18169691Skan */ 19117397Skan 20117397Skan#include <sys/param.h> 21117397Skan#include <sys/systm.h> 22117397Skan#include <sys/kernel.h> 23117397Skan#include <sys/device.h> 24117397Skan#include <sys/ioctl.h> 25117397Skan 26117397Skan#include <dev/i2c/i2cvar.h> 27117397Skan#include <dev/i2c/ihidev.h> 28117397Skan 29117397Skan#include <dev/wscons/wsconsio.h> 30117397Skan#include <dev/wscons/wsmousevar.h> 31117397Skan 32117397Skan#include <dev/hid/hid.h> 33117397Skan#include <dev/hid/hidmsvar.h> 34117397Skan 35117397Skanstruct ims_softc { 36117397Skan struct ihidev sc_hdev; 37117397Skan struct hidms sc_ms; 38117397Skan}; 39117397Skan 40117397Skanvoid ims_intr(struct ihidev *addr, void *ibuf, u_int len); 41117397Skan 42117397Skanint ims_enable(void *); 43117397Skanvoid ims_disable(void *); 44117397Skanint ims_ioctl(void *, u_long, caddr_t, int, struct proc *); 45117397Skan 46117397Skanconst struct wsmouse_accessops ims_accessops = { 47117397Skan ims_enable, 48117397Skan ims_ioctl, 49117397Skan ims_disable, 50117397Skan}; 51117397Skan 52117397Skanint ims_match(struct device *, void *, void *); 53117397Skanvoid ims_attach(struct device *, struct device *, void *); 54117397Skanint ims_detach(struct device *, int); 55117397Skan 56117397Skanstruct cfdriver ims_cd = { 57117397Skan NULL, "ims", DV_DULL 58117397Skan}; 59117397Skan 60117397Skanconst struct cfattach ims_ca = { 61132720Skan sizeof(struct ims_softc), 62132720Skan ims_match, 63117397Skan ims_attach, 64169691Skan ims_detach 65169691Skan}; 66117397Skan 67117397Skanint 68169691Skanims_match(struct device *parent, void *match, void *aux) 69117397Skan{ 70117397Skan struct ihidev_attach_arg *iha = (struct ihidev_attach_arg *)aux; 71117397Skan int size; 72132720Skan void *desc; 73117397Skan 74117397Skan ihidev_get_report_desc(iha->parent, &desc, &size); 75117397Skan 76169691Skan if (hid_is_collection(desc, size, iha->reportid, 77132720Skan HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_POINTER))) 78169691Skan return (IMATCH_IFACECLASS); 79169691Skan 80132720Skan if (hid_is_collection(desc, size, iha->reportid, 81169691Skan HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) 82169691Skan return (IMATCH_IFACECLASS); 83132720Skan 84132720Skan if (hid_is_collection(desc, size, iha->reportid, 85132720Skan HID_USAGE2(HUP_DIGITIZERS, HUD_PEN))) 86117397Skan return (IMATCH_IFACECLASS); 87117397Skan 88132720Skan if (hid_is_collection(desc, size, iha->reportid, 89117397Skan HID_USAGE2(HUP_DIGITIZERS, HUD_TOUCHSCREEN)) && 90169691Skan hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X), 91169691Skan iha->reportid, hid_input, NULL, NULL)) 92117397Skan return (IMATCH_IFACECLASS); 93117397Skan 94169691Skan return (IMATCH_NONE); 95169691Skan} 96169691Skan 97169691Skanvoid 98169691Skanims_attach(struct device *parent, struct device *self, void *aux) 99169691Skan{ 100169691Skan struct ims_softc *sc = (struct ims_softc *)self; 101117397Skan struct hidms *ms = &sc->sc_ms; 102117397Skan struct ihidev_attach_arg *iha = (struct ihidev_attach_arg *)aux; 103169691Skan int size, repid; 104117397Skan void *desc; 105132720Skan 106117397Skan sc->sc_hdev.sc_intr = ims_intr; 107169691Skan sc->sc_hdev.sc_parent = iha->parent; 108169691Skan sc->sc_hdev.sc_report_id = iha->reportid; 109117397Skan 110117397Skan ihidev_get_report_desc(iha->parent, &desc, &size); 111117397Skan repid = iha->reportid; 112132720Skan sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid); 113132720Skan sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid); 114169691Skan sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid); 115117397Skan 116117397Skan if (hidms_setup(self, ms, 0, iha->reportid, desc, size) != 0) 117132720Skan return; 118117397Skan 119169691Skan hidms_attach(ms, &ims_accessops); 120169691Skan} 121117397Skan 122117397Skanint 123169691Skanims_detach(struct device *self, int flags) 124169691Skan{ 125169691Skan struct ims_softc *sc = (struct ims_softc *)self; 126117397Skan struct hidms *ms = &sc->sc_ms; 127117397Skan 128132720Skan return hidms_detach(ms, flags); 129117397Skan} 130169691Skan 131169691Skanvoid 132169691Skanims_intr(struct ihidev *addr, void *buf, u_int len) 133117397Skan{ 134117397Skan struct ims_softc *sc = (struct ims_softc *)addr; 135169691Skan struct hidms *ms = &sc->sc_ms; 136169691Skan 137169691Skan if (ms->sc_enabled != 0) 138169691Skan hidms_input(ms, (uint8_t *)buf, len); 139169691Skan} 140169691Skan 141169691Skanint 142169691Skanims_enable(void *v) 143169691Skan{ 144169691Skan struct ims_softc *sc = v; 145169691Skan struct hidms *ms = &sc->sc_ms; 146169691Skan int rv; 147169691Skan 148169691Skan if ((rv = hidms_enable(ms)) != 0) 149169691Skan return rv; 150169691Skan 151169691Skan return ihidev_open(&sc->sc_hdev); 152169691Skan} 153169691Skan 154169691Skanvoid 155169691Skanims_disable(void *v) 156169691Skan{ 157169691Skan struct ims_softc *sc = v; 158169691Skan struct hidms *ms = &sc->sc_ms; 159169691Skan 160169691Skan hidms_disable(ms); 161169691Skan ihidev_close(&sc->sc_hdev); 162169691Skan} 163169691Skan 164169691Skanint 165117397Skanims_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 166117397Skan{ 167132720Skan struct ims_softc *sc = v; 168117397Skan struct hidms *ms = &sc->sc_ms; 169117397Skan int rc; 170169691Skan 171117397Skan#if 0 172117397Skan rc = ihidev_ioctl(&sc->sc_hdev, cmd, data, flag, p); 173117397Skan if (rc != -1) 174169691Skan return rc; 175169691Skan#endif 176169691Skan 177169691Skan rc = hidms_ioctl(ms, cmd, data, flag, p); 178117397Skan if (rc != -1) 179169691Skan return rc; 180169691Skan 181169691Skan switch (cmd) { 182169691Skan case WSMOUSEIO_GTYPE: 183169691Skan *(u_int *)data = WSMOUSE_TYPE_TOUCHPAD; 184169691Skan return 0; 185169691Skan default: 186117397Skan return -1; 187169691Skan } 188117397Skan} 189132720Skan