Home | History | Annotate | Line # | Download | only in usb
ugen.c revision 1.11
      1 /*	$NetBSD: ugen.c,v 1.11 1999/01/08 11:58:25 augustss Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Lennart Augustsson (augustss (at) carlstedt.se) at
      9  * Carlstedt Research & Technology.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  * 3. All advertising materials mentioning features or use of this software
     20  *    must display the following acknowledgement:
     21  *        This product includes software developed by the NetBSD
     22  *        Foundation, Inc. and its contributors.
     23  * 4. Neither the name of The NetBSD Foundation nor the names of its
     24  *    contributors may be used to endorse or promote products derived
     25  *    from this software without specific prior written permission.
     26  *
     27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     37  * POSSIBILITY OF SUCH DAMAGE.
     38  */
     39 
     40 
     41 #include <sys/param.h>
     42 #include <sys/systm.h>
     43 #include <sys/kernel.h>
     44 #include <sys/malloc.h>
     45 #if defined(__NetBSD__)
     46 #include <sys/device.h>
     47 #include <sys/ioctl.h>
     48 #elif defined(__FreeBSD__)
     49 #include <sys/module.h>
     50 #include <sys/bus.h>
     51 #include <sys/ioccom.h>
     52 #include <sys/conf.h>
     53 #include <sys/fcntl.h>
     54 #include <sys/filio.h>
     55 #endif
     56 #include <sys/tty.h>
     57 #include <sys/file.h>
     58 #include <sys/select.h>
     59 #include <sys/proc.h>
     60 #include <sys/vnode.h>
     61 #include <sys/poll.h>
     62 
     63 #include <dev/usb/usb.h>
     64 #include <dev/usb/usbdi.h>
     65 #include <dev/usb/usbdi_util.h>
     66 
     67 #ifdef USB_DEBUG
     68 #define DPRINTF(x)	if (ugendebug) printf x
     69 #define DPRINTFN(n,x)	if (ugendebug>(n)) printf x
     70 int	ugendebug = 0;
     71 #else
     72 #define DPRINTF(x)
     73 #define DPRINTFN(n,x)
     74 #endif
     75 
     76 struct ugen_endpoint {
     77 	struct ugen_softc *sc;
     78 	usb_endpoint_descriptor_t *edesc;
     79 	usbd_interface_handle iface;
     80 	int state;
     81 #define UGEN_OPEN	0x01	/* device is open */
     82 #define	UGEN_ASLP	0x02	/* waiting for data */
     83 #define UGEN_SHORT_OK	0x04	/* short xfers are OK */
     84 	usbd_pipe_handle pipeh;
     85 	struct clist q;
     86 	struct selinfo rsel;
     87 	void *ibuf;
     88 };
     89 
     90 #define	UGEN_CHUNK	128	/* chunk size for read */
     91 #define	UGEN_IBSIZE	1020	/* buffer size */
     92 #define	UGEN_BBSIZE	1024
     93 
     94 struct ugen_softc {
     95 	bdevice sc_dev;		/* base device */
     96 	struct usbd_device *sc_udev;
     97 
     98 	struct ugen_endpoint sc_endpoints[USB_MAX_ENDPOINTS][2];
     99 #define OUT 0			/* index order is important, from UE_OUT */
    100 #define IN  1			/* from UE_IN */
    101 
    102 	int sc_disconnected;		/* device is gone */
    103 };
    104 
    105 int ugenopen __P((dev_t, int, int, struct proc *));
    106 int ugenclose __P((dev_t, int, int, struct proc *p));
    107 int ugenread __P((dev_t, struct uio *uio, int));
    108 int ugenwrite __P((dev_t, struct uio *uio, int));
    109 int ugenioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
    110 int ugenpoll __P((dev_t, int, struct proc *));
    111 void ugenintr __P((usbd_request_handle reqh, usbd_private_handle addr,
    112 		   usbd_status status));
    113 void ugen_disco __P((void *));
    114 
    115 int ugen_set_config __P((struct ugen_softc *sc, int configno));
    116 usb_config_descriptor_t *ugen_get_cdesc __P((struct ugen_softc *sc, int index,
    117 					     int *lenp));
    118 usbd_status ugen_set_interface __P((struct ugen_softc *, int, int));
    119 int ugen_get_alt_index __P((struct ugen_softc *sc, int ifaceidx));
    120 
    121 #define UGENUNIT(n) (((n) >> 4) & 0xf)
    122 #define UGENENDPOINT(n) ((n) & 0xf)
    123 
    124 USB_DECLARE_DRIVER(ugen);
    125 
    126 USB_MATCH(ugen)
    127 {
    128 	USB_MATCH_START(ugen, uaa);
    129 
    130 	if (uaa->usegeneric)
    131 		return (UMATCH_GENERIC);
    132 	else
    133 		return (UMATCH_NONE);
    134 }
    135 
    136 USB_ATTACH(ugen)
    137 {
    138 	USB_ATTACH_START(ugen, sc, uaa);
    139 	char devinfo[1024];
    140 	usbd_status r;
    141 	int conf;
    142 
    143 	usbd_devinfo(uaa->device, 0, devinfo);
    144 	USB_ATTACH_SETUP;
    145 	printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
    146 
    147 	sc->sc_udev = uaa->device;
    148 	conf = 1;		/* XXX should not hard code 1 */
    149 	r = ugen_set_config(sc, conf);
    150 	if (r != USBD_NORMAL_COMPLETION) {
    151 		printf("%s: setting configuration %d failed\n",
    152 		       USBDEVNAME(sc->sc_dev), conf);
    153 		sc->sc_disconnected = 1;
    154 		USB_ATTACH_ERROR_RETURN;
    155 	}
    156 	USB_ATTACH_SUCCESS_RETURN;
    157 }
    158 
    159 int
    160 ugen_set_config(sc, configno)
    161 	struct ugen_softc *sc;
    162 	int configno;
    163 {
    164 	usbd_device_handle dev = sc->sc_udev;
    165 	usbd_interface_handle iface;
    166 	usb_endpoint_descriptor_t *ed;
    167 	struct ugen_endpoint *sce;
    168 	u_int8_t niface, nendpt;
    169 	int ifaceno, endptno, endpt;
    170 	usbd_status r;
    171 
    172 	DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
    173 		    USBDEVNAME(sc->sc_dev), configno, sc));
    174 	if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) {
    175 		/* Avoid setting the current value. */
    176 		r = usbd_set_config_no(dev, configno, 0);
    177 		if (r != USBD_NORMAL_COMPLETION)
    178 			return (r);
    179 	}
    180 
    181 	r = usbd_interface_count(dev, &niface);
    182 	if (r != USBD_NORMAL_COMPLETION)
    183 		return (r);
    184 	memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
    185 	for (ifaceno = 0; ifaceno < niface; ifaceno++) {
    186 		DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno));
    187 		r = usbd_device2interface_handle(dev, ifaceno, &iface);
    188 		if (r != USBD_NORMAL_COMPLETION)
    189 			return (r);
    190 		r = usbd_endpoint_count(iface, &nendpt);
    191 		if (r != USBD_NORMAL_COMPLETION)
    192 			return (r);
    193 		for (endptno = 0; endptno < nendpt; endptno++) {
    194 			ed = usbd_interface2endpoint_descriptor(iface,endptno);
    195 			endpt = ed->bEndpointAddress;
    196 			sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)]
    197 				               [UE_GET_IN(endpt)];
    198 			DPRINTFN(1,("ugen_set_config: endptno %d, endpt=0x%02x"
    199 				    "(%d,%d), sce=%p\n",
    200 				    endptno, endpt, UE_GET_ADDR(endpt),
    201 				    UE_GET_IN(endpt), sce));
    202 			sce->sc = sc;
    203 			sce->edesc = ed;
    204 			sce->iface = iface;
    205 		}
    206 	}
    207 	return (USBD_NORMAL_COMPLETION);
    208 }
    209 
    210 void
    211 ugen_disco(p)
    212 	void *p;
    213 {
    214 	struct ugen_softc *sc = p;
    215 	sc->sc_disconnected = 1;
    216 }
    217 
    218 int
    219 ugenopen(dev, flag, mode, p)
    220 	dev_t dev;
    221 	int flag;
    222 	int mode;
    223 	struct proc *p;
    224 {
    225 	int unit = UGENUNIT(dev);
    226 	int endpt = UGENENDPOINT(dev);
    227 	usb_endpoint_descriptor_t *edesc;
    228 	struct ugen_endpoint *sce;
    229 	int dir, isize;
    230 	usbd_status r;
    231 
    232 	USB_GET_SC_OPEN(ugen, unit, sc);
    233  	DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
    234 		     flag, mode, unit, endpt));
    235 
    236 	if (sc->sc_disconnected)
    237 		return (EIO);
    238 
    239 	if (endpt == USB_CONTROL_ENDPOINT) {
    240 		/*if ((flag & (FWRITE|FREAD)) != (FWRITE|FREAD))
    241 		  return (EACCES);*/
    242 		sce = &sc->sc_endpoints[USB_CONTROL_ENDPOINT][OUT];
    243 		if (sce->state & UGEN_OPEN)
    244 			return (EBUSY);
    245 	} else {
    246 		switch (flag & (FWRITE|FREAD)) {
    247 		case FWRITE:
    248 			dir = OUT;
    249 			break;
    250 		case FREAD:
    251 			dir = IN;
    252 			break;
    253 		default:
    254 			return (EACCES);
    255 		}
    256 		sce = &sc->sc_endpoints[endpt][dir];
    257 		DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
    258 			     sc, endpt, dir, sce));
    259 		if (sce->state & UGEN_OPEN)
    260 			return (EBUSY);
    261 		edesc = sce->edesc;
    262 		if (!edesc)
    263 			return (ENXIO);
    264 		switch (edesc->bmAttributes & UE_XFERTYPE) {
    265 		case UE_INTERRUPT:
    266 			isize = UGETW(edesc->wMaxPacketSize);
    267 			if (isize == 0)	/* shouldn't happen */
    268 				return (EINVAL);
    269 			sce->ibuf = malloc(isize, M_USB, M_WAITOK);
    270 			DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
    271 				     endpt, isize));
    272 #if defined(__NetBSD__)
    273                         if (clalloc(&sce->q, UGEN_IBSIZE, 0) == -1)
    274                                 return (ENOMEM);
    275 #elif defined(__FreeBSD__)
    276 			clist_alloc_cblocks(&sce->q, UGEN_IBSIZE, 0);
    277 #endif
    278 			r = usbd_open_pipe_intr(sce->iface,
    279 				edesc->bEndpointAddress,
    280 				USBD_SHORT_XFER_OK, &sce->pipeh, sce,
    281 				sce->ibuf, isize, ugenintr);
    282 			if (r != USBD_NORMAL_COMPLETION) {
    283 				free(sce->ibuf, M_USB);
    284 #if defined(__NetBSD__)
    285 				clfree(&sce->q);
    286 #elif defined(__FreeBSD__)
    287 				clist_free_cblocks(&sce->q);
    288 #endif
    289 				return (EIO);
    290 			}
    291 			usbd_set_disco(sce->pipeh, ugen_disco, sc);
    292 			DPRINTFN(5, ("ugenopen: interrupt open done\n"));
    293 			break;
    294 		case UE_BULK:
    295 			r = usbd_open_pipe(sce->iface,
    296 					   edesc->bEndpointAddress, 0,
    297 					   &sce->pipeh);
    298 			if (r != USBD_NORMAL_COMPLETION)
    299 				return (EIO);
    300 			break;
    301 		case UE_CONTROL:
    302 		case UE_ISOCHRONOUS:
    303 			return (EINVAL);
    304 		}
    305 	}
    306 	sce->state |= UGEN_OPEN;
    307 	return (0);
    308 }
    309 
    310 int
    311 ugenclose(dev, flag, mode, p)
    312 	dev_t dev;
    313 	int flag;
    314 	int mode;
    315 	struct proc *p;
    316 {
    317 	USB_GET_SC(ugen, UGENUNIT(dev), sc);
    318 	int endpt = UGENENDPOINT(dev);
    319 	struct ugen_endpoint *sce;
    320 	int dir;
    321 
    322 	DPRINTFN(5, ("ugenclose: flag=%d, mode=%d\n", flag, mode));
    323 	if (sc->sc_disconnected)
    324 		return (EIO);
    325 
    326 	if (endpt == USB_CONTROL_ENDPOINT) {
    327 		DPRINTFN(5, ("ugenclose: close control\n"));
    328 		sc->sc_endpoints[endpt][OUT].state = 0;
    329 		return (0);
    330 	}
    331 
    332 	flag = FWRITE | FREAD;	/* XXX bug if generic open/close */
    333 
    334 	/* The open modes have been joined, so check for both modes. */
    335 	for (dir = OUT; dir <= IN; dir++) {
    336 		if (flag & (dir == OUT ? FWRITE : FREAD)) {
    337 			sce = &sc->sc_endpoints[endpt][dir];
    338 			if (!sce || !sce->pipeh) /* XXX */
    339 				continue; /* XXX */
    340 			DPRINTFN(5, ("ugenclose: endpt=%d dir=%d sce=%p\n",
    341 				     endpt, dir, sce));
    342 			sce->state = 0;
    343 
    344 			usbd_abort_pipe(sce->pipeh);
    345 			usbd_close_pipe(sce->pipeh);
    346 			sce->pipeh = 0;
    347 
    348 			if (sce->ibuf) {
    349 				free(sce->ibuf, M_USB);
    350 				sce->ibuf = 0;
    351 			}
    352 		}
    353 	}
    354 
    355 	return (0);
    356 }
    357 
    358 int
    359 ugenread(dev, uio, flag)
    360 	dev_t dev;
    361 	struct uio *uio;
    362 	int flag;
    363 {
    364 	USB_GET_SC(ugen, UGENUNIT(dev), sc);
    365 	int endpt = UGENENDPOINT(dev);
    366 	struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][IN];
    367 	u_int32_t n, tn;
    368 	char buf[UGEN_BBSIZE];
    369 	usbd_request_handle reqh;
    370 	usbd_status r;
    371 	int s;
    372 	int error = 0;
    373 	u_char buffer[UGEN_CHUNK];
    374 
    375 	DPRINTFN(5, ("ugenread: %d:%d\n", UGENUNIT(dev), UGENENDPOINT(dev)));
    376 	if (sc->sc_disconnected)
    377 		return (EIO);
    378 
    379 #ifdef DIAGNOSTIC
    380 	if (!sce->edesc) {
    381 		printf("ugenread: no edesc\n");
    382 		return (EIO);
    383 	}
    384 	if (!sce->pipeh) {
    385 		printf("ugenread: no pipe\n");
    386 		return (EIO);
    387 	}
    388 #endif
    389 
    390 	switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
    391 	case UE_INTERRUPT:
    392 		/* Block until activity occured. */
    393 		s = splusb();
    394 		while (sce->q.c_cc == 0) {
    395 			if (flag & IO_NDELAY) {
    396 				splx(s);
    397 				return (EWOULDBLOCK);
    398 			}
    399 			sce->state |= UGEN_ASLP;
    400 			DPRINTFN(5, ("ugenread: sleep on %p\n", sc));
    401 			error = tsleep((caddr_t)sce, PZERO | PCATCH,
    402 				       "ugenri", 0);
    403 			DPRINTFN(5, ("ugenread: woke, error=%d\n", error));
    404 			if (error) {
    405 				sce->state &= ~UGEN_ASLP;
    406 				splx(s);
    407 				return (error);
    408 			}
    409 		}
    410 		splx(s);
    411 
    412 		/* Transfer as many chunks as possible. */
    413 		while (sce->q.c_cc > 0 && uio->uio_resid > 0) {
    414 			n = min(sce->q.c_cc, uio->uio_resid);
    415 			if (n > sizeof(buffer))
    416 				n = sizeof(buffer);
    417 
    418 			/* Remove a small chunk from the input queue. */
    419 			q_to_b(&sce->q, buffer, n);
    420 			DPRINTFN(5, ("ugenread: got %d chars\n", n));
    421 
    422 			/* Copy the data to the user process. */
    423 			error = uiomove(buffer, n, uio);
    424 			if (error)
    425 				break;
    426 		}
    427 		break;
    428 	case UE_BULK:
    429 		reqh = usbd_alloc_request();
    430 		if (reqh == 0)
    431 			return (ENOMEM);
    432 		while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
    433 			DPRINTFN(1, ("ugenread: start transfer %d bytes\n",n));
    434 			tn = n;
    435 			r = usbd_bulk_transfer(reqh, sce->pipeh, 0, buf,
    436 					       &tn, "ugenrb");
    437 			if (r != USBD_NORMAL_COMPLETION) {
    438 				if (r == USBD_INTERRUPTED)
    439 					error = EINTR;
    440 				else
    441 					error = EIO;
    442 				break;
    443 			}
    444 			DPRINTFN(1, ("ugenread: got %d bytes\n", tn));
    445 			error = uiomove(buf, tn, uio);
    446 			if (error || tn < n)
    447 				break;
    448 		}
    449 		usbd_free_request(reqh);
    450 		break;
    451 	default:
    452 		return (ENXIO);
    453 	}
    454 
    455 	return (error);
    456 }
    457 
    458 int
    459 ugenwrite(dev, uio, flag)
    460 	dev_t dev;
    461 	struct uio *uio;
    462 	int flag;
    463 {
    464 	USB_GET_SC(ugen, UGENUNIT(dev), sc);
    465 	int endpt = UGENENDPOINT(dev);
    466 	struct ugen_endpoint *sce = &sc->sc_endpoints[endpt][OUT];
    467 	size_t n;
    468 	int error = 0;
    469 	char buf[UGEN_BBSIZE];
    470 	usbd_request_handle reqh;
    471 	usbd_status r;
    472 
    473 	if (sc->sc_disconnected)
    474 		return (EIO);
    475 
    476 #ifdef DIAGNOSTIC
    477 	if (!sce->edesc) {
    478 		printf("ugenwrite: no edesc\n");
    479 		return (EIO);
    480 	}
    481 	if (!sce->pipeh) {
    482 		printf("ugenwrite: no pipe\n");
    483 		return (EIO);
    484 	}
    485 #endif
    486 
    487 	DPRINTF(("ugenwrite\n"));
    488 	switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
    489 	case UE_BULK:
    490 		reqh = usbd_alloc_request();
    491 		if (reqh == 0)
    492 			return (EIO);
    493 		while ((n = min(UGEN_BBSIZE, uio->uio_resid)) != 0) {
    494 			error = uiomove(buf, n, uio);
    495 			if (error)
    496 				break;
    497 			DPRINTFN(1, ("ugenwrite: transfer %d bytes\n", n));
    498 			r = usbd_bulk_transfer(reqh, sce->pipeh, 0, buf,
    499 					       &n, "ugenwb");
    500 			if (r != USBD_NORMAL_COMPLETION) {
    501 				if (r == USBD_INTERRUPTED)
    502 					error = EINTR;
    503 				else
    504 					error = EIO;
    505 				break;
    506 			}
    507 		}
    508 		usbd_free_request(reqh);
    509 		break;
    510 	default:
    511 		return (ENXIO);
    512 	}
    513 	return (error);
    514 }
    515 
    516 
    517 void
    518 ugenintr(reqh, addr, status)
    519 	usbd_request_handle reqh;
    520 	usbd_private_handle addr;
    521 	usbd_status status;
    522 {
    523 	struct ugen_endpoint *sce = addr;
    524 	/*struct ugen_softc *sc = sce->sc;*/
    525 	usbd_private_handle priv;
    526 	void *buffer;
    527 	u_int32_t count;
    528 	usbd_status xstatus;
    529 	u_char *ibuf;
    530 
    531 	if (status == USBD_CANCELLED)
    532 		return;
    533 
    534 	if (status != USBD_NORMAL_COMPLETION) {
    535 		DPRINTF(("ugenintr: status=%d\n", status));
    536 		usbd_clear_endpoint_stall_async(sce->pipeh);
    537 		return;
    538 	}
    539 
    540 	(void)usbd_get_request_status(reqh, &priv, &buffer, &count, &xstatus);
    541 	ibuf = sce->ibuf;
    542 
    543 	DPRINTFN(5, ("ugenintr: reqh=%p status=%d count=%d\n",
    544 		     reqh, xstatus, count));
    545 	DPRINTFN(5, ("          data = %02x %02x %02x\n",
    546 		     ibuf[0], ibuf[1], ibuf[2]));
    547 
    548 	(void)b_to_q(ibuf, count, &sce->q);
    549 
    550 	if (sce->state & UGEN_ASLP) {
    551 		sce->state &= ~UGEN_ASLP;
    552 		DPRINTFN(5, ("ugen_intr: waking %p\n", sce));
    553 		wakeup((caddr_t)sce);
    554 	}
    555 	selwakeup(&sce->rsel);
    556 }
    557 
    558 usbd_status
    559 ugen_set_interface(sc, ifaceidx, altno)
    560 	struct ugen_softc *sc;
    561 	int ifaceidx, altno;
    562 {
    563 	usbd_interface_handle iface;
    564 	usb_endpoint_descriptor_t *ed;
    565 	usbd_status r;
    566 	struct ugen_endpoint *sce;
    567 	u_int8_t niface, nendpt, endptno, endpt;
    568 
    569 	DPRINTFN(15, ("ugen_set_interface %d %d\n", ifaceidx, altno));
    570 
    571 	r = usbd_interface_count(sc->sc_udev, &niface);
    572 	if (r != USBD_NORMAL_COMPLETION)
    573 		return (r);
    574 	if (ifaceidx < 0 || ifaceidx >= niface)
    575 		return (USBD_INVAL);
    576 
    577 	r = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
    578 	if (r != USBD_NORMAL_COMPLETION)
    579 		return (r);
    580 	r = usbd_endpoint_count(iface, &nendpt);
    581 	if (r != USBD_NORMAL_COMPLETION)
    582 		return (r);
    583 	for (endptno = 0; endptno < nendpt; endptno++) {
    584 		ed = usbd_interface2endpoint_descriptor(iface,endptno);
    585 		endpt = ed->bEndpointAddress;
    586 		sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][UE_GET_IN(endpt)];
    587 		sce->sc = 0;
    588 		sce->edesc = 0;
    589 		sce->iface = 0;
    590 	}
    591 
    592 	/* change setting */
    593 	r = usbd_set_interface(iface, altno);
    594 	if (r != USBD_NORMAL_COMPLETION)
    595 		return (r);
    596 
    597 	r = usbd_endpoint_count(iface, &nendpt);
    598 	if (r != USBD_NORMAL_COMPLETION)
    599 		return (r);
    600 	for (endptno = 0; endptno < nendpt; endptno++) {
    601 		ed = usbd_interface2endpoint_descriptor(iface,endptno);
    602 		endpt = ed->bEndpointAddress;
    603 		sce = &sc->sc_endpoints[UE_GET_ADDR(endpt)][UE_GET_IN(endpt)];
    604 		sce->sc = sc;
    605 		sce->edesc = ed;
    606 		sce->iface = iface;
    607 	}
    608 	return (0);
    609 }
    610 
    611 /* Retrieve a complete descriptor for a certain device and index. */
    612 usb_config_descriptor_t *
    613 ugen_get_cdesc(sc, index, lenp)
    614 	struct ugen_softc *sc;
    615 	int index;
    616 	int *lenp;
    617 {
    618 	usb_config_descriptor_t *cdesc, *tdesc, cdescr;
    619 	int len;
    620 	usbd_status r;
    621 
    622 	if (index == USB_CURRENT_CONFIG_INDEX) {
    623 		tdesc = usbd_get_config_descriptor(sc->sc_udev);
    624 		len = UGETW(tdesc->wTotalLength);
    625 		if (lenp)
    626 			*lenp = len;
    627 		cdesc = malloc(len, M_TEMP, M_WAITOK);
    628 		memcpy(cdesc, tdesc, len);
    629 		DPRINTFN(5,("ugen_get_cdesc: current, len=%d\n", len));
    630 	} else {
    631 		r = usbd_get_config_desc(sc->sc_udev, index, &cdescr);
    632 		if (r != USBD_NORMAL_COMPLETION)
    633 			return (0);
    634 		len = UGETW(cdescr.wTotalLength);
    635 		DPRINTFN(5,("ugen_get_cdesc: index=%d, len=%d\n", index, len));
    636 		if (lenp)
    637 			*lenp = len;
    638 		cdesc = malloc(len, M_TEMP, M_WAITOK);
    639 		r = usbd_get_config_desc_full(sc->sc_udev, index, cdesc, len);
    640 		if (r != USBD_NORMAL_COMPLETION) {
    641 			free(cdesc, M_TEMP);
    642 			return (0);
    643 		}
    644 	}
    645 	return (cdesc);
    646 }
    647 
    648 int
    649 ugen_get_alt_index(sc, ifaceidx)
    650 	struct ugen_softc *sc;
    651 	int ifaceidx;
    652 {
    653 	usbd_interface_handle iface;
    654 	usbd_status r;
    655 
    656 	r = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);
    657 	if (r != USBD_NORMAL_COMPLETION)
    658 			return (-1);
    659 	return (usbd_get_interface_altindex(iface));
    660 }
    661 
    662 int
    663 ugenioctl(dev, cmd, addr, flag, p)
    664 	dev_t dev;
    665 	u_long cmd;
    666 	caddr_t addr;
    667 	int flag;
    668 	struct proc *p;
    669 {
    670 	USB_GET_SC(ugen, UGENUNIT(dev), sc);
    671 	int endpt = UGENENDPOINT(dev);
    672 	struct ugen_endpoint *sce;
    673 	usbd_status r;
    674 	usbd_interface_handle iface;
    675 	struct usb_config_desc *cd;
    676 	usb_config_descriptor_t *cdesc;
    677 	struct usb_interface_desc *id;
    678 	usb_interface_descriptor_t *idesc;
    679 	struct usb_endpoint_desc *ed;
    680 	usb_endpoint_descriptor_t *edesc;
    681 	struct usb_alt_interface *ai;
    682 	struct usb_string_desc *si;
    683 	u_int8_t conf, alt;
    684 
    685 	DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd));
    686 	if (sc->sc_disconnected)
    687 		return (EIO);
    688 
    689 	switch (cmd) {
    690 	case FIONBIO:
    691 		/* All handled in the upper FS layer. */
    692 		return (0);
    693 	case USB_SET_SHORT_XFER:
    694 		/* This flag only affects read */
    695 		sce = &sc->sc_endpoints[endpt][IN];
    696 #ifdef DIAGNOSTIC
    697 		if (!sce->pipeh) {
    698 			printf("ugenioctl: no pipe\n");
    699 			return (EIO);
    700 		}
    701 #endif
    702 		if (*(int *)addr)
    703 			sce->state |= UGEN_SHORT_OK;
    704 		else
    705 			sce->state &= ~UGEN_SHORT_OK;
    706 		return (0);
    707 	default:
    708 		break;
    709 	}
    710 
    711 	if (endpt != USB_CONTROL_ENDPOINT)
    712 		return (EINVAL);
    713 
    714 	switch (cmd) {
    715 #ifdef USB_DEBUG
    716 	case USB_SETDEBUG:
    717 		ugendebug = *(int *)addr;
    718 		break;
    719 #endif
    720 	case USB_GET_CONFIG:
    721 		r = usbd_get_config(sc->sc_udev, &conf);
    722 		if (r != USBD_NORMAL_COMPLETION)
    723 			return (EIO);
    724 		*(int *)addr = conf;
    725 		break;
    726 	case USB_SET_CONFIG:
    727 		if (!(flag & FWRITE))
    728 			return (EPERM);
    729 		r = ugen_set_config(sc, *(int *)addr);
    730 		if (r != USBD_NORMAL_COMPLETION)
    731 			return (EIO);
    732 		break;
    733 	case USB_GET_ALTINTERFACE:
    734 		ai = (struct usb_alt_interface *)addr;
    735 		r = usbd_device2interface_handle(sc->sc_udev,
    736 						 ai->interface_index, &iface);
    737 		if (r != USBD_NORMAL_COMPLETION)
    738 			return (EINVAL);
    739 		idesc = usbd_get_interface_descriptor(iface);
    740 		if (!idesc)
    741 			return (EIO);
    742 		ai->alt_no = idesc->bAlternateSetting;
    743 		break;
    744 	case USB_SET_ALTINTERFACE:
    745 		if (!(flag & FWRITE))
    746 			return (EPERM);
    747 		ai = (struct usb_alt_interface *)addr;
    748 		r = usbd_device2interface_handle(sc->sc_udev,
    749 						 ai->interface_index, &iface);
    750 		if (r != USBD_NORMAL_COMPLETION)
    751 			return (EINVAL);
    752 		r = ugen_set_interface(sc, ai->interface_index, ai->alt_no);
    753 		if (r != USBD_NORMAL_COMPLETION)
    754 			return (EINVAL);
    755 		break;
    756 	case USB_GET_NO_ALT:
    757 		ai = (struct usb_alt_interface *)addr;
    758 		cdesc = ugen_get_cdesc(sc, ai->config_index, 0);
    759 		if (!cdesc)
    760 			return (EINVAL);
    761 		idesc = usbd_find_idesc(cdesc, ai->interface_index, 0);
    762 		if (!idesc)
    763 			return (EINVAL);
    764 		ai->alt_no = usbd_get_no_alts(cdesc, idesc->bInterfaceNumber);
    765 		break;
    766 	case USB_GET_DEVICE_DESC:
    767 		*(usb_device_descriptor_t *)addr =
    768 			*usbd_get_device_descriptor(sc->sc_udev);
    769 		break;
    770 	case USB_GET_CONFIG_DESC:
    771 		cd = (struct usb_config_desc *)addr;
    772 		cdesc = ugen_get_cdesc(sc, cd->config_index, 0);
    773 		if (!cdesc)
    774 			return (EINVAL);
    775 		cd->desc = *cdesc;
    776 		free(cdesc, M_TEMP);
    777 		break;
    778 	case USB_GET_INTERFACE_DESC:
    779 		id = (struct usb_interface_desc *)addr;
    780 		cdesc = ugen_get_cdesc(sc, id->config_index, 0);
    781 		if (!cdesc)
    782 			return (EINVAL);
    783 		if (id->config_index == USB_CURRENT_CONFIG_INDEX &&
    784 		    id->alt_index == USB_CURRENT_ALT_INDEX)
    785 			alt = ugen_get_alt_index(sc, id->interface_index);
    786 		else
    787 			alt = id->alt_index;
    788 		idesc = usbd_find_idesc(cdesc, id->interface_index, alt);
    789 		if (!idesc) {
    790 			free(cdesc, M_TEMP);
    791 			return (EINVAL);
    792 		}
    793 		id->desc = *idesc;
    794 		free(cdesc, M_TEMP);
    795 		break;
    796 	case USB_GET_ENDPOINT_DESC:
    797 		ed = (struct usb_endpoint_desc *)addr;
    798 		cdesc = ugen_get_cdesc(sc, ed->config_index, 0);
    799 		if (!cdesc)
    800 			return (EINVAL);
    801 		if (ed->config_index == USB_CURRENT_CONFIG_INDEX &&
    802 		    ed->alt_index == USB_CURRENT_ALT_INDEX)
    803 			alt = ugen_get_alt_index(sc, ed->interface_index);
    804 		else
    805 			alt = ed->alt_index;
    806 		edesc = usbd_find_edesc(cdesc, ed->interface_index,
    807 					alt, ed->endpoint_index);
    808 		if (!edesc) {
    809 			free(cdesc, M_TEMP);
    810 			return (EINVAL);
    811 		}
    812 		ed->desc = *edesc;
    813 		free(cdesc, M_TEMP);
    814 		break;
    815 	case USB_GET_FULL_DESC:
    816 	{
    817 		int len;
    818 		struct iovec iov;
    819 		struct uio uio;
    820 		struct usb_full_desc *fd = (struct usb_full_desc *)addr;
    821 		int error;
    822 
    823 		cdesc = ugen_get_cdesc(sc, fd->config_index, &len);
    824 		if (len > fd->size)
    825 			len = fd->size;
    826 		iov.iov_base = (caddr_t)fd->data;
    827 		iov.iov_len = len;
    828 		uio.uio_iov = &iov;
    829 		uio.uio_iovcnt = 1;
    830 		uio.uio_resid = len;
    831 		uio.uio_offset = 0;
    832 		uio.uio_segflg = UIO_USERSPACE;
    833 		uio.uio_rw = UIO_READ;
    834 		uio.uio_procp = p;
    835 		error = uiomove(cdesc, len, &uio);
    836 		free(cdesc, M_TEMP);
    837 		return (error);
    838 	}
    839 	case USB_GET_STRING_DESC:
    840 		si = (struct usb_string_desc *)addr;
    841 		r = usbd_get_string_desc(sc->sc_udev, si->string_index,
    842 					 si->language_id, &si->desc);
    843 		if (r != USBD_NORMAL_COMPLETION)
    844 			return (EINVAL);
    845 		break;
    846 	case USB_DO_REQUEST:
    847 	{
    848 		struct usb_ctl_request *ur = (void *)addr;
    849 		int len = UGETW(ur->request.wLength);
    850 		struct iovec iov;
    851 		struct uio uio;
    852 		void *ptr = 0;
    853 		usbd_status r;
    854 		int error = 0;
    855 
    856 		if (!(flag & FWRITE))
    857 			return (EPERM);
    858 		/* Avoid requests that would damage the bus integrity. */
    859 		if ((ur->request.bmRequestType == UT_WRITE_DEVICE &&
    860 		     ur->request.bRequest == UR_SET_ADDRESS) ||
    861 		    (ur->request.bmRequestType == UT_WRITE_DEVICE &&
    862 		     ur->request.bRequest == UR_SET_CONFIG) ||
    863 		    (ur->request.bmRequestType == UT_WRITE_INTERFACE &&
    864 		     ur->request.bRequest == UR_SET_INTERFACE))
    865 			return (EINVAL);
    866 
    867 		if (len < 0 || len > 32767)
    868 			return (EINVAL);
    869 		if (len != 0) {
    870 			iov.iov_base = (caddr_t)ur->data;
    871 			iov.iov_len = len;
    872 			uio.uio_iov = &iov;
    873 			uio.uio_iovcnt = 1;
    874 			uio.uio_resid = len;
    875 			uio.uio_offset = 0;
    876 			uio.uio_segflg = UIO_USERSPACE;
    877 			uio.uio_rw =
    878 				ur->request.bmRequestType & UT_READ ?
    879 				UIO_READ : UIO_WRITE;
    880 			uio.uio_procp = p;
    881 			ptr = malloc(len, M_TEMP, M_WAITOK);
    882 			if (uio.uio_rw == UIO_WRITE) {
    883 				error = uiomove(ptr, len, &uio);
    884 				if (error)
    885 					goto ret;
    886 			}
    887 		}
    888 		r = usbd_do_request_flags(sc->sc_udev, &ur->request,
    889 					  ptr, ur->flags, &ur->actlen);
    890 		if (r) {
    891 			error = EIO;
    892 			goto ret;
    893 		}
    894 		if (len != 0) {
    895 			if (uio.uio_rw == UIO_READ) {
    896 				error = uiomove(ptr, len, &uio);
    897 				if (error)
    898 					goto ret;
    899 			}
    900 		}
    901 	ret:
    902 		if (ptr)
    903 			free(ptr, M_TEMP);
    904 		return (error);
    905 	}
    906 	case USB_GET_DEVICEINFO:
    907 		usbd_fill_deviceinfo(sc->sc_udev,
    908 				     (struct usb_device_info *)addr);
    909 		break;
    910 	default:
    911 		return (EINVAL);
    912 	}
    913 	return (0);
    914 }
    915 
    916 int
    917 ugenpoll(dev, events, p)
    918 	dev_t dev;
    919 	int events;
    920 	struct proc *p;
    921 {
    922 	USB_GET_SC(ugen, UGENUNIT(dev), sc);
    923 	/* XXX */
    924 	struct ugen_endpoint *sce;
    925 	int revents = 0;
    926 	int s;
    927 
    928 	if (sc->sc_disconnected)
    929 		return (EIO);
    930 
    931 	sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN];
    932 #ifdef DIAGNOSTIC
    933 	if (!sce->edesc) {
    934 		printf("ugenwrite: no edesc\n");
    935 		return (EIO);
    936 	}
    937 	if (!sce->pipeh) {
    938 		printf("ugenpoll: no pipe\n");
    939 		return (EIO);
    940 	}
    941 #endif
    942 	s = splusb();
    943 	switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
    944 	case UE_INTERRUPT:
    945 		if (events & (POLLIN | POLLRDNORM)) {
    946 			if (sce->q.c_cc > 0)
    947 				revents |= events & (POLLIN | POLLRDNORM);
    948 			else
    949 				selrecord(p, &sce->rsel);
    950 		}
    951 		break;
    952 	case UE_BULK:
    953 		/*
    954 		 * We have no easy way of determining if a read will
    955 		 * yield any data or a write will happen.
    956 		 * Pretend they will.
    957 		 */
    958 		revents |= events &
    959 			   (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM);
    960 		break;
    961 	default:
    962 		break;
    963 	}
    964 	splx(s);
    965 	return (revents);
    966 }
    967 
    968 #if defined(__FreeBSD__)
    969 static int
    970 ugen_detach(device_t self)
    971 {
    972         struct ugen_softc *sc = device_get_softc(self);
    973 	char *devinfo = (char *) device_get_desc(self);
    974 
    975 	if (devinfo) {
    976 		device_set_desc(self, NULL);
    977 		free(devinfo, M_USB);
    978 	}
    979 	return 0;
    980 }
    981 
    982 DRIVER_MODULE(ugen, usb, ugen_driver, ugen_devclass, usbd_driver_load, 0);
    983 #endif
    984