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-all
mailing list