svn commit: r189906 - in head/sys/dev/usb: . image serial

Andrew Thompson thompsa at FreeBSD.org
Mon Mar 16 18:46:41 PDT 2009


Author: thompsa
Date: Tue Mar 17 01:46:40 2009
New Revision: 189906
URL: http://svn.freebsd.org/changeset/base/189906

Log:
  MFp4 //depot/projects/usb 159225,159241,159292
  
  Fix regression issue in the USB file system interface.
   - Use cdev_privdata pointer as indicator of correct file handle.
   - Remove redundant FIFO opened flags.
  
  Don't send ZLP at close for ulpt and uscanner devices as this causes some
  models to stop working. This reverts back to the USB1 behaviour.
  
  Submitted by:	Hans Petter Selasky

Modified:
  head/sys/dev/usb/image/uscanner.c
  head/sys/dev/usb/serial/ulpt.c
  head/sys/dev/usb/usb_dev.c
  head/sys/dev/usb/usb_dev.h
  head/sys/dev/usb/usb_device.h

Modified: head/sys/dev/usb/image/uscanner.c
==============================================================================
--- head/sys/dev/usb/image/uscanner.c	Tue Mar 17 01:42:46 2009	(r189905)
+++ head/sys/dev/usb/image/uscanner.c	Tue Mar 17 01:46:40 2009	(r189906)
@@ -149,7 +149,7 @@ static const struct usb2_config uscanner
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
 		.mh.bufsize = USCANNER_BSIZE,
-		.mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1,.force_short_xfer = 1,},
+		.mh.flags = {.pipe_bof = 1,.proxy_buffer = 1,},
 		.mh.callback = &uscanner_write_callback,
 	},
 

Modified: head/sys/dev/usb/serial/ulpt.c
==============================================================================
--- head/sys/dev/usb/serial/ulpt.c	Tue Mar 17 01:42:46 2009	(r189905)
+++ head/sys/dev/usb/serial/ulpt.c	Tue Mar 17 01:46:40 2009	(r189906)
@@ -200,7 +200,8 @@ ulpt_write_callback(struct usb2_xfer *xf
 		DPRINTF("no FIFO\n");
 		return;
 	}
-	DPRINTF("state=0x%x\n", USB_GET_STATE(xfer));
+	DPRINTF("state=0x%x actlen=%u\n",
+	    USB_GET_STATE(xfer), xfer->actlen);
 
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_TRANSFERRED:
@@ -208,7 +209,6 @@ ulpt_write_callback(struct usb2_xfer *xf
 tr_setup:
 		if (usb2_fifo_get_data(f, xfer->frbuffers,
 		    0, xfer->max_data_length, &actlen, 0)) {
-
 			xfer->frlengths[0] = actlen;
 			usb2_start_hardware(xfer);
 		}
@@ -339,7 +339,7 @@ static const struct usb2_config ulpt_con
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
 		.mh.bufsize = ULPT_BSIZE,
-		.mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1},
+		.mh.flags = {.pipe_bof = 1,.proxy_buffer = 1},
 		.mh.callback = &ulpt_write_callback,
 	},
 

