diff options
-rw-r--r-- | drivers/usb/gadget/f_uvc.c | 15 | ||||
-rw-r--r-- | drivers/usb/gadget/uvc.h | 1 | ||||
-rw-r--r-- | drivers/usb/gadget/uvc_v4l2.c | 14 |
3 files changed, 23 insertions, 7 deletions
diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 49939e44ed74..38dcedddc52c 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -266,6 +266,13 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) return 0; } +void uvc_function_setup_continue(struct uvc_device *uvc) +{ + struct usb_composite_dev *cdev = uvc->func.config->cdev; + + usb_composite_setup_continue(cdev); +} + static int uvc_function_get_alt(struct usb_function *f, unsigned interface) { @@ -328,7 +335,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) v4l2_event_queue(uvc->vdev, &v4l2_event); uvc->state = UVC_STATE_CONNECTED; - break; + return 0; case 1: if (uvc->state != UVC_STATE_CONNECTED) @@ -345,15 +352,11 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_STREAMON; v4l2_event_queue(uvc->vdev, &v4l2_event); - - uvc->state = UVC_STATE_STREAMING; - break; + return USB_GADGET_DELAYED_STATUS; default: return -EINVAL; } - - return 0; } static void diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h index 7e90b1d12d09..817e9e19cecf 100644 --- a/drivers/usb/gadget/uvc.h +++ b/drivers/usb/gadget/uvc.h @@ -188,6 +188,7 @@ struct uvc_file_handle * Functions */ +extern void uvc_function_setup_continue(struct uvc_device *uvc); extern void uvc_endpoint_stream(struct uvc_device *dev); extern void uvc_function_connect(struct uvc_device *uvc); diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c index 0080d073bd5e..2bb5af8d2b23 100644 --- a/drivers/usb/gadget/uvc_v4l2.c +++ b/drivers/usb/gadget/uvc_v4l2.c @@ -253,7 +253,19 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) if (*type != video->queue.type) return -EINVAL; - return uvc_video_enable(video, 1); + /* Enable UVC video. */ + ret = uvc_video_enable(video, 1); + if (ret < 0) + return ret; + + /* + * Complete the alternate setting selection setup phase now that + * userspace is ready to provide video frames. + */ + uvc_function_setup_continue(uvc); + uvc->state = UVC_STATE_STREAMING; + + return 0; } case VIDIOC_STREAMOFF: |