ugen.c revision 1.22 1 /* $NetBSD: ugen.c,v 1.22 1999/09/05 19:32:18 augustss Exp $ */
2
3 /*
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (augustss (at) carlstedt.se) at
9 * Carlstedt Research & Technology.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/malloc.h>
45 #if defined(__NetBSD__) || defined(__OpenBSD__)
46 #include <sys/device.h>
47 #include <sys/ioctl.h>
48 #elif defined(__FreeBSD__)
49 #include <sys/module.h>
50 #include <sys/bus.h>
51 #include <sys/ioccom.h>
52 #include <sys/conf.h>
53 #include <sys/fcntl.h>
54 #include <sys/filio.h>
55 #endif
56 #include <sys/conf.h>
57 #include <sys/tty.h>
58 #include <sys/file.h>
59 #include <sys/select.h>
60 #include <sys/proc.h>
61 #include <sys/vnode.h>
62 #include <sys/poll.h>
63
64 #include <dev/usb/usb.h>
65 #include <dev/usb/usbdi.h>
66 #include <dev/usb/usbdi_util.h>
67
68 #ifdef USB_DEBUG
69 #define DPRINTF(x) if (ugendebug) logprintf x
70 #define DPRINTFN(n,x) if (ugendebug>(n)) logprintf x
71 int ugendebug = 0;
72 #else
73 #define DPRINTF(x)
74 #define DPRINTFN(n,x)
75 #endif
76
77 struct ugen_endpoint {
78 struct ugen_softc *sc;
79 usb_endpoint_descriptor_t *edesc;
80 usbd_interface_handle iface;
81 int state;
82 #define UGEN_ASLP 0x02 /* waiting for data */
83 #define UGEN_SHORT_OK 0x04 /* short xfers are OK */
84 usbd_pipe_handle pipeh;
85 struct clist q;
86 struct selinfo rsel;
87 void *ibuf;
88 u_int32_t timeout;
89 };
90
91 #define UGEN_CHUNK 128 /* chunk size for read */
92 #define UGEN_IBSIZE 1020 /* buffer size */
93 #define UGEN_BBSIZE 1024
94
95 struct ugen_softc {
96 USBBASEDEVICE sc_dev; /* base device */
97 usbd_device_handle sc_udev;
98
99 char sc_is_open[USB_MAX_ENDPOINTS];
100 struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2];
101 #define OUT 0
102 #define IN 1
103
104 int sc_refcnt;
105 u_char sc_dying;
106 };
107
108 #if defined(__NetBSD__) || defined(__OpenBSD__)
109 cdev_decl(ugen);
110 #elif defined(__FreeBSD__)
111 d_open_t ugenopen;
112 d_close_t ugenclose;
113 d_read_t ugenread;
114 d_write_t ugenwrite;
115 d_ioctl_t ugenioctl;
116 d_poll_t ugenpoll;
117
118 #define UGEN_CDEV_MAJOR 114
119
120 static struct cdevsw ugen_cdevsw = {
121 /* open */ ugenopen,
122 /* close */ ugenclose,
123 /* read */ ugenread,
124 /* write */ ugenwrite,
125 /* ioctl */ ugenioctl,
126 /* stop */ nostop,
127 /* reset */ noreset,
128 /* devtotty */ nodevtotty,
129 /* poll */ ugenpoll,
130 /* mmap */ nommap,
131 /* strategy */ nostrategy,
132 /* name */ "ugen",
133 /* parms */ noparms,
134 /* maj */ UGEN_CDEV_MAJOR,
135 /* dump */ nodump,
136 /* psize */ nopsize,
137 /* flags */ 0,
138 /* maxio */ 0,
139 /* bmaj */ -1
140 };
141 #endif
142
143 void ugenintr __P((usbd_request_handle reqh, usbd_private_handle addr,
144 usbd_status status));
145
146 int ugen_do_read __P((struct ugen_softc *, int, struct uio *, int));
147 int ugen_do_write __P((struct ugen_softc *, int, struct uio *, int));
148 int ugen_do_ioctl __P((struct ugen_softc *, int, u_long,
149 caddr_t, int, struct proc *));
150 int ugen_set_config __P((struct ugen_softc *sc, int configno));
151 usb_config_descriptor_t *ugen_get_cdesc __P((struct ugen_softc *sc, int index,
152 int *lenp));
153 usbd_status ugen_set_interface __P((struct ugen_softc *, int, int));
154 int ugen_get_alt_index __P((struct ugen_softc *sc, int ifaceidx));
155
156 #define UGENUNIT(n) ((minor(n) >> 4) & 0xf)
157 #define UGENENDPOINT(n) (minor(n) & 0xf)
158 #define UGENDEV(u, e) (makedev(0, ((u) << 4) | (e)))
159
160 USB_DECLARE_DRIVER(ugen);
161
162 USB_MATCH(ugen)
163 {
164 USB_MATCH_START(ugen, uaa);
165
166 if (uaa->usegeneric)
167 return (UMATCH_GENERIC);
168 else
169 return (UMATCH_NONE);
170 }
171
172 USB_ATTACH(ugen)
173 {
174 USB_ATTACH_START(ugen, sc, uaa);
175 char devinfo[1024];
176 usbd_status r;
177 int conf;
178
179 usbd_devinfo(uaa->device, 0, devinfo);
180 USB_ATTACH_SETUP;
181 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
182
183 sc->sc_udev = uaa->device;
184 conf = 1; /* XXX should not hard code 1 */
185 r = ugen_set_config(sc, conf);
186 if (r != USBD_NORMAL_COMPLETION) {
187 printf("%s: setting configuration %d failed\n",
188 USBDEVNAME(sc->sc_dev), conf);
189 sc->sc_dying = 1;
190 USB_ATTACH_ERROR_RETURN;
191 }
192 USB_ATTACH_SUCCESS_RETURN;
193 }
194
195 int
196 ugen_set_config(sc, configno)
197 struct ugen_softc *sc;
198 int configno;
199 {
200 usbd_device_handle dev = sc->sc_udev;
201 usbd_interface_handle iface;
202 usb_endpoint_descriptor_t *ed;
203 struct ugen_endpoint *sce;
204 u_int8_t niface, nendpt;
205 int ifaceno, endptno, endpt;
206 usbd_status r;
207 int dir;
208
209 DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
210 USBDEVNAME(sc->sc_dev), configno, sc));
211 if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) {
212 /* Avoid setting the current value. */
213 r = usbd_set_config_no(dev, configno, 0);
214 if (r != USBD_NORMAL_COMPLETION)
215 return (r);
216 }
217
218 r = usbd_interface_count(dev, &niface);
219 if (r != USBD_NORMAL_COMPLETION)
220 return (r);
221 memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
222 for (ifaceno = 0; ifaceno < niface; ifaceno++) {
223 DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno));
224 r = usbd_device2interface_handle(dev, ifaceno, &iface);
225 if (r != USBD_NORMAL_COMPLETION)
226 return (r);
227 r = usbd_endpoint_count(iface, &nendpt);
228 if (r != USBD_NORMAL_COMPLETION)
229 return (r);
230 for (endptno = 0; endptno < nendpt; endptno++) {
231 ed = usbd_interface2endpoint_descriptor(iface,endptno);
232 endpt = ed->bEndpointAddress;
233 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
234 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
235 DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x"
236 "(%d,%d), sce=%p\n",
237 endptno, endpt, UE_GET_ADDR(endpt),
238 UE_GET_DIR(endpt), sce));
239 sce->sc = sc;
240 sce->edesc = ed;
241 sce->iface = iface;
242 }
243 }
244 return (USBD_NORMAL_COMPLETION);
245 }
246
247 int
248 ugenopen(dev, flag, mode, p)
249 dev_t dev;
250 int flag;
251 int mode;
252 struct proc *p;
253 {
254 int unit = UGENUNIT(dev);
255 int endpt = UGENENDPOINT(dev);
256 usb_endpoint_descriptor_t *edesc;
257 struct ugen_endpoint *sce;
258 int dir, isize;
259 usbd_status r;
260
261 USB_GET_SC_OPEN(ugen, unit, sc);
262 DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
263 flag, mode, unit, endpt));
264
265 if (sc->sc_dying)
266 return (ENXIO);
267
268 if (sc->sc_is_open[endpt])
269 return (EBUSY);
270
271 if (endpt == USB_CONTROL_ENDPOINT) {
272 sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1;
273 return (0);
274 }
275 /* Make sure there are pipes for all directions. */
276 for (dir = OUT; dir <= IN; dir++) {
277 if (flag & (dir == OUT ? FWRITE : FREAD)) {
278 sce = &sc->sc_endpoints[endpt][dir];
279 if (sce == 0 || sce->edesc == 0)
280 return (ENXIO);
281 }
282 }
283
284 /* Actually open the pipes. */
285 /* XXX Should back out properly if it fails. */
286 for (dir = OUT; dir <= IN; dir++) {
287 if (!(flag & (dir == OUT ? FWRITE : FREAD)))
288 continue;
289 sce = &sc->sc_endpoints[endpt][dir];
290 sce->state = 0;
291 sce->timeout = USBD_NO_TIMEOUT;
292 DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
293 sc, endpt, dir, sce));
294 edesc = sce->edesc;
295 if (!edesc)
296 return (ENXIO);
297 switch (edesc->bmAttributes & UE_XFERTYPE) {
298 case UE_INTERRUPT:
299 isize = UGETW(edesc->wMaxPacketSize);
300 if (isize == 0) /* shouldn't happen */
301 return (EINVAL);
302 sce->ibuf = malloc(isize, M_USBDEV, M_WAITOK);
303 DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
304 endpt, isize));
305 #if defined(__NetBSD__) || defined(__OpenBSD__)
306 if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1)
307 return (ENOMEM);
308 #elif defined(__FreeBSD__)
309 clist_alloc_cblocks(&sce->q, UGEN_IBSIZE, 0);
310 #endif
311 r = usbd_open_pipe_intr(sce->iface,
312 edesc->bEndpointAddress,
313 USBD_SHORT_XFER_OK, &sce->pipeh, sce,
314 sce->ibuf, isize, ugenintr);
315 if (r != USBD_NORMAL_COMPLETION) {
316 free(sce->ibuf, M_USBDEV);
317 #if defined(__NetBSD__) || defined(__OpenBSD__)
318 clfree(&sce->q);
319 #elif defined(__FreeBSD__)
320 clist_free_cblocks(&sce->q);
321 #endif
322 return (EIO);
323 }
324 DPRINTFN(5, ("ugenopen: interrupt open done\n"));
325 break;
326 case UE_BULK:
327 r = usbd_open_pipe(sce->iface,
328 edesc->bEndpointAddress, 0,
329 &sce->pipeh);
330 if (r != USBD_NORMAL_COMPLETION)
331 return (EIO);
332 break;
333 case UE_CONTROL:
334 case UE_ISOCHRONOUS:
335 return (EINVAL);
336 }
337 }
338 sc->sc_is_open[endpt] = 1;
339 return (0);
340 }
341
342 int
343 ugenclose(dev, flag, mode, p)
344 dev_t dev;
345 int flag;
346 int mode;
347 struct proc *p;
348 {
349 USB_GET_SC(ugen, UGENUNIT(dev), sc);
350 int endpt = UGENENDPOINT(dev);
351 struct ugen_endpoint *sce;
352 int dir;
353
354 DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n",
355 flag, mode, UGENUNIT(dev), endpt));
356
357 #ifdef DIAGNOSTIC
358 if (!sc->sc_is_open[endpt]) {
359 printf("ugenclose: not open\n");
360 return (EINVAL);
361 }
362 #endif
363
364 if (endpt == USB_CONTROL_ENDPOINT) {
365 DPRINTFN(5, ("ugenclose: close control\n"));
366 sc->sc_is_open[endpt] = 0;
367 return (0);
368 }
369
370 for (dir = OUT; dir <= IN; dir++) {
371 if (!(flag & (dir == OUT ? FWRITE : FREAD)))
372 continue;
373 sce = &sc->sc_endpoints[endpt][dir];
374 if (!sce || !sce->pipeh)
375 continue;
376 DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n",
377 endpt, dir, sce));
378
379 usbd_abort_pipe(sce->pipeh);
380 usbd_close_pipe(sce->pipeh);
381 sce->pipeh = 0;
382
383 if (sce->ibuf) {
384 free(sce->ibuf, M_USBDEV);
385 sce->ibuf = 0;
386 clfree(&sce->q);
387 }
388 }
389 sc->sc_is_open[endpt] = 0;
390
391 return (0);
392 }
393
394 int
395 ugen_do_read(sc, endpt, uio, flag)
396 struct ugen_softc *sc;
397 int endpt;
398 struct uio *uio;
399 int flag;
400 {
401 struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN];
402 u_int32_t n, tn;
403 char buf[UGEN_BBSIZE];
404 usbd_request_handle reqh;
405 usbd_status r;
406 int s;
407 int error = 0;
408 u_char buffer[UGEN_CHUNK];
409
410 #ifdef __NetBSD__
411 DPRINTFN(5, ("ugenread: %d:%d\n", sc->sc_dev.dv_unit, endpt));
412 #endif
413 if (sc->sc_dying)
414 return (EIO);
415
416 #ifdef DIAGNOSTIC
417 if (!sce->edesc) {
418 printf("ugenread: no edesc\n");
419 return (EIO);
420 }
421 if (!sce->pipeh) {
422 printf("ugenread: no pipe\n");
423 return (EIO);
424 }
425 #endif
426
427 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
428 case UE_INTERRUPT:
429 /* Block until activity occured. */
430 s = splusb();
431 while (sce->q.c_cc == 0) {
432 if (flag & IO_NDELAY) {
433 splx(s);
434 return (EWOULDBLOCK);
435 }
436 sce->state |= UGEN_ASLP;
437 DPRINTFN(5, ("ugenread: sleep on %p\n", sc));
438 error = tsleep(sce, PZERO | PCATCH, "ugenri", 0);
439 DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
440 if (sc->sc_dying)
441 error = EIO;
442 if (error) {
443 sce->state &= ~UGEN_ASLP;
444 break;
445 }
446 }
447 splx(s);
448
449 /* Transfer as many chunks as possible. */
450 while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) {
451 n = min(sce->q.c_cc, uio->uio_resid);
452 if (n > sizeof(buffer))
453 n = sizeof(buffer);
454
455 /* Remove a small chunk from the input queue. */
456 q_to_b(&sce->q, buffer, n);
457 DPRINTFN(5, ("ugenread: got %d chars\n", n));
458
459 /* Copy the data to the user process. */
460 error = uiomove(buffer, n, uio);
461 if (error)
462 break;
463 }
464 break;
465 case UE_BULK:
466 reqh = usbd_alloc_request();
467 if (reqh == 0)
468 return (ENOMEM);
469 while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
470 DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n));
471 tn = n;
472 r = usbd_bulk_transfer(
473 reqh, sce->pipeh,
474 sce->state & UGEN_SHORT_OK ?
475 USBD_SHORT_XFER_OK : 0,
476 sce->timeout, buf, &tn, "ugenrb");
477 if (r != USBD_NORMAL_COMPLETION) {
478 if (r == USBD_INTERRUPTED)
479 error = EINTR;
480 else if (r == USBD_TIMEOUT)
481 error = ETIMEDOUT;
482 else
483 error = EIO;
484 break;
485 }
486 DPRINTFN(1, ("ugenread: got %d bytes\n", tn));
487 error = uiomove(buf, tn, uio);
488 if (error || tn < n)
489 break;
490 }
491 usbd_free_request(reqh);
492 break;
493 default:
494 return (ENXIO);
495 }
496 return (error);
497 }
498
499 int
500 ugenread(dev, uio, flag)
501 dev_t dev;
502 struct uio *uio;
503 int flag;
504 {
505 USB_GET_SC(ugen, UGENUNIT(dev), sc);
506 int endpt = UGENENDPOINT(dev);
507 int error;
508
509 sc->sc_refcnt++;
510 error = ugen_do_read(sc, endpt, uio, flag);
511 if (--sc->sc_refcnt < 0)
512 usb_detach_wakeup(USBDEV(sc->sc_dev));
513 return (error);
514 }
515
516 int
517 ugen_do_write(sc, endpt, uio, flag)
518 struct ugen_softc *sc;
519 int endpt;
520 struct uio *uio;
521 int flag;
522 {
523 struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT];
524 u_int32_t n;
525 int error = 0;
526 char buf[UGEN_BBSIZE];
527 usbd_request_handle reqh;
528 usbd_status r;
529
530 if (sc->sc_dying)
531 return (EIO);
532
533 #ifdef DIAGNOSTIC
534 if (!sce->edesc) {
535 printf("ugenwrite: no edesc\n");
536 return (EIO);
537 }
538 if (!sce->pipeh) {
539 printf("ugenwrite: no pipe\n");
540 return (EIO);
541 }
542 #endif
543
544 DPRINTF(("ugenwrite\n"));
545 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
546 case UE_BULK:
547 reqh = usbd_alloc_request();
548 if (reqh == 0)
549 return (EIO);
550 while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
551 error = uiomove(buf, n, uio);
552 if (error)
553 break;
554 DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
555 r = usbd_bulk_transfer(reqh, sce->pipeh, 0,
556 sce->timeout, buf, &n,"ugenwb");
557 if (r != USBD_NORMAL_COMPLETION) {
558 if (r == USBD_INTERRUPTED)
559 error = EINTR;
560 else
561 error = EIO;
562 break;
563 }
564 }
565 usbd_free_request(reqh);
566 break;
567 default:
568 return (ENXIO);
569 }
570 return (error);
571 }
572
573 int
574 ugenwrite(dev, uio, flag)
575 dev_t dev;
576 struct uio *uio;
577 int flag;
578 {
579 USB_GET_SC(ugen, UGENUNIT(dev), sc);
580 int endpt = UGENENDPOINT(dev);
581 int error;
582
583 sc->sc_refcnt++;
584 error = ugen_do_write(sc, endpt, uio, flag);
585 if (--sc->sc_refcnt < 0)
586 usb_detach_wakeup(USBDEV(sc->sc_dev));
587 return (error);
588 }
589
590 int
591 ugen_activate(self, act)
592 device_ptr_t self;
593 enum devact act;
594 {
595 struct ugen_softc *sc = (struct ugen_softc *)self;
596
597 switch (act) {
598 case DVACT_ACTIVATE:
599 return (EOPNOTSUPP);
600 break;
601
602 case DVACT_DEACTIVATE:
603 sc->sc_dying = 1;
604 break;
605 }
606 return (0);
607 }
608
609 int
610 ugen_detach(self, flags)
611 device_ptr_t self;
612 int flags;
613 {
614 struct ugen_softc *sc = (struct ugen_softc *)self;
615 struct ugen_endpoint *sce;
616 int maj, mn;
617 int i, dir;
618 int s;
619
620 DPRINTF(("ugen_detach: sc=%p flags=%d\n", sc, flags));
621
622 sc->sc_dying = 1;
623 /* Abort all pipes. Causes processes waiting for transfer to wake. */
624 for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
625 for (dir = OUT; dir <= IN; dir++) {
626 sce = &sc->sc_endpoints[i][dir];
627 if (sce && sce->pipeh)
628 usbd_abort_pipe(sce->pipeh);
629 }
630 }
631
632 s = splusb();
633 if (--sc->sc_refcnt >= 0) {
634 /* Wake everyone */
635 for (i = 0; i < USB_MAX_ENDPOINTS; i++)
636 wakeup(&sc->sc_endpoints[i][IN]);
637 /* Wait for processes to go away. */
638 usb_detach_wait(USBDEV(sc->sc_dev));
639 }
640 splx(s);
641
642 /* locate the major number */
643 for (maj = 0; maj < nchrdev; maj++)
644 if (cdevsw[maj].d_open == ugenopen)
645 break;
646
647 /* Nuke the vnodes for any open instances (calls close). */
648 mn = self->dv_unit * USB_MAX_ENDPOINTS;
649 vdevgone(maj, mn, mn + USB_MAX_ENDPOINTS - 1, VCHR);
650
651 return (0);
652 }
653
654 void
655 ugenintr(reqh, addr, status)
656 usbd_request_handle reqh;
657 usbd_private_handle addr;
658 usbd_status status;
659 {
660 struct ugen_endpoint *sce = addr;
661 /*struct ugen_softc *sc = sce->sc;*/
662 u_int32_t count;
663 u_char *ibuf;
664
665 if (status == USBD_CANCELLED)
666 return;
667
668 if (status != USBD_NORMAL_COMPLETION) {
669 DPRINTF(("ugenintr: status=%d\n", status));
670 usbd_clear_endpoint_stall_async(sce->pipeh);
671 return;
672 }
673
674 usbd_get_request_status(reqh, 0, 0, &count, 0);
675 ibuf = sce->ibuf;
676
677 DPRINTFN(5, ("ugenintr: reqh=%p status=%d count=%d\n",
678 reqh, status, count));
679 DPRINTFN(5, (" data = %02x %02x %02x\n",
680 ibuf[0], ibuf[1], ibuf[2]));
681
682 (void)b_to_q(ibuf, count, &sce->q);
683
684 if (sce->state & UGEN_ASLP) {
685 sce->state &= ~UGEN_ASLP;
686 DPRINTFN(5, ("ugen_intr: waking %p\n", sce));
687 wakeup(sce);
688 }
689 selwakeup(&sce->rsel);
690 }
691
692 usbd_status
693 ugen_set_interface(sc, ifaceidx, altno)
694 struct ugen_softc *sc;
695 int ifaceidx, altno;
696 {
697 usbd_interface_handle iface;
698 usb_endpoint_descriptor_t *ed;
699 usbd_status r;
700 struct ugen_endpoint *sce;
701 u_int8_t niface, nendpt, endptno, endpt;
702 int dir;
703
704 DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno));
705
706 r = usbd_interface_count(sc->sc_udev, &niface);
707 if (r != USBD_NORMAL_COMPLETION)
708 return (r);
709 if (ifaceidx < 0 || ifaceidx >= niface)
710 return (USBD_INVAL);
711
712 r = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
713 if (r != USBD_NORMAL_COMPLETION)
714 return (r);
715 r = usbd_endpoint_count(iface, &nendpt);
716 if (r != USBD_NORMAL_COMPLETION)
717 return (r);
718 for (endptno = 0; endptno < nendpt; endptno++) {
719 ed = usbd_interface2endpoint_descriptor(iface,endptno);
720 endpt = ed->bEndpointAddress;
721 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
722 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
723 sce->sc = 0;
724 sce->edesc = 0;
725 sce->iface = 0;
726 }
727
728 /* change setting */
729 r = usbd_set_interface(iface, altno);
730 if (r != USBD_NORMAL_COMPLETION)
731 return (r);
732
733 r = usbd_endpoint_count(iface, &nendpt);
734 if (r != USBD_NORMAL_COMPLETION)
735 return (r);
736 for (endptno = 0; endptno < nendpt; endptno++) {
737 ed = usbd_interface2endpoint_descriptor(iface,endptno);
738 endpt = ed->bEndpointAddress;
739 dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
740 sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
741 sce->sc = sc;
742 sce->edesc = ed;
743 sce->iface = iface;
744 }
745 return (0);
746 }
747
748 /* Retrieve a complete descriptor for a certain device and index. */
749 usb_config_descriptor_t *
750 ugen_get_cdesc(sc, index, lenp)
751 struct ugen_softc *sc;
752 int index;
753 int *lenp;
754 {
755 usb_config_descriptor_t *cdesc, *tdesc, cdescr;
756 int len;
757 usbd_status r;
758
759 if (index == USB_CURRENT_CONFIG_INDEX) {
760 tdesc = usbd_get_config_descriptor(sc->sc_udev);
761 len = UGETW(tdesc->wTotalLength);
762 if (lenp)
763 *lenp = len;
764 cdesc = malloc(len, M_TEMP, M_WAITOK);
765 memcpy(cdesc, tdesc, len);
766 DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len));
767 } else {
768 r = usbd_get_config_desc(sc->sc_udev, index, &cdescr);
769 if (r != USBD_NORMAL_COMPLETION)
770 return (0);
771 len = UGETW(cdescr.wTotalLength);
772 DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len));
773 if (lenp)
774 *lenp = len;
775 cdesc = malloc(len, M_TEMP, M_WAITOK);
776 r = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len);
777 if (r != USBD_NORMAL_COMPLETION) {
778 free(cdesc, M_TEMP);
779 return (0);
780 }
781 }
782 return (cdesc);
783 }
784
785 int
786 ugen_get_alt_index(sc, ifaceidx)
787 struct ugen_softc *sc;
788 int ifaceidx;
789 {
790 usbd_interface_handle iface;
791 usbd_status r;
792
793 r = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
794 if (r != USBD_NORMAL_COMPLETION)
795 return (-1);
796 return (usbd_get_interface_altindex(iface));
797 }
798
799 int
800 ugen_do_ioctl(sc, endpt, cmd, addr, flag, p)
801 struct ugen_softc *sc;
802 int endpt;
803 u_long cmd;
804 caddr_t addr;
805 int flag;
806 struct proc *p;
807 {
808 struct ugen_endpoint *sce;
809 usbd_status r;
810 usbd_interface_handle iface;
811 struct usb_config_desc *cd;
812 usb_config_descriptor_t *cdesc;
813 struct usb_interface_desc *id;
814 usb_interface_descriptor_t *idesc;
815 struct usb_endpoint_desc *ed;
816 usb_endpoint_descriptor_t *edesc;
817 struct usb_alt_interface *ai;
818 struct usb_string_desc *si;
819 u_int8_t conf, alt;
820
821 DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd));
822 if (sc->sc_dying)
823 return (EIO);
824
825 switch (cmd) {
826 case FIONBIO:
827 /* All handled in the upper FS layer. */
828 return (0);
829 case USB_SET_SHORT_XFER:
830 /* This flag only affects read */
831 if (endpt == USB_CONTROL_ENDPOINT)
832 return (EINVAL);
833 sce = &sc->sc_endpoints[endpt][IN];
834 #ifdef DIAGNOSTIC
835 if (!sce->pipeh) {
836 printf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n");
837 return (EIO);
838 }
839 #endif
840 if (*(int *)addr)
841 sce->state |= UGEN_SHORT_OK;
842 else
843 sce->state &= ~UGEN_SHORT_OK;
844 return (0);
845 case USB_SET_TIMEOUT:
846 sce = &sc->sc_endpoints[endpt][IN];
847 #ifdef DIAGNOSTIC
848 if (!sce->pipeh) {
849 printf("ugenioctl: USB_SET_TIMEOUT, no pipe\n");
850 return (EIO);
851 }
852 #endif
853 sce->timeout = *(int *)addr;
854 return (0);
855 default:
856 break;
857 }
858
859 if (endpt != USB_CONTROL_ENDPOINT)
860 return (EINVAL);
861
862 switch (cmd) {
863 #ifdef USB_DEBUG
864 case USB_SETDEBUG:
865 ugendebug = *(int *)addr;
866 break;
867 #endif
868 case USB_GET_CONFIG:
869 r = usbd_get_config(sc->sc_udev, &conf);
870 if (r != USBD_NORMAL_COMPLETION)
871 return (EIO);
872 *(int *)addr = conf;
873 break;
874 case USB_SET_CONFIG:
875 if (!(flag & FWRITE))
876 return (EPERM);
877 r = ugen_set_config(sc, *(int *)addr);
878 if (r != USBD_NORMAL_COMPLETION)
879 return (EIO);
880 break;
881 case USB_GET_ALTINTERFACE:
882 ai = (struct usb_alt_interface *)addr;
883 r = usbd_device2interface_handle(sc->sc_udev,
884 ai->interface_index, &iface);
885 if (r != USBD_NORMAL_COMPLETION)
886 return (EINVAL);
887 idesc = usbd_get_interface_descriptor(iface);
888 if (!idesc)
889 return (EIO);
890 ai->alt_no = idesc->bAlternateSetting;
891 break;
892 case USB_SET_ALTINTERFACE:
893 if (!(flag & FWRITE))
894 return (EPERM);
895 ai = (struct usb_alt_interface *)addr;
896 r = usbd_device2interface_handle(sc->sc_udev,
897 ai->interface_index, &iface);
898 if (r != USBD_NORMAL_COMPLETION)
899 return (EINVAL);
900 r = ugen_set_interface(sc, ai->interface_index, ai->alt_no);
901 if (r != USBD_NORMAL_COMPLETION)
902 return (EINVAL);
903 break;
904 case USB_GET_NO_ALT:
905 ai = (struct usb_alt_interface *)addr;
906 cdesc = ugen_get_cdesc(sc, ai->config_index, 0);
907 if (!cdesc)
908 return (EINVAL);
909 idesc = usbd_find_idesc(cdesc, ai->interface_index, 0);
910 if (!idesc) {
911 free(cdesc, M_TEMP);
912 return (EINVAL);
913 }
914 ai->alt_no = usbd_get_no_alts(cdesc, idesc->bInterfaceNumber);
915 free(cdesc, M_TEMP);
916 break;
917 case USB_GET_DEVICE_DESC:
918 *(usb_device_descriptor_t *)addr =
919 *usbd_get_device_descriptor(sc->sc_udev);
920 break;
921 case USB_GET_CONFIG_DESC:
922 cd = (struct usb_config_desc *)addr;
923 cdesc = ugen_get_cdesc(sc, cd->config_index, 0);
924 if (!cdesc)
925 return (EINVAL);
926 cd->desc = *cdesc;
927 free(cdesc, M_TEMP);
928 break;
929 case USB_GET_INTERFACE_DESC:
930 id = (struct usb_interface_desc *)addr;
931 cdesc = ugen_get_cdesc(sc, id->config_index, 0);
932 if (!cdesc)
933 return (EINVAL);
934 if (id->config_index == USB_CURRENT_CONFIG_INDEX &&
935 id->alt_index == USB_CURRENT_ALT_INDEX)
936 alt = ugen_get_alt_index(sc, id->interface_index);
937 else
938 alt = id->alt_index;
939 idesc = usbd_find_idesc(cdesc, id->interface_index, alt);
940 if (!idesc) {
941 free(cdesc, M_TEMP);
942 return (EINVAL);
943 }
944 id->desc = *idesc;
945 free(cdesc, M_TEMP);
946 break;
947 case USB_GET_ENDPOINT_DESC:
948 ed = (struct usb_endpoint_desc *)addr;
949 cdesc = ugen_get_cdesc(sc, ed->config_index, 0);
950 if (!cdesc)
951 return (EINVAL);
952 if (ed->config_index == USB_CURRENT_CONFIG_INDEX &&
953 ed->alt_index == USB_CURRENT_ALT_INDEX)
954 alt = ugen_get_alt_index(sc, ed->interface_index);
955 else
956 alt = ed->alt_index;
957 edesc = usbd_find_edesc(cdesc, ed->interface_index,
958 alt, ed->endpoint_index);
959 if (!edesc) {
960 free(cdesc, M_TEMP);
961 return (EINVAL);
962 }
963 ed->desc = *edesc;
964 free(cdesc, M_TEMP);
965 break;
966 case USB_GET_FULL_DESC:
967 {
968 int len;
969 struct iovec iov;
970 struct uio uio;
971 struct usb_full_desc *fd = (struct usb_full_desc *)addr;
972 int error;
973
974 cdesc = ugen_get_cdesc(sc, fd->config_index, &len);
975 if (len > fd->size)
976 len = fd->size;
977 iov.iov_base = (caddr_t)fd->data;
978 iov.iov_len = len;
979 uio.uio_iov = &iov;
980 uio.uio_iovcnt = 1;
981 uio.uio_resid = len;
982 uio.uio_offset = 0;
983 uio.uio_segflg = UIO_USERSPACE;
984 uio.uio_rw = UIO_READ;
985 uio.uio_procp = p;
986 error = uiomove((caddr_t)cdesc, len, &uio);
987 free(cdesc, M_TEMP);
988 return (error);
989 }
990 case USB_GET_STRING_DESC:
991 si = (struct usb_string_desc *)addr;
992 r = usbd_get_string_desc(sc->sc_udev, si->string_index,
993 si->language_id, &si->desc);
994 if (r != USBD_NORMAL_COMPLETION)
995 return (EINVAL);
996 break;
997 case USB_DO_REQUEST:
998 {
999 struct usb_ctl_request *ur = (void *)addr;
1000 int len = UGETW(ur->request.wLength);
1001 struct iovec iov;
1002 struct uio uio;
1003 void *ptr = 0;
1004 usbd_status r;
1005 int error = 0;
1006
1007 if (!(flag & FWRITE))
1008 return (EPERM);
1009 /* Avoid requests that would damage the bus integrity. */
1010 if ((ur->request.bmRequestType == UT_WRITE_DEVICE &&
1011 ur->request.bRequest == UR_SET_ADDRESS) ||
1012 (ur->request.bmRequestType == UT_WRITE_DEVICE &&
1013 ur->request.bRequest == UR_SET_CONFIG) ||
1014 (ur->request.bmRequestType == UT_WRITE_INTERFACE &&
1015 ur->request.bRequest == UR_SET_INTERFACE))
1016 return (EINVAL);
1017
1018 if (len < 0 || len > 32767)
1019 return (EINVAL);
1020 if (len != 0) {
1021 iov.iov_base = (caddr_t)ur->data;
1022 iov.iov_len = len;
1023 uio.uio_iov = &iov;
1024 uio.uio_iovcnt = 1;
1025 uio.uio_resid = len;
1026 uio.uio_offset = 0;
1027 uio.uio_segflg = UIO_USERSPACE;
1028 uio.uio_rw =
1029 ur->request.bmRequestType & UT_READ ?
1030 UIO_READ : UIO_WRITE;
1031 uio.uio_procp = p;
1032 ptr = malloc(len, M_TEMP, M_WAITOK);
1033 if (uio.uio_rw == UIO_WRITE) {
1034 error = uiomove(ptr, len, &uio);
1035 if (error)
1036 goto ret;
1037 }
1038 }
1039 r = usbd_do_request_flags(sc->sc_udev, &ur->request,
1040 ptr, ur->flags, &ur->actlen);
1041 if (r != USBD_NORMAL_COMPLETION) {
1042 error = EIO;
1043 goto ret;
1044 }
1045 if (len != 0) {
1046 if (uio.uio_rw == UIO_READ) {
1047 error = uiomove(ptr, len, &uio);
1048 if (error)
1049 goto ret;
1050 }
1051 }
1052 ret:
1053 if (ptr)
1054 free(ptr, M_TEMP);
1055 return (error);
1056 }
1057 case USB_GET_DEVICEINFO:
1058 usbd_fill_deviceinfo(sc->sc_udev,
1059 (struct usb_device_info *)addr);
1060 break;
1061 default:
1062 return (EINVAL);
1063 }
1064 return (0);
1065 }
1066
1067 int
1068 ugenioctl(dev, cmd, addr, flag, p)
1069 dev_t dev;
1070 u_long cmd;
1071 caddr_t addr;
1072 int flag;
1073 struct proc *p;
1074 {
1075 USB_GET_SC(ugen, UGENUNIT(dev), sc);
1076 int endpt = UGENENDPOINT(dev);
1077 int error;
1078
1079 sc->sc_refcnt++;
1080 error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p);
1081 if (--sc->sc_refcnt < 0)
1082 usb_detach_wakeup(USBDEV(sc->sc_dev));
1083 return (error);
1084 }
1085
1086 int
1087 ugenpoll(dev, events, p)
1088 dev_t dev;
1089 int events;
1090 struct proc *p;
1091 {
1092 USB_GET_SC(ugen, UGENUNIT(dev), sc);
1093 struct ugen_endpoint *sce;
1094 int revents = 0;
1095 int s;
1096
1097 if (sc->sc_dying)
1098 return (EIO);
1099
1100 /* XXX always IN */
1101 sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN];
1102 #ifdef DIAGNOSTIC
1103 if (!sce->edesc) {
1104 printf("ugenwrite: no edesc\n");
1105 return (EIO);
1106 }
1107 if (!sce->pipeh) {
1108 printf("ugenpoll: no pipe\n");
1109 return (EIO);
1110 }
1111 #endif
1112 s = splusb();
1113 switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
1114 case UE_INTERRUPT:
1115 if (events & (POLLIN | POLLRDNORM)) {
1116 if (sce->q.c_cc > 0)
1117 revents |= events & (POLLIN | POLLRDNORM);
1118 else
1119 selrecord(p, &sce->rsel);
1120 }
1121 break;
1122 case UE_BULK:
1123 /*
1124 * We have no easy way of determining if a read will
1125 * yield any data or a write will happen.
1126 * Pretend they will.
1127 */
1128 revents |= events &
1129 (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM);
1130 break;
1131 default:
1132 break;
1133 }
1134 splx(s);
1135 return (revents);
1136 }
1137
1138 #if defined(__FreeBSD__)
1139 DEV_DRIVER_MODULE(ugen, uhub, ugen_driver, ugen_devclass, ugen_cdevsw, usbd_driver_load, 0);
1140 #endif
1141