Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 Feb 2009 17:14:03 +0000 (UTC)
From:      Andrew Thompson <thompsa@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r189172 - head/sys/dev/usb
Message-ID:  <200902281714.n1SHE3r5015514@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: thompsa
Date: Sat Feb 28 17:14:03 2009
New Revision: 189172
URL: http://svn.freebsd.org/changeset/base/189172

Log:
  - Remove the usb interface number from the device nodes as it is not needed.
  - Do not recreate the device nodes in set_alt_interface as the endpoints do not
    change.
  
  Submitted by:	Hans Petter Selasky

Modified:
  head/sys/dev/usb/usb_dev.c
  head/sys/dev/usb/usb_dev.h
  head/sys/dev/usb/usb_device.c
  head/sys/dev/usb/usb_device.h

Modified: head/sys/dev/usb/usb_dev.c
==============================================================================
--- head/sys/dev/usb/usb_dev.c	Sat Feb 28 17:01:55 2009	(r189171)
+++ head/sys/dev/usb/usb_dev.c	Sat Feb 28 17:14:03 2009	(r189172)
@@ -82,7 +82,7 @@ static int	usb2_fifo_uiomove(struct usb2
 static void	usb2_fifo_check_methods(struct usb2_fifo_methods *);
 static struct	usb2_fifo *usb2_fifo_alloc(void);
 static struct	usb2_pipe *usb2_dev_get_pipe(struct usb2_device *, uint8_t,
-		    uint8_t, uint8_t);
+		    uint8_t);
 static void	usb2_loc_fill(struct usb2_fs_privdata *,
 		    struct usb2_cdev_privdata *);
 static void	usb2_close(void *);
@@ -140,7 +140,6 @@ usb2_loc_fill(struct usb2_fs_privdata* p
 {
 	cpd->bus_index = pd->bus_index;
 	cpd->dev_index = pd->dev_index;
-	cpd->iface_index = pd->iface_index;
 	cpd->ep_addr = pd->ep_addr;
 	cpd->fifo_index = pd->fifo_index;
 }
@@ -238,19 +237,6 @@ usb2_ref_device(struct usb2_cdev_privdat
 		}
 	}
 
