aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/function/f_uvc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/function/f_uvc.c')
-rw-r--r--drivers/usb/gadget/function/f_uvc.c54
1 files changed, 44 insertions, 10 deletions
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
index e126439e4b65..945b3bd2ca98 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -279,27 +279,41 @@ uvc_function_get_alt(struct usb_function *f, unsigned interface)
279 else if (interface != uvc->streaming_intf) 279 else if (interface != uvc->streaming_intf)
280 return -EINVAL; 280 return -EINVAL;
281 else 281 else
282 return uvc->state == UVC_STATE_STREAMING ? 1 : 0; 282 return uvc->video.ep->driver_data ? 1 : 0;
283} 283}
284 284
285static int 285static int
286uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) 286uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
287{ 287{
288 struct uvc_device *uvc = to_uvc(f); 288 struct uvc_device *uvc = to_uvc(f);
289 struct usb_composite_dev *cdev = f->config->cdev;
289 struct v4l2_event v4l2_event; 290 struct v4l2_event v4l2_event;
290 struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; 291 struct uvc_event *uvc_event = (void *)&v4l2_event.u.data;
291 int ret; 292 int ret;
292 293
293 INFO(f->config->cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt); 294 INFO(cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt);
294 295
295 if (interface == uvc->control_intf) { 296 if (interface == uvc->control_intf) {
296 if (alt) 297 if (alt)
297 return -EINVAL; 298 return -EINVAL;
298 299
300 if (uvc->control_ep->driver_data) {
301 INFO(cdev, "reset UVC Control\n");
302 usb_ep_disable(uvc->control_ep);
303 uvc->control_ep->driver_data = NULL;
304 }
305
306 if (!uvc->control_ep->desc)
307 if (config_ep_by_speed(cdev->gadget, f, uvc->control_ep))
308 return -EINVAL;
309
310 usb_ep_enable(uvc->control_ep);
311 uvc->control_ep->driver_data = uvc;
312
299 if (uvc->state == UVC_STATE_DISCONNECTED) { 313 if (uvc->state == UVC_STATE_DISCONNECTED) {
300 memset(&v4l2_event, 0, sizeof(v4l2_event)); 314 memset(&v4l2_event, 0, sizeof(v4l2_event));
301 v4l2_event.type = UVC_EVENT_CONNECT; 315 v4l2_event.type = UVC_EVENT_CONNECT;
302 uvc_event->speed = f->config->cdev->gadget->speed; 316 uvc_event->speed = cdev->gadget->speed;
303 v4l2_event_queue(uvc->vdev, &v4l2_event); 317 v4l2_event_queue(uvc->vdev, &v4l2_event);
304 318
305 uvc->state = UVC_STATE_CONNECTED; 319 uvc->state = UVC_STATE_CONNECTED;
@@ -321,8 +335,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
321 if (uvc->state != UVC_STATE_STREAMING) 335 if (uvc->state != UVC_STATE_STREAMING)
322 return 0; 336 return 0;
323 337
324 if (uvc->video.ep) 338 if (uvc->video.ep) {
325 usb_ep_disable(uvc->video.ep); 339 usb_ep_disable(uvc->video.ep);
340 uvc->video.ep->driver_data = NULL;
341 }
326 342
327 memset(&v4l2_event, 0, sizeof(v4l2_event)); 343 memset(&v4l2_event, 0, sizeof(v4l2_event));
328 v4l2_event.type = UVC_EVENT_STREAMOFF; 344 v4l2_event.type = UVC_EVENT_STREAMOFF;
@@ -335,14 +351,22 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
335 if (uvc->state != UVC_STATE_CONNECTED) 351 if (uvc->state != UVC_STATE_CONNECTED)
336 return 0; 352 return 0;
337 353
338 if (uvc->video.ep) { 354 if (!uvc->video.ep)
339 ret = config_ep_by_speed(f->config->cdev->gadget, 355 return -EINVAL;
340 &(uvc->func), uvc->video.ep); 356
341 if (ret) 357 if (uvc->video.ep->driver_data) {
342 return ret; 358 INFO(cdev, "reset UVC\n");
343 usb_ep_enable(uvc->video.ep); 359 usb_ep_disable(uvc->video.ep);
360 uvc->video.ep->driver_data = NULL;
344 } 361 }
345 362
363 ret = config_ep_by_speed(f->config->cdev->gadget,
364 &(uvc->func), uvc->video.ep);
365 if (ret)
366 return ret;
367 usb_ep_enable(uvc->video.ep);
368 uvc->video.ep->driver_data = uvc;
369
346 memset(&v4l2_event, 0, sizeof(v4l2_event)); 370 memset(&v4l2_event, 0, sizeof(v4l2_event));
347 v4l2_event.type = UVC_EVENT_STREAMON; 371 v4l2_event.type = UVC_EVENT_STREAMON;
348 v4l2_event_queue(uvc->vdev, &v4l2_event); 372 v4l2_event_queue(uvc->vdev, &v4l2_event);
@@ -366,6 +390,16 @@ uvc_function_disable(struct usb_function *f)
366 v4l2_event_queue(uvc->vdev, &v4l2_event); 390 v4l2_event_queue(uvc->vdev, &v4l2_event);
367 391
368 uvc->state = UVC_STATE_DISCONNECTED; 392 uvc->state = UVC_STATE_DISCONNECTED;
393
394 if (uvc->video.ep->driver_data) {
395 usb_ep_disable(uvc->video.ep);
396 uvc->video.ep->driver_data = NULL;
397 }
398
399 if (uvc->control_ep->driver_data) {
400 usb_ep_disable(uvc->control_ep);
401 uvc->control_ep->driver_data = NULL;
402 }
369} 403}
370 404
371/* -------------------------------------------------------------------------- 405/* --------------------------------------------------------------------------