public inbox for linux-usb@vger.kernel.org
 help / color / mirror / Atom feed
From: Daniel Scally <dan.scally@ideasonboard.com>
To: linux-usb@vger.kernel.org
Cc: laurent.pinchart@ideasonboard.com, gregkh@linuxfoundation.org,
	mgr@pengutronix.de, kieran.bingham@ideasonboard.com,
	Daniel Scally <dan.scally@ideasonboard.com>
Subject: [PATCH 3/3] usb: gadget: uvc: Allow disabling of interrupt endpoint
Date: Mon,  5 Dec 2022 14:37:58 +0000	[thread overview]
Message-ID: <20221205143758.1096914-4-dan.scally@ideasonboard.com> (raw)
In-Reply-To: <20221205143758.1096914-1-dan.scally@ideasonboard.com>

The f_uvc code includes an interrupt endpoint against the VideoControl
interface. According to section 2.4.2 of the UVC specification however
this endpoint is optional in at least some cases:

"This endpoint is optional, but may be mandatory under certain
conditions"

The conditions enumerated are whether...

1. The device supports hardware triggers
2. The device implements any AutoUpdate controls
3. The device implements any Asynchronous controls

As all of those things are implementation dependent, this endpoint
might be unnecessary for some users. Check whether the user has
requested it be disable via configfs and don't proceed with its
instantiation if so.

Signed-off-by: Daniel Scally <dan.scally@ideasonboard.com>
---
 drivers/usb/gadget/function/f_uvc.c | 42 ++++++++++++++++++-----------
 drivers/usb/gadget/function/uvc.h   |  1 +
 2 files changed, 27 insertions(+), 16 deletions(-)

diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
index 49b7231742d6..76ec84d3a5fd 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -79,7 +79,7 @@ static struct usb_interface_descriptor uvc_control_intf = {
 	.bDescriptorType	= USB_DT_INTERFACE,
 	.bInterfaceNumber	= UVC_INTF_VIDEO_CONTROL,
 	.bAlternateSetting	= 0,
-	.bNumEndpoints		= 1,
+	.bNumEndpoints		= 0,
 	.bInterfaceClass	= USB_CLASS_VIDEO,
 	.bInterfaceSubClass	= UVC_SC_VIDEOCONTROL,
 	.bInterfaceProtocol	= 0x00,
@@ -290,14 +290,16 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
 		if (alt)
 			return -EINVAL;
 
-		uvcg_info(f, "reset UVC interrupt endpoint\n");
-		usb_ep_disable(uvc->interrupt_ep);
+		if (!uvc->disable_interrupt_ep) {
+			uvcg_info(f, "reset UVC interrupt endpoint\n");
+			usb_ep_disable(uvc->interrupt_ep);
 
-		if (!uvc->interrupt_ep->desc)
-			if (config_ep_by_speed(cdev->gadget, f, uvc->interrupt_ep))
-				return -EINVAL;
+			if (!uvc->interrupt_ep->desc)
+				if (config_ep_by_speed(cdev->gadget, f, uvc->interrupt_ep))
+					return -EINVAL;
 
-		usb_ep_enable(uvc->interrupt_ep);
+			usb_ep_enable(uvc->interrupt_ep);
+		}
 
 		if (uvc->state == UVC_STATE_DISCONNECTED) {
 			memset(&v4l2_event, 0, sizeof(v4l2_event));
@@ -375,7 +377,8 @@ uvc_function_disable(struct usb_function *f)
 	uvc->state = UVC_STATE_DISCONNECTED;
 
 	usb_ep_disable(uvc->video.ep);
-	usb_ep_disable(uvc->interrupt_ep);
+	if (!uvc->disable_interrupt_ep)
+		usb_ep_disable(uvc->interrupt_ep);
 }
 
 /* --------------------------------------------------------------------------
@@ -523,8 +526,10 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	control_size = 0;
 	streaming_size = 0;
 	bytes = uvc_iad.bLength + uvc_control_intf.bLength
-	      + uvc_interrupt_ep.bLength + uvc_control_cs_ep.bLength
-	      + uvc_streaming_intf_alt0.bLength;
+	       + uvc_control_cs_ep.bLength + uvc_streaming_intf_alt0.bLength;
+
+	if (!uvc->disable_interrupt_ep)
+		bytes += uvc_interrupt_ep.bLength;
 
 	if (speed == USB_SPEED_SUPER) {
 		bytes += uvc_ss_control_comp.bLength;
@@ -569,7 +574,8 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
 	uvc_control_header->bInCollection = 1;
 	uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
 
-	UVC_COPY_DESCRIPTOR(mem, dst, &uvc_interrupt_ep);
+	if (!uvc->disable_interrupt_ep)
+		UVC_COPY_DESCRIPTOR(mem, dst, &uvc_interrupt_ep);
 	if (speed == USB_SPEED_SUPER)
 		UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp);
 
@@ -656,12 +662,16 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 			    (opts->streaming_maxburst + 1));
 
 	/* Allocate endpoints. */
-	ep = usb_ep_autoconfig(cdev->gadget, &uvc_interrupt_ep);
-	if (!ep) {
-		uvcg_info(f, "Unable to allocate control EP\n");
-		goto error;
+	if (!opts->disable_interrupt_ep) {
+		ep = usb_ep_autoconfig(cdev->gadget, &uvc_interrupt_ep);
+		if (!ep) {
+			uvcg_info(f, "Unable to allocate interrupt EP\n");
+			goto error;
+		}
+		uvc->interrupt_ep = ep;
+		uvc_control_intf.bNumEndpoints = 1;
 	}
-	uvc->interrupt_ep = ep;
+	uvc->disable_interrupt_ep = opts->disable_interrupt_ep;
 
 	if (gadget_is_superspeed(c->cdev->gadget))
 		ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep,
diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h
index 48b71e04c2b1..0d0ef9b90b1a 100644
--- a/drivers/usb/gadget/function/uvc.h
+++ b/drivers/usb/gadget/function/uvc.h
@@ -149,6 +149,7 @@ struct uvc_device {
 	struct usb_ep *interrupt_ep;
 	struct usb_request *control_req;
 	void *control_buf;
+	bool disable_interrupt_ep;
 
 	unsigned int streaming_intf;
 
-- 
2.34.1


  parent reply	other threads:[~2022-12-05 14:38 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-05 14:37 [PATCH 0/3] Add ability to disable UVC Gadget's interrupt endpoint Daniel Scally
2022-12-05 14:37 ` [PATCH 1/3] usb: gadget: uvc: Rename uvc_control_ep Daniel Scally
2022-12-08 15:33   ` Greg KH
2022-12-08 15:39     ` Dan Scally
2022-12-28  1:59   ` Laurent Pinchart
2023-01-01 20:25     ` Dan Scally
2022-12-05 14:37 ` [PATCH 2/3] usb: gadget: uvc: Add new disable_interrupt_ep attribute Daniel Scally
2022-12-08 15:32   ` Greg KH
2022-12-28  2:02   ` Laurent Pinchart
2022-12-05 14:37 ` Daniel Scally [this message]
2022-12-28  2:09   ` [PATCH 3/3] usb: gadget: uvc: Allow disabling of interrupt endpoint Laurent Pinchart
2023-01-01 20:46     ` Dan Scally
2023-01-02 10:24       ` Laurent Pinchart

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221205143758.1096914-4-dan.scally@ideasonboard.com \
    --to=dan.scally@ideasonboard.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=kieran.bingham@ideasonboard.com \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-usb@vger.kernel.org \
    --cc=mgr@pengutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox