ims.c revision 1.1
1/* $OpenBSD: ims.c,v 1.1 2016/01/12 01:11:15 jcs Exp $ */ 2/* 3 * HID-over-i2c mouse/trackpad driver 4 * 5 * Copyright (c) 2015, 2016 joshua stein <jcs@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#include <sys/param.h> 21#include <sys/systm.h> 22#include <sys/kernel.h> 23#include <sys/device.h> 24#include <sys/ioctl.h> 25 26#include <dev/i2c/i2cvar.h> 27#include <dev/i2c/ihidev.h> 28 29#include <dev/wscons/wsconsio.h> 30#include <dev/wscons/wsmousevar.h> 31 32#include <dev/hid/hid.h> 33#include <dev/hid/hidmsvar.h> 34 35struct ims_softc { 36 struct ihidev sc_hdev; 37 struct hidms sc_ms; 38}; 39 40void ims_intr(struct ihidev *addr, void *ibuf, u_int len); 41 42int ims_enable(void *); 43void ims_disable(void *); 44int ims_ioctl(void *, u_long, caddr_t, int, struct proc *); 45 46const struct wsmouse_accessops ims_accessops = { 47 ims_enable, 48 ims_ioctl, 49 ims_disable, 50}; 51 52int ims_match(struct device *, void *, void *); 53void ims_attach(struct device *, struct device *, void *); 54int ims_detach(struct device *, int); 55 56struct cfdriver ims_cd = { 57 NULL, "ims", DV_DULL 58}; 59 60const struct cfattach ims_ca = { 61 sizeof(struct ims_softc), 62 ims_match, 63 ims_attach, 64 ims_detach 65}; 66 67int 68ims_match(struct device *parent, void *match, void *aux) 69{ 70 struct ihidev_attach_arg *iha = (struct ihidev_attach_arg *)aux; 71 int size; 72 void *desc; 73 74 ihidev_get_report_desc(iha->parent, &desc, &size); 75 76 if (hid_is_collection(desc, size, iha->reportid, 77 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_POINTER))) 78 return (IMATCH_IFACECLASS); 79 80 if (hid_is_collection(desc, size, iha->reportid, 81 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) 82 return (IMATCH_IFACECLASS); 83 84 if (hid_is_collection(desc, size, iha->reportid, 85 HID_USAGE2(HUP_DIGITIZERS, HUD_PEN))) 86 return (IMATCH_IFACECLASS); 87 88 return (IMATCH_NONE); 89} 90 91void 92ims_attach(struct device *parent, struct device *self, void *aux) 93{ 94 struct ims_softc *sc = (struct ims_softc *)self; 95 struct hidms *ms = &sc->sc_ms; 96 struct ihidev_attach_arg *iha = (struct ihidev_attach_arg *)aux; 97 int size, repid; 98 void *desc; 99 100 sc->sc_hdev.sc_intr = ims_intr; 101 sc->sc_hdev.sc_parent = iha->parent; 102 sc->sc_hdev.sc_report_id = iha->reportid; 103 104 ihidev_get_report_desc(iha->parent, &desc, &size); 105 repid = iha->reportid; 106 sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid); 107 sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid); 108 sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid); 109 110 if (hidms_setup(self, ms, 0, iha->reportid, desc, size) != 0) 111 return; 112 113 hidms_attach(ms, &ims_accessops); 114} 115 116int 117ims_detach(struct device *self, int flags) 118{ 119 struct ims_softc *sc = (struct ims_softc *)self; 120 struct hidms *ms = &sc->sc_ms; 121 122 return hidms_detach(ms, flags); 123} 124 125void 126ims_intr(struct ihidev *addr, void *buf, u_int len) 127{ 128 struct ims_softc *sc = (struct ims_softc *)addr; 129 struct hidms *ms = &sc->sc_ms; 130 131 if (ms->sc_enabled != 0) 132 hidms_input(ms, (uint8_t *)buf, len); 133} 134 135int 136ims_enable(void *v) 137{ 138 struct ims_softc *sc = v; 139 struct hidms *ms = &sc->sc_ms; 140 int rv; 141 142 if ((rv = hidms_enable(ms)) != 0) 143 return rv; 144 145 return ihidev_open(&sc->sc_hdev); 146} 147 148void 149ims_disable(void *v) 150{ 151 struct ims_softc *sc = v; 152 struct hidms *ms = &sc->sc_ms; 153 154 hidms_disable(ms); 155 ihidev_close(&sc->sc_hdev); 156} 157 158int 159ims_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 160{ 161 struct ims_softc *sc = v; 162 struct hidms *ms = &sc->sc_ms; 163 int rc; 164 165#if 0 166 rc = ihidev_ioctl(&sc->sc_hdev, cmd, data, flag, p); 167 if (rc != -1) 168 return rc; 169#endif 170 171 rc = hidms_ioctl(ms, cmd, data, flag, p); 172 if (rc != -1) 173 return rc; 174 175 switch (cmd) { 176 case WSMOUSEIO_GTYPE: 177 /* XXX: should we set something else? */ 178 *(u_int *)data = WSMOUSE_TYPE_USB; 179 return 0; 180 default: 181 return -1; 182 } 183} 184