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