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