This source file includes following definitions.
- uhid_match
- uhid_attach
- uhid_activate
- uhid_detach
- uhid_intr
- uhidopen
- uhidclose
- uhid_do_read
- uhidread
- uhid_do_write
- uhidwrite
- uhid_do_ioctl
- uhidioctl
- uhidpoll
- filt_uhidrdetach
- filt_uhidread
- uhidkqfilter
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/signalvar.h>
50 #include <sys/device.h>
51 #include <sys/ioctl.h>
52 #include <sys/conf.h>
53 #include <sys/tty.h>
54 #include <sys/file.h>
55 #include <sys/selinfo.h>
56 #include <sys/proc.h>
57 #include <sys/vnode.h>
58 #include <sys/poll.h>
59
60 #include <dev/usb/usb.h>
61 #include <dev/usb/usbhid.h>
62
63 #include <dev/usb/usbdevs.h>
64 #include <dev/usb/usbdi.h>
65 #include <dev/usb/usbdi_util.h>
66 #include <dev/usb/hid.h>
67 #include <dev/usb/usb_quirks.h>
68
69 #include <dev/usb/uhidev.h>
70
71 #ifdef UHID_DEBUG
72 #define DPRINTF(x) do { if (uhiddebug) printf x; } while (0)
73 #define DPRINTFN(n,x) do { if (uhiddebug>(n)) printf x; } while (0)
74 int uhiddebug = 0;
75 #else
76 #define DPRINTF(x)
77 #define DPRINTFN(n,x)
78 #endif
79
80 struct uhid_softc {
81 struct uhidev sc_hdev;
82
83 int sc_isize;
84 int sc_osize;
85 int sc_fsize;
86
87 u_char *sc_obuf;
88
89 struct clist sc_q;
90 struct selinfo sc_rsel;
91 struct proc *sc_async;
92 u_char sc_state;
93 #define UHID_ASLP 0x01
94 #define UHID_IMMED 0x02
95
96 int sc_refcnt;
97 u_char sc_dying;
98 };
99
100 #define UHIDUNIT(dev) (minor(dev))
101 #define UHID_CHUNK 128
102 #define UHID_BSIZE 1020
103
104 void uhid_intr(struct uhidev *, void *, u_int len);
105
106 int uhid_do_read(struct uhid_softc *, struct uio *uio, int);
107 int uhid_do_write(struct uhid_softc *, struct uio *uio, int);
108 int uhid_do_ioctl(struct uhid_softc*, u_long, caddr_t, int,
109 struct proc *);
110
111 int uhid_match(struct device *, void *, void *);
112 void uhid_attach(struct device *, struct device *, void *);
113 int uhid_detach(struct device *, int);
114 int uhid_activate(struct device *, enum devact);
115
116 struct cfdriver uhid_cd = {
117 NULL, "uhid", DV_DULL
118 };
119
120 const struct cfattach uhid_ca = {
121 sizeof(struct uhid_softc),
122 uhid_match,
123 uhid_attach,
124 uhid_detach,
125 uhid_activate,
126 };
127
128 int
129 uhid_match(struct device *parent, void *match, void *aux)
130 {
131 struct usb_attach_arg *uaa = aux;
132 struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
133
134 DPRINTF(("uhid_match: report=%d\n", uha->reportid));
135
136 if (uha->matchlvl)
137 return (uha->matchlvl);
138 return (UMATCH_IFACECLASS_GENERIC);
139 }
140
141 void
142 uhid_attach(struct device *parent, struct device *self, void *aux)
143 {
144 struct uhid_softc *sc = (struct uhid_softc *)self;
145 struct usb_attach_arg *uaa = aux;
146 struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa;
147 int size, repid;
148 void *desc;
149
150 sc->sc_hdev.sc_intr = uhid_intr;
151 sc->sc_hdev.sc_parent = uha->parent;
152 sc->sc_hdev.sc_report_id = uha->reportid;
153
154 uhidev_get_report_desc(uha->parent, &desc, &size);
155 repid = uha->reportid;
156 sc->sc_isize = hid_report_size(desc, size, hid_input, repid);
157 sc->sc_osize = hid_report_size(desc, size, hid_output, repid);
158 sc->sc_fsize = hid_report_size(desc, size, hid_feature, repid);
159
160 printf(": input=%d, output=%d, feature=%d\n",
161 sc->sc_isize, sc->sc_osize, sc->sc_fsize);
162 }
163
164 int
165 uhid_activate(struct device *self, enum devact act)
166 {
167 struct uhid_softc *sc = (struct uhid_softc *)self;
168
169 switch (act) {
170 case DVACT_ACTIVATE:
171 break;
172
173 case DVACT_DEACTIVATE:
174 sc->sc_dying = 1;
175 break;
176 }
177 return (0);
178 }
179
180 int
181 uhid_detach(struct device *self, int flags)
182 {
183 struct uhid_softc *sc = (struct uhid_softc *)self;
184 int s;
185 int maj, mn;
186
187 DPRINTF(("uhid_detach: sc=%p flags=%d\n", sc, flags));
188
189 sc->sc_dying = 1;
190
191 if (sc->sc_hdev.sc_state & UHIDEV_OPEN) {
192 s = splusb();
193 if (--sc->sc_refcnt >= 0) {
194
195 wakeup(&sc->sc_q);
196
197 usb_detach_wait(&sc->sc_hdev.sc_dev);
198 }
199 splx(s);
200 }
201
202
203 for (maj = 0; maj < nchrdev; maj++)
204 if (cdevsw[maj].d_open == uhidopen)
205 break;
206
207
208 mn = self->dv_unit;
209 vdevgone(maj, mn, mn, VCHR);
210
211 #if 0
212 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH,
213 sc->sc_hdev.sc_parent->sc_udev,
214 &sc->sc_hdev.sc_dev);
215 #endif
216
217 return (0);
218 }
219
220 void
221 uhid_intr(struct uhidev *addr, void *data, u_int len)
222 {
223 struct uhid_softc *sc = (struct uhid_softc *)addr;
224
225 #ifdef UHID_DEBUG
226 if (uhiddebug > 5) {
227 u_int32_t i;
228
229 DPRINTF(("uhid_intr: data ="));
230 for (i = 0; i < len; i++)
231 DPRINTF((" %02x", ((u_char *)data)[i]));
232 DPRINTF(("\n"));
233 }
234 #endif
235
236 (void)b_to_q(data, len, &sc->sc_q);
237
238 if (sc->sc_state & UHID_ASLP) {
239 sc->sc_state &= ~UHID_ASLP;
240 DPRINTFN(5, ("uhid_intr: waking %p\n", &sc->sc_q));
241 wakeup(&sc->sc_q);
242 }
243 selwakeup(&sc->sc_rsel);
244 if (sc->sc_async != NULL) {
245 DPRINTFN(3, ("uhid_intr: sending SIGIO %p\n", sc->sc_async));
246 psignal(sc->sc_async, SIGIO);
247 }
248 }
249
250 int
251 uhidopen(dev_t dev, int flag, int mode, struct proc *p)
252 {
253 struct uhid_softc *sc;
254 int error;
255
256 if (UHIDUNIT(dev) >= uhid_cd.cd_ndevs)
257 return (ENXIO);
258 sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
259 if (sc == NULL)
260 return (ENXIO);
261
262 DPRINTF(("uhidopen: sc=%p\n", sc));
263
264 if (sc->sc_dying)
265 return (ENXIO);
266
267 error = uhidev_open(&sc->sc_hdev);
268 if (error)
269 return (error);
270
271 if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1) {
272 uhidev_close(&sc->sc_hdev);
273 return (ENOMEM);
274 }
275 sc->sc_obuf = malloc(sc->sc_osize, M_USBDEV, M_WAITOK);
276 sc->sc_state &= ~UHID_IMMED;
277 sc->sc_async = NULL;
278
279 return (0);
280 }
281
282 int
283 uhidclose(dev_t dev, int flag, int mode, struct proc *p)
284 {
285 struct uhid_softc *sc;
286
287 sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
288
289 DPRINTF(("uhidclose: sc=%p\n", sc));
290
291 clfree(&sc->sc_q);
292 free(sc->sc_obuf, M_USBDEV);
293 sc->sc_async = NULL;
294 uhidev_close(&sc->sc_hdev);
295
296 return (0);
297 }
298
299 int
300 uhid_do_read(struct uhid_softc *sc, struct uio *uio, int flag)
301 {
302 int s;
303 int error = 0;
304 int extra;
305 size_t length;
306 u_char buffer[UHID_CHUNK];
307 usbd_status err;
308
309 DPRINTFN(1, ("uhidread\n"));
310 if (sc->sc_state & UHID_IMMED) {
311 DPRINTFN(1, ("uhidread immed\n"));
312 extra = sc->sc_hdev.sc_report_id != 0;
313 err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT,
314 buffer, sc->sc_isize + extra);
315 if (err)
316 return (EIO);
317 return (uiomove(buffer+extra, sc->sc_isize, uio));
318 }
319
320 s = splusb();
321 while (sc->sc_q.c_cc == 0) {
322 if (flag & IO_NDELAY) {
323 splx(s);
324 return (EWOULDBLOCK);
325 }
326 sc->sc_state |= UHID_ASLP;
327 DPRINTFN(5, ("uhidread: sleep on %p\n", &sc->sc_q));
328 error = tsleep(&sc->sc_q, PZERO | PCATCH, "uhidrea", 0);
329 DPRINTFN(5, ("uhidread: woke, error=%d\n", error));
330 if (sc->sc_dying)
331 error = EIO;
332 if (error) {
333 sc->sc_state &= ~UHID_ASLP;
334 break;
335 }
336 }
337 splx(s);
338
339
340 while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0 && !error) {
341 length = min(sc->sc_q.c_cc, uio->uio_resid);
342 if (length > sizeof(buffer))
343 length = sizeof(buffer);
344
345
346 (void) q_to_b(&sc->sc_q, buffer, length);
347 DPRINTFN(5, ("uhidread: got %lu chars\n", (u_long)length));
348
349
350 if ((error = uiomove(buffer, length, uio)) != 0)
351 break;
352 }
353
354 return (error);
355 }
356
357 int
358 uhidread(dev_t dev, struct uio *uio, int flag)
359 {
360 struct uhid_softc *sc;
361 int error;
362
363 sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
364
365 sc->sc_refcnt++;
366 error = uhid_do_read(sc, uio, flag);
367 if (--sc->sc_refcnt < 0)
368 usb_detach_wakeup(&sc->sc_hdev.sc_dev);
369 return (error);
370 }
371
372 int
373 uhid_do_write(struct uhid_softc *sc, struct uio *uio, int flag)
374 {
375 int error;
376 int size;
377 usbd_status err;
378
379 DPRINTFN(1, ("uhidwrite\n"));
380
381 if (sc->sc_dying)
382 return (EIO);
383
384 size = sc->sc_osize;
385 error = 0;
386 if (uio->uio_resid != size)
387 return (EINVAL);
388 error = uiomove(sc->sc_obuf, size, uio);
389 if (!error) {
390 err = uhidev_set_report(&sc->sc_hdev, UHID_OUTPUT_REPORT,
391 sc->sc_obuf, size);
392 if (err)
393 error = EIO;
394 }
395
396 return (error);
397 }
398
399 int
400 uhidwrite(dev_t dev, struct uio *uio, int flag)
401 {
402 struct uhid_softc *sc;
403 int error;
404
405 sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
406
407 sc->sc_refcnt++;
408 error = uhid_do_write(sc, uio, flag);
409 if (--sc->sc_refcnt < 0)
410 usb_detach_wakeup(&sc->sc_hdev.sc_dev);
411 return (error);
412 }
413
414 int
415 uhid_do_ioctl(struct uhid_softc *sc, u_long cmd, caddr_t addr,
416 int flag, struct proc *p)
417 {
418 struct usb_ctl_report_desc *rd;
419 struct usb_ctl_report *re;
420 u_char buffer[UHID_CHUNK];
421 int size, extra;
422 usbd_status err;
423 void *desc;
424
425 DPRINTFN(2, ("uhidioctl: cmd=%lx\n", cmd));
426
427 if (sc->sc_dying)
428 return (EIO);
429
430 switch (cmd) {
431 case FIONBIO:
432
433 break;
434
435 case FIOASYNC:
436 if (*(int *)addr) {
437 if (sc->sc_async != NULL)
438 return (EBUSY);
439 sc->sc_async = p;
440 DPRINTF(("uhid_do_ioctl: FIOASYNC %p\n", p));
441 } else
442 sc->sc_async = NULL;
443 break;
444
445
446 case TIOCSPGRP:
447 if (sc->sc_async == NULL)
448 return (EINVAL);
449 if (*(int *)addr != sc->sc_async->p_pgid)
450 return (EPERM);
451 break;
452
453 case USB_GET_REPORT_DESC:
454 uhidev_get_report_desc(sc->sc_hdev.sc_parent, &desc, &size);
455 rd = (struct usb_ctl_report_desc *)addr;
456 size = min(size, sizeof rd->ucrd_data);
457 rd->ucrd_size = size;
458 memcpy(rd->ucrd_data, desc, size);
459 break;
460
461 case USB_SET_IMMED:
462 if (*(int *)addr) {
463 extra = sc->sc_hdev.sc_report_id != 0;
464 err = uhidev_get_report(&sc->sc_hdev, UHID_INPUT_REPORT,
465 buffer, sc->sc_isize + extra);
466 if (err)
467 return (EOPNOTSUPP);
468
469 sc->sc_state |= UHID_IMMED;
470 } else
471 sc->sc_state &= ~UHID_IMMED;
472 break;
473
474 case USB_GET_REPORT:
475 re = (struct usb_ctl_report *)addr;
476 switch (re->ucr_report) {
477 case UHID_INPUT_REPORT:
478 size = sc->sc_isize;
479 break;
480 case UHID_OUTPUT_REPORT:
481 size = sc->sc_osize;
482 break;
483 case UHID_FEATURE_REPORT:
484 size = sc->sc_fsize;
485 break;
486 default:
487 return (EINVAL);
488 }
489 extra = sc->sc_hdev.sc_report_id != 0;
490 err = uhidev_get_report(&sc->sc_hdev, re->ucr_report,
491 re->ucr_data, size + extra);
492 if (extra)
493 memcpy(re->ucr_data, re->ucr_data+1, size);
494 if (err)
495 return (EIO);
496 break;
497
498 case USB_SET_REPORT:
499 re = (struct usb_ctl_report *)addr;
500 switch (re->ucr_report) {
501 case UHID_INPUT_REPORT:
502 size = sc->sc_isize;
503 break;
504 case UHID_OUTPUT_REPORT:
505 size = sc->sc_osize;
506 break;
507 case UHID_FEATURE_REPORT:
508 size = sc->sc_fsize;
509 break;
510 default:
511 return (EINVAL);
512 }
513 err = uhidev_set_report(&sc->sc_hdev, re->ucr_report,
514 re->ucr_data, size);
515 if (err)
516 return (EIO);
517 break;
518
519 case USB_GET_REPORT_ID:
520 *(int *)addr = sc->sc_hdev.sc_report_id;
521 break;
522
523 default:
524 return (EINVAL);
525 }
526 return (0);
527 }
528
529 int
530 uhidioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
531 {
532 struct uhid_softc *sc;
533 int error;
534
535 sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
536
537 sc->sc_refcnt++;
538 error = uhid_do_ioctl(sc, cmd, addr, flag, p);
539 if (--sc->sc_refcnt < 0)
540 usb_detach_wakeup(&sc->sc_hdev.sc_dev);
541 return (error);
542 }
543
544 int
545 uhidpoll(dev_t dev, int events, struct proc *p)
546 {
547 struct uhid_softc *sc;
548 int revents = 0;
549 int s;
550
551 sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
552
553 if (sc->sc_dying)
554 return (POLLERR);
555
556 s = splusb();
557 if (events & (POLLOUT | POLLWRNORM))
558 revents |= events & (POLLOUT | POLLWRNORM);
559 if (events & (POLLIN | POLLRDNORM)) {
560 if (sc->sc_q.c_cc > 0)
561 revents |= events & (POLLIN | POLLRDNORM);
562 else
563 selrecord(p, &sc->sc_rsel);
564 }
565
566 splx(s);
567 return (revents);
568 }
569
570 void filt_uhidrdetach(struct knote *);
571 int filt_uhidread(struct knote *, long);
572 int uhidkqfilter(dev_t, struct knote *);
573
574 void
575 filt_uhidrdetach(struct knote *kn)
576 {
577 struct uhid_softc *sc = (void *)kn->kn_hook;
578 int s;
579
580 s = splusb();
581 SLIST_REMOVE(&sc->sc_rsel.si_note, kn, knote, kn_selnext);
582 splx(s);
583 }
584
585 int
586 filt_uhidread(struct knote *kn, long hint)
587 {
588 struct uhid_softc *sc = (void *)kn->kn_hook;
589
590 kn->kn_data = sc->sc_q.c_cc;
591 return (kn->kn_data > 0);
592 }
593
594 struct filterops uhidread_filtops =
595 { 1, NULL, filt_uhidrdetach, filt_uhidread };
596
597 struct filterops uhid_seltrue_filtops =
598 { 1, NULL, filt_uhidrdetach, filt_seltrue };
599
600 int
601 uhidkqfilter(dev_t dev, struct knote *kn)
602 {
603 struct uhid_softc *sc;
604 struct klist *klist;
605 int s;
606
607 sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
608
609 if (sc->sc_dying)
610 return (EIO);
611
612 switch (kn->kn_filter) {
613 case EVFILT_READ:
614 klist = &sc->sc_rsel.si_note;
615 kn->kn_fop = &uhidread_filtops;
616 break;
617
618 case EVFILT_WRITE:
619 klist = &sc->sc_rsel.si_note;
620 kn->kn_fop = &uhid_seltrue_filtops;
621 break;
622
623 default:
624 return (1);
625 }
626
627 kn->kn_hook = (void *)sc;
628
629 s = splusb();
630 SLIST_INSERT_HEAD(klist, kn, kn_selnext);
631 splx(s);
632
633 return (0);
634 }