This source file includes following definitions.
- ums_match
- ums_attach
- ums_activate
- ums_detach
- ums_intr
- ums_enable
- ums_disable
- ums_ioctl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/malloc.h>
49 #include <sys/device.h>
50 #include <sys/ioctl.h>
51 #include <sys/tty.h>
52 #include <sys/file.h>
53 #include <sys/selinfo.h>
54 #include <sys/proc.h>
55 #include <sys/vnode.h>
56 #include <sys/poll.h>
57
58 #include <dev/usb/usb.h>
59 #include <dev/usb/usbhid.h>
60
61 #include <dev/usb/usbdi.h>
62 #include <dev/usb/usbdi_util.h>
63 #include <dev/usb/usbdevs.h>
64 #include <dev/usb/usb_quirks.h>
65 #include <dev/usb/uhidev.h>
66 #include <dev/usb/hid.h>
67
68 #include <dev/wscons/wsconsio.h>
69 #include <dev/wscons/wsmousevar.h>
70
71 #ifdef USB_DEBUG
72 #define DPRINTF(x) do { if (umsdebug) printf x; } while (0)
73 #define DPRINTFN(n,x) do { if (umsdebug>(n)) printf x; } while (0)
74 int umsdebug = 0;
75 #else
76 #define DPRINTF(x)
77 #define DPRINTFN(n,x)
78 #endif
79
80 #define UMS_BUT(i) ((i) == 1 || (i) == 2 ? 3 - (i) : i)
81
82 #define UMSUNIT(s) (minor(s))
83
84 #define PS2LBUTMASK x01
85 #define PS2RBUTMASK x02
86 #define PS2MBUTMASK x04
87 #define PS2BUTMASK 0x0f
88
89 #define MAX_BUTTONS 16
90
91 struct ums_softc {
92 struct uhidev sc_hdev;
93
94 struct hid_location sc_loc_x, sc_loc_y, sc_loc_z, sc_loc_w;
95 struct hid_location sc_loc_btn[MAX_BUTTONS];
96
97 int sc_enabled;
98
99 int flags;
100 #define UMS_Z 0x01
101 #define UMS_SPUR_BUT_UP 0x02
102 #define UMS_REVZ 0x04
103
104 int nbuttons;
105
106 u_int32_t sc_buttons;
107 struct device *sc_wsmousedev;
108
109 char sc_dying;
110 };
111
112 #define MOUSE_FLAGS_MASK (HIO_CONST|HIO_RELATIVE)
113 #define MOUSE_FLAGS (HIO_RELATIVE)
114
115 void ums_intr(struct uhidev *addr, void *ibuf, u_int len);
116
117 int ums_enable(void *);
118 void ums_disable(void *);
119 int ums_ioctl(void *, u_long, caddr_t, int, struct proc *);
120
121 const struct wsmouse_accessops ums_accessops = {
122 ums_enable,
123 ums_ioctl,
124 ums_disable,
125 };
126
127 int ums_match(struct device *, void *, void *);
128 void ums_attach(struct device *, struct device *, void *);
129 int ums_detach(struct device *, int);
130 int ums_activate(struct device *, enum devact);
131
132 struct cfdriver ums_cd = {
133 NULL, "ums", DV_DULL
134 };
135
136 const struct cfattach ums_ca = {
137 sizeof(struct ums_softc),
138 ums_match,
139 ums_attach,
140 ums_detach,
141 ums_activate,
142 };
143
144 int
145 ums_match(struct device *parent, void *match, void *aux)
146 {
147 struct usb_attach_arg *uaa = aux;
148 struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
149 int size;
150 void *desc;
151
152 uhidev_get_report_desc(uha->parent, &desc, &size);
153 if (!hid_is_collection(desc, size, uha->reportid,
154 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)))
155 return (UMATCH_NONE);
156
157 return (UMATCH_IFACECLASS);
158 }
159
160 void
161 ums_attach(struct device *parent, struct device *self, void *aux)
162 {
163 struct ums_softc *sc = (struct ums_softc *)self;
164 struct usb_attach_arg *uaa = aux;
165 struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
166 struct wsmousedev_attach_args a;
167 int size;
168 void *desc;
169 u_int32_t flags, quirks;
170 int i;
171 struct hid_location loc_btn;
172
173 sc->sc_hdev.sc_intr = ums_intr;
174 sc->sc_hdev.sc_parent = uha->parent;
175 sc->sc_hdev.sc_report_id = uha->reportid;
176
177 quirks = usbd_get_quirks(uha->parent->sc_udev)->uq_flags;
178 if (quirks & UQ_MS_REVZ)
179 sc->flags |= UMS_REVZ;
180 if (quirks & UQ_SPUR_BUT_UP)
181 sc->flags |= UMS_SPUR_BUT_UP;
182
183 uhidev_get_report_desc(uha->parent, &desc, &size);
184
185 if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
186 uha->reportid, hid_input, &sc->sc_loc_x, &flags)) {
187 printf("\n%s: mouse has no X report\n",
188 sc->sc_hdev.sc_dev.dv_xname);
189 return;
190 }
191 if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
192 printf("\n%s: X report 0x%04x not supported\n",
193 sc->sc_hdev.sc_dev.dv_xname, flags);
194 return;
195 }
196
197 if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
198 uha->reportid, hid_input, &sc->sc_loc_y, &flags)) {
199 printf("\n%s: mouse has no Y report\n",
200 sc->sc_hdev.sc_dev.dv_xname);
201 return;
202 }
203 if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
204 printf("\n%s: Y report 0x%04x not supported\n",
205 sc->sc_hdev.sc_dev.dv_xname, flags);
206 return;
207 }
208
209
210 if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
211 uha->reportid, hid_input, &sc->sc_loc_z, &flags)) {
212 if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
213 DPRINTF(("\n%s: Wheel report 0x%04x not supported\n",
214 sc->sc_hdev.sc_dev.dv_xname, flags));
215 sc->sc_loc_z.size = 0;
216 } else {
217 sc->flags |= UMS_Z;
218
219 sc->flags ^= UMS_REVZ;
220 }
221
222
223
224
225 if (hid_locate(desc, size,
226 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
227 uha->reportid, hid_input, &sc->sc_loc_w, &flags)) {
228 if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
229 DPRINTF(("\n%s: Z report 0x%04x not supported\n",
230 sc->sc_hdev.sc_dev.dv_xname, flags));
231
232 sc->sc_loc_w.size = 0;
233 }
234 }
235 } else if (hid_locate(desc, size,
236 HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
237 uha->reportid, hid_input, &sc->sc_loc_z, &flags)) {
238 if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
239 DPRINTF(("\n%s: Z report 0x%04x not supported\n",
240 sc->sc_hdev.sc_dev.dv_xname, flags));
241 sc->sc_loc_z.size = 0;
242 } else {
243 sc->flags |= UMS_Z;
244 }
245 }
246
247
248 for (i = 1; i <= MAX_BUTTONS; i++)
249 if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
250 uha->reportid, hid_input, &loc_btn, 0))
251 break;
252 sc->nbuttons = i - 1;
253
254 printf(": %d button%s%s\n",
255 sc->nbuttons, sc->nbuttons == 1 ? "" : "s",
256 sc->flags & UMS_Z ? " and Z dir." : "");
257
258 for (i = 1; i <= sc->nbuttons; i++)
259 hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
260 uha->reportid, hid_input,
261 &sc->sc_loc_btn[i-1], 0);
262
263 #ifdef USB_DEBUG
264 DPRINTF(("ums_attach: sc=%p\n", sc));
265 DPRINTF(("ums_attach: X\t%d/%d\n",
266 sc->sc_loc_x.pos, sc->sc_loc_x.size));
267 DPRINTF(("ums_attach: Y\t%d/%d\n",
268 sc->sc_loc_y.pos, sc->sc_loc_y.size));
269 if (sc->flags & UMS_Z)
270 DPRINTF(("ums_attach: Z\t%d/%d\n",
271 sc->sc_loc_z.pos, sc->sc_loc_z.size));
272 for (i = 1; i <= sc->nbuttons; i++) {
273 DPRINTF(("ums_attach: B%d\t%d/%d\n",
274 i, sc->sc_loc_btn[i-1].pos,sc->sc_loc_btn[i-1].size));
275 }
276 #endif
277
278 a.accessops = &ums_accessops;
279 a.accesscookie = sc;
280
281 sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
282 }
283
284 int
285 ums_activate(struct device *self, enum devact act)
286 {
287 struct ums_softc *sc = (struct ums_softc *)self;
288 int rv = 0;
289
290 switch (act) {
291 case DVACT_ACTIVATE:
292 break;
293
294 case DVACT_DEACTIVATE:
295 if (sc->sc_wsmousedev != NULL)
296 rv = config_deactivate(sc->sc_wsmousedev);
297 sc->sc_dying = 1;
298 break;
299 }
300 return (rv);
301 }
302
303 int
304 ums_detach(struct device *self, int flags)
305 {
306 struct ums_softc *sc = (struct ums_softc *)self;
307 int rv = 0;
308
309 DPRINTF(("ums_detach: sc=%p flags=%d\n", sc, flags));
310
311
312 if (sc->sc_wsmousedev != NULL)
313 rv = config_detach(sc->sc_wsmousedev, flags);
314
315 return (rv);
316 }
317
318 void
319 ums_intr(struct uhidev *addr, void *ibuf, u_int len)
320 {
321 struct ums_softc *sc = (struct ums_softc *)addr;
322 int dx, dy, dz, dw;
323 u_int32_t buttons = 0;
324 int i;
325 int s;
326
327 DPRINTFN(5,("ums_intr: len=%d\n", len));
328
329 dx = hid_get_data(ibuf, &sc->sc_loc_x);
330 dy = -hid_get_data(ibuf, &sc->sc_loc_y);
331 dz = hid_get_data(ibuf, &sc->sc_loc_z);
332 dw = hid_get_data(ibuf, &sc->sc_loc_w);
333 if (sc->flags & UMS_REVZ)
334 dz = -dz;
335 for (i = 0; i < sc->nbuttons; i++)
336 if (hid_get_data(ibuf, &sc->sc_loc_btn[i]))
337 buttons |= (1 << UMS_BUT(i));
338
339 if (dx != 0 || dy != 0 || dz != 0 || dw != 0 ||
340 buttons != sc->sc_buttons) {
341 DPRINTFN(10, ("ums_intr: x:%d y:%d z:%d w:%d buttons:0x%x\n",
342 dx, dy, dz, dw, buttons));
343 sc->sc_buttons = buttons;
344 if (sc->sc_wsmousedev != NULL) {
345 s = spltty();
346 wsmouse_input(sc->sc_wsmousedev, buttons,
347 dx, dy, dz, dw, WSMOUSE_INPUT_DELTA);
348 splx(s);
349 }
350 }
351 }
352
353 int
354 ums_enable(void *v)
355 {
356 struct ums_softc *sc = v;
357
358 DPRINTFN(1,("ums_enable: sc=%p\n", sc));
359
360 if (sc->sc_dying)
361 return (EIO);
362
363 if (sc->sc_enabled)
364 return (EBUSY);
365
366 sc->sc_enabled = 1;
367 sc->sc_buttons = 0;
368
369 return (uhidev_open(&sc->sc_hdev));
370 }
371
372 void
373 ums_disable(void *v)
374 {
375 struct ums_softc *sc = v;
376
377 DPRINTFN(1,("ums_disable: sc=%p\n", sc));
378 #ifdef DIAGNOSTIC
379 if (!sc->sc_enabled) {
380 printf("ums_disable: not enabled\n");
381 return;
382 }
383 #endif
384
385 sc->sc_enabled = 0;
386 uhidev_close(&sc->sc_hdev);
387 }
388
389 int
390 ums_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
391
392 {
393 switch (cmd) {
394 case WSMOUSEIO_GTYPE:
395 *(u_int *)data = WSMOUSE_TYPE_USB;
396 return (0);
397 }
398
399 return (-1);
400 }