From patchwork Mon Dec 5 14:37:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Scally X-Patchwork-Id: 13064561 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 760BDC47088 for ; Mon, 5 Dec 2022 14:38:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231742AbiLEOiM (ORCPT ); Mon, 5 Dec 2022 09:38:12 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45060 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229970AbiLEOiK (ORCPT ); Mon, 5 Dec 2022 09:38:10 -0500 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 85DFEC753 for ; Mon, 5 Dec 2022 06:38:09 -0800 (PST) Received: from mail.ideasonboard.com (cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 85320589; Mon, 5 Dec 2022 15:38:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1670251087; bh=lIb6Y9z0mV5ts1vXngiUBxzZUtOO/7Uc4svs5jIi+IU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Cy7QKR6rxB2QDoW3RJJgioJWcGF6irGazZNlo8gTc8oJuFDC6+3w0XwEqkNn/eZhs NhgG+df9/LPLcaqBUkJsJ/tFzEcrjdcxYC6DDDLWUP+2nC32uOIFAOuLJg9FVt4Gx4 wyerTzWoojxh4lBtNhgvPZXzypLs5FhWEOF2NSNI= From: Daniel Scally To: linux-usb@vger.kernel.org Cc: laurent.pinchart@ideasonboard.com, gregkh@linuxfoundation.org, mgr@pengutronix.de, kieran.bingham@ideasonboard.com, Daniel Scally Subject: [PATCH 1/3] usb: gadget: uvc: Rename uvc_control_ep Date: Mon, 5 Dec 2022 14:37:56 +0000 Message-Id: <20221205143758.1096914-2-dan.scally@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221205143758.1096914-1-dan.scally@ideasonboard.com> References: <20221205143758.1096914-1-dan.scally@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org The f_uvc code defines an endpoint named "uvc_control_ep" but it is configured with a non-zero endpoint address and has its bmAttributes flagged as USB_ENDPOINT_XFER_INT - this cannot be the VideoControl interface's control endpoint, as the default endpoint 0 is used for that purpose. This is instead the optional interrupt endpoint that can be contained by a VideoControl interface. Rename the variables to make that clear. Signed-off-by: Daniel Scally --- drivers/usb/gadget/function/f_uvc.c | 24 ++++++++++++------------ drivers/usb/gadget/function/uvc.h | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 6e196e06181e..49b7231742d6 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -86,7 +86,7 @@ static struct usb_interface_descriptor uvc_control_intf = { .iInterface = 0, }; -static struct usb_endpoint_descriptor uvc_control_ep = { +static struct usb_endpoint_descriptor uvc_interrupt_ep = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, @@ -290,14 +290,14 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) if (alt) return -EINVAL; - uvcg_info(f, "reset UVC Control\n"); - usb_ep_disable(uvc->control_ep); + uvcg_info(f, "reset UVC interrupt endpoint\n"); + usb_ep_disable(uvc->interrupt_ep); - if (!uvc->control_ep->desc) - if (config_ep_by_speed(cdev->gadget, f, uvc->control_ep)) + if (!uvc->interrupt_ep->desc) + if (config_ep_by_speed(cdev->gadget, f, uvc->interrupt_ep)) return -EINVAL; - usb_ep_enable(uvc->control_ep); + usb_ep_enable(uvc->interrupt_ep); if (uvc->state == UVC_STATE_DISCONNECTED) { memset(&v4l2_event, 0, sizeof(v4l2_event)); @@ -375,7 +375,7 @@ uvc_function_disable(struct usb_function *f) uvc->state = UVC_STATE_DISCONNECTED; usb_ep_disable(uvc->video.ep); - usb_ep_disable(uvc->control_ep); + usb_ep_disable(uvc->interrupt_ep); } /* -------------------------------------------------------------------------- @@ -511,7 +511,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed) * uvc_iad * uvc_control_intf * Class-specific UVC control descriptors - * uvc_control_ep + * uvc_interrupt_ep * uvc_control_cs_ep * uvc_ss_control_comp (for SS only) * uvc_streaming_intf_alt0 @@ -523,7 +523,7 @@ 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_control_ep.bLength + uvc_control_cs_ep.bLength + + uvc_interrupt_ep.bLength + uvc_control_cs_ep.bLength + uvc_streaming_intf_alt0.bLength; if (speed == USB_SPEED_SUPER) { @@ -569,7 +569,7 @@ 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_control_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 +656,12 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) (opts->streaming_maxburst + 1)); /* Allocate endpoints. */ - ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); + ep = usb_ep_autoconfig(cdev->gadget, &uvc_interrupt_ep); if (!ep) { uvcg_info(f, "Unable to allocate control EP\n"); goto error; } - uvc->control_ep = ep; + uvc->interrupt_ep = 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 40226b1f7e14..48b71e04c2b1 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -146,7 +146,7 @@ struct uvc_device { } desc; unsigned int control_intf; - struct usb_ep *control_ep; + struct usb_ep *interrupt_ep; struct usb_request *control_req; void *control_buf; From patchwork Mon Dec 5 14:37:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Scally X-Patchwork-Id: 13064562 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9D802C4321E for ; Mon, 5 Dec 2022 14:38:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231426AbiLEOiP (ORCPT ); Mon, 5 Dec 2022 09:38:15 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45098 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230233AbiLEOiN (ORCPT ); Mon, 5 Dec 2022 09:38:13 -0500 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 89C43C753 for ; Mon, 5 Dec 2022 06:38:12 -0800 (PST) Received: from mail.ideasonboard.com (cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0D867CCE; Mon, 5 Dec 2022 15:38:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1670251088; bh=hJBT0sUavQp/sARd0RRFTGO5t5tSiL35RmW4HmnVMyY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uJsAsULj/OhPa7wbKIDlUvhVATjBevgLdtXIM5oWoO7FSajKYiIWplET+H7EiXZR+ o1Rwz/vKHGu99bVH8bwRgubfAmm4PqqifrHFuV9i1u0qphxLu5K5B/oIpFUW2gXjOF CyTMsD/vtbR4CbwNFOhDmJ9T56DHJymnvR5FQSFg= From: Daniel Scally To: linux-usb@vger.kernel.org Cc: laurent.pinchart@ideasonboard.com, gregkh@linuxfoundation.org, mgr@pengutronix.de, kieran.bingham@ideasonboard.com, Daniel Scally Subject: [PATCH 2/3] usb: gadget: uvc: Add new disable_interrupt_ep attribute Date: Mon, 5 Dec 2022 14:37:57 +0000 Message-Id: <20221205143758.1096914-3-dan.scally@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221205143758.1096914-1-dan.scally@ideasonboard.com> References: <20221205143758.1096914-1-dan.scally@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Add a new attribute to the default control config group that allows users to specify whether they want to disable the default interrupt endpoint for the VideoControl interface. Signed-off-by: Daniel Scally --- drivers/usb/gadget/function/u_uvc.h | 2 + drivers/usb/gadget/function/uvc_configfs.c | 53 ++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/drivers/usb/gadget/function/u_uvc.h b/drivers/usb/gadget/function/u_uvc.h index 24b8681b0d6f..7e6d31a8fad7 100644 --- a/drivers/usb/gadget/function/u_uvc.h +++ b/drivers/usb/gadget/function/u_uvc.h @@ -29,6 +29,8 @@ struct f_uvc_opts { unsigned int streaming_interface; char function_name[32]; + bool disable_interrupt_ep; + /* * Control descriptors array pointers for full-/high-speed and * super-speed. They point by default to the uvc_fs_control_cls and diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index 4303a3283ba0..644d87eee164 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -716,8 +716,61 @@ static ssize_t uvcg_default_control_b_interface_number_show( UVC_ATTR_RO(uvcg_default_control_, b_interface_number, bInterfaceNumber); +static ssize_t uvcg_default_control_disable_interrupt_ep_show( + struct config_item *item, char *page) +{ + struct config_group *group = to_config_group(item); + struct mutex *su_mutex = &group->cg_subsys->su_mutex; + struct config_item *opts_item; + struct f_uvc_opts *opts; + int result = 0; + + mutex_lock(su_mutex); /* for navigating configfs hierarchy */ + + opts_item = item->ci_parent; + opts = to_f_uvc_opts(opts_item); + + mutex_lock(&opts->lock); + result += sprintf(page, "%u\n", opts->disable_interrupt_ep); + mutex_unlock(&opts->lock); + + mutex_unlock(su_mutex); + + return result; +} + +static ssize_t uvcg_default_control_disable_interrupt_ep_store( + struct config_item *item, const char *page, size_t len) +{ + struct config_group *group = to_config_group(item); + struct mutex *su_mutex = &group->cg_subsys->su_mutex; + struct config_item *opts_item; + struct f_uvc_opts *opts; + ssize_t ret; + u8 num; + + ret = kstrtou8(page, 0, &num); + if (ret) + return ret; + + mutex_lock(su_mutex); /* for navigating configfs hierarchy */ + + opts_item = item->ci_parent; + opts = to_f_uvc_opts(opts_item); + + mutex_lock(&opts->lock); + opts->disable_interrupt_ep = num; + mutex_unlock(&opts->lock); + + mutex_unlock(su_mutex); + + return len; +} +UVC_ATTR(uvcg_default_control_, disable_interrupt_ep, disable_interrupt_ep); + static struct configfs_attribute *uvcg_default_control_attrs[] = { &uvcg_default_control_attr_b_interface_number, + &uvcg_default_control_attr_disable_interrupt_ep, NULL, }; From patchwork Mon Dec 5 14:37:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Scally X-Patchwork-Id: 13064563 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2BBA5C47089 for ; Mon, 5 Dec 2022 14:38:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232016AbiLEOiQ (ORCPT ); Mon, 5 Dec 2022 09:38:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45096 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229970AbiLEOiN (ORCPT ); Mon, 5 Dec 2022 09:38:13 -0500 Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 235D4C74C for ; Mon, 5 Dec 2022 06:38:12 -0800 (PST) Received: from mail.ideasonboard.com (cpc141996-chfd3-2-0-cust928.12-3.cable.virginm.net [86.13.91.161]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 86402E51; Mon, 5 Dec 2022 15:38:08 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1670251088; bh=xItBthATwl+7FRlN7wfUYhNeekMKhm56cDEEWhhuKc8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=s5QyB9GT0dXnGuoJ6PXeUJx8PIZnIrpLrHzAoFDhnSBU2WELGbCe89eEXiuEtV6ol DWxTpf+HTEBtk8CgXKPDvBuYhhNscTQtQfnjN4bMuk1kGVeE/iZ259u43vSQNRN9S+ xcaIu/VnTsefEaudtdDVbJ/997kfgJ0vtnzXnO3w= From: Daniel Scally To: linux-usb@vger.kernel.org Cc: laurent.pinchart@ideasonboard.com, gregkh@linuxfoundation.org, mgr@pengutronix.de, kieran.bingham@ideasonboard.com, Daniel Scally Subject: [PATCH 3/3] usb: gadget: uvc: Allow disabling of interrupt endpoint Date: Mon, 5 Dec 2022 14:37:58 +0000 Message-Id: <20221205143758.1096914-4-dan.scally@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20221205143758.1096914-1-dan.scally@ideasonboard.com> References: <20221205143758.1096914-1-dan.scally@ideasonboard.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org 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 --- 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;