Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp4986599imu; Wed, 19 Dec 2018 03:47:28 -0800 (PST) X-Google-Smtp-Source: AFSGD/UklmJxTx/XaUacxg6XEGRTrK1euB/A8LvxasCr53j8Q3q8yfAG2Jr7oK/r7T0WpgV1pKsc X-Received: by 2002:a63:2744:: with SMTP id n65mr18966061pgn.65.1545220048424; Wed, 19 Dec 2018 03:47:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1545220048; cv=none; d=google.com; s=arc-20160816; b=HoPlcsn5mjWPPkNyiJLMOuAenNQ+n1M+UDjzNhTHiUc6fcyFGu36cNLEdDgv4yOhZl mWaPd8Z4u4la0btYU/KeU3cUnLSiJ/KEEA14X8BDAF9VEktX3DXbgPfca3pZ2xtO6UYo eSYa5PfBwjaPkomqLoSiIfUI6571MzvRWfBBfnnIsnwwGSoYpvkst+5A35sInNQUuLA3 YDe+nN5Y5Cwx13MuPPrUuoq3p06qwb+zHDEApgqfdzdSctgm0j2z+ZNthf8Xlv6+JwxT H0BmBXdlw4DFDAuxucjOyuMSHveZdzKwIB6XYKND9pUtZTuEUF9AlcHANaPUQjY/dsrb WsfA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=s9tTl1Uu1L14s+z7JX7I3BlZV9zUli45r6LkSMCfPCY=; b=AwAo2SSXml6uBFIzWTUkn4y+oLTBuu35ujDj0tXPuu5VVT7QYfEd5Pbqs8dTZGx9rN UXy5KG7I7gSgsgPNwTmROQXfuGsoLGEbg1yHnrSWkpys6on9w0FC5zgrWOMIW22+QpPa tvIu8MraUOZoOrKrw9eSlHbItwLceNopefNHKUS4rxBgUJ3FbM2g30916tkM4DDwpuzn JN9Xc26zPvpjW6HHIpGu6utZKkSIM2tDGUpv4NjwaGDwvJFrr0uHRva5Y1tDYP4YEQEK tvzcTQozQhdiBGFVfint6uW66BZD6Izv+4BRLpuMmHX1zrhcPIYf9+OX65L+t7YGvdNJ 8abg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=GD+hB4yx; 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 m39si15878172plg.315.2018.12.19.03.47.11; Wed, 19 Dec 2018 03:47:28 -0800 (PST) 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=GD+hB4yx; 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 S1728855AbeLSJ1h (ORCPT + 99 others); Wed, 19 Dec 2018 04:27:37 -0500 Received: from perceval.ideasonboard.com ([213.167.242.64]:38824 "EHLO perceval.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728758AbeLSJ1I (ORCPT ); Wed, 19 Dec 2018 04:27:08 -0500 Received: from localhost.localdomain (unknown [96.44.9.229]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 9D74D594; Wed, 19 Dec 2018 10:27:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1545211625; bh=awknGeUKgI4OqBELYeQWFt1Lkslp4zbOOL2rEmCg2FA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GD+hB4yxDIDClk3tHoRAGFltYd+1L7c5zQo6MAubMV2O9lRxYXRAqRycTwqYagZKD OQuVNd2aEFdGX1+w+fqY0X+MV+WQzH5H9QwodEvF4e1TfTYCo+//fGCCPZBqL2RJsk EsDgLY4tGIGewEYpPLO4V6HV5+aUcAtgdIEmshA8= 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 v3 2/6] usb: gadget: uvc: enqueue usb request in setup handler for control OUT Date: Wed, 19 Dec 2018 04:26:43 -0500 Message-Id: <20181219092647.12397-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181219092647.12397-1-paul.elder@ideasonboard.com> References: <20181219092647.12397-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 --- 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 3e07dcb885b7..772c99c297fc 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 7bfa43dbef9e..35353ffdf3b4 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.19.2