summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/usb/image/uscanner.c2
-rw-r--r--sys/dev/usb/serial/ulpt.c6
-rw-r--r--sys/dev/usb/usb_dev.c114
-rw-r--r--sys/dev/usb/usb_dev.h6
-rw-r--r--sys/dev/usb/usb_device.h2
5 files changed, 70 insertions, 60 deletions
diff --git a/sys/dev/usb/image/uscanner.c b/sys/dev/usb/image/uscanner.c
index 916295e..946b35e 100644
--- a/sys/dev/usb/image/uscanner.c
+++ b/sys/dev/usb/image/uscanner.c
@@ -149,7 +149,7 @@ static const struct usb2_config uscanner_config[USCANNER_N_TRANSFER] = {
.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,
},
diff --git a/sys/dev/usb/serial/ulpt.c b/sys/dev/usb/serial/ulpt.c
index 2ecce99..56ff9fc 100644
--- a/sys/dev/usb/serial/ulpt.c
+++ b/sys/dev/usb/serial/ulpt.c
@@ -200,7 +200,8 @@ ulpt_write_callback(struct usb2_xfer *xfer)
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 *xfer)
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_config[ULPT_N_TRANSFER] = {
.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,
},
diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c
index 512b1f8..d3d98ff 100644
--- a/sys/dev/usb/usb_dev.c
+++ b/sys/dev/usb/usb_dev.c
@@ -72,7 +72,8 @@ SYSCTL_INT(_hw_usb2_dev, OID_AUTO, debug, CTLFLAG_RW,
/* 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_privdata* cpd, int need_uref)
{
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_privdata* cpd, int need_uref)
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_privdata* cpd, int need_uref)
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_privdata* cpd, int need_uref)
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_privdata *cpd)
/* 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_privdata *cpd)
/* 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_privdata *cpd)
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 *udev, uint8_t ep_index, uint8_t dir)
* 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 fflags)
/* 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 fflags)
/* 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 fflags)
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, int devtype, struct thread *td)
}
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, int devtype, struct thread *td)
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, int devtype, struct thread *td)
}
}
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 *udev, void *priv_sc,
/* 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 *udev, void *priv_sc,
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 *udev, void *priv_sc,
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_sc)
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, struct usb2_page_cache *pc,
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_fifo *f, void *ptr,
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, uint32_t startentry, uint32_t user_len)
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;
+}
diff --git a/sys/dev/usb/usb_dev.h b/sys/dev/usb/usb_dev.h
index 92be7af..e1c8b94 100644
--- a/sys/dev/usb/usb_dev.h
+++ b/sys/dev/usb/usb_dev.h
@@ -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(const char *target);
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_ */
diff --git a/sys/dev/usb/usb_device.h b/sys/dev/usb/usb_device.h
index 8ebf9e5..a6a5d79 100644
--- a/sys/dev/usb/usb_device.h
+++ b/sys/dev/usb/usb_device.h
@@ -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
OpenPOWER on IntegriCloud