From 8d2a02b24d66aa359e83eebc1ed3c0f85367a1cb Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Thu, 16 May 2024 03:11:33 +0000 Subject: [PATCH] AX88772C_eeprom and ax8872c build together --- kernel/drivers/usb/gadget/function/f_uvc.c | 117 +++++++++++++++++++++++++++++++++------------------------- 1 files changed, 66 insertions(+), 51 deletions(-) diff --git a/kernel/drivers/usb/gadget/function/f_uvc.c b/kernel/drivers/usb/gadget/function/f_uvc.c index dba91c5..2b7f5be 100644 --- a/kernel/drivers/usb/gadget/function/f_uvc.c +++ b/kernel/drivers/usb/gadget/function/f_uvc.c @@ -44,7 +44,7 @@ #define UVC_STRING_STREAMING_IDX 1 static struct usb_string uvc_en_us_strings[] = { - [UVC_STRING_CONTROL_IDX].s = "UVC Camera", + /* [UVC_STRING_CONTROL_IDX].s = DYNAMIC, */ [UVC_STRING_STREAMING_IDX].s = "Video Streaming", { } }; @@ -263,11 +263,6 @@ (struct usb_descriptor_header *)&uvc_ss_bulk_streaming_comp, NULL, }; -void uvc_set_trace_param(unsigned int trace) -{ - uvc_gadget_trace_param = trace; -} -EXPORT_SYMBOL(uvc_set_trace_param); /* -------------------------------------------------------------------------- * Control requests @@ -289,8 +284,9 @@ memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_DATA; - uvc_event->data.length = req->actual; - memcpy(&uvc_event->data.data, req->buf, req->actual); + uvc_event->data.length = min_t(unsigned int, req->actual, + sizeof(uvc_event->data.data)); + memcpy(&uvc_event->data.data, req->buf, uvc_event->data.length); v4l2_event_queue(&uvc->vdev, &v4l2_event); } } @@ -302,18 +298,13 @@ struct v4l2_event v4l2_event; struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; - /* printk(KERN_INFO "setup request %02x %02x value %04x index %04x %04x\n", - * ctrl->bRequestType, ctrl->bRequest, le16_to_cpu(ctrl->wValue), - * le16_to_cpu(ctrl->wIndex), le16_to_cpu(ctrl->wLength)); - */ - uvc_trace(UVC_TRACE_CONTROL, "setup request %02x %02x value %04x index %04x %04x\n", ctrl->bRequestType, ctrl->bRequest, le16_to_cpu(ctrl->wValue), le16_to_cpu(ctrl->wIndex), le16_to_cpu(ctrl->wLength)); if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) { - INFO(f->config->cdev, "invalid request type\n"); + uvcg_info(f, "invalid request type\n"); return -EINVAL; } @@ -348,7 +339,7 @@ struct uvc_device *uvc = to_uvc(f); struct f_uvc_opts *opts; - INFO(f->config->cdev, "uvc_function_get_alt(%u)\n", interface); + uvcg_info(f, "%s(%u)\n", __func__, interface); opts = fi_to_f_uvc_opts(f->fi); @@ -379,7 +370,7 @@ struct f_uvc_opts *opts; int ret; - INFO(cdev, "uvc_function_set_alt(%u, %u)\n", interface, alt); + uvcg_info(f, "%s(%u, %u)\n", __func__, interface, alt); opts = fi_to_f_uvc_opts(f->fi); @@ -387,7 +378,7 @@ if (alt) return -EINVAL; - INFO(cdev, "reset UVC Control\n"); + uvcg_info(f, "reset UVC Control\n"); usb_ep_disable(uvc->control_ep); if (!uvc->control_ep->desc) @@ -516,14 +507,13 @@ struct uvc_device *uvc = to_uvc(f); struct v4l2_event v4l2_event; - INFO(f->config->cdev, "uvc_function_disable\n"); + uvcg_info(f, "%s()\n", __func__); memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_DISCONNECT; v4l2_event_queue(&uvc->vdev, &v4l2_event); uvc->state = UVC_STATE_DISCONNECTED; - f->config->cdev->gadget->uvc_enabled = false; usb_ep_disable(uvc->video.ep); usb_ep_disable(uvc->control_ep); @@ -560,23 +550,19 @@ void uvc_function_connect(struct uvc_device *uvc) { - struct usb_composite_dev *cdev = uvc->func.config->cdev; int ret; - cdev->gadget->uvc_enabled = true; - if ((ret = usb_function_activate(&uvc->func)) < 0) - INFO(cdev, "UVC connect failed with %d\n", ret); + uvcg_info(&uvc->func, "UVC connect failed with %d\n", ret); } void uvc_function_disconnect(struct uvc_device *uvc) { - struct usb_composite_dev *cdev = uvc->func.config->cdev; int ret; if ((ret = usb_function_deactivate(&uvc->func)) < 0) - INFO(cdev, "UVC disconnect failed with %d\n", ret); + uvcg_info(&uvc->func, "UVC disconnect failed with %d\n", ret); } /* -------------------------------------------------------------------------- @@ -600,17 +586,19 @@ int ret; /* TODO reference counting. */ + memset(&uvc->vdev, 0, sizeof(uvc->vdev)); uvc->vdev.v4l2_dev = &uvc->v4l2_dev; uvc->vdev.fops = &uvc_v4l2_fops; uvc->vdev.ioctl_ops = &uvc_v4l2_ioctl_ops; uvc->vdev.release = video_device_release_empty; uvc->vdev.vfl_dir = VFL_DIR_TX; uvc->vdev.lock = &uvc->video.mutex; + uvc->vdev.device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; strlcpy(uvc->vdev.name, cdev->gadget->name, sizeof(uvc->vdev.name)); video_set_drvdata(&uvc->vdev, uvc); - ret = video_register_device(&uvc->vdev, VFL_TYPE_GRABBER, -1); + ret = video_register_device(&uvc->vdev, VFL_TYPE_VIDEO, -1); if (ret < 0) return ret; @@ -794,7 +782,7 @@ int ret = -EINVAL; u8 address; - INFO(cdev, "uvc_function_bind\n"); + uvcg_info(f, "%s()\n", __func__); opts = fi_to_f_uvc_opts(f->fi); /* Sanity check the streaming endpoint module parameters. @@ -815,8 +803,8 @@ if (opts->streaming_maxburst && (opts->streaming_maxpacket % 1024) != 0) { opts->streaming_maxpacket = roundup(opts->streaming_maxpacket, 1024); - INFO(cdev, "overriding streaming_maxpacket to %d\n", - opts->streaming_maxpacket); + uvcg_info(f, "overriding streaming_maxpacket to %d\n", + opts->streaming_maxpacket); } /* Fill in the FS/HS/SS Video Streaming specific descriptors from the @@ -880,7 +868,7 @@ /* Allocate endpoints. */ ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); if (!ep) { - INFO(cdev, "Unable to allocate control EP\n"); + uvcg_info(f, "Unable to allocate control EP\n"); goto error; } uvc->control_ep = ep; @@ -921,7 +909,7 @@ } if (!ep) { - INFO(cdev, "Unable to allocate streaming EP\n"); + uvcg_info(f, "Unable to allocate streaming EP\n"); goto error; } uvc->video.ep = ep; @@ -937,9 +925,12 @@ uvc_ss_bulk_streaming_ep.bEndpointAddress = address; } +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) if (opts->device_name) uvc_en_us_strings[UVC_STRING_CONTROL_IDX].s = opts->device_name; +#endif + uvc_en_us_strings[UVC_STRING_CONTROL_IDX].s = opts->function_name; us = usb_gstrings_attach(cdev, uvc_function_strings, ARRAY_SIZE(uvc_en_us_strings)); if (IS_ERR(us)) { @@ -1014,35 +1005,29 @@ uvc->control_req->context = uvc; if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) { - printk(KERN_INFO "v4l2_device_register failed\n"); + uvcg_err(f, "failed to register V4L2 device\n"); goto error; } - uvc->video.async_wq = alloc_workqueue("uvcgvideo", - WQ_UNBOUND | WQ_HIGHPRI, - 0); - if (!uvc->video.async_wq) - goto error; - /* Initialise video. */ - ret = uvcg_video_init(&uvc->video); + ret = uvcg_video_init(&uvc->video, uvc); if (ret < 0) - goto error; + goto v4l2_error; if (opts->streaming_bulk) uvc->video.max_payload_size = uvc->video.imagesize; /* Register a V4L2 device. */ ret = uvc_register_video(uvc); if (ret < 0) { - printk(KERN_INFO "Unable to register video device\n"); - goto error; + uvcg_err(f, "failed to register video device\n"); + goto v4l2_error; } return 0; -error: +v4l2_error: v4l2_device_unregister(&uvc->v4l2_dev); - +error: if (uvc->control_req) usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); kfree(uvc->control_buf); @@ -1061,11 +1046,13 @@ mutex_destroy(&opts->lock); +#if defined(CONFIG_ARCH_ROCKCHIP) && defined(CONFIG_NO_GKI) if (opts->device_name_allocated) { opts->device_name_allocated = false; kfree(opts->device_name); opts->device_name = NULL; } +#endif kfree(opts); } @@ -1114,6 +1101,7 @@ pd->bmControls[0] = 1; pd->bmControls[1] = 0; pd->iProcessing = 0; + pd->bmVideoStandards = 0; od = &opts->uvc_output_terminal; od->bLength = UVC_DT_OUTPUT_TERMINAL_SIZE; @@ -1185,8 +1173,8 @@ opts->streaming_interval = 1; opts->streaming_maxpacket = 1024; - opts->uvc_num_request = UVC_NUM_REQUESTS; opts->pm_qos_latency = 0; + snprintf(opts->function_name, sizeof(opts->function_name), "UVC Camera"); ret = uvcg_attach_configfs(opts); if (ret < 0) { @@ -1206,22 +1194,48 @@ kfree(uvc); } -static void uvc_unbind(struct usb_configuration *c, struct usb_function *f) +static void uvc_function_unbind(struct usb_configuration *c, + struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct uvc_device *uvc = to_uvc(f); + struct uvc_video *video = &uvc->video; + long wait_ret = 1; - INFO(cdev, "%s\n", __func__); + uvcg_info(f, "%s()\n", __func__); + + if (video->async_wq) + destroy_workqueue(video->async_wq); + + /* If we know we're connected via v4l2, then there should be a cleanup + * of the device from userspace either via UVC_EVENT_DISCONNECT or + * though the video device removal uevent. Allow some time for the + * application to close out before things get deleted. + */ + if (uvc->func_connected) { + uvcg_dbg(f, "waiting for clean disconnect\n"); + wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue, + uvc->func_connected == false, msecs_to_jiffies(500)); + uvcg_dbg(f, "done waiting with ret: %ld\n", wait_ret); + } device_remove_file(&uvc->vdev.dev, &dev_attr_function_name); video_unregister_device(&uvc->vdev); v4l2_device_unregister(&uvc->v4l2_dev); + if (uvc->func_connected) { + /* Wait for the release to occur to ensure there are no longer any + * pending operations that may cause panics when resources are cleaned + * up. + */ + uvcg_warn(f, "%s no clean disconnect, wait for release\n", __func__); + wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue, + uvc->func_connected == false, msecs_to_jiffies(1000)); + uvcg_dbg(f, "done waiting for release with ret: %ld\n", wait_ret); + } + usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); kfree(uvc->control_buf); - - if (uvc->video.async_wq) - destroy_workqueue(uvc->video.async_wq); usb_free_all_descriptors(f); } @@ -1238,6 +1252,7 @@ mutex_init(&uvc->video.mutex); uvc->state = UVC_STATE_DISCONNECTED; + init_waitqueue_head(&uvc->func_connected_queue); opts = fi_to_f_uvc_opts(fi); mutex_lock(&opts->lock); @@ -1268,7 +1283,7 @@ /* Register the function. */ uvc->func.name = "uvc"; uvc->func.bind = uvc_function_bind; - uvc->func.unbind = uvc_unbind; + uvc->func.unbind = uvc_function_unbind; uvc->func.get_alt = uvc_function_get_alt; uvc->func.set_alt = uvc_function_set_alt; uvc->func.disable = uvc_function_disable; -- Gitblit v1.6.2