|
@@ -933,28 +933,24 @@ static void clean_req (struct usb_ep *ep, struct usb_request *req)
|
|
|
static void ep0_complete (struct usb_ep *ep, struct usb_request *req)
|
|
|
{
|
|
|
struct dev_data *dev = ep->driver_data;
|
|
|
+ unsigned long flags;
|
|
|
int free = 1;
|
|
|
|
|
|
/* for control OUT, data must still get to userspace */
|
|
|
+ spin_lock_irqsave(&dev->lock, flags);
|
|
|
if (!dev->setup_in) {
|
|
|
dev->setup_out_error = (req->status != 0);
|
|
|
if (!dev->setup_out_error)
|
|
|
free = 0;
|
|
|
dev->setup_out_ready = 1;
|
|
|
ep0_readable (dev);
|
|
|
- } else {
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- spin_lock_irqsave(&dev->lock, flags);
|
|
|
- if (dev->state == STATE_DEV_SETUP)
|
|
|
- dev->state = STATE_DEV_CONNECTED;
|
|
|
- spin_unlock_irqrestore(&dev->lock, flags);
|
|
|
}
|
|
|
|
|
|
/* clean up as appropriate */
|
|
|
if (free && req->buf != &dev->rbuf)
|
|
|
clean_req (ep, req);
|
|
|
req->complete = epio_complete;
|
|
|
+ spin_unlock_irqrestore(&dev->lock, flags);
|
|
|
}
|
|
|
|
|
|
static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len)
|
|
@@ -1036,6 +1032,13 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
|
|
|
spin_lock_irq (&dev->lock);
|
|
|
if (retval)
|
|
|
goto done;
|
|
|
+
|
|
|
+ if (dev->state != STATE_DEV_SETUP) {
|
|
|
+ retval = -ECANCELED;
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ dev->state = STATE_DEV_CONNECTED;
|
|
|
+
|
|
|
if (dev->setup_out_error)
|
|
|
retval = -EIO;
|
|
|
else {
|
|
@@ -1187,6 +1190,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
|
|
if (dev->setup_in) {
|
|
|
retval = setup_req (dev->gadget->ep0, dev->req, len);
|
|
|
if (retval == 0) {
|
|
|
+ dev->state = STATE_DEV_CONNECTED;
|
|
|
spin_unlock_irq (&dev->lock);
|
|
|
if (copy_from_user (dev->req->buf, buf, len))
|
|
|
retval = -EFAULT;
|