Received: by 2002:ac0:a582:0:0:0:0:0 with SMTP id m2-v6csp360079imm; Tue, 9 Oct 2018 19:52:17 -0700 (PDT) X-Google-Smtp-Source: ACcGV63rjTbgWUI0E0XK4nJtWh7HHWzYFrMM1I6P4lrJKI366dPYfUgFyHtI2RdgM7UowBHvmbgJ X-Received: by 2002:a17:902:30a3:: with SMTP id v32-v6mr30699863plb.277.1539139937772; Tue, 09 Oct 2018 19:52:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1539139937; cv=none; d=google.com; s=arc-20160816; b=SPw/1WmqRZ+mMR+6RyVF1VkcSTtEGGW3yytMj/Nq55AGm3b32teLCOqaX9kJhsaWWA s1K/N528sIGzq/5SGJ6ZUr8AP4zYDIWCybkS6lfrfTNYZ8bv4DyGXY2NAmcBS43rwsH5 MeGuB7631Xa4pC2ZvZCM1a/djN8xMCLiqFDRaOX16V0OuVpc8qY+CAYKCM3u6ZJDvyNW 3pz3wkuf9eRq0G/D+YlXw+WI+n/cqNGqf6PdIv4n8KYzGVDnJ+kxEyO0DXOtUvJTUisG hCUZSsSPgbiX1p6NJjSwLEjYQDh2axyip6fMwhN/ASyO5XcRxnBIvS1IxqOljRK4VKDQ 6yyg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature; bh=38f4D9MFWQ/qSpgzCjRmPJ1+QwxTkLMHRfeaO1ucTxU=; b=YUmtUntxY6fo0yx2wFPJj+k9JqHRYuqLf0N+P7WRlMuQKNQinSq34ba+PI2Zge/wXj 2HzEszx6TFHNchsNtdJslXKDMwNcG3GlG7W8QA0HaWiSj5Pt/gVzuw4UM55KHTB0h9zi HEEthf6IQLhTSeFqupggs2CjAha+tieqVr5AYC+6zPYiPN8OWwC7SB+7cz7dROEwRNas jPcdO0lRlCPn3MlDWGoEWUH04YXBfMU6rB7mALkwgUGjogqlWqlaNX8ig5/PB8cyr/pZ fMLGZRq0IDwPrkkaFPpG5B/reO4gnpowNRueqa2Xt+lWtW2JaGYIrKX0yMlMG9Qm+Q72 u01w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=PslQessQ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id n24-v6si22514379pff.136.2018.10.09.19.52.03; Tue, 09 Oct 2018 19:52:17 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=PslQessQ; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727412AbeJJKJV (ORCPT + 99 others); Wed, 10 Oct 2018 06:09:21 -0400 Received: from perceval.ideasonboard.com ([213.167.242.64]:44280 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726701AbeJJKJV (ORCPT ); Wed, 10 Oct 2018 06:09:21 -0400 Received: from garnet.amanokami.net (unknown [96.44.9.229]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D35CF1BFA; Wed, 10 Oct 2018 04:49:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1539139762; bh=2uMXRpN7ZfS0oDUuPn6ctdCkiFckaZQyBU511QaXG8I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PslQessQqG1rDn6xLKRkwx+xolhTdjTKyNyg/6ngqfnkNWiIgOstm8PhJJT6svZPx jLvV6SUYxr8k9qyydfY9mCdC1PzoZrYS/cF+qaYN0oAlIoBY2xA4SvJD1/5MVTw6o1 bKevTCXs4RsGIxw8iJMK3r+IqeezasTF05TaM4yo= From: Paul Elder To: laurent.pinchart@ideasonboard.com, kieran.bingham@ideasonboard.com Cc: Paul Elder , b-liu@ti.com, gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, balbi@kernel.org, stern@rowland.harvard.edu, rogerq@ti.com Subject: [PATCH 2/6] usb: gadget: uvc: enqueue usb request in setup handler for control OUT Date: Tue, 9 Oct 2018 22:48:59 -0400 Message-Id: <20181010024903.1633-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20181010024903.1633-1-paul.elder@ideasonboard.com> References: <20181010024903.1633-1-paul.elder@ideasonboard.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- 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 dc12d868f9e8..8452de3dfccc 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 038482ff40e8..2e2251bdef03 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); -- 2.18.0