summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/function/f_uvc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-10-08 02:48:26 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2022-10-08 02:48:26 +0300
commitd3dcbe24a0fc6373ce7e4a65acd5c785aa8e2396 (patch)
tree2072b4977f2e22f0b51bd7e48f131c48c14e896d /drivers/usb/gadget/function/f_uvc.c
parent6181073dd6a7e5deafc60e7981bd765b6c93da8c (diff)
parent00988f70a0763f14c97c4c0df76fb9aa4959e953 (diff)
downloadlinux-d3dcbe24a0fc6373ce7e4a65acd5c785aa8e2396.tar.xz
Merge tag 'usb-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB / Thunderbolt updates from Greg KH: "Here is the big set of USB and Thunderbolt driver changes for 6.1-rc1. Nothing major in here, lots of little things with new devices supported and updates for a few drivers. Highlights include: - thunderbolt/USB4 devices supported a bit better than before, and some new ids to enable new hardware devices - USB gadget uvc updates for newer video formats and better v4l integration (the v4l portions were acked by those maintainers) - typec updates for tiny issues and more typec drivers for new chips. - xhci tiny updates for minor issues - big usb-serial ftdi_sio driver update to handle new devices better - lots of tiny dwc3 fixes and updates for the IP block that is showing up everywhere these days - dts updates for new devices being supported - other tiny janitorial and cleanups fixes for lots of different USB drivers. Full details are in the shortlog. All of these have been in linux-next for a while with no reported issues" * tag 'usb-6.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (169 commits) usb: gadget: uvc: don't put item still in use usb: gadget: uvc: Fix argument to sizeof() in uvc_register_video() usb: host: ehci-exynos: switch to using gpiod API Revert "usb: dwc3: Don't switch OTG -> peripheral if extcon is present" Revert "USB: fixup for merge issue with "usb: dwc3: Don't switch OTG -> peripheral if extcon is present"" dt-bindings: usb: Convert FOTG210 to dt schema usb: mtu3: fix failed runtime suspend in host only mode USB: omap_udc: Fix spelling mistake: "tranceiver_ctrl" -> "transceiver_ctrl" usb: typec: ucsi_ccg: Disable UCSI ALT support on Tegra usb: typec: Replace custom implementation of device_match_fwnode() usb: typec: ucsi: Don't warn on probe deferral usb: add quirks for Lenovo OneLink+ Dock MAINTAINERS: switch dwc3 to Thinh usb: idmouse: fix an uninit-value in idmouse_open USB: PHY: JZ4770: Switch to use dev_err_probe() helper usb: phy: generic: Switch to use dev_err_probe() helper usb: ulpi: use DEFINE_SHOW_ATTRIBUTE to simplify ulpi_regs usb: cdns3: remove dead code usb: cdc-wdm: Use skb_put_data() instead of skb_put/memcpy pair usb: musb: sunxi: Switch to use dev_err_probe() helper ...
Diffstat (limited to 'drivers/usb/gadget/function/f_uvc.c')
-rw-r--r--drivers/usb/gadget/function/f_uvc.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
index 71669e0e4d00..6e196e06181e 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -421,7 +421,7 @@ uvc_register_video(struct uvc_device *uvc)
int ret;
/* TODO reference counting. */
- memset(&uvc->vdev, 0, sizeof(uvc->video));
+ memset(&uvc->vdev, 0, sizeof(uvc->vdev));
uvc->vdev.v4l2_dev = &uvc->v4l2_dev;
uvc->vdev.v4l2_dev->dev = &cdev->gadget->dev;
uvc->vdev.fops = &uvc_v4l2_fops;
@@ -430,7 +430,7 @@ uvc_register_video(struct uvc_device *uvc)
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));
+ strscpy(uvc->vdev.name, cdev->gadget->name, sizeof(uvc->vdev.name));
video_set_drvdata(&uvc->vdev, uvc);
@@ -888,6 +888,7 @@ static void uvc_free(struct usb_function *f)
struct uvc_device *uvc = to_uvc(f);
struct f_uvc_opts *opts = container_of(f->fi, struct f_uvc_opts,
func_inst);
+ config_item_put(&uvc->header->item);
--opts->refcnt;
kfree(uvc);
}
@@ -897,10 +898,14 @@ static void uvc_function_unbind(struct usb_configuration *c,
{
struct usb_composite_dev *cdev = c->cdev;
struct uvc_device *uvc = to_uvc(f);
+ struct uvc_video *video = &uvc->video;
long wait_ret = 1;
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
@@ -941,6 +946,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
struct uvc_device *uvc;
struct f_uvc_opts *opts;
struct uvc_descriptor_header **strm_cls;
+ struct config_item *streaming, *header, *h;
uvc = kzalloc(sizeof(*uvc), GFP_KERNEL);
if (uvc == NULL)
@@ -973,6 +979,28 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
uvc->desc.fs_streaming = opts->fs_streaming;
uvc->desc.hs_streaming = opts->hs_streaming;
uvc->desc.ss_streaming = opts->ss_streaming;
+
+ streaming = config_group_find_item(&opts->func_inst.group, "streaming");
+ if (!streaming)
+ goto err_config;
+
+ header = config_group_find_item(to_config_group(streaming), "header");
+ config_item_put(streaming);
+ if (!header)
+ goto err_config;
+
+ h = config_group_find_item(to_config_group(header), "h");
+ config_item_put(header);
+ if (!h)
+ goto err_config;
+
+ uvc->header = to_uvcg_streaming_header(h);
+ if (!uvc->header->linked) {
+ mutex_unlock(&opts->lock);
+ kfree(uvc);
+ return ERR_PTR(-EBUSY);
+ }
+
++opts->refcnt;
mutex_unlock(&opts->lock);
@@ -988,6 +1016,11 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
uvc->func.bind_deactivated = true;
return &uvc->func;
+
+err_config:
+ mutex_unlock(&opts->lock);
+ kfree(uvc);
+ return ERR_PTR(-ENOENT);
}
DECLARE_USB_FUNCTION_INIT(uvc, uvc_alloc_inst, uvc_alloc);