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