From 9999e48639b3cecb08ffb37358bcba3b48161b29 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 10 May 2024 08:50:17 +0000 Subject: [PATCH] add ax88772_rst --- kernel/drivers/usb/gadget/function/uvc_v4l2.c | 76 +++++++++++++++++++++++++++----------- 1 files changed, 54 insertions(+), 22 deletions(-) diff --git a/kernel/drivers/usb/gadget/function/uvc_v4l2.c b/kernel/drivers/usb/gadget/function/uvc_v4l2.c index d822456..d1398ae 100644 --- a/kernel/drivers/usb/gadget/function/uvc_v4l2.c +++ b/kernel/drivers/usb/gadget/function/uvc_v4l2.c @@ -75,10 +75,6 @@ strlcpy(cap->card, cdev->gadget->name, sizeof(cap->card)); strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev), sizeof(cap->bus_info)); - - cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; - return 0; } @@ -119,8 +115,8 @@ } if (i == ARRAY_SIZE(uvc_formats)) { - printk(KERN_INFO "Unsupported format 0x%08x.\n", - fmt->fmt.pix.pixelformat); + uvcg_info(&uvc->func, "Unsupported format 0x%08x.\n", + fmt->fmt.pix.pixelformat); return -EINVAL; } @@ -177,7 +173,8 @@ if (ret < 0) return ret; - queue_work(video->async_wq, &video->pump); + if (uvc->state == UVC_STATE_STREAMING) + queue_work(video->async_wq, &video->pump); return ret; } @@ -217,16 +214,15 @@ * settings for zero-bandwidth and full-bandwidth * cases, but the same is not true for BULK endpoints, * as they have a single alt-setting. + * + * For ISOC endpoints, Complete the alternate setting + * selection setup phase now that userspace is ready + * to provide video frames. */ - if (!usb_endpoint_xfer_bulk(video->ep->desc)) { - /* - * Complete the alternate setting selection - * setup phase now that userspace is ready - * to provide video frames. - */ + if (!usb_endpoint_xfer_bulk(video->ep->desc)) uvc_function_setup_continue(uvc); - uvc->state = UVC_STATE_STREAMING; - } + + uvc->state = UVC_STATE_STREAMING; return 0; } @@ -248,17 +244,56 @@ uvc_v4l2_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) { + struct uvc_device *uvc = video_get_drvdata(fh->vdev); + struct uvc_file_handle *handle = to_uvc_file_handle(fh); + int ret; + if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST) return -EINVAL; - return v4l2_event_subscribe(fh, sub, 2, NULL); + if (sub->type == UVC_EVENT_SETUP && uvc->func_connected) + return -EBUSY; + + ret = v4l2_event_subscribe(fh, sub, 2, NULL); + if (ret < 0) + return ret; + + if (sub->type == UVC_EVENT_SETUP) { + uvc->func_connected = true; + handle->is_uvc_app_handle = true; + uvc_function_connect(uvc); + } + + return 0; +} + +static void uvc_v4l2_disable(struct uvc_device *uvc) +{ + uvc_function_disconnect(uvc); + uvcg_video_enable(&uvc->video, 0); + uvcg_free_buffers(&uvc->video.queue); + uvc->func_connected = false; + wake_up_interruptible(&uvc->func_connected_queue); } static int uvc_v4l2_unsubscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub) { - return v4l2_event_unsubscribe(fh, sub); + struct uvc_device *uvc = video_get_drvdata(fh->vdev); + struct uvc_file_handle *handle = to_uvc_file_handle(fh); + int ret; + + ret = v4l2_event_unsubscribe(fh, sub); + if (ret < 0) + return ret; + + if (sub->type == UVC_EVENT_SETUP && handle->is_uvc_app_handle) { + uvc_v4l2_disable(uvc); + handle->is_uvc_app_handle = false; + } + + return 0; } static long @@ -313,7 +348,6 @@ handle->device = &uvc->video; file->private_data = &handle->vfh; - uvc_function_connect(uvc); return 0; } @@ -325,11 +359,9 @@ struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data); struct uvc_video *video = handle->device; - uvc_function_disconnect(uvc); - mutex_lock(&video->mutex); - uvcg_video_enable(video, 0); - uvcg_free_buffers(&video->queue); + if (handle->is_uvc_app_handle) + uvc_v4l2_disable(uvc); mutex_unlock(&video->mutex); file->private_data = NULL; -- Gitblit v1.6.2