|
@@ -135,6 +135,7 @@ struct dev_data {
|
|
setup_out_ready : 1,
|
|
setup_out_ready : 1,
|
|
setup_out_error : 1,
|
|
setup_out_error : 1,
|
|
setup_abort : 1;
|
|
setup_abort : 1;
|
|
|
|
+ unsigned setup_wLength;
|
|
|
|
|
|
/* the rest is basically write-once */
|
|
/* the rest is basically write-once */
|
|
struct usb_config_descriptor *config, *hs_config;
|
|
struct usb_config_descriptor *config, *hs_config;
|
|
@@ -942,6 +943,7 @@ static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len)
|
|
}
|
|
}
|
|
req->complete = ep0_complete;
|
|
req->complete = ep0_complete;
|
|
req->length = len;
|
|
req->length = len;
|
|
|
|
+ req->zero = 0;
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1161,10 +1163,13 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
|
spin_unlock_irq (&dev->lock);
|
|
spin_unlock_irq (&dev->lock);
|
|
if (copy_from_user (dev->req->buf, buf, len))
|
|
if (copy_from_user (dev->req->buf, buf, len))
|
|
retval = -EFAULT;
|
|
retval = -EFAULT;
|
|
- else
|
|
|
|
|
|
+ else {
|
|
|
|
+ if (len < dev->setup_wLength)
|
|
|
|
+ dev->req->zero = 1;
|
|
retval = usb_ep_queue (
|
|
retval = usb_ep_queue (
|
|
dev->gadget->ep0, dev->req,
|
|
dev->gadget->ep0, dev->req,
|
|
GFP_KERNEL);
|
|
GFP_KERNEL);
|
|
|
|
+ }
|
|
if (retval < 0) {
|
|
if (retval < 0) {
|
|
spin_lock_irq (&dev->lock);
|
|
spin_lock_irq (&dev->lock);
|
|
clean_req (dev->gadget->ep0, dev->req);
|
|
clean_req (dev->gadget->ep0, dev->req);
|
|
@@ -1483,6 +1488,7 @@ unrecognized:
|
|
delegate:
|
|
delegate:
|
|
dev->setup_in = (ctrl->bRequestType & USB_DIR_IN)
|
|
dev->setup_in = (ctrl->bRequestType & USB_DIR_IN)
|
|
? 1 : 0;
|
|
? 1 : 0;
|
|
|
|
+ dev->setup_wLength = w_length;
|
|
dev->setup_out_ready = 0;
|
|
dev->setup_out_ready = 0;
|
|
dev->setup_out_error = 0;
|
|
dev->setup_out_error = 0;
|
|
value = 0;
|
|
value = 0;
|