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