Annotation of sys/dev/usb/ugen.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ugen.c,v 1.50 2007/06/29 13:31:42 henning Exp $ */
2: /* $NetBSD: ugen.c,v 1.63 2002/11/26 18:49:48 christos Exp $ */
3: /* $FreeBSD: src/sys/dev/usb/ugen.c,v 1.26 1999/11/17 22:33:41 n_hibma Exp $ */
4:
5: /*
6: * Copyright (c) 1998 The NetBSD Foundation, Inc.
7: * All rights reserved.
8: *
9: * This code is derived from software contributed to The NetBSD Foundation
10: * by Lennart Augustsson (lennart@augustsson.net) at
11: * Carlstedt Research & Technology.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
21: * 3. All advertising materials mentioning features or use of this software
22: * must display the following acknowledgement:
23: * This product includes software developed by the NetBSD
24: * Foundation, Inc. and its contributors.
25: * 4. Neither the name of The NetBSD Foundation nor the names of its
26: * contributors may be used to endorse or promote products derived
27: * from this software without specific prior written permission.
28: *
29: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
30: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39: * POSSIBILITY OF SUCH DAMAGE.
40: */
41:
42:
43: #include <sys/param.h>
44: #include <sys/systm.h>
45: #include <sys/kernel.h>
46: #include <sys/malloc.h>
47: #include <sys/device.h>
48: #include <sys/ioctl.h>
49: #include <sys/conf.h>
50: #include <sys/tty.h>
51: #include <sys/file.h>
52: #include <sys/selinfo.h>
53: #include <sys/proc.h>
54: #include <sys/vnode.h>
55: #include <sys/poll.h>
56:
57: #include <dev/usb/usb.h>
58: #include <dev/usb/usbdi.h>
59: #include <dev/usb/usbdi_util.h>
60: #include <dev/usb/usbdevs.h>
61:
62: #ifdef UGEN_DEBUG
63: #define DPRINTF(x) do { if (ugendebug) printf x; } while (0)
64: #define DPRINTFN(n,x) do { if (ugendebug>(n)) printf x; } while (0)
65: int ugendebug = 0;
66: #else
67: #define DPRINTF(x)
68: #define DPRINTFN(n,x)
69: #endif
70:
71: #define UGEN_CHUNK 128 /* chunk size for read */
72: #define UGEN_IBSIZE 1020 /* buffer size */
73: #define UGEN_BBSIZE 1024
74:
75: #define UGEN_NISOFRAMES 500 /* 0.5 seconds worth */
76: #define UGEN_NISOREQS 6 /* number of outstanding xfer requests */
77: #define UGEN_NISORFRMS 4 /* number of frames (miliseconds) per req */
78:
79: struct ugen_endpoint {
80: struct ugen_softc *sc;
81: usb_endpoint_descriptor_t *edesc;
82: usbd_interface_handle iface;
83: int state;
84: #define UGEN_ASLP 0x02 /* waiting for data */
85: #define UGEN_SHORT_OK 0x04 /* short xfers are OK */
86: usbd_pipe_handle pipeh;
87: struct clist q;
88: struct selinfo rsel;
89: u_char *ibuf; /* start of buffer (circular for isoc) */
90: u_char *fill; /* location for input (isoc) */
91: u_char *limit; /* end of circular buffer (isoc) */
92: u_char *cur; /* current read location (isoc) */
93: u_int32_t timeout;
94: struct isoreq {
95: struct ugen_endpoint *sce;
96: usbd_xfer_handle xfer;
97: void *dmabuf;
98: u_int16_t sizes[UGEN_NISORFRMS];
99: } isoreqs[UGEN_NISOREQS];
100: };
101:
102: struct ugen_softc {
103: struct device sc_dev; /* base device */
104: usbd_device_handle sc_udev;
105:
106: char sc_is_open[USB_MAX_ENDPOINTS];
107: struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2];
108: #define OUT 0
109: #define IN 1
110:
111: int sc_refcnt;
112: u_char sc_dying;
113: };
114:
115: void ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr,
116: usbd_status status);
117: void ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr,
118: usbd_status status);
119: int ugen_do_read(struct ugen_softc *, int, struct uio *, int);
120: int ugen_do_write(struct ugen_softc *, int, struct uio *, int);
121: int ugen_do_ioctl(struct ugen_softc *, int, u_long,
122: caddr_t, int, struct proc *);
123: int ugen_set_config(struct ugen_softc *sc, int configno);
124: usb_config_descriptor_t *ugen_get_cdesc(struct ugen_softc *sc,
125: int index, int *lenp);
126: usbd_status ugen_set_interface(struct ugen_softc *, int, int);
127: int ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx);
128:
129: #define UGENUNIT(n) ((minor(n) >> 4) & 0xf)
130: #define UGENENDPOINT(n) (minor(n) & 0xf)
131: #define UGENDEV(u, e) (makedev(0, ((u) << 4) | (e)))
132:
133: int ugen_match(struct device *, void *, void *);
134: void ugen_attach(struct device *, struct device *, void *);
135: int ugen_detach(struct device *, int);
136: int ugen_activate(struct device *, enum devact);
137:
138: struct cfdriver ugen_cd = {
139: NULL, "ugen", DV_DULL
140: };
141:
142: const struct cfattach ugen_ca = {
143: sizeof(struct ugen_softc),
144: ugen_match,
145: ugen_attach,
146: ugen_detach,
147: ugen_activate,
148: };
149:
150: int
151: ugen_match(struct device *parent, void *match, void *aux)
152: {
153: struct usb_attach_arg *uaa = aux;
154:
155: #if 0
156: if (uaa->matchlvl)
157: return (uaa->matchlvl);
158: #endif
159: if (uaa->usegeneric) {
160: #ifdef __macppc__
161: /*
162: * Some Apple laptops have USB phantom devices which match
163: * the ADB devices. We want to ignore them to avoid
164: * confusing users, as the real hardware underneath is adb
165: * and has already attached.
166: */
167: if (uaa->vendor == USB_VENDOR_APPLE &&
168: uaa->product == USB_PRODUCT_APPLE_ADB)
169: return (UMATCH_NONE);
170: #endif
171: return (UMATCH_GENERIC);
172: } else
173: return (UMATCH_NONE);
174: }
175:
176: void
177: ugen_attach(struct device *parent, struct device *self, void *aux)
178: {
179: struct ugen_softc *sc = (struct ugen_softc *)self;
180: struct usb_attach_arg *uaa = aux;
181: usbd_device_handle udev;
182: char *devinfop;
183: usbd_status err;
184: int conf;
185:
186: devinfop = usbd_devinfo_alloc(uaa->device, 0);
187: printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfop);
188: usbd_devinfo_free(devinfop);
189:
190: sc->sc_udev = udev = uaa->device;
191:
192: /* First set configuration index 0, the default one for ugen. */
193: err = usbd_set_config_index(udev, 0, 0);
194: if (err) {
195: printf("%s: setting configuration index 0 failed\n",
196: sc->sc_dev.dv_xname);
197: sc->sc_dying = 1;
198: return;
199: }
200: conf = usbd_get_config_descriptor(udev)->bConfigurationValue;
201:
202: /* Set up all the local state for this configuration. */
203: err = ugen_set_config(sc, conf);
204: if (err) {
205: printf("%s: setting configuration %d failed\n",
206: sc->sc_dev.dv_xname, conf);
207: sc->sc_dying = 1;
208: return;
209: }
210:
211: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
212: &sc->sc_dev);
213: }
214:
215: int
216: ugen_set_config(struct ugen_softc *sc, int configno)
217: {
218: usbd_device_handle dev = sc->sc_udev;
219: usbd_interface_handle iface;
220: usb_endpoint_descriptor_t *ed;
221: struct ugen_endpoint *sce;
222: u_int8_t niface, nendpt;
223: int ifaceno, endptno, endpt;
224: usbd_status err;
225: int dir;
226:
227: DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
228: sc->sc_dev.dv_xname, configno, sc));
229:
230: /*
231: * We start at 1, not 0, because we don't care whether the
232: * control endpoint is open or not. It is always present.
233: */
234: for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++)
235: if (sc->sc_is_open[endptno]) {
236: DPRINTFN(1,
237: ("ugen_set_config: %s - endpoint %d is open\n",
238: sc->sc_dev.dv_xname, endptno));
239: return (USBD_IN_USE);
240: }
241:
242: /* Avoid setting the current value. */
243: if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) {
244: err = usbd_set_config_no(dev, configno, 1);
245: if (err)
246: return (err);
247: }
248:
249: err = usbd_interface_count(dev, &niface);
250: if (err)
251: return (err);
252: memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
253: for (ifaceno = 0; ifaceno < niface; ifaceno++) {
254: DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno));
255: err = usbd_device2interface_handle(dev, ifaceno, &iface);
256: if (err)
257: return (err);
258: err = usbd_endpoint_count(iface, &nendpt);
259: if (err)
260: return (err);
261: for (endptno = 0; endptno < nendpt; endptno++) {
262: ed = usbd_interface2endpoint_descriptor(iface,endptno);
263: endpt = ed->bEndpointAddress;
264: dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
265: sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
266: DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x"
267: "(%d,%d), sce=%p\n",
268: endptno, endpt, UE_GET_ADDR(endpt),
269: UE_GET_DIR(endpt), sce));
270: sce->sc = sc;
271: sce->edesc = ed;
272: sce->iface = iface;
273: }
274: }
275: return (USBD_NORMAL_COMPLETION);
276: }
277:
278: int
279: ugenopen(dev_t dev, int flag, int mode, struct proc *p)
280: {
281: struct ugen_softc *sc;
282: int unit = UGENUNIT(dev);
283: int endpt = UGENENDPOINT(dev);
284: usb_endpoint_descriptor_t *edesc;
285: struct ugen_endpoint *sce;
286: int dir, isize;
287: usbd_status err;
288: usbd_xfer_handle xfer;
289: void *buf;
290: int i, j;
291:
292: if (unit >= ugen_cd.cd_ndevs)
293: return (ENXIO);
294: sc = ugen_cd.cd_devs[unit];
295: if (sc == NULL)
296: return (ENXIO);
297:
298: DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
299: flag, mode, unit, endpt));
300:
301: if (sc == NULL || sc->sc_dying)
302: return (ENXIO);
303:
304: if (sc->sc_is_open[endpt])
305: return (EBUSY);
306:
307: if (endpt == USB_CONTROL_ENDPOINT) {
308: sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1;
309: return (0);
310: }
311:
312: /* Make sure there are pipes for all directions. */
313: for (dir = OUT; dir <= IN; dir++) {
314: if (flag & (dir == OUT ? FWRITE : FREAD)) {
315: sce = &sc->sc_endpoints[endpt][dir];
316: if (sce == 0 || sce->edesc == 0)
317: return (ENXIO);
318: }
319: }
320:
321: /* Actually open the pipes. */
322: /* XXX Should back out properly if it fails. */
323: for (dir = OUT; dir <= IN; dir++) {
324: if (!(flag & (dir == OUT ? FWRITE : FREAD)))
325: continue;
326: sce = &sc->sc_endpoints[endpt][dir];
327: sce->state = 0;
328: sce->timeout = USBD_NO_TIMEOUT;
329: DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
330: sc, endpt, dir, sce));
331: edesc = sce->edesc;
332: switch (edesc->bmAttributes & UE_XFERTYPE) {
333: case UE_INTERRUPT:
334: if (dir == OUT) {
335: err = usbd_open_pipe(sce->iface,
336: edesc->bEndpointAddress, 0, &sce->pipeh);
337: if (err)
338: return (EIO);
339: break;
340: }
341: isize = UGETW(edesc->wMaxPacketSize);
342: if (isize == 0) /* shouldn't happen */
343: return (EINVAL);
344: sce->ibuf = malloc(isize, M_USBDEV, M_WAITOK);
345: DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
346: endpt, isize));
347: if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1)
348: return (ENOMEM);
349: err = usbd_open_pipe_intr(sce->iface,
350: edesc->bEndpointAddress,
351: USBD_SHORT_XFER_OK, &sce->pipeh, sce,
352: sce->ibuf, isize, ugenintr,
353: USBD_DEFAULT_INTERVAL);
354: if (err) {
355: free(sce->ibuf, M_USBDEV);
356: clfree(&sce->q);
357: return (EIO);
358: }
359: DPRINTFN(5, ("ugenopen: interrupt open done\n"));
360: break;
361: case UE_BULK:
362: err = usbd_open_pipe(sce->iface,
363: edesc->bEndpointAddress, 0, &sce->pipeh);
364: if (err)
365: return (EIO);
366: break;
367: case UE_ISOCHRONOUS:
368: if (dir == OUT)
369: return (EINVAL);
370: isize = UGETW(edesc->wMaxPacketSize);
371: if (isize == 0) /* shouldn't happen */
372: return (EINVAL);
373: sce->ibuf = malloc(isize * UGEN_NISOFRAMES,
374: M_USBDEV, M_WAITOK);
375: sce->cur = sce->fill = sce->ibuf;
376: sce->limit = sce->ibuf + isize * UGEN_NISOFRAMES;
377: DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n",
378: endpt, isize));
379: err = usbd_open_pipe(sce->iface,
380: edesc->bEndpointAddress, 0, &sce->pipeh);
381: if (err) {
382: free(sce->ibuf, M_USBDEV);
383: return (EIO);
384: }
385: for(i = 0; i < UGEN_NISOREQS; ++i) {
386: sce->isoreqs[i].sce = sce;
387: xfer = usbd_alloc_xfer(sc->sc_udev);
388: if (xfer == 0)
389: goto bad;
390: sce->isoreqs[i].xfer = xfer;
391: buf = usbd_alloc_buffer
392: (xfer, isize * UGEN_NISORFRMS);
393: if (buf == 0) {
394: i++;
395: goto bad;
396: }
397: sce->isoreqs[i].dmabuf = buf;
398: for(j = 0; j < UGEN_NISORFRMS; ++j)
399: sce->isoreqs[i].sizes[j] = isize;
400: usbd_setup_isoc_xfer
401: (xfer, sce->pipeh, &sce->isoreqs[i],
402: sce->isoreqs[i].sizes,
403: UGEN_NISORFRMS, USBD_NO_COPY,
404: ugen_isoc_rintr);
405: (void)usbd_transfer(xfer);
406: }
407: DPRINTFN(5, ("ugenopen: isoc open done\n"));
408: break;
409: bad:
410: while (--i >= 0) /* implicit buffer free */
411: usbd_free_xfer(sce->isoreqs[i].xfer);
412: return (ENOMEM);
413: case UE_CONTROL:
414: sce->timeout = USBD_DEFAULT_TIMEOUT;
415: return (EINVAL);
416: }
417: }
418: sc->sc_is_open[endpt] = 1;
419: return (0);
420: }
421:
422: int
423: ugenclose(dev_t dev, int flag, int mode, struct proc *p)
424: {
425: int endpt = UGENENDPOINT(dev);
426: struct ugen_softc *sc;
427: struct ugen_endpoint *sce;
428: int dir;
429: int i;
430:
431: sc = ugen_cd.cd_devs[UGENUNIT(dev)];
432:
433: DPRINTFN(5, ("ugenclose: flag=%d, mode=%d, unit=%d, endpt=%d\n",
434: flag, mode, UGENUNIT(dev), endpt));
435:
436: #ifdef DIAGNOSTIC
437: if (!sc->sc_is_open[endpt]) {
438: printf("ugenclose: not open\n");
439: return (EINVAL);
440: }
441: #endif
442:
443: if (endpt == USB_CONTROL_ENDPOINT) {
444: DPRINTFN(5, ("ugenclose: close control\n"));
445: sc->sc_is_open[endpt] = 0;
446: return (0);
447: }
448:
449: for (dir = OUT; dir <= IN; dir++) {
450: if (!(flag & (dir == OUT ? FWRITE : FREAD)))
451: continue;
452: sce = &sc->sc_endpoints[endpt][dir];
453: if (sce == NULL || sce->pipeh == NULL)
454: continue;
455: DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n",
456: endpt, dir, sce));
457:
458: usbd_abort_pipe(sce->pipeh);
459: usbd_close_pipe(sce->pipeh);
460: sce->pipeh = NULL;
461:
462: switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
463: case UE_INTERRUPT:
464: ndflush(&sce->q, sce->q.c_cc);
465: clfree(&sce->q);
466: break;
467: case UE_ISOCHRONOUS:
468: for (i = 0; i < UGEN_NISOREQS; ++i)
469: usbd_free_xfer(sce->isoreqs[i].xfer);
470:
471: default:
472: break;
473: }
474:
475: if (sce->ibuf != NULL) {
476: free(sce->ibuf, M_USBDEV);
477: sce->ibuf = NULL;
478: clfree(&sce->q);
479: }
480: }
481: sc->sc_is_open[endpt] = 0;
482:
483: return (0);
484: }
485:
486: int
487: ugen_do_read(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
488: {
489: struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN];
490: u_int32_t n, tn;
491: char buf[UGEN_BBSIZE];
492: usbd_xfer_handle xfer;
493: usbd_status err;
494: int s;
495: int error = 0;
496: u_char buffer[UGEN_CHUNK];
497:
498: DPRINTFN(5, ("%s: ugenread: %d\n", sc->sc_dev.dv_xname, endpt));
499:
500: if (sc->sc_dying)
501: return (EIO);
502:
503: if (endpt == USB_CONTROL_ENDPOINT)
504: return (ENODEV);
505:
506: #ifdef DIAGNOSTIC
507: if (sce->edesc == NULL) {
508: printf("ugenread: no edesc\n");
509: return (EIO);
510: }
511: if (sce->pipeh == NULL) {
512: printf("ugenread: no pipe\n");
513: return (EIO);
514: }
515: #endif
516:
517: switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
518: case UE_INTERRUPT:
519: /* Block until activity occurred. */
520: s = splusb();
521: while (sce->q.c_cc == 0) {
522: if (flag & IO_NDELAY) {
523: splx(s);
524: return (EWOULDBLOCK);
525: }
526: sce->state |= UGEN_ASLP;
527: DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
528: error = tsleep(sce, PZERO | PCATCH, "ugenri",
529: (sce->timeout * hz) / 1000);
530: DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
531: if (sc->sc_dying)
532: error = EIO;
533: if (error == EWOULDBLOCK) { /* timeout, return 0 */
534: error = 0;
535: break;
536: }
537: if (error) {
538: sce->state &= ~UGEN_ASLP;
539: break;
540: }
541: }
542: splx(s);
543:
544: /* Transfer as many chunks as possible. */
545: while (sce->q.c_cc > 0 && uio->uio_resid > 0 && !error) {
546: n = min(sce->q.c_cc, uio->uio_resid);
547: if (n > sizeof(buffer))
548: n = sizeof(buffer);
549:
550: /* Remove a small chunk from the input queue. */
551: q_to_b(&sce->q, buffer, n);
552: DPRINTFN(5, ("ugenread: got %d chars\n", n));
553:
554: /* Copy the data to the user process. */
555: error = uiomove(buffer, n, uio);
556: if (error)
557: break;
558: }
559: break;
560: case UE_BULK:
561: xfer = usbd_alloc_xfer(sc->sc_udev);
562: if (xfer == 0)
563: return (ENOMEM);
564: while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
565: DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n));
566: tn = n;
567: err = usbd_bulk_transfer(
568: xfer, sce->pipeh,
569: sce->state & UGEN_SHORT_OK ?
570: USBD_SHORT_XFER_OK : 0,
571: sce->timeout, buf, &tn, "ugenrb");
572: if (err) {
573: if (err == USBD_INTERRUPTED)
574: error = EINTR;
575: else if (err == USBD_TIMEOUT)
576: error = ETIMEDOUT;
577: else
578: error = EIO;
579: break;
580: }
581: DPRINTFN(1, ("ugenread: got %d bytes\n", tn));
582: error = uiomove(buf, tn, uio);
583: if (error || tn < n)
584: break;
585: }
586: usbd_free_xfer(xfer);
587: break;
588: case UE_ISOCHRONOUS:
589: s = splusb();
590: while (sce->cur == sce->fill) {
591: if (flag & IO_NDELAY) {
592: splx(s);
593: return (EWOULDBLOCK);
594: }
595: sce->state |= UGEN_ASLP;
596: DPRINTFN(5, ("ugenread: sleep on %p\n", sce));
597: error = tsleep(sce, PZERO | PCATCH, "ugenri", 0);
598: DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
599: if (sc->sc_dying)
600: error = EIO;
601: if (error) {
602: sce->state &= ~UGEN_ASLP;
603: break;
604: }
605: }
606:
607: while (sce->cur != sce->fill && uio->uio_resid > 0 && !error) {
608: if(sce->fill > sce->cur)
609: n = min(sce->fill - sce->cur, uio->uio_resid);
610: else
611: n = min(sce->limit - sce->cur, uio->uio_resid);
612:
613: DPRINTFN(5, ("ugenread: isoc got %d chars\n", n));
614:
615: /* Copy the data to the user process. */
616: error = uiomove(sce->cur, n, uio);
617: if (error)
618: break;
619: sce->cur += n;
620: if(sce->cur >= sce->limit)
621: sce->cur = sce->ibuf;
622: }
623: splx(s);
624: break;
625:
626:
627: default:
628: return (ENXIO);
629: }
630: return (error);
631: }
632:
633: int
634: ugenread(dev_t dev, struct uio *uio, int flag)
635: {
636: int endpt = UGENENDPOINT(dev);
637: struct ugen_softc *sc;
638: int error;
639:
640: sc = ugen_cd.cd_devs[UGENUNIT(dev)];
641:
642: sc->sc_refcnt++;
643: error = ugen_do_read(sc, endpt, uio, flag);
644: if (--sc->sc_refcnt < 0)
645: usb_detach_wakeup(&sc->sc_dev);
646: return (error);
647: }
648:
649: int
650: ugen_do_write(struct ugen_softc *sc, int endpt, struct uio *uio, int flag)
651: {
652: struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT];
653: u_int32_t n;
654: int error = 0;
655: char buf[UGEN_BBSIZE];
656: usbd_xfer_handle xfer;
657: usbd_status err;
658:
659: DPRINTFN(5, ("%s: ugenwrite: %d\n", sc->sc_dev.dv_xname, endpt));
660:
661: if (sc->sc_dying)
662: return (EIO);
663:
664: if (endpt == USB_CONTROL_ENDPOINT)
665: return (ENODEV);
666:
667: #ifdef DIAGNOSTIC
668: if (sce->edesc == NULL) {
669: printf("ugenwrite: no edesc\n");
670: return (EIO);
671: }
672: if (sce->pipeh == NULL) {
673: printf("ugenwrite: no pipe\n");
674: return (EIO);
675: }
676: #endif
677:
678: switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
679: case UE_BULK:
680: xfer = usbd_alloc_xfer(sc->sc_udev);
681: if (xfer == 0)
682: return (EIO);
683: while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
684: error = uiomove(buf, n, uio);
685: if (error)
686: break;
687: DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
688: err = usbd_bulk_transfer(xfer, sce->pipeh, 0,
689: sce->timeout, buf, &n,"ugenwb");
690: if (err) {
691: if (err == USBD_INTERRUPTED)
692: error = EINTR;
693: else if (err == USBD_TIMEOUT)
694: error = ETIMEDOUT;
695: else
696: error = EIO;
697: break;
698: }
699: }
700: usbd_free_xfer(xfer);
701: break;
702: case UE_INTERRUPT:
703: xfer = usbd_alloc_xfer(sc->sc_udev);
704: if (xfer == 0)
705: return (EIO);
706: while ((n = min(UGETW(sce->edesc->wMaxPacketSize),
707: uio->uio_resid)) != 0) {
708: error = uiomove(buf, n, uio);
709: if (error)
710: break;
711: DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
712: err = usbd_intr_transfer(xfer, sce->pipeh, 0,
713: sce->timeout, buf, &n, "ugenwi");
714: if (err) {
715: if (err == USBD_INTERRUPTED)
716: error = EINTR;
717: else if (err == USBD_TIMEOUT)
718: error = ETIMEDOUT;
719: else
720: error = EIO;
721: break;
722: }
723: }
724: usbd_free_xfer(xfer);
725: break;
726: default:
727: return (ENXIO);
728: }
729: return (error);
730: }
731:
732: int
733: ugenwrite(dev_t dev, struct uio *uio, int flag)
734: {
735: int endpt = UGENENDPOINT(dev);
736: struct ugen_softc *sc;
737: int error;
738:
739: sc = ugen_cd.cd_devs[UGENUNIT(dev)];
740:
741: sc->sc_refcnt++;
742: error = ugen_do_write(sc, endpt, uio, flag);
743: if (--sc->sc_refcnt < 0)
744: usb_detach_wakeup(&sc->sc_dev);
745: return (error);
746: }
747:
748: int
749: ugen_activate(struct device *self, enum devact act)
750: {
751: struct ugen_softc *sc = (struct ugen_softc *)self;
752:
753: switch (act) {
754: case DVACT_ACTIVATE:
755: break;
756:
757: case DVACT_DEACTIVATE:
758: sc->sc_dying = 1;
759: break;
760: }
761: return (0);
762: }
763:
764: int
765: ugen_detach(struct device *self, int flags)
766: {
767: struct ugen_softc *sc = (struct ugen_softc *)self;
768: struct ugen_endpoint *sce;
769: int i, dir;
770: int s;
771: int maj, mn;
772:
773: DPRINTF(("ugen_detach: sc=%p flags=%d\n", sc, flags));
774:
775: sc->sc_dying = 1;
776: /* Abort all pipes. Causes processes waiting for transfer to wake. */
777: for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
778: for (dir = OUT; dir <= IN; dir++) {
779: sce = &sc->sc_endpoints[i][dir];
780: if (sce && sce->pipeh)
781: usbd_abort_pipe(sce->pipeh);
782: }
783: }
784:
785: s = splusb();
786: if (--sc->sc_refcnt >= 0) {
787: /* Wake everyone */
788: for (i = 0; i < USB_MAX_ENDPOINTS; i++)
789: wakeup(&sc->sc_endpoints[i][IN]);
790: /* Wait for processes to go away. */
791: usb_detach_wait(&sc->sc_dev);
792: }
793: splx(s);
794:
795: /* locate the major number */
796: for (maj = 0; maj < nchrdev; maj++)
797: if (cdevsw[maj].d_open == ugenopen)
798: break;
799:
800: /* Nuke the vnodes for any open instances (calls close). */
801: mn = self->dv_unit * USB_MAX_ENDPOINTS;
802: vdevgone(maj, mn, mn + USB_MAX_ENDPOINTS - 1, VCHR);
803:
804: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
805: &sc->sc_dev);
806:
807: return (0);
808: }
809:
810: void
811: ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr, usbd_status status)
812: {
813: struct ugen_endpoint *sce = addr;
814: /*struct ugen_softc *sc = sce->sc;*/
815: u_int32_t count;
816: u_char *ibuf;
817:
818: if (status == USBD_CANCELLED)
819: return;
820:
821: if (status != USBD_NORMAL_COMPLETION) {
822: DPRINTF(("ugenintr: status=%d\n", status));
823: if (status == USBD_STALLED)
824: usbd_clear_endpoint_stall_async(sce->pipeh);
825: return;
826: }
827:
828: usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
829: ibuf = sce->ibuf;
830:
831: DPRINTFN(5, ("ugenintr: xfer=%p status=%d count=%d\n",
832: xfer, status, count));
833: DPRINTFN(5, (" data = %02x %02x %02x\n",
834: ibuf[0], ibuf[1], ibuf[2]));
835:
836: (void)b_to_q(ibuf, count, &sce->q);
837:
838: if (sce->state & UGEN_ASLP) {
839: sce->state &= ~UGEN_ASLP;
840: DPRINTFN(5, ("ugen_intr: waking %p\n", sce));
841: wakeup(sce);
842: }
843: selwakeup(&sce->rsel);
844: }
845:
846: void
847: ugen_isoc_rintr(usbd_xfer_handle xfer, usbd_private_handle addr,
848: usbd_status status)
849: {
850: struct isoreq *req = addr;
851: struct ugen_endpoint *sce = req->sce;
852: u_int32_t count, n;
853: int i, isize;
854:
855: /* Return if we are aborting. */
856: if (status == USBD_CANCELLED)
857: return;
858:
859: usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
860: DPRINTFN(5,("ugen_isoc_rintr: xfer %d, count=%d\n", req - sce->isoreqs,
861: count));
862:
863: /* throw away oldest input if the buffer is full */
864: if(sce->fill < sce->cur && sce->cur <= sce->fill + count) {
865: sce->cur += count;
866: if(sce->cur >= sce->limit)
867: sce->cur = sce->ibuf + (sce->limit - sce->cur);
868: DPRINTFN(5, ("ugen_isoc_rintr: throwing away %d bytes\n",
869: count));
870: }
871:
872: isize = UGETW(sce->edesc->wMaxPacketSize);
873: for (i = 0; i < UGEN_NISORFRMS; i++) {
874: u_int32_t actlen = req->sizes[i];
875: char const *buf = (char const *)req->dmabuf + isize * i;
876:
877: /* copy data to buffer */
878: while (actlen > 0) {
879: n = min(actlen, sce->limit - sce->fill);
880: memcpy(sce->fill, buf, n);
881:
882: buf += n;
883: actlen -= n;
884: sce->fill += n;
885: if(sce->fill == sce->limit)
886: sce->fill = sce->ibuf;
887: }
888:
889: /* setup size for next transfer */
890: req->sizes[i] = isize;
891: }
892:
893: usbd_setup_isoc_xfer(xfer, sce->pipeh, req, req->sizes, UGEN_NISORFRMS,
894: USBD_NO_COPY, ugen_isoc_rintr);
895: (void)usbd_transfer(xfer);
896:
897: if (sce->state & UGEN_ASLP) {
898: sce->state &= ~UGEN_ASLP;
899: DPRINTFN(5, ("ugen_isoc_rintr: waking %p\n", sce));
900: wakeup(sce);
901: }
902: selwakeup(&sce->rsel);
903: }
904:
905: usbd_status
906: ugen_set_interface(struct ugen_softc *sc, int ifaceidx, int altno)
907: {
908: usbd_interface_handle iface;
909: usb_endpoint_descriptor_t *ed;
910: usbd_status err;
911: struct ugen_endpoint *sce;
912: u_int8_t niface, nendpt, endptno, endpt;
913: int dir;
914:
915: DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno));
916:
917: err = usbd_interface_count(sc->sc_udev, &niface);
918: if (err)
919: return (err);
920: if (ifaceidx < 0 || ifaceidx >= niface)
921: return (USBD_INVAL);
922:
923: err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
924: if (err)
925: return (err);
926: err = usbd_endpoint_count(iface, &nendpt);
927: if (err)
928: return (err);
929: /* XXX should only do this after setting new altno has succeeded */
930: for (endptno = 0; endptno < nendpt; endptno++) {
931: ed = usbd_interface2endpoint_descriptor(iface,endptno);
932: endpt = ed->bEndpointAddress;
933: dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
934: sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
935: sce->sc = 0;
936: sce->edesc = 0;
937: sce->iface = 0;
938: }
939:
940: /* change setting */
941: err = usbd_set_interface(iface, altno);
942: if (err)
943: return (err);
944:
945: err = usbd_endpoint_count(iface, &nendpt);
946: if (err)
947: return (err);
948: for (endptno = 0; endptno < nendpt; endptno++) {
949: ed = usbd_interface2endpoint_descriptor(iface,endptno);
950: endpt = ed->bEndpointAddress;
951: dir = UE_GET_DIR(endpt) == UE_DIR_IN ? IN : OUT;
952: sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][dir];
953: sce->sc = sc;
954: sce->edesc = ed;
955: sce->iface = iface;
956: }
957: return (0);
958: }
959:
960: /* Retrieve a complete descriptor for a certain device and index. */
961: usb_config_descriptor_t *
962: ugen_get_cdesc(struct ugen_softc *sc, int index, int *lenp)
963: {
964: usb_config_descriptor_t *cdesc, *tdesc, cdescr;
965: int len;
966: usbd_status err;
967:
968: if (index == USB_CURRENT_CONFIG_INDEX) {
969: tdesc = usbd_get_config_descriptor(sc->sc_udev);
970: len = UGETW(tdesc->wTotalLength);
971: if (lenp)
972: *lenp = len;
973: cdesc = malloc(len, M_TEMP, M_WAITOK);
974: memcpy(cdesc, tdesc, len);
975: DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len));
976: } else {
977: err = usbd_get_config_desc(sc->sc_udev, index, &cdescr);
978: if (err)
979: return (0);
980: len = UGETW(cdescr.wTotalLength);
981: DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len));
982: if (lenp)
983: *lenp = len;
984: cdesc = malloc(len, M_TEMP, M_WAITOK);
985: err = usbd_get_config_desc_full(sc->sc_udev, index, cdesc,
986: len);
987: if (err) {
988: free(cdesc, M_TEMP);
989: return (0);
990: }
991: }
992: return (cdesc);
993: }
994:
995: int
996: ugen_get_alt_index(struct ugen_softc *sc, int ifaceidx)
997: {
998: usbd_interface_handle iface;
999: usbd_status err;
1000:
1001: err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
1002: if (err)
1003: return (-1);
1004: return (usbd_get_interface_altindex(iface));
1005: }
1006:
1007: int
1008: ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd,
1009: caddr_t addr, int flag, struct proc *p)
1010: {
1011: struct ugen_endpoint *sce;
1012: usbd_status err;
1013: usbd_interface_handle iface;
1014: struct usb_config_desc *cd;
1015: usb_config_descriptor_t *cdesc;
1016: struct usb_interface_desc *id;
1017: usb_interface_descriptor_t *idesc;
1018: struct usb_endpoint_desc *ed;
1019: usb_endpoint_descriptor_t *edesc;
1020: struct usb_alt_interface *ai;
1021: struct usb_string_desc *si;
1022: u_int8_t conf, alt;
1023:
1024: DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd));
1025: if (sc->sc_dying)
1026: return (EIO);
1027:
1028: switch (cmd) {
1029: case FIONBIO:
1030: /* All handled in the upper FS layer. */
1031: return (0);
1032: case USB_SET_SHORT_XFER:
1033: if (endpt == USB_CONTROL_ENDPOINT)
1034: return (EINVAL);
1035: /* This flag only affects read */
1036: sce = &sc->sc_endpoints[endpt][IN];
1037: if (sce == NULL || sce->pipeh == NULL)
1038: return (EINVAL);
1039: if (*(int *)addr)
1040: sce->state |= UGEN_SHORT_OK;
1041: else
1042: sce->state &= ~UGEN_SHORT_OK;
1043: return (0);
1044: case USB_SET_TIMEOUT:
1045: sce = &sc->sc_endpoints[endpt][IN];
1046: if (sce == NULL
1047: /* XXX this shouldn't happen, but the distinction between
1048: input and output pipes isn't clear enough.
1049: || sce->pipeh == NULL */
1050: )
1051: return (EINVAL);
1052: sce->timeout = *(int *)addr;
1053: return (0);
1054: default:
1055: break;
1056: }
1057:
1058: if (endpt != USB_CONTROL_ENDPOINT)
1059: return (EINVAL);
1060:
1061: switch (cmd) {
1062: #ifdef UGEN_DEBUG
1063: case USB_SETDEBUG:
1064: ugendebug = *(int *)addr;
1065: break;
1066: #endif
1067: case USB_GET_CONFIG:
1068: err = usbd_get_config(sc->sc_udev, &conf);
1069: if (err)
1070: return (EIO);
1071: *(int *)addr = conf;
1072: break;
1073: case USB_SET_CONFIG:
1074: if (!(flag & FWRITE))
1075: return (EPERM);
1076: err = ugen_set_config(sc, *(int *)addr);
1077: switch (err) {
1078: case USBD_NORMAL_COMPLETION:
1079: break;
1080: case USBD_IN_USE:
1081: return (EBUSY);
1082: default:
1083: return (EIO);
1084: }
1085: break;
1086: case USB_GET_ALTINTERFACE:
1087: ai = (struct usb_alt_interface *)addr;
1088: err = usbd_device2interface_handle(sc->sc_udev,
1089: ai->uai_interface_index, &iface);
1090: if (err)
1091: return (EINVAL);
1092: idesc = usbd_get_interface_descriptor(iface);
1093: if (idesc == NULL)
1094: return (EIO);
1095: ai->uai_alt_no = idesc->bAlternateSetting;
1096: break;
1097: case USB_SET_ALTINTERFACE:
1098: if (!(flag & FWRITE))
1099: return (EPERM);
1100: ai = (struct usb_alt_interface *)addr;
1101: err = usbd_device2interface_handle(sc->sc_udev,
1102: ai->uai_interface_index, &iface);
1103: if (err)
1104: return (EINVAL);
1105: err = ugen_set_interface(sc, ai->uai_interface_index,
1106: ai->uai_alt_no);
1107: if (err)
1108: return (EINVAL);
1109: break;
1110: case USB_GET_NO_ALT:
1111: ai = (struct usb_alt_interface *)addr;
1112: cdesc = ugen_get_cdesc(sc, ai->uai_config_index, 0);
1113: if (cdesc == NULL)
1114: return (EINVAL);
1115: idesc = usbd_find_idesc(cdesc, ai->uai_interface_index, 0);
1116: if (idesc == NULL) {
1117: free(cdesc, M_TEMP);
1118: return (EINVAL);
1119: }
1120: ai->uai_alt_no = usbd_get_no_alts(cdesc,
1121: idesc->bInterfaceNumber);
1122: free(cdesc, M_TEMP);
1123: break;
1124: case USB_GET_DEVICE_DESC:
1125: *(usb_device_descriptor_t *)addr =
1126: *usbd_get_device_descriptor(sc->sc_udev);
1127: break;
1128: case USB_GET_CONFIG_DESC:
1129: cd = (struct usb_config_desc *)addr;
1130: cdesc = ugen_get_cdesc(sc, cd->ucd_config_index, 0);
1131: if (cdesc == NULL)
1132: return (EINVAL);
1133: cd->ucd_desc = *cdesc;
1134: free(cdesc, M_TEMP);
1135: break;
1136: case USB_GET_INTERFACE_DESC:
1137: id = (struct usb_interface_desc *)addr;
1138: cdesc = ugen_get_cdesc(sc, id->uid_config_index, 0);
1139: if (cdesc == NULL)
1140: return (EINVAL);
1141: if (id->uid_config_index == USB_CURRENT_CONFIG_INDEX &&
1142: id->uid_alt_index == USB_CURRENT_ALT_INDEX)
1143: alt = ugen_get_alt_index(sc, id->uid_interface_index);
1144: else
1145: alt = id->uid_alt_index;
1146: idesc = usbd_find_idesc(cdesc, id->uid_interface_index, alt);
1147: if (idesc == NULL) {
1148: free(cdesc, M_TEMP);
1149: return (EINVAL);
1150: }
1151: id->uid_desc = *idesc;
1152: free(cdesc, M_TEMP);
1153: break;
1154: case USB_GET_ENDPOINT_DESC:
1155: ed = (struct usb_endpoint_desc *)addr;
1156: cdesc = ugen_get_cdesc(sc, ed->ued_config_index, 0);
1157: if (cdesc == NULL)
1158: return (EINVAL);
1159: if (ed->ued_config_index == USB_CURRENT_CONFIG_INDEX &&
1160: ed->ued_alt_index == USB_CURRENT_ALT_INDEX)
1161: alt = ugen_get_alt_index(sc, ed->ued_interface_index);
1162: else
1163: alt = ed->ued_alt_index;
1164: edesc = usbd_find_edesc(cdesc, ed->ued_interface_index,
1165: alt, ed->ued_endpoint_index);
1166: if (edesc == NULL) {
1167: free(cdesc, M_TEMP);
1168: return (EINVAL);
1169: }
1170: ed->ued_desc = *edesc;
1171: free(cdesc, M_TEMP);
1172: break;
1173: case USB_GET_FULL_DESC:
1174: {
1175: int len;
1176: struct iovec iov;
1177: struct uio uio;
1178: struct usb_full_desc *fd = (struct usb_full_desc *)addr;
1179: int error;
1180:
1181: cdesc = ugen_get_cdesc(sc, fd->ufd_config_index, &len);
1182: if (len > fd->ufd_size)
1183: len = fd->ufd_size;
1184: iov.iov_base = (caddr_t)fd->ufd_data;
1185: iov.iov_len = len;
1186: uio.uio_iov = &iov;
1187: uio.uio_iovcnt = 1;
1188: uio.uio_resid = len;
1189: uio.uio_offset = 0;
1190: uio.uio_segflg = UIO_USERSPACE;
1191: uio.uio_rw = UIO_READ;
1192: uio.uio_procp = p;
1193: error = uiomove((void *)cdesc, len, &uio);
1194: free(cdesc, M_TEMP);
1195: return (error);
1196: }
1197: case USB_GET_STRING_DESC:
1198: {
1199: int len;
1200: si = (struct usb_string_desc *)addr;
1201: err = usbd_get_string_desc(sc->sc_udev, si->usd_string_index,
1202: si->usd_language_id, &si->usd_desc, &len);
1203: if (err)
1204: return (EINVAL);
1205: break;
1206: }
1207: case USB_DO_REQUEST:
1208: {
1209: struct usb_ctl_request *ur = (void *)addr;
1210: int len = UGETW(ur->ucr_request.wLength);
1211: struct iovec iov;
1212: struct uio uio;
1213: void *ptr = 0;
1214: usbd_status err;
1215: int error = 0;
1216:
1217: if (!(flag & FWRITE))
1218: return (EPERM);
1219: /* Avoid requests that would damage the bus integrity. */
1220: if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
1221: ur->ucr_request.bRequest == UR_SET_ADDRESS) ||
1222: (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
1223: ur->ucr_request.bRequest == UR_SET_CONFIG) ||
1224: (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE &&
1225: ur->ucr_request.bRequest == UR_SET_INTERFACE))
1226: return (EINVAL);
1227:
1228: if (len < 0 || len > 32767)
1229: return (EINVAL);
1230: if (len != 0) {
1231: iov.iov_base = (caddr_t)ur->ucr_data;
1232: iov.iov_len = len;
1233: uio.uio_iov = &iov;
1234: uio.uio_iovcnt = 1;
1235: uio.uio_resid = len;
1236: uio.uio_offset = 0;
1237: uio.uio_segflg = UIO_USERSPACE;
1238: uio.uio_rw =
1239: ur->ucr_request.bmRequestType & UT_READ ?
1240: UIO_READ : UIO_WRITE;
1241: uio.uio_procp = p;
1242: ptr = malloc(len, M_TEMP, M_WAITOK);
1243: if (uio.uio_rw == UIO_WRITE) {
1244: error = uiomove(ptr, len, &uio);
1245: if (error)
1246: goto ret;
1247: }
1248: }
1249: sce = &sc->sc_endpoints[endpt][IN];
1250: err = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request,
1251: ptr, ur->ucr_flags, &ur->ucr_actlen, sce->timeout);
1252: if (err) {
1253: error = EIO;
1254: goto ret;
1255: }
1256: if (len != 0) {
1257: if (uio.uio_rw == UIO_READ) {
1258: error = uiomove(ptr, len, &uio);
1259: if (error)
1260: goto ret;
1261: }
1262: }
1263: ret:
1264: if (ptr)
1265: free(ptr, M_TEMP);
1266: return (error);
1267: }
1268: case USB_GET_DEVICEINFO:
1269: usbd_fill_deviceinfo(sc->sc_udev,
1270: (struct usb_device_info *)addr, 1);
1271: break;
1272: default:
1273: return (EINVAL);
1274: }
1275: return (0);
1276: }
1277:
1278: int
1279: ugenioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
1280: {
1281: int endpt = UGENENDPOINT(dev);
1282: struct ugen_softc *sc;
1283: int error;
1284:
1285: sc = ugen_cd.cd_devs[UGENUNIT(dev)];
1286:
1287: sc->sc_refcnt++;
1288: error = ugen_do_ioctl(sc, endpt, cmd, addr, flag, p);
1289: if (--sc->sc_refcnt < 0)
1290: usb_detach_wakeup(&sc->sc_dev);
1291: return (error);
1292: }
1293:
1294: int
1295: ugenpoll(dev_t dev, int events, struct proc *p)
1296: {
1297: struct ugen_softc *sc;
1298: struct ugen_endpoint *sce;
1299: int revents = 0;
1300: int s;
1301:
1302: sc = ugen_cd.cd_devs[UGENUNIT(dev)];
1303:
1304: if (sc->sc_dying)
1305: return (POLLERR);
1306:
1307: /* XXX always IN */
1308: sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN];
1309: if (sce == NULL)
1310: return (POLLERR);
1311: #ifdef DIAGNOSTIC
1312: if (!sce->edesc) {
1313: printf("ugenpoll: no edesc\n");
1314: return (POLLERR);
1315: }
1316: if (!sce->pipeh) {
1317: printf("ugenpoll: no pipe\n");
1318: return (POLLERR);
1319: }
1320: #endif
1321: s = splusb();
1322: switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
1323: case UE_INTERRUPT:
1324: if (events & (POLLIN | POLLRDNORM)) {
1325: if (sce->q.c_cc > 0)
1326: revents |= events & (POLLIN | POLLRDNORM);
1327: else
1328: selrecord(p, &sce->rsel);
1329: }
1330: break;
1331: case UE_ISOCHRONOUS:
1332: if (events & (POLLIN | POLLRDNORM)) {
1333: if (sce->cur != sce->fill)
1334: revents |= events & (POLLIN | POLLRDNORM);
1335: else
1336: selrecord(p, &sce->rsel);
1337: }
1338: break;
1339: case UE_BULK:
1340: /*
1341: * We have no easy way of determining if a read will
1342: * yield any data or a write will happen.
1343: * Pretend they will.
1344: */
1345: revents |= events &
1346: (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM);
1347: break;
1348: default:
1349: break;
1350: }
1351: splx(s);
1352: return (revents);
1353: }
1354:
1355: void filt_ugenrdetach(struct knote *);
1356: int filt_ugenread_intr(struct knote *, long);
1357: int filt_ugenread_isoc(struct knote *, long);
1358: int ugenkqfilter(dev_t, struct knote *);
1359:
1360: void
1361: filt_ugenrdetach(struct knote *kn)
1362: {
1363: struct ugen_endpoint *sce = (void *)kn->kn_hook;
1364: int s;
1365:
1366: s = splusb();
1367: SLIST_REMOVE(&sce->rsel.si_note, kn, knote, kn_selnext);
1368: splx(s);
1369: }
1370:
1371: int
1372: filt_ugenread_intr(struct knote *kn, long hint)
1373: {
1374: struct ugen_endpoint *sce = (void *)kn->kn_hook;
1375:
1376: kn->kn_data = sce->q.c_cc;
1377: return (kn->kn_data > 0);
1378: }
1379:
1380: int
1381: filt_ugenread_isoc(struct knote *kn, long hint)
1382: {
1383: struct ugen_endpoint *sce = (void *)kn->kn_hook;
1384:
1385: if (sce->cur == sce->fill)
1386: return (0);
1387:
1388: if (sce->cur < sce->fill)
1389: kn->kn_data = sce->fill - sce->cur;
1390: else
1391: kn->kn_data = (sce->limit - sce->cur) +
1392: (sce->fill - sce->ibuf);
1393:
1394: return (1);
1395: }
1396:
1397: struct filterops ugenread_intr_filtops =
1398: { 1, NULL, filt_ugenrdetach, filt_ugenread_intr };
1399:
1400: struct filterops ugenread_isoc_filtops =
1401: { 1, NULL, filt_ugenrdetach, filt_ugenread_isoc };
1402:
1403: struct filterops ugen_seltrue_filtops =
1404: { 1, NULL, filt_ugenrdetach, filt_seltrue };
1405:
1406: int
1407: ugenkqfilter(dev_t dev, struct knote *kn)
1408: {
1409: struct ugen_softc *sc;
1410: struct ugen_endpoint *sce;
1411: struct klist *klist;
1412: int s;
1413:
1414: sc = ugen_cd.cd_devs[UGENUNIT(dev)];
1415:
1416: if (sc->sc_dying)
1417: return (1);
1418:
1419: /* XXX always IN */
1420: sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN];
1421: if (sce == NULL)
1422: return (1);
1423:
1424: switch (kn->kn_filter) {
1425: case EVFILT_READ:
1426: klist = &sce->rsel.si_note;
1427: switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
1428: case UE_INTERRUPT:
1429: kn->kn_fop = &ugenread_intr_filtops;
1430: break;
1431: case UE_ISOCHRONOUS:
1432: kn->kn_fop = &ugenread_isoc_filtops;
1433: break;
1434: case UE_BULK:
1435: /*
1436: * We have no easy way of determining if a read will
1437: * yield any data or a write will happen.
1438: * So, emulate "seltrue".
1439: */
1440: kn->kn_fop = &ugen_seltrue_filtops;
1441: break;
1442: default:
1443: return (1);
1444: }
1445: break;
1446:
1447: case EVFILT_WRITE:
1448: klist = &sce->rsel.si_note;
1449: switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
1450: case UE_INTERRUPT:
1451: case UE_ISOCHRONOUS:
1452: /* XXX poll doesn't support this */
1453: return (1);
1454:
1455: case UE_BULK:
1456: /*
1457: * We have no easy way of determining if a read will
1458: * yield any data or a write will happen.
1459: * So, emulate "seltrue".
1460: */
1461: kn->kn_fop = &ugen_seltrue_filtops;
1462: break;
1463: default:
1464: return (1);
1465: }
1466: break;
1467:
1468: default:
1469: return (1);
1470: }
1471:
1472: kn->kn_hook = (void *)sce;
1473:
1474: s = splusb();
1475: SLIST_INSERT_HEAD(klist, kn, kn_selnext);
1476: splx(s);
1477:
1478: return (0);
1479: }
CVSweb