Modified: head/sys/dev/usb/usb_dev.c
==============================================================================
--- head/sys/dev/usb/usb_dev.c	Tue Mar 17 01:42:46 2009	(r189905)
+++ head/sys/dev/usb/usb_dev.c	Tue Mar 17 01:46:40 2009	(r189906)
@@ -72,7 +72,8 @@ SYSCTL_INT(_hw_usb2_dev, OID_AUTO, debug
 
 /* prototypes */
 
-static int	usb2_fifo_open(struct usb2_fifo *, int);
+static int	usb2_fifo_open(struct usb2_cdev_privdata *, 
+		    struct usb2_fifo *, int);
 static void	usb2_fifo_close(struct usb2_fifo *, int);
 static void	usb2_dev_init(void *);
 static void	usb2_dev_init_post(void *);
@@ -160,7 +161,6 @@ usb2_ref_device(struct usb2_cdev_privdat
 {
 	struct usb2_fifo **ppf;
 	struct usb2_fifo *f;
-	int dev_ep_index;
 
 	DPRINTFN(2, "usb2_ref_device, cpd=%p need uref=%d\n", cpd, need_uref);
 
@@ -180,7 +180,6 @@ usb2_ref_device(struct usb2_cdev_privdat
 		goto error;
 	}
 	/* check if we are doing an open */
-	dev_ep_index = cpd->ep_addr;
 	if (cpd->fflags == 0) {
 		/* set defaults */
 		cpd->txfifo = NULL;
@@ -200,15 +199,12 @@ usb2_ref_device(struct usb2_cdev_privdat
 			cpd->is_write = 1;	/* ref */
 			if (f == NULL || f->refcount == USB_FIFO_REF_MAX)
 				goto error;
+			if (f->curr_cpd != cpd)
+				goto error;
 			/* check if USB-FS is active */
 			if (f->fs_ep_max != 0) {
 				cpd->is_usbfs = 1;
 			}
-			/*
-			 * Get real endpoint index associated with
-			 * this FIFO:
-			 */
-			dev_ep_index = f->dev_ep_index;
 		} else {
 			cpd->txfifo = NULL;
 			cpd->is_write = 0;	/* no ref */
@@ -222,15 +218,12 @@ usb2_ref_device(struct usb2_cdev_privdat
 			cpd->is_read = 1;	/* ref */
 			if (f == NULL || f->refcount == USB_FIFO_REF_MAX)
 				goto error;
+			if (f->curr_cpd != cpd)
+				goto error;
 			/* check if USB-FS is active */
 			if (f->fs_ep_max != 0) {
 				cpd->is_usbfs = 1;
 			}
-			/*
-			 * Get real endpoint index associated with
-			 * this FIFO:
-			 */
-			dev_ep_index = f->dev_ep_index;
 		} else {
 			cpd->rxfifo = NULL;
 			cpd->is_read = 0;	/* no ref */
@@ -434,7 +427,7 @@ usb2_fifo_create(struct usb2_cdev_privda
 					/* wrong endpoint index */
 					continue;
 				}
-				if (f->opened) {
+				if (f->curr_cpd != NULL) {
 					/* FIFO is opened */
 					is_busy = 1;
 					continue;
@@ -451,7 +444,7 @@ usb2_fifo_create(struct usb2_cdev_privda
 					/* wrong endpoint index */
 					continue;
 				}
-				if (f->opened) {
+				if (f->curr_cpd != NULL) {
 					/* FIFO is opened */
 					is_busy = 1;
 					continue;
@@ -466,10 +459,20 @@ usb2_fifo_create(struct usb2_cdev_privda
 	if (no_null == 0) {
 		if (ep >= (USB_EP_MAX / 2)) {
 			/* we don't create any endpoints in this range */
-			DPRINTFN(5, "dev_ep_index out of range\n");
+			DPRINTFN(5, "ep out of range\n");
 			return (is_busy ? EBUSY : EINVAL);
 		}
 	}
+
+	if ((ep != 0) && is_busy) {
+		/*
+		 * Only the default control endpoint is allowed to be
+		 * opened multiple times!
+		 */
+		DPRINTFN(5, "busy\n");
+		return (EBUSY);
+	}
+
 	/* Check TX FIFO */
 	if (is_tx &&
 	    (udev->fifo[n + USB_FIFO_TX] == NULL)) {
@@ -639,7 +642,8 @@ usb2_dev_get_pipe(struct usb2_device *ud
  * Else: Failure
  *------------------------------------------------------------------------*/
 static int
-usb2_fifo_open(struct usb2_fifo *f, int fflags)
+usb2_fifo_open(struct usb2_cdev_privdata *cpd, 
+    struct usb2_fifo *f, int fflags)
 {
 	int err;
 
@@ -660,11 +664,14 @@ usb2_fifo_open(struct usb2_fifo *f, int 
 
 	/* check if we are already opened */
 	/* we don't need any locks when checking this variable */
-	if (f->opened) {
+	if (f->curr_cpd != NULL) {
 		err = EBUSY;
 		goto done;
 	}
 
+	/* reset short flag before open */
+	f->flag_short = 0;
+
 	/* call open method */
 	err = (f->methods->f_open) (f, fflags);
 	if (err) {
@@ -690,9 +697,9 @@ usb2_fifo_open(struct usb2_fifo *f, int 
 	/* reset ASYNC proc flag */
 	f->async_p = NULL;
 
-	/* flag the fifo as opened to prevent others */
 	mtx_lock(&usb2_ref_lock);
-	f->opened = 1;
+	/* flag the fifo as opened to prevent others */
+	f->curr_cpd = cpd;
 	mtx_unlock(&usb2_ref_lock);
 
 	/* reset queue */
@@ -733,14 +740,14 @@ usb2_fifo_close(struct usb2_fifo *f, int
 	int err;
 
 	/* check if we are not opened */
-	if (!f->opened) {
+	if (f->curr_cpd == NULL) {
 		/* nothing to do - already closed */
 		return;
 	}
 	mtx_lock(f->priv_mtx);
 
-	/* clear current file flag */
-	f->opened = 0;
+	/* clear current cdev private data pointer */
+	f->curr_cpd = NULL;
 
 	/* check if we are selected */
 	if (f->flag_isselect) {
@@ -834,21 +841,6 @@ usb2_open(struct cdev *dev, int fflags, 
 	}
 	cpd->fflags = fflags;	/* access mode for open lifetime */
 
-	/* Check if the endpoint is already open, we always allow EP0 */
-	if (ep > 0) {
-		if ((fflags & FREAD && cpd->udev->ep_rd_opened & (1 << ep)) ||
-		    (fflags & FWRITE && cpd->udev->ep_wr_opened & (1 << ep))) {
-			DPRINTFN(2, "endpoint already open\n");
-			usb2_unref_device(cpd);
-			free(cpd, M_USBDEV);
-			return (EBUSY);
-		}
-		if (fflags & FREAD)
-			cpd->udev->ep_rd_opened |= (1 << ep);
-		if (fflags & FWRITE)
-			cpd->udev->ep_wr_opened |= (1 << ep);
-	}
-
 	/* create FIFOs, if any */
 	err = usb2_fifo_create(cpd);
 	/* check for error */
@@ -859,7 +851,7 @@ usb2_open(struct cdev *dev, int fflags, 
 		return (err);
 	}
 	if (fflags & FREAD) {
-		err = usb2_fifo_open(cpd->rxfifo, fflags);
+		err = usb2_fifo_open(cpd, cpd->rxfifo, fflags);
 		if (err) {
 			DPRINTFN(2, "read open failed\n");
 			usb2_unref_device(cpd);
@@ -868,7 +860,7 @@ usb2_open(struct cdev *dev, int fflags, 
 		}
 	}
 	if (fflags & FWRITE) {
-		err = usb2_fifo_open(cpd->txfifo, fflags);
+		err = usb2_fifo_open(cpd, cpd->txfifo, fflags);
 		if (err) {
 			DPRINTFN(2, "write open failed\n");
 			if (fflags & FREAD) {
@@ -892,27 +884,20 @@ static void
 usb2_close(void *arg)
 {
 	struct usb2_cdev_privdata *cpd = arg;
-	struct usb2_device *udev;
 	int err;
 
-	DPRINTFN(2, "usb2_close, cpd=%p\n", cpd);
+	DPRINTFN(2, "cpd=%p\n", cpd);
 
 	err = usb2_ref_device(cpd, 1);
 	if (err) {
 		free(cpd, M_USBDEV);
 		return;
 	}
-
-	udev = cpd->udev;
 	if (cpd->fflags & FREAD) {
 		usb2_fifo_close(cpd->rxfifo, cpd->fflags);
-		/* clear read bitmask */
-		udev->ep_rd_opened &= ~(1 << cpd->ep_addr);
 	}
 	if (cpd->fflags & FWRITE) {
 		usb2_fifo_close(cpd->txfifo, cpd->fflags);
-		/* clear write bitmask */
-		udev->ep_wr_opened &= ~(1 << cpd->ep_addr);
 	}
 
 	usb2_unref_device(cpd);
@@ -1621,7 +1606,6 @@ usb2_fifo_attach(struct usb2_device *ude
 	/* initialise FIFO structures */
 
 	f_tx->fifo_index = n + USB_FIFO_TX;
-	f_tx->dev_ep_index = (n / 2) + (USB_EP_MAX / 2);
 	f_tx->priv_mtx = priv_mtx;
 	f_tx->priv_sc0 = priv_sc;
 	f_tx->methods = pm;
@@ -1629,7 +1613,6 @@ usb2_fifo_attach(struct usb2_device *ude
 	f_tx->udev = udev;
 
 	f_rx->fifo_index = n + USB_FIFO_RX;
-	f_rx->dev_ep_index = (n / 2) + (USB_EP_MAX / 2);
 	f_rx->priv_mtx = priv_mtx;
 	f_rx->priv_sc0 = priv_sc;
 	f_rx->methods = pm;
@@ -1684,12 +1667,13 @@ usb2_fifo_attach(struct usb2_device *ude
 		pd->bus_index = device_get_unit(udev->bus->bdev);
 		pd->dev_index = udev->device_index;
 		pd->ep_addr = -1;	/* not an endpoint */
-		pd->fifo_index = f_tx->fifo_index;
+		pd->fifo_index = f_tx->fifo_index & f_rx->fifo_index;
 		pd->mode = FREAD|FWRITE;
 
 		/* Now, create the device itself */
 		f_sc->dev = make_dev(&usb2_devsw, 0, uid, gid, mode,
 		    devname);
+		/* XXX setting si_drv1 and creating the device is not atomic! */
 		f_sc->dev->si_drv1 = pd;
 	}
 
@@ -1762,7 +1746,9 @@ usb2_fifo_detach(struct usb2_fifo_sc *f_
 	f_sc->fp[USB_FIFO_RX] = NULL;
 
 	if (f_sc->dev != NULL) {
-		destroy_dev_sched_cb(f_sc->dev, usb2_fifo_cleanup, f_sc->dev->si_drv1);
+		destroy_dev_sched_cb(f_sc->dev, 
+		    usb2_fifo_cleanup, f_sc->dev->si_drv1);
+		f_sc->dev = NULL;
 	}
 
 	DPRINTFN(2, "detached %p\n", f_sc);
@@ -1949,6 +1935,13 @@ usb2_fifo_get_data(struct usb2_fifo *f, 
 				break;
 			}
 			if (f->flag_flushing) {
+				/* check if we should send a short packet */
+				if (f->flag_short != 0) {
+					f->flag_short = 0;
+					tr_data = 1;
+					break;
+				}
+				/* flushing complete */
 				f->flag_flushing = 0;
 				usb2_fifo_wakeup(f);
 			}
@@ -2007,6 +2000,13 @@ usb2_fifo_get_data_linear(struct usb2_fi
 				break;
 			}
 			if (f->flag_flushing) {
+				/* check if we should send a short packet */
+				if (f->flag_short != 0) {
+					f->flag_short = 0;
+					tr_data = 1;
+					break;
+				}
+				/* flushing complete */
 				f->flag_flushing = 0;
 				usb2_fifo_wakeup(f);
 			}
@@ -2186,3 +2186,13 @@ usb2_read_symlink(uint8_t *user_ptr, uin
 	sx_unlock(&usb2_sym_lock);
 	return (error);
 }
+
+void
+usb2_fifo_set_close_zlp(struct usb2_fifo *f, uint8_t onoff)
+{
+	if (f == NULL)
+		return;
+
+	/* send a Zero Length Packet, ZLP, before close */
+	f->flag_short = onoff;
+}

Modified: head/sys/dev/usb/usb_dev.h
==============================================================================
--- head/sys/dev/usb/usb_dev.h	Tue Mar 17 01:42:46 2009	(r189905)
+++ head/sys/dev/usb/usb_dev.h	Tue Mar 17 01:46:40 2009	(r189906)
@@ -93,12 +93,12 @@ struct usb2_cdev_privdata {
 	int			bus_index;	/* bus index */
 	int			dev_index;	/* device index */
 	int			ep_addr;	/* endpoint address */
+	int			fflags;
 	uint8_t			fifo_index;	/* FIFO index */
 	uint8_t			is_read;	/* location has read access */
 	uint8_t			is_write;	/* location has write access */
 	uint8_t			is_uref;	/* USB refcount decr. needed */
 	uint8_t			is_usbfs;	/* USB-FS is active */
-	int			fflags;
 };
 
 struct usb2_fs_privdata {
@@ -130,7 +130,8 @@ struct usb2_fifo {
 	struct usb2_xfer *xfer[2];
 	struct usb2_xfer **fs_xfer;
 	struct mtx *priv_mtx;		/* client data */
-	int    opened;			/* set if FIFO is opened by a FILE */
+	/* set if FIFO is opened by a FILE: */
+	struct usb2_cdev_privdata *curr_cpd;
 	void   *priv_sc0;		/* client data */
 	void   *priv_sc1;		/* client data */
 	void   *queue_data;
@@ -194,5 +195,6 @@ struct usb2_symlink *usb2_alloc_symlink(
 void	usb2_free_symlink(struct usb2_symlink *ps);
 int	usb2_read_symlink(uint8_t *user_ptr, uint32_t startentry,
 	    uint32_t user_len);
+void	usb2_fifo_set_close_zlp(struct usb2_fifo *, uint8_t);
 
 #endif					/* _USB2_DEV_H_ */

Modified: head/sys/dev/usb/usb_device.h
==============================================================================
--- head/sys/dev/usb/usb_device.h	Tue Mar 17 01:42:46 2009	(r189905)
+++ head/sys/dev/usb/usb_device.h	Tue Mar 17 01:46:40 2009	(r189906)
@@ -127,8 +127,6 @@ struct usb2_device {
 
 	uint32_t plugtime;		/* copy of "ticks" */
 
-	uint16_t ep_rd_opened;		/* bitmask of endpoints opened */
-	uint16_t ep_wr_opened;		/*  from the device nodes. */
 	uint16_t refcount;
 #define	USB_DEV_REF_MAX 0xffff
 


More information about the svn-src-head mailing list