Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752605AbbGWMfJ (ORCPT ); Thu, 23 Jul 2015 08:35:09 -0400 Received: from mga03.intel.com ([134.134.136.65]:45271 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751844AbbGWMfD convert rfc822-to-8bit (ORCPT ); Thu, 23 Jul 2015 08:35:03 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,530,1432623600"; d="scan'208,223";a="769812832" From: "Du, Changbin" To: Felipe Balbi CC: Greg Kroah-Hartman , "linux-usb@vger.kernel.org" , "linux-kernel@vger.kernel.org" Subject: [PATCH] usb/gadget: make composite gadget meet usb compliance for vbus draw Thread-Topic: [PATCH] usb/gadget: make composite gadget meet usb compliance for vbus draw Thread-Index: AdDFQ/v32ELIUcFWTwaMp7sIW5cuUw== Date: Thu, 23 Jul 2015 12:34:58 +0000 Message-ID: <0C18FE92A7765D4EB9EE5D38D86A563A01D14FD5@SHSMSX103.ccr.corp.intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 8BIT MIME-Version: 1.0 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4031 Lines: 129 >From 0a8e0d63a9887735c6782d7b0c15c2c1fdf1952a Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Thu, 23 Jul 2015 20:08:04 +0800 Subject: [PATCH] usb/gadget: make composite gadget meet usb compliance for vbus draw USB-IF compliance requirement limits the vbus current according to current state. USB2 Spec requires that un-configured current must be <= 100mA, for USB3 is 150mA, OTG is 2.5mA. So set corresponding vbus draw current according to device mode. Signed-off-by: Du, Changbin --- drivers/usb/gadget/composite.c | 39 ++++++++++++++++++++++++++++++++------- include/linux/usb/composite.h | 8 ++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 4e3447b..fdfd625 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -610,6 +610,21 @@ static void device_qual(struct usb_composite_dev *cdev) qual->bRESERVED = 0; } +static unsigned unconfigured_vbus_draw(struct usb_composite_dev *cdev) +{ + struct usb_gadget *g = cdev->gadget; + unsigned power; + + if (gadget_is_otg(g)) + power = USB_OTG_VBUS_DRAW_UNCONF; + else if (g->speed == USB_SPEED_SUPER) + power = USB3_VBUS_DRAW_UNCONF; + else + power = USB2_VBUS_DRAW_UNCONF; + + return power; +} + /*-------------------------------------------------------------------------*/ static void reset_config(struct usb_composite_dev *cdev) @@ -634,7 +649,7 @@ static int set_config(struct usb_composite_dev *cdev, struct usb_gadget *gadget = cdev->gadget; struct usb_configuration *c = NULL; int result = -EINVAL; - unsigned power = gadget_is_otg(gadget) ? 8 : 100; + unsigned power = unconfigured_vbus_draw(cdev); int tmp; if (number) { @@ -1829,6 +1844,15 @@ done: return value; } +static void composite_reset(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev = get_gadget_data(gadget); + + DBG(cdev, "reset\n"); + usb_gadget_vbus_draw(gadget, unconfigured_vbus_draw(cdev)); + composite_disconnect(gadget); +} + void composite_disconnect(struct usb_gadget *gadget) { struct usb_composite_dev *cdev = get_gadget_data(gadget); @@ -2095,7 +2119,7 @@ void composite_suspend(struct usb_gadget *gadget) cdev->suspended = 1; - usb_gadget_vbus_draw(gadget, 2); + usb_gadget_vbus_draw(gadget, USB_VBUS_DRAW_SUSPEND); } void composite_resume(struct usb_gadget *gadget) @@ -2117,10 +2141,11 @@ void composite_resume(struct usb_gadget *gadget) } maxpower = cdev->config->MaxPower; - - usb_gadget_vbus_draw(gadget, maxpower ? - maxpower : CONFIG_USB_GADGET_VBUS_DRAW); - } + if (!maxpower) + maxpower = CONFIG_USB_GADGET_VBUS_DRAW; + } else + maxpower = unconfigured_vbus_draw(cdev); + usb_gadget_vbus_draw(gadget, maxpower); cdev->suspended = 0; } @@ -2132,7 +2157,7 @@ static const struct usb_gadget_driver composite_driver_template = { .unbind = composite_unbind, .setup = composite_setup, - .reset = composite_disconnect, + .reset = composite_reset, .disconnect = composite_disconnect, .suspend = composite_suspend, diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 2511469..90b434d 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -333,6 +333,14 @@ enum { USB_GADGET_FIRST_AVAIL_IDX, }; +/* USB2 compliance requires that un-configured current draw <= 100mA, + * USB3 requires it <= 150mA, OTG requires it <= 2.5mA. + */ +#define USB2_VBUS_DRAW_UNCONF 100 +#define USB3_VBUS_DRAW_UNCONF 150 +#define USB_OTG_VBUS_DRAW_UNCONF 2 +#define USB_VBUS_DRAW_SUSPEND 2 + /** * struct usb_composite_driver - groups configurations into a gadget * @name: For diagnostics, identifies the driver. -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/