diff options
-rw-r--r-- | sys/dev/usb/image/uscanner.c | 2 | ||||
-rw-r--r-- | sys/dev/usb/serial/ulpt.c | 6 | ||||
-rw-r--r-- | sys/dev/usb/usb_dev.c | 114 | ||||
-rw-r--r-- | sys/dev/usb/usb_dev.h | 6 | ||||
-rw-r--r-- | sys/dev/usb/usb_device.h | 2 |
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 |