-	/* check if we require an interface */
-	cpd->iface = usb2_get_iface(cpd->udev, cpd->iface_index);
-	if (dev_ep_index != 0) {
-		/* non control endpoint - we need an interface */
-		if (cpd->iface == NULL) {
-			DPRINTFN(2, "no iface\n");
-			goto error;
-		}
-		if (cpd->iface->idesc == NULL) {
-			DPRINTFN(2, "no idesc\n");
-			goto error;
-		}
-	}
 	/* when everything is OK we increment the refcounts */
 	if (cpd->is_write) {
 		DPRINTFN(2, "ref write\n");
@@ -394,7 +380,6 @@ usb2_fifo_create(struct usb2_cdev_privda
 	struct usb2_device *udev = cpd->udev;
 	struct usb2_fifo *f;
 	struct usb2_pipe *pipe;
-	uint8_t iface_index = cpd->iface_index;
 	uint8_t n;
 	uint8_t is_tx;
 	uint8_t is_rx;
@@ -449,11 +434,6 @@ usb2_fifo_create(struct usb2_cdev_privda
 					/* wrong endpoint index */
 					continue;
 				}
-				if (ep != 0 &&
-				    f->iface_index != iface_index) {
-					/* wrong interface index */
-					continue;
-				}
 				if (f->opened) {
 					/* FIFO is opened */
 					is_busy = 1;
@@ -471,11 +451,6 @@ usb2_fifo_create(struct usb2_cdev_privda
 					/* wrong endpoint index */
 					continue;
 				}
-				if (ep != 0 &&
-				    f->iface_index != iface_index) {
-					/* wrong interface index */
-					continue;
-				}
 				if (f->opened) {
 					/* FIFO is opened */
 					is_busy = 1;
@@ -499,8 +474,8 @@ usb2_fifo_create(struct usb2_cdev_privda
 	if (is_tx &&
 	    (udev->fifo[n + USB_FIFO_TX] == NULL)) {
 		pipe = usb2_dev_get_pipe(udev,
-		    iface_index, ep, USB_FIFO_TX);
-		DPRINTFN(5, "dev_get_pipe(%d, 0x%x, 0x%x)\n", iface_index, ep, USB_FIFO_TX);
+		    ep, USB_FIFO_TX);
+		DPRINTFN(5, "dev_get_pipe(%d, 0x%x)\n", ep, USB_FIFO_TX);
 		if (pipe == NULL) {
 			DPRINTFN(5, "dev_get_pipe returned NULL\n");
 			return (EINVAL);
@@ -516,7 +491,7 @@ usb2_fifo_create(struct usb2_cdev_privda
 		f->priv_mtx = udev->default_mtx;
 		f->priv_sc0 = pipe;
 		f->methods = &usb2_ugen_methods;
-		f->iface_index = iface_index;
+		f->iface_index = pipe->iface_index;
 		f->udev = udev;
 		mtx_lock(&usb2_ref_lock);
 		udev->fifo[n + USB_FIFO_TX] = f;
@@ -527,8 +502,8 @@ usb2_fifo_create(struct usb2_cdev_privda
 	    (udev->fifo[n + USB_FIFO_RX] == NULL)) {
 
 		pipe = usb2_dev_get_pipe(udev,
-		    iface_index, ep, USB_FIFO_RX);
-		DPRINTFN(5, "dev_get_pipe(%d, 0x%x, 0x%x)\n", iface_index, ep, USB_FIFO_RX);
+		    ep, USB_FIFO_RX);
+		DPRINTFN(5, "dev_get_pipe(%d, 0x%x)\n", ep, USB_FIFO_RX);
 		if (pipe == NULL) {
 			DPRINTFN(5, "dev_get_pipe returned NULL\n");
 			return (EINVAL);
@@ -544,7 +519,7 @@ usb2_fifo_create(struct usb2_cdev_privda
 		f->priv_mtx = udev->default_mtx;
 		f->priv_sc0 = pipe;
 		f->methods = &usb2_ugen_methods;
-		f->iface_index = iface_index;
+		f->iface_index = pipe->iface_index;
 		f->udev = udev;
 		mtx_lock(&usb2_ref_lock);
 		udev->fifo[n + USB_FIFO_RX] = f;
@@ -624,7 +599,7 @@ usb2_fifo_free(struct usb2_fifo *f)
 
 static struct usb2_pipe *
 usb2_dev_get_pipe(struct usb2_device *udev,
-    uint8_t iface_index, uint8_t ep_index, uint8_t dir)
+    uint8_t ep_index, uint8_t dir)
 {
 	struct usb2_pipe *pipe;
 	uint8_t ep_dir;
@@ -656,15 +631,6 @@ usb2_dev_get_pipe(struct usb2_device *ud
 		/* invalid pipe */
 		return (NULL);
 	}
-	if (ep_index != 0) {
-		if (pipe->iface_index != iface_index) {
-			/*
-			 * Permissions violation - trying to access a
-			 * pipe that does not belong to the interface.
-			 */
-			return (NULL);
-		}
-	}
 	return (pipe);			/* success */
 }
 
@@ -1059,7 +1025,12 @@ usb2_ioctl(struct cdev *dev, u_long cmd,
 	if (err != 0)
 		return (err);
 
-	err = usb2_ref_device(cpd, 1);
+	/* 
+	 * Performance optimistaion: We try to check for IOCTL's that
+	 * don't need the USB reference first. Then we grab the USB
+	 * reference if we need it!
+	 */
+	err = usb2_ref_device(cpd, 0 /* no uref */ );
 	if (err) {
 		return (ENXIO);
 	}
@@ -1719,7 +1690,6 @@ usb2_fifo_attach(struct usb2_device *ude
 		pd = malloc(sizeof(struct usb2_fs_privdata), M_USBDEV, M_WAITOK | M_ZERO);
 		pd->bus_index = device_get_unit(udev->bus->bdev);
 		pd->dev_index = udev->device_index;
-		pd->iface_index = iface_index;
 		pd->ep_addr = -1;	/* not an endpoint */
 		pd->fifo_index = f_tx->fifo_index;
 		pd->mode = FREAD|FWRITE;

Modified: head/sys/dev/usb/usb_dev.h
==============================================================================
--- head/sys/dev/usb/usb_dev.h	Sat Feb 28 17:01:55 2009	(r189171)
+++ head/sys/dev/usb/usb_dev.h	Sat Feb 28 17:14:03 2009	(r189172)
@@ -92,7 +92,6 @@ struct usb2_cdev_privdata {
 	struct usb2_fifo	*txfifo;
 	int			bus_index;	/* bus index */
 	int			dev_index;	/* device index */
-	int			iface_index;	/* interface index */
 	int			ep_addr;	/* endpoint address */
 	uint8_t			fifo_index;	/* FIFO index */
 	uint8_t			is_read;	/* location has read access */
@@ -105,7 +104,6 @@ struct usb2_cdev_privdata {
 struct usb2_fs_privdata {
 	int bus_index;
 	int dev_index;
-	int iface_index;
 	int ep_addr;
 	int mode;
 	int fifo_index;

Modified: head/sys/dev/usb/usb_device.c
==============================================================================
--- head/sys/dev/usb/usb_device.c	Sat Feb 28 17:01:55 2009	(r189171)
+++ head/sys/dev/usb/usb_device.c	Sat Feb 28 17:14:03 2009	(r189172)
@@ -74,7 +74,7 @@ static usb2_error_t usb2_fill_iface_data
 		    uint8_t);
 static void	usb2_notify_addq(const char *type, struct usb2_device *);
 static void	usb2_fifo_free_wrap(struct usb2_device *, uint8_t, uint8_t);
-static struct cdev *usb2_make_dev(struct usb2_device *, int, int, int);
+static struct cdev *usb2_make_dev(struct usb2_device *, int, int);
 static void	usb2_cdev_create(struct usb2_device *);
 static void	usb2_cdev_free(struct usb2_device *);
 static void	usb2_cdev_cleanup(void *);
@@ -421,7 +421,6 @@ usb2_fill_iface_data(struct usb2_device 
 	iface->idesc = id;
 	iface->alt_index = alt_index;
 	iface->parent_iface_index = USB_IFACE_INDEX_ANY;
-	iface->ep_in_mask = iface->ep_out_mask = 0;
 
 	nendpt = id->bNumEndpoints;
 	DPRINTFN(5, "found idesc nendpt=%d\n", nendpt);
@@ -445,14 +444,6 @@ usb2_fill_iface_data(struct usb2_device 
 found:
 		ed = (void *)desc;
 
-		/* Fill in the endpoint bitmasks */
-		if (ed->bEndpointAddress & UE_DIR_IN)
-			iface->ep_in_mask |=
-			    1 << UE_GET_ADDR(ed->bEndpointAddress);
-		else
-			iface->ep_out_mask |=
-			    1 << UE_GET_ADDR(ed->bEndpointAddress);
-
 		/* find a free pipe */
 		while (pipe != pipe_end) {
 			if (pipe->edesc == NULL) {
@@ -730,7 +721,6 @@ usb2_set_alt_interface_index(struct usb2
 	 * Free all generic FIFOs for this interface, except control
 	 * endpoint FIFOs:
 	 */
-	usb2_cdev_free(udev);
 	usb2_fifo_free_wrap(udev, iface_index, 0);
 
 	err = usb2_fill_iface_data(udev, iface_index, alt_index);
@@ -740,9 +730,6 @@ usb2_set_alt_interface_index(struct usb2
 	err = usb2_req_set_alt_interface_no(udev, NULL, iface_index,
 	    iface->idesc->bAlternateSetting);
 
-	/* create device nodes for each endpoint */
-	usb2_cdev_create(udev);
-
 done:
 	if (do_unlock) {
 		sx_unlock(udev->default_sx + 1);
@@ -1447,7 +1434,7 @@ usb2_alloc_device(device_t parent_dev, s
 	udev->device_index = device_index;
 
 	/* Create the control endpoint device */
-	udev->default_dev = usb2_make_dev(udev, 0 , 0, FREAD|FWRITE);
+	udev->default_dev = usb2_make_dev(udev, 0, FREAD|FWRITE);
 	/* Create a link from /dev/ugenX.X to the default endpoint */
 	snprintf(udev->ugen_name, sizeof(udev->ugen_name),
 	    USB_GENERIC_NAME "%u.%u", device_get_unit(bus->bdev),
@@ -1720,7 +1707,7 @@ done:
 }
 
 static struct cdev *
-usb2_make_dev(struct usb2_device *udev, int iface_index, int ep, int mode)
+usb2_make_dev(struct usb2_device *udev, int ep, int mode)
 {
 	struct usb2_fs_privdata* pd;
 	char devname[20];
@@ -1730,14 +1717,13 @@ usb2_make_dev(struct usb2_device *udev, 
 	    M_WAITOK | M_ZERO);
 	pd->bus_index = device_get_unit(udev->bus->bdev);
 	pd->dev_index = udev->device_index;
-	pd->iface_index = iface_index;
 	pd->ep_addr = ep;
 	pd->mode = mode;
 
 	/* Now, create the device itself */
-	snprintf(devname, sizeof(devname), "%u.%u.%u.%u",
+	snprintf(devname, sizeof(devname), "%u.%u.%u",
 	    pd->bus_index, pd->dev_index,
-	    pd->iface_index, pd->ep_addr);
+	    pd->ep_addr);
 	pd->cdev = make_dev(&usb2_devsw, 0, UID_ROOT,
 	    GID_OPERATOR, 0600, USB_DEVICE_DIR "/%s", devname);
 	pd->cdev->si_drv1 = pd;
@@ -1748,20 +1734,18 @@ usb2_make_dev(struct usb2_device *udev, 
 static void
 usb2_cdev_create(struct usb2_device *udev)
 {
-	struct usb2_interface *iface;
+	struct usb2_config_descriptor *cd = usb2_get_config_descriptor(udev);
+	struct usb2_endpoint_descriptor *ed;
+	struct usb2_descriptor *desc;
 	struct usb2_fs_privdata* pd;
 	struct cdev *dev;
-	uint8_t niface;
-	int i, ep, mode, inmode, outmode;
+	int inmode, outmode, inmask, outmask, mode;
+	uint8_t ep;
 
 	KASSERT(LIST_FIRST(&udev->pd_list) == NULL, ("stale cdev entries"));
 
 	DPRINTFN(2, "Creating device nodes\n");
 
-	usb2_interface_count(udev, &niface);
-	if (niface == 0)
-		return;		/* nothing to do */
-
 	if (usb2_get_mode(udev) == USB_MODE_DEVICE) {
 		inmode = FWRITE;
 		outmode = FREAD;
@@ -1770,24 +1754,40 @@ usb2_cdev_create(struct usb2_device *ude
 		outmode = FWRITE;
 	}
 
-	for (i = 0; i < niface; i++) {
-		iface = usb2_get_iface(udev, i);
-		if (iface == NULL)
-			break;
+	inmask = 0;
+	outmask = 0;
+	desc = NULL;
 
-		/* Create all available endpoints except EP0 */
-		for (ep = 1; ep < 16; ep++) {
-			mode = 0;
-			mode |= iface->ep_in_mask & (1 << ep) ? inmode : 0;
-			mode |= iface->ep_out_mask & (1 << ep) ? outmode : 0;
-			if (mode == 0)
-				continue;	/* no IN or OUT endpoint */
-
-			dev = usb2_make_dev(udev, i , ep, mode);
-			pd = dev->si_drv1;
-			LIST_INSERT_HEAD(&udev->pd_list, pd, pd_next);
+	/*
+	 * Collect all used endpoint numbers instead of just
+	 * generating 16 static endpoints.
+	 */
+	while ((desc = usb2_desc_foreach(cd, desc))) {
+		/* filter out all endpoint descriptors */
+		if ((desc->bDescriptorType == UDESC_ENDPOINT) &&
+		    (desc->bLength >= sizeof(*ed))) {
+			ed = (struct usb2_endpoint_descriptor *)desc;
+
+			/* update masks */
+			ep = ed->bEndpointAddress;
+			if (UE_GET_DIR(ep)  == UE_DIR_OUT)
+				outmask |= 1 << UE_GET_ADDR(ep);
+			else
+				inmask |= 1 << UE_GET_ADDR(ep);
 		}
 	}
+
+	/* Create all available endpoints except EP0 */
+	for (ep = 1; ep < 16; ep++) {
+		mode = inmask & (1 << ep) ? inmode : 0;
+		mode |= outmask & (1 << ep) ? outmode : 0;
+		if (mode == 0)
+			continue;	/* no IN or OUT endpoint */
+
+		dev = usb2_make_dev(udev, ep, mode);
+		pd = dev->si_drv1;
+		LIST_INSERT_HEAD(&udev->pd_list, pd, pd_next);
+	}
 }
 
 static void

Modified: head/sys/dev/usb/usb_device.h
==============================================================================
--- head/sys/dev/usb/usb_device.h	Sat Feb 28 17:01:55 2009	(r189171)
+++ head/sys/dev/usb/usb_device.h	Sat Feb 28 17:14:03 2009	(r189172)
@@ -65,8 +65,6 @@ struct usb2_interface {
 	device_t subdev;
 	uint8_t	alt_index;
 	uint8_t	parent_iface_index;
-	uint16_t ep_in_mask;		/* bitmask of IN endpoints */
-	uint16_t ep_out_mask;		/* bitmask of OUT endpoints */
 };
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902281714.n1SHE3r5015514>