From patchwork Fri Jul 28 12:33:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guennadi Liakhovetski X-Patchwork-Id: 9868665 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3942860382 for ; Fri, 28 Jul 2017 12:33:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3446B288CD for ; Fri, 28 Jul 2017 12:33:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 29477288DD; Fri, 28 Jul 2017 12:33:43 +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=-6.4 required=2.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_HI,RCVD_IN_SORBS_SPAM,UNPARSEABLE_RELAY 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 898B7288CD for ; Fri, 28 Jul 2017 12:33:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751966AbdG1Mdl (ORCPT ); Fri, 28 Jul 2017 08:33:41 -0400 Received: from mout.gmx.net ([212.227.15.15]:50148 "EHLO mout.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751949AbdG1Mdk (ORCPT ); Fri, 28 Jul 2017 08:33:40 -0400 Received: from axis700.grange ([87.78.105.5]) by mail.gmx.com (mrgmx001 [212.227.17.190]) with ESMTPSA (Nemesis) id 0MQ2Wx-1dVrOr3I3f-005EWW for ; Fri, 28 Jul 2017 14:33:38 +0200 Received: from 200r.grange (200r.grange [192.168.1.16]) by axis700.grange (Postfix) with ESMTP id 71D878B126 for ; Fri, 28 Jul 2017 14:30:58 +0200 (CEST) Received: from lyakh (uid 1000) (envelope-from g.liakhovetski@gmx.de) id 808eb5 by 200r.grange (DragonFly Mail Agent v0.9); Fri, 28 Jul 2017 14:33:25 +0200 From: Guennadi Liakhovetski To: linux-media@vger.kernel.org Cc: Laurent Pinchart , Hans Verkuil , Guennadi Liakhovetski Subject: [PATCH 6/6 v5] uvcvideo: handle control pipe protocol STALLs Date: Fri, 28 Jul 2017 14:33:25 +0200 Message-Id: <1501245205-15802-7-git-send-email-g.liakhovetski@gmx.de> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1501245205-15802-1-git-send-email-g.liakhovetski@gmx.de> References: <1501245205-15802-1-git-send-email-g.liakhovetski@gmx.de> X-Provags-ID: V03:K0:a5JlpEkm7Pt9OtOze/3oE7A2YoTX2J5XXMu5reZQwUMER5hNPXC 0kSFTmkyuQkUjzze6jNtZqvjHkHvXaoelKQoZVF97Y8CFE/Cs7TXQJpONXNcBekjy0hlxjb EMp/8RxK3ZhVcrpwOhfTSK8U+Kcbx7FiC0YPmdUDunBmCvveHScipDSZIPHn4ttg/awzRuT dcapXn9++1mZH4Bp1zT1w== X-UI-Out-Filterresults: notjunk:1; V01:K0:AGywor5tlKg=:KuyoNut5N3I3/+LMlMSLWS AJrAXHoO4iJ/eQwTtK5HdVnuVHW6k/X8gxuQ3P4mZq1btnnn3wCm6HT79Qz3zfgmh2y1APd3x gVMlAUBhe0MxVJNmqTqkReZavRCffNO/9KsRKsGFhpgZFXlk9WycYMsDLiDEvgxPW/FaXOCxt xfkIN/Mcdzl2poGvVQ0Xa+hWYxbS+OCm5KYrgStwgGZn4Op7shE4pE7TxuU2L8vJg/tGAwHJA ATeuqvMnj2PEeNEjIuXa4swADcdR6GF45GRayLnwrTZfwhj4wN5u5qCquy3+HUYe5Xv7PuN69 R7SlSpAAA08q0gP0AvHjSUGoTVy+NAT7M5gu7J0hFjRfbnYebn0JU3AQzDFEG9Cmu+cn8HzpU UDPqU/5OeYG0G1XL8hSgquLIaSRwIkAtHusOf6i13ZFEAgKJY/BtDpk/vASzIWr6A0PFOGXro Jlh3raMY8HsZKnitvzu3afR1v49+/MubxM8SwG73/oUecb5aRl2ufDuykhZhmgN3Vt4BORAlf Ouk3Ik+sLLGGRl5lNzE2balfgjlLBkZgwd/1y9s1DN/yPSQZM2jfrxR84gfPaAKOAldmdZpyn bbFsEiutlXT3OquYSnu46hfbByKfkEYnyc0gXPHxSvXlKOJRipWVmuqW0iJcTSMnNpzJq1W3i aV6TIezSbgBb9g6wyceR1UGjfTvo39dY/zlxkteECYGqhf6VLcevgmbdPHTLFTlssbciW2lzL 6X/SeNAU9wx9TZd4ZQcRUPhZI/mUDqYOu9FMNShjO0uITdwu//xiJs5eXtCQllTW9iz8CAst3 6mVmaQP+IA1oKWkgrAwiibwKCpfeQ== Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When a command ends up in a STALL on the control pipe, use the Request Error Code control to provide a more precise error information to the user. Signed-off-by: Guennadi Liakhovetski --- drivers/media/usb/uvc/uvc_video.c | 59 +++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index 006691e..887561b 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -34,15 +34,59 @@ static int __uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, __u8 intfnum, __u8 cs, void *data, __u16 size, int timeout) { - __u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE; + __u8 type = USB_TYPE_CLASS | USB_RECIP_INTERFACE, tmp, error; unsigned int pipe; + int ret; pipe = (query & 0x80) ? usb_rcvctrlpipe(dev->udev, 0) : usb_sndctrlpipe(dev->udev, 0); type |= (query & 0x80) ? USB_DIR_IN : USB_DIR_OUT; - return usb_control_msg(dev->udev, pipe, query, type, cs << 8, + ret = usb_control_msg(dev->udev, pipe, query, type, cs << 8, unit << 8 | intfnum, data, size, timeout); + + if (ret != -EPIPE) + return ret; + + tmp = *(u8 *)data; + + pipe = usb_rcvctrlpipe(dev->udev, 0); + type = USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN; + ret = usb_control_msg(dev->udev, pipe, UVC_GET_CUR, type, + UVC_VC_REQUEST_ERROR_CODE_CONTROL << 8, + unit << 8 | intfnum, data, 1, timeout); + error = *(u8 *)data; + *(u8 *)data = tmp; + + if (ret < 0) + return ret; + + if (!ret) + return -EINVAL; + + uvc_trace(UVC_TRACE_CONTROL, "Control error %u\n", error); + + switch (error) { + case 0: + /* Cannot happen - we received a STALL */ + return -EPIPE; + case 1: /* Not ready */ + return -EAGAIN; + case 2: /* Wrong state */ + return -EILSEQ; + case 3: /* Power */ + return -EREMOTE; + case 4: /* Out of range */ + return -ERANGE; + case 5: /* Invalid unit */ + case 6: /* Invalid control */ + case 7: /* Invalid Request */ + case 8: /* Invalid value within range */ + default: /* reserved or unknown */ + break; + } + + return -EINVAL; } static const char *uvc_query_name(__u8 query) @@ -80,7 +124,7 @@ int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, uvc_printk(KERN_ERR, "Failed to query (%s) UVC control %u on " "unit %u: %d (exp. %u).\n", uvc_query_name(query), cs, unit, ret, size); - return -EIO; + return ret < 0 ? ret : -EIO; } return 0; @@ -203,13 +247,15 @@ static int uvc_get_video_ctrl(struct uvc_streaming *stream, uvc_warn_once(stream->dev, UVC_WARN_PROBE_DEF, "UVC non " "compliance - GET_DEF(PROBE) not supported. " "Enabling workaround.\n"); - ret = -EIO; + if (ret >= 0) + ret = -EIO; goto out; } else if (ret != size) { uvc_printk(KERN_ERR, "Failed to query (%u) UVC %s control : " "%d (exp. %u).\n", query, probe ? "probe" : "commit", ret, size); - ret = -EIO; + if (ret >= 0) + ret = -EIO; goto out; } @@ -290,7 +336,8 @@ static int uvc_set_video_ctrl(struct uvc_streaming *stream, uvc_printk(KERN_ERR, "Failed to set UVC %s control : " "%d (exp. %u).\n", probe ? "probe" : "commit", ret, size); - ret = -EIO; + if (ret >= 0) + ret = -EIO; } kfree(data);