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