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