Line data Source code
1 : /* $OpenBSD: ims.c,v 1.2 2018/09/01 20:50:16 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 :
35 : struct ims_softc {
36 : struct ihidev sc_hdev;
37 : struct hidms sc_ms;
38 : };
39 :
40 : void ims_intr(struct ihidev *addr, void *ibuf, u_int len);
41 :
42 : int ims_enable(void *);
43 : void ims_disable(void *);
44 : int ims_ioctl(void *, u_long, caddr_t, int, struct proc *);
45 :
46 : const struct wsmouse_accessops ims_accessops = {
47 : ims_enable,
48 : ims_ioctl,
49 : ims_disable,
50 : };
51 :
52 : int ims_match(struct device *, void *, void *);
53 : void ims_attach(struct device *, struct device *, void *);
54 : int ims_detach(struct device *, int);
55 :
56 : struct cfdriver ims_cd = {
57 : NULL, "ims", DV_DULL
58 : };
59 :
60 : const struct cfattach ims_ca = {
61 : sizeof(struct ims_softc),
62 : ims_match,
63 : ims_attach,
64 : ims_detach
65 : };
66 :
67 : int
68 0 : ims_match(struct device *parent, void *match, void *aux)
69 : {
70 0 : struct ihidev_attach_arg *iha = (struct ihidev_attach_arg *)aux;
71 0 : int size;
72 0 : void *desc;
73 :
74 0 : ihidev_get_report_desc(iha->parent, &desc, &size);
75 :
76 0 : if (hid_is_collection(desc, size, iha->reportid,
77 : HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_POINTER)))
78 0 : return (IMATCH_IFACECLASS);
79 :
80 0 : if (hid_is_collection(desc, size, iha->reportid,
81 : HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)))
82 0 : return (IMATCH_IFACECLASS);
83 :
84 0 : if (hid_is_collection(desc, size, iha->reportid,
85 : HID_USAGE2(HUP_DIGITIZERS, HUD_PEN)))
86 0 : return (IMATCH_IFACECLASS);
87 :
88 0 : if (hid_is_collection(desc, size, iha->reportid,
89 0 : HID_USAGE2(HUP_DIGITIZERS, HUD_TOUCHSCREEN)) &&
90 0 : hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
91 0 : iha->reportid, hid_input, NULL, NULL))
92 0 : return (IMATCH_IFACECLASS);
93 :
94 0 : return (IMATCH_NONE);
95 0 : }
96 :
97 : void
98 0 : ims_attach(struct device *parent, struct device *self, void *aux)
99 : {
100 0 : struct ims_softc *sc = (struct ims_softc *)self;
101 0 : struct hidms *ms = &sc->sc_ms;
102 0 : struct ihidev_attach_arg *iha = (struct ihidev_attach_arg *)aux;
103 0 : int size, repid;
104 0 : void *desc;
105 :
106 0 : sc->sc_hdev.sc_intr = ims_intr;
107 0 : sc->sc_hdev.sc_parent = iha->parent;
108 0 : sc->sc_hdev.sc_report_id = iha->reportid;
109 :
110 0 : ihidev_get_report_desc(iha->parent, &desc, &size);
111 0 : repid = iha->reportid;
112 0 : sc->sc_hdev.sc_isize = hid_report_size(desc, size, hid_input, repid);
113 0 : sc->sc_hdev.sc_osize = hid_report_size(desc, size, hid_output, repid);
114 0 : sc->sc_hdev.sc_fsize = hid_report_size(desc, size, hid_feature, repid);
115 :
116 0 : if (hidms_setup(self, ms, 0, iha->reportid, desc, size) != 0)
117 0 : return;
118 :
119 0 : hidms_attach(ms, &ims_accessops);
120 0 : }
121 :
122 : int
123 0 : ims_detach(struct device *self, int flags)
124 : {
125 0 : struct ims_softc *sc = (struct ims_softc *)self;
126 0 : struct hidms *ms = &sc->sc_ms;
127 :
128 0 : return hidms_detach(ms, flags);
129 : }
130 :
131 : void
132 0 : ims_intr(struct ihidev *addr, void *buf, u_int len)
133 : {
134 0 : struct ims_softc *sc = (struct ims_softc *)addr;
135 0 : struct hidms *ms = &sc->sc_ms;
136 :
137 0 : if (ms->sc_enabled != 0)
138 0 : hidms_input(ms, (uint8_t *)buf, len);
139 0 : }
140 :
141 : int
142 0 : ims_enable(void *v)
143 : {
144 0 : struct ims_softc *sc = v;
145 0 : struct hidms *ms = &sc->sc_ms;
146 : int rv;
147 :
148 0 : if ((rv = hidms_enable(ms)) != 0)
149 0 : return rv;
150 :
151 0 : return ihidev_open(&sc->sc_hdev);
152 0 : }
153 :
154 : void
155 0 : ims_disable(void *v)
156 : {
157 0 : struct ims_softc *sc = v;
158 0 : struct hidms *ms = &sc->sc_ms;
159 :
160 0 : hidms_disable(ms);
161 0 : ihidev_close(&sc->sc_hdev);
162 0 : }
163 :
164 : int
165 0 : ims_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
166 : {
167 0 : struct ims_softc *sc = v;
168 0 : struct hidms *ms = &sc->sc_ms;
169 : int rc;
170 :
171 : #if 0
172 : rc = ihidev_ioctl(&sc->sc_hdev, cmd, data, flag, p);
173 : if (rc != -1)
174 : return rc;
175 : #endif
176 :
177 0 : rc = hidms_ioctl(ms, cmd, data, flag, p);
178 0 : if (rc != -1)
179 0 : return rc;
180 :
181 0 : switch (cmd) {
182 : case WSMOUSEIO_GTYPE:
183 : /* XXX: should we set something else? */
184 0 : *(u_int *)data = WSMOUSE_TYPE_USB;
185 0 : return 0;
186 : default:
187 0 : return -1;
188 : }
189 0 : }
|