From patchwork Thu Jan 24 03:02:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 10778229 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 222FE91E for ; Thu, 24 Jan 2019 03:02:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 11A992D0CE for ; Thu, 24 Jan 2019 03:02:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 05D412D11F; Thu, 24 Jan 2019 03:02:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A27332D0CE for ; Thu, 24 Jan 2019 03:02:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727281AbfAXDCo (ORCPT ); Wed, 23 Jan 2019 22:02:44 -0500 Received: from perceval.ideasonboard.com ([213.167.242.64]:52884 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727252AbfAXDCn (ORCPT ); Wed, 23 Jan 2019 22:02:43 -0500 Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D45252F4; Thu, 24 Jan 2019 04:02:40 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1548298962; bh=VjKrHTmb5cEJmKf1BZYTq4g9kl+oCzQPLLfe1Y43/qA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Dxlr7Uh8uicM43ZQ5p3tgbIyPhUhRlwynaFs/bOn9bXabwPvDbIzFakJEP4Shg6iF myjvmUKuVDu/ye4uZyEha6ZZlIV1VImOOTi/O4bGaZ7Pt2raoehVwR1TyaIb3cvFt/ wRiZ7jcFQqs7jJxOy1+4lOuOnKo//elV9c3ZP494= From: Paul Elder To: laurent.pinchart@ideasonboard.com, kieran.bingham@ideasonboard.com Cc: Paul Elder , b-liu@ti.com, stern@rowland.harvard.edu, rogerq@ti.com, balbi@kernel.org, gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v7 1/6] usb: uvc: include videodev2.h in g_uvc.h Date: Wed, 23 Jan 2019 22:02:23 -0500 Message-Id: <20190124030228.19840-2-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190124030228.19840-1-paul.elder@ideasonboard.com> References: <20190124030228.19840-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP V4L2_EVENT_PRIVATE_START is used in g_uvc.h but is defined in videodev2.h, which is not included and causes a compiler warning: linux/usb/g_uvc.h:15:28: error: ‘V4L2_EVENT_PRIVATE_START’ undeclared here (not in a function) #define UVC_EVENT_FIRST (V4L2_EVENT_PRIVATE_START + 0) Include videodev2.h in g_uvc.h. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- No change from v6 No change from v5 No change from v4 No change from v3 No change from v2 No change from v1 include/uapi/linux/usb/g_uvc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/uapi/linux/usb/g_uvc.h b/include/uapi/linux/usb/g_uvc.h index 3c9ee3020cbb..6698c3263ae8 100644 --- a/include/uapi/linux/usb/g_uvc.h +++ b/include/uapi/linux/usb/g_uvc.h @@ -11,6 +11,7 @@ #include #include #include +#include #define UVC_EVENT_FIRST (V4L2_EVENT_PRIVATE_START + 0) #define UVC_EVENT_CONNECT (V4L2_EVENT_PRIVATE_START + 0) From patchwork Thu Jan 24 03:02:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 10778239 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 69D3E13B4 for ; Thu, 24 Jan 2019 03:03:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 58E102D0CE for ; Thu, 24 Jan 2019 03:03:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4C4EC2D11F; Thu, 24 Jan 2019 03:03:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D90BA2D0CE for ; Thu, 24 Jan 2019 03:03:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727455AbfAXDDQ (ORCPT ); Wed, 23 Jan 2019 22:03:16 -0500 Received: from perceval.ideasonboard.com ([213.167.242.64]:52892 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727287AbfAXDCo (ORCPT ); Wed, 23 Jan 2019 22:02:44 -0500 Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 688892F5; Thu, 24 Jan 2019 04:02:42 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1548298963; bh=gDgqOLOAlTTlDqkJPzJ/gWei3MxDhHhHiJ/8lWc3gRs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Z95LNSPQE1Eo3wllPRwDv7N1UsmCc3bAze4X0gfiIF1zFsMjJ2RrZAuMX8wIcn5uN vH4KOL8Pnx5meovlDfIGOVWbLgVizSnW6QAFuybnvWqAH5zO9HbRbGWjB/HV2D0ZiE 0EWmf01un3cBlQlMD/elP5KsHtAT+WtcPdHyLzRw= From: Paul Elder To: laurent.pinchart@ideasonboard.com, kieran.bingham@ideasonboard.com Cc: Paul Elder , b-liu@ti.com, stern@rowland.harvard.edu, rogerq@ti.com, balbi@kernel.org, gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v7 2/6] usb: gadget: uvc: enqueue usb request in setup handler for control OUT Date: Wed, 23 Jan 2019 22:02:24 -0500 Message-Id: <20190124030228.19840-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190124030228.19840-1-paul.elder@ideasonboard.com> References: <20190124030228.19840-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently, for uvc class-specific control IN and OUT requests, in the setup handler a UVC_EVENT_SETUP with the setup control is enqueued to userspace. In response to this, the uvc function driver expects userspace to call ioctl UVCIOC_SEND_RESPONSE containing uvc request data. In the case of control IN this is fine, but for control OUT it causes a problem. Since the host sends data immediately after the setup stage completes, it is possible that the empty uvc request data is not enqueued in time for the UDC driver to put the data stage data into (this causes some UDC drivers, such as MUSB, to reply with a STALL). This problem is remedied by having the setup handler enqueue the empty uvc request data, instead of waiting for userspace to do it. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- No change from v6 No change from v5 No change from v4 No change from v3 No change from v2 No change from v1 drivers/usb/gadget/function/f_uvc.c | 25 +++++++++++++++++++------ drivers/usb/gadget/function/uvc_v4l2.c | 7 +++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 4134117b5f81..f571623cc6e4 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -223,8 +223,6 @@ static int uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) { struct uvc_device *uvc = to_uvc(f); - struct v4l2_event v4l2_event; - struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_CLASS) { uvcg_info(f, "invalid request type\n"); @@ -241,10 +239,25 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) uvc->event_setup_out = !(ctrl->bRequestType & USB_DIR_IN); uvc->event_length = le16_to_cpu(ctrl->wLength); - memset(&v4l2_event, 0, sizeof(v4l2_event)); - v4l2_event.type = UVC_EVENT_SETUP; - memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req)); - v4l2_event_queue(&uvc->vdev, &v4l2_event); + if (uvc->event_setup_out) { + struct usb_request *req = uvc->control_req; + + /* + * Enqueue the request immediately for control OUT as the + * host will start the data stage straight away. + */ + req->length = uvc->event_length; + req->zero = 0; + usb_ep_queue(f->config->cdev->gadget->ep0, req, GFP_KERNEL); + } else { + struct v4l2_event v4l2_event; + struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; + + memset(&v4l2_event, 0, sizeof(v4l2_event)); + v4l2_event.type = UVC_EVENT_SETUP; + memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req)); + v4l2_event_queue(&uvc->vdev, &v4l2_event); + } return 0; } diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index 7816ea9886e1..ac48f49d9f10 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -35,6 +35,13 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data) struct usb_composite_dev *cdev = uvc->func.config->cdev; struct usb_request *req = uvc->control_req; + /* + * For control OUT transfers the request has been enqueued synchronously + * by the setup handler, there's nothing to be done here. + */ + if (uvc->event_setup_out) + return 0; + if (data->length < 0) return usb_ep_set_halt(cdev->gadget->ep0); From patchwork Thu Jan 24 03:02:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 10778237 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EF08D91E for ; Thu, 24 Jan 2019 03:03:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DFE612D0CE for ; Thu, 24 Jan 2019 03:03:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D3ECB2D11F; Thu, 24 Jan 2019 03:03:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7379C2D0CE for ; Thu, 24 Jan 2019 03:03:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727342AbfAXDDJ (ORCPT ); Wed, 23 Jan 2019 22:03:09 -0500 Received: from perceval.ideasonboard.com ([213.167.242.64]:52904 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727301AbfAXDCr (ORCPT ); Wed, 23 Jan 2019 22:02:47 -0500 Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 004FC23D; Thu, 24 Jan 2019 04:02:43 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1548298965; bh=Z9YyvXe8h7O+MZFwd3GSpNK5/KhnYqDwT/dXV6zErbQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bJyVysG5pFscKZ3o5ocFUkWEI3RflgypqmDmeK0Tyah/Pim46xqFV8D7EtWqLkTW3 XMHdFZDyEqNM9K9A+A5Qg5rbDjdqQKU2njyJAHCr0coXOL9yLn1kxsI9edCCl9+Iwh 9QeVg7wzz60znNOl9E46ulos4qjISTdB+y3p+LIY= From: Paul Elder To: laurent.pinchart@ideasonboard.com, kieran.bingham@ideasonboard.com Cc: Paul Elder , b-liu@ti.com, stern@rowland.harvard.edu, rogerq@ti.com, balbi@kernel.org, gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v7 3/6] usb: gadget: uvc: package setup and data for control OUT requests Date: Wed, 23 Jan 2019 22:02:25 -0500 Message-Id: <20190124030228.19840-4-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190124030228.19840-1-paul.elder@ideasonboard.com> References: <20190124030228.19840-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Since "usb: gadget: uvc: enqueue uvc_request_data in setup handler for control OUT requests" it is no longer necessary for userspace to call ioctl UVCIOC_SEND_RESPONSE in response to receiving a UVC_EVENT_SETUP from the uvc function driver for a control OUT request. This change means that for control OUT userspace will receive a UVC_EVENT_SETUP and not do anything with it. This is a waste of a pair of context switches, so we put the setup and data stage data into a single UVC_EVENT_DATA to give to userspace. Previously struct uvc_request_data had 60 bytes allocated for data, and since uvc data at most is 34 bytes in UVC 1.1 and 48 bytes in UVC 1.5, we can afford to cut out 8 bytes to store the setup control. Since the setup control is discarded after the handling of the setup stage, it must be saved in struct uvc_device during the setup handler in order for the data stage handler to be able to read it and send it to userspace. Signed-off-by: Paul Elder Reviewed-by: Laurent Pinchart --- No change from v6 No change from v5 No change from v4 No change from v3 No change from v2 No change from v1 drivers/usb/gadget/function/f_uvc.c | 3 +++ drivers/usb/gadget/function/uvc.h | 1 + include/uapi/linux/usb/g_uvc.h | 3 ++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index f571623cc6e4..6303ed346af9 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -215,6 +215,8 @@ uvc_function_ep0_complete(struct usb_ep *ep, struct usb_request *req) v4l2_event.type = UVC_EVENT_DATA; uvc_event->data.length = req->actual; memcpy(&uvc_event->data.data, req->buf, req->actual); + memcpy(&uvc_event->data.setup, &uvc->control_setup, + sizeof(uvc_event->data.setup)); v4l2_event_queue(&uvc->vdev, &v4l2_event); } } @@ -238,6 +240,7 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) */ uvc->event_setup_out = !(ctrl->bRequestType & USB_DIR_IN); uvc->event_length = le16_to_cpu(ctrl->wLength); + memcpy(&uvc->control_setup, ctrl, sizeof(uvc->control_setup)); if (uvc->event_setup_out) { struct usb_request *req = uvc->control_req; diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 671020c8a836..1d89b1df4ba0 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -163,6 +163,7 @@ struct uvc_device { unsigned int control_intf; struct usb_ep *control_ep; struct usb_request *control_req; + struct usb_ctrlrequest control_setup; void *control_buf; unsigned int streaming_intf; diff --git a/include/uapi/linux/usb/g_uvc.h b/include/uapi/linux/usb/g_uvc.h index 6698c3263ae8..10fbb4382925 100644 --- a/include/uapi/linux/usb/g_uvc.h +++ b/include/uapi/linux/usb/g_uvc.h @@ -24,7 +24,8 @@ struct uvc_request_data { __s32 length; - __u8 data[60]; + struct usb_ctrlrequest setup; + __u8 data[52]; }; struct uvc_event { From patchwork Thu Jan 24 03:02:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 10778235 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2140513B4 for ; Thu, 24 Jan 2019 03:03:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 119882D0CE for ; Thu, 24 Jan 2019 03:03:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 05A2B2D11F; Thu, 24 Jan 2019 03:03:08 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EA8DF2D0CE for ; Thu, 24 Jan 2019 03:03:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727335AbfAXDCt (ORCPT ); Wed, 23 Jan 2019 22:02:49 -0500 Received: from perceval.ideasonboard.com ([213.167.242.64]:52918 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727315AbfAXDCs (ORCPT ); Wed, 23 Jan 2019 22:02:48 -0500 Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 882942F4; Thu, 24 Jan 2019 04:02:45 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1548298966; bh=W248YTYRKAUTDyD3PHOYUspxlWEogAay3y6YyoFQkN0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DL48IS1zYQ0LWbI9IVDMkJpwlO/potkb9rl6OtPSk87LVqtBfiwi/u7srb9sjaES2 NmfR5FUD46AjzZ3NZz/N1PqZTBhz4otivStpv6vahTp4nEGfek1uGk312CQ7mAEcJE 61fclzFlbaZxouTxx2ldWqZtlylcT1AvKl4NIlyw= From: Paul Elder To: laurent.pinchart@ideasonboard.com, kieran.bingham@ideasonboard.com Cc: Paul Elder , b-liu@ti.com, stern@rowland.harvard.edu, rogerq@ti.com, balbi@kernel.org, gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v7 4/6] usb: gadget: add mechanism to specify an explicit status stage Date: Wed, 23 Jan 2019 22:02:26 -0500 Message-Id: <20190124030228.19840-5-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190124030228.19840-1-paul.elder@ideasonboard.com> References: <20190124030228.19840-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP A usb gadget function driver may or may not want to delay the status stage of a control OUT request. An instance where it might want to is to asynchronously validate the data of a class-specific request. A function driver that wants an explicit status stage should set the newly added explicit_status flag of the usb_request corresponding to the data stage. Later on, the function driver can explicitly complete the status stage by enqueueing a usb_request for ACK, or calling usb_ep_set_halt() for STALL. To support both explicit and implicit status stages, a UDC driver must call the newly added usb_gadget_control_complete function right before calling usb_gadget_giveback_request. To support the explicit status stage, it might then check what stage the usb_request was queued in, and for control IN ACK the host's zero-length data packet, or for control OUT send a zero-length DATA1 ACK packet. Signed-off-by: Paul Elder v4 Acked-by: Alan Stern v1 Reviewed-by: Laurent Pinchart --- No change from v6 No change from v5 Changes from v4: - Change parameter of usb_gadget_control_complete to simply take a usb_request - Make usb_gadget_control_complete do nothing if the request has no length (ie. no data stage) Changes from v3: - More specific in commit message about what to do for udc driver acking - Set explicit_status in usb_gadget_control_complete - Make explicit_status type bool Changes from v2: Add status parameter to usb_gadget_control_complete, so that a usb_request is not queued if the status of the just given back request is nonzero. Changes from v1: Complete change of API. Now we use a flag that should be set in the usb_request that is queued for the data stage to signal to the UDC that we want to delay the status stage (as opposed to setting a flag in the UDC itself, that persists across all requests). We now also provide a function for UDC drivers to very easily allow implicit status stages, to mitigate the need to convert all function drivers to this new API at once, and to make it easier for UDC drivers to convert. drivers/usb/gadget/udc/core.c | 34 ++++++++++++++++++++++++++++++++++ include/linux/usb/gadget.h | 10 ++++++++++ 2 files changed, 44 insertions(+) diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index af88b48c1cea..57b2c2550537 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -894,6 +894,40 @@ EXPORT_SYMBOL_GPL(usb_gadget_giveback_request); /* ------------------------------------------------------------------------- */ +/** + * usb_gadget_control_complete - complete the status stage of a control + * request, or delay it + * Context: in_interrupt() + * + * @gadget: gadget whose control request's status stage should be completed + * @request: usb request whose status stage should be completed + * + * This is called by device controller drivers before returning the completed + * request back to the gadget layer, to either complete or delay the status + * stage. It exits without doing anything if the request has a non-zero status, + * if it has zero length, or if its explicit_status flag is set. + */ +void usb_gadget_control_complete(struct usb_gadget *gadget, + struct usb_request *request) +{ + struct usb_request *req; + + if (request->explicit_status || request->status || !request->length) + return; + + /* Send an implicit status-stage request for ep0 */ + req = usb_ep_alloc_request(gadget->ep0, GFP_ATOMIC); + if (req) { + req->length = 0; + req->explicit_status = 1; + req->complete = usb_ep_free_request; + usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); + } +} +EXPORT_SYMBOL_GPL(usb_gadget_control_complete); + +/* ------------------------------------------------------------------------- */ + /** * gadget_find_ep_by_name - returns ep whose name is the same as sting passed * in second parameter or NULL if searched endpoint not found diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index e5cd84a0f84a..bf4f021ce139 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -73,6 +73,7 @@ struct usb_ep; * Note that for writes (IN transfers) some data bytes may still * reside in a device-side FIFO when the request is reported as * complete. + * @explicit_status: If true, delays the status stage * * These are allocated/freed through the endpoint they're used with. The * hardware's driver can add extra per-request data to the memory it returns, @@ -114,6 +115,8 @@ struct usb_request { int status; unsigned actual; + + bool explicit_status; }; /*-------------------------------------------------------------------------*/ @@ -850,6 +853,13 @@ extern void usb_gadget_giveback_request(struct usb_ep *ep, /*-------------------------------------------------------------------------*/ +/* utility to complete or delay status stage */ + +void usb_gadget_control_complete(struct usb_gadget *gadget, + struct usb_request *request); + +/*-------------------------------------------------------------------------*/ + /* utility to find endpoint by name */ extern struct usb_ep *gadget_find_ep_by_name(struct usb_gadget *g, From patchwork Thu Jan 24 03:02:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 10778233 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6FA7C13B4 for ; Thu, 24 Jan 2019 03:03:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6037D2D0CE for ; Thu, 24 Jan 2019 03:03:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 544862D11F; Thu, 24 Jan 2019 03:03:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B8CFE2D0CE for ; Thu, 24 Jan 2019 03:03:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727349AbfAXDCu (ORCPT ); Wed, 23 Jan 2019 22:02:50 -0500 Received: from perceval.ideasonboard.com ([213.167.242.64]:52924 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727252AbfAXDCu (ORCPT ); Wed, 23 Jan 2019 22:02:50 -0500 Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1B5122F5; Thu, 24 Jan 2019 04:02:47 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1548298968; bh=jK9l6KTbRd/p2CLZjYqss5k9r6Xs5TVksT3qoRQaUbA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DLTiKGkaqBzTpO2S/LFs1cSuEOE3E109/tAp1vEeMr1fSpQ04DEj9YjAJJG5mBE4v qLIZxAANU3tceHJl9SvkwLHgwAPmmMCfwgWo9RKVWgrXFOrl5jGrtEY9Al98M+t2vR w6nGlz3JmavKU5JQr/dRUDEji+U+6HV51hxLrS+c= From: Paul Elder To: laurent.pinchart@ideasonboard.com, kieran.bingham@ideasonboard.com Cc: Paul Elder , b-liu@ti.com, stern@rowland.harvard.edu, rogerq@ti.com, balbi@kernel.org, gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v7 5/6] usb: musb: gadget: implement optional explicit status stage Date: Wed, 23 Jan 2019 22:02:27 -0500 Message-Id: <20190124030228.19840-6-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190124030228.19840-1-paul.elder@ideasonboard.com> References: <20190124030228.19840-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Implement the mechanism for optional explicit status stage for the MUSB driver. This allows a function driver to specify what to reply for the status stage. The functionality for an implicit status stage is retained. Signed-off-by: Paul Elder v1 Reviewed-by: Laurent Pinchart v1 Acked-by: Bin Liu --- Changes from v6: - check that the request queued for the status stage of a control OUT request has zero length Changes from v5: - giveback usb request to gadget driver after enqueueing for the status stage Changes from v4: - call usb_gadget_control_complete before usb_gadget_giveback_request - set musb ep0 state to statusin in ep0_send_ack - make sure to not double-write musb register in ep0_rxstate, since musb_g_ep0_giveback will take care of writing them No change from v3 Changes from v2: - update call to usb_gadget_control_complete to include status - since sending STALL from the function driver is now done with usb_ep_set_halt, there is no need for the internal ep0_send_response to take a stall/ack parameter; remove the parameter and make the function only send ack, and remove checking for the status reply in the usb_request for the status stage Changes from v1: - obvious change to implement v2 mechanism laid out by 4/6 of this series (send_response, and musb_g_ep0_send_response function has been removed, call to usb_gadget_control_complete has been added) - ep0_send_response's ack argument has been changed from stall - last_packet flag in ep0_rxstate has been removed, since it is equal to req != NULL drivers/usb/musb/musb_gadget.c | 2 ++ drivers/usb/musb/musb_gadget_ep0.c | 36 ++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index ffe462a657b1..2a36bebf955d 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -144,6 +144,8 @@ __acquires(ep->musb->lock) unmap_dma_buffer(req, musb); trace_musb_req_gb(req); + if (req->ep->end_point.address == 0) + usb_gadget_control_complete(&musb->g, &req->request); usb_gadget_giveback_request(&req->ep->end_point, &req->request); spin_lock(&musb->lock); ep->busy = busy; diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 91a5027b5c1f..e6531ebe789e 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -458,6 +458,25 @@ __acquires(musb->lock) return handled; } +static int ep0_send_ack(struct musb *musb) +{ + void __iomem *regs = musb->control_ep->regs; + u16 csr; + + if (musb->ep0_state != MUSB_EP0_STAGE_RX && + musb->ep0_state != MUSB_EP0_STAGE_STATUSIN) + return -EINVAL; + + csr = MUSB_CSR0_P_DATAEND | MUSB_CSR0_P_SVDRXPKTRDY; + + musb_ep_select(musb->mregs, 0); + musb_writew(regs, MUSB_CSR0, csr); + + musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; + + return 0; +} + /* we have an ep0out data packet * Context: caller holds controller lock */ @@ -504,12 +523,15 @@ static void ep0_rxstate(struct musb *musb) if (req) { musb->ackpend = csr; musb_g_ep0_giveback(musb, req); + if (req->explicit_status) + return; if (!musb->ackpend) return; musb->ackpend = 0; + } else { + musb_ep_select(musb->mregs, 0); + musb_writew(regs, MUSB_CSR0, csr); } - musb_ep_select(musb->mregs, 0); - musb_writew(regs, MUSB_CSR0, csr); } /* @@ -937,6 +959,7 @@ musb_g_ep0_queue(struct usb_ep *e, struct usb_request *r, gfp_t gfp_flags) case MUSB_EP0_STAGE_RX: /* control-OUT data */ case MUSB_EP0_STAGE_TX: /* control-IN data */ case MUSB_EP0_STAGE_ACKWAIT: /* zero-length data */ + case MUSB_EP0_STAGE_STATUSIN: status = 0; break; default: @@ -978,6 +1001,15 @@ musb_g_ep0_queue(struct usb_ep *e, struct usb_request *r, gfp_t gfp_flags) } else if (musb->ackpend) { musb_writew(regs, MUSB_CSR0, musb->ackpend); musb->ackpend = 0; + + /* status stage of OUT with data, issue IN status, then giveback */ + } else if (musb->ep0_state == MUSB_EP0_STAGE_STATUSIN) { + if (req->request.length) + status = -EINVAL; + else { + status = ep0_send_ack(musb); + musb_g_ep0_giveback(ep->musb, r); + } } cleanup: From patchwork Thu Jan 24 03:02:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 10778231 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8FF3291E for ; Thu, 24 Jan 2019 03:03:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7CCE62D0CE for ; Thu, 24 Jan 2019 03:03:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6B33C2D11F; Thu, 24 Jan 2019 03:03:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C42C82D0CE for ; Thu, 24 Jan 2019 03:03:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727384AbfAXDCx (ORCPT ); Wed, 23 Jan 2019 22:02:53 -0500 Received: from perceval.ideasonboard.com ([213.167.242.64]:52938 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727342AbfAXDCw (ORCPT ); Wed, 23 Jan 2019 22:02:52 -0500 Received: from localhost.localdomain (unknown [96.44.9.117]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id A433823D; Thu, 24 Jan 2019 04:02:48 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1548298969; bh=pvTulY8PyOJgbb2q7UKgbyj6XlrVByBxyEzxK2Jb4bg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=gPXc14X5Ylf+hfOdyHoI/MsBHPKZWcI+i0iO8l2Q/J88wPlN+uaHoCl+LrGp+47XZ uFNeCH6IpQDs++X6P+2q6H0hg7jkFHQ0cmJz3+mINBHvOnKFxxg2VjNfxX246xQM4K /2Y99MVBfXkDRmr651RjC4hyfa5+evPJEpl4o2no= From: Paul Elder To: laurent.pinchart@ideasonboard.com, kieran.bingham@ideasonboard.com Cc: Paul Elder , b-liu@ti.com, stern@rowland.harvard.edu, rogerq@ti.com, balbi@kernel.org, gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v7 6/6] usb: gadget: uvc: allow ioctl to send response in status stage Date: Wed, 23 Jan 2019 22:02:28 -0500 Message-Id: <20190124030228.19840-7-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190124030228.19840-1-paul.elder@ideasonboard.com> References: <20190124030228.19840-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP We now have a mechanism to signal the UDC driver to reply to a control OUT request with STALL or ACK, and we have packaged the setup stage data and the data stage data of a control OUT request into a single UVC_EVENT_DATA for userspace to consume. After telling the UDC to delay the status stage, the ioctl UVCIOC_SEND_RESPONSE should be called to notify the UDC driver to reply with STALL or ACK, for control OUT requests. In the case of a control IN request, the ioctl sends the UVC data as before. This means that the completion handler will also be called for the status stage, so make the UVC gadget driver aware of if the completion handler is called for the status stage, and do nothing (as opposed to giving userspace the UVC data again). Signed-off-by: Paul Elder --- No change from v6 Changes from v5: - add event_status flag and use to keep track of whether or not the gadget is in the status stage or not - do nothing if the completion handler is called during the status stage No change from v4 No change from v3 Changes from v2: - calling usb_ep_set_halt in uvc_send_response if data->length < 0 is now common for both IN and OUT transfers so make that check common - remove now unnecessary field setting for the usb_request to be queued for the status stage Changes from v1: - remove usb_ep_delay_status call from the old proposed API - changed portions of uvc_send_response to match v2 API - remove UDC warning that send_response is not implemented drivers/usb/gadget/function/f_uvc.c | 11 +++++++++-- drivers/usb/gadget/function/uvc.h | 1 + drivers/usb/gadget/function/uvc_v4l2.c | 24 ++++++++++++++++++------ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 6303ed346af9..dd3a06e28435 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -208,15 +208,19 @@ uvc_function_ep0_complete(struct usb_ep *ep, struct usb_request *req) struct v4l2_event v4l2_event; struct uvc_event *uvc_event = (void *)&v4l2_event.u.data; - if (uvc->event_setup_out) { - uvc->event_setup_out = 0; + if (uvc->event_status) { + uvc->event_status = 0; + return; + } + if (uvc->event_setup_out) { 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); memcpy(&uvc_event->data.setup, &uvc->control_setup, sizeof(uvc_event->data.setup)); + v4l2_event_queue(&uvc->vdev, &v4l2_event); } } @@ -242,6 +246,8 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) uvc->event_length = le16_to_cpu(ctrl->wLength); memcpy(&uvc->control_setup, ctrl, sizeof(uvc->control_setup)); + uvc->event_status = 0; + if (uvc->event_setup_out) { struct usb_request *req = uvc->control_req; @@ -251,6 +257,7 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) */ req->length = uvc->event_length; req->zero = 0; + req->explicit_status = 1; usb_ep_queue(f->config->cdev->gadget->ep0, req, GFP_KERNEL); } else { struct v4l2_event v4l2_event; diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 1d89b1df4ba0..5754548d94c5 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -171,6 +171,7 @@ struct uvc_device { /* Events */ unsigned int event_length; unsigned int event_setup_out : 1; + unsigned int event_status : 1; }; static inline struct uvc_device *to_uvc(struct usb_function *f) diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index ac48f49d9f10..338811c612c5 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -35,15 +35,27 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data) struct usb_composite_dev *cdev = uvc->func.config->cdev; struct usb_request *req = uvc->control_req; + if (data->length < 0) + return usb_ep_set_halt(cdev->gadget->ep0); + /* * For control OUT transfers the request has been enqueued synchronously - * by the setup handler, there's nothing to be done here. + * by the setup handler, we just need to tell the UDC whether to ACK or + * STALL the control transfer. */ - if (uvc->event_setup_out) - return 0; - - if (data->length < 0) - return usb_ep_set_halt(cdev->gadget->ep0); + if (uvc->event_setup_out) { + /* + * The length field carries the control request status. + * Negative values signal a STALL and zero values an ACK. + * Positive values are not valid as there is no data to send + * back in the status stage. + */ + if (data->length > 0) + return -EINVAL; + + uvc->event_status = 1; + return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL); + } req->length = min_t(unsigned int, uvc->event_length, data->length); req->zero = data->length < uvc->event_length;