|
@@ -286,11 +286,12 @@ static int
|
|
uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
|
|
uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
|
|
{
|
|
{
|
|
struct uvc_device *uvc = to_uvc(f);
|
|
struct uvc_device *uvc = to_uvc(f);
|
|
|
|
+ struct usb_composite_dev *cdev = f->config->cdev;
|
|
struct v4l2_event v4l2_event;
|
|
struct v4l2_event v4l2_event;
|
|
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
|
|
struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
|
|
|
|
|
|
+ INFO(cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
|
|
|
|
|
|
if (interface == uvc->control_intf) {
|
|
if (interface == uvc->control_intf) {
|
|
if (alt)
|
|
if (alt)
|
|
@@ -299,7 +300,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
|
|
if (uvc->state == UVC_STATE_DISCONNECTED) {
|
|
if (uvc->state == UVC_STATE_DISCONNECTED) {
|
|
memset(&v4l2_event, 0, sizeof(v4l2_event));
|
|
memset(&v4l2_event, 0, sizeof(v4l2_event));
|
|
v4l2_event.type = UVC_EVENT_CONNECT;
|
|
v4l2_event.type = UVC_EVENT_CONNECT;
|
|
- uvc_event->speed = f->config->cdev->gadget->speed;
|
|
|
|
|
|
+ uvc_event->speed = cdev->gadget->speed;
|
|
v4l2_event_queue(uvc->vdev, &v4l2_event);
|
|
v4l2_event_queue(uvc->vdev, &v4l2_event);
|
|
|
|
|
|
uvc->state = UVC_STATE_CONNECTED;
|
|
uvc->state = UVC_STATE_CONNECTED;
|
|
@@ -321,8 +322,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
|
|
if (uvc->state != UVC_STATE_STREAMING)
|
|
if (uvc->state != UVC_STATE_STREAMING)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- if (uvc->video.ep)
|
|
|
|
|
|
+ if (uvc->video.ep) {
|
|
usb_ep_disable(uvc->video.ep);
|
|
usb_ep_disable(uvc->video.ep);
|
|
|
|
+ uvc->video.ep->driver_data = NULL;
|
|
|
|
+ }
|
|
|
|
|
|
memset(&v4l2_event, 0, sizeof(v4l2_event));
|
|
memset(&v4l2_event, 0, sizeof(v4l2_event));
|
|
v4l2_event.type = UVC_EVENT_STREAMOFF;
|
|
v4l2_event.type = UVC_EVENT_STREAMOFF;
|
|
@@ -335,14 +338,22 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
|
|
if (uvc->state != UVC_STATE_CONNECTED)
|
|
if (uvc->state != UVC_STATE_CONNECTED)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- if (uvc->video.ep) {
|
|
|
|
- ret = config_ep_by_speed(f->config->cdev->gadget,
|
|
|
|
- &(uvc->func), uvc->video.ep);
|
|
|
|
- if (ret)
|
|
|
|
- return ret;
|
|
|
|
- usb_ep_enable(uvc->video.ep);
|
|
|
|
|
|
+ if (!uvc->video.ep)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ if (uvc->video.ep->driver_data) {
|
|
|
|
+ INFO(cdev, "reset UVC\n");
|
|
|
|
+ usb_ep_disable(uvc->video.ep);
|
|
|
|
+ uvc->video.ep->driver_data = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ ret = config_ep_by_speed(f->config->cdev->gadget,
|
|
|
|
+ &(uvc->func), uvc->video.ep);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+ usb_ep_enable(uvc->video.ep);
|
|
|
|
+ uvc->video.ep->driver_data = uvc;
|
|
|
|
+
|
|
memset(&v4l2_event, 0, sizeof(v4l2_event));
|
|
memset(&v4l2_event, 0, sizeof(v4l2_event));
|
|
v4l2_event.type = UVC_EVENT_STREAMON;
|
|
v4l2_event.type = UVC_EVENT_STREAMON;
|
|
v4l2_event_queue(uvc->vdev, &v4l2_event);
|
|
v4l2_event_queue(uvc->vdev, &v4l2_event);
|