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