Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752612AbbG1ErN (ORCPT ); Tue, 28 Jul 2015 00:47:13 -0400 Received: from mga02.intel.com ([134.134.136.20]:28148 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750712AbbG1ErM convert rfc822-to-8bit (ORCPT ); Tue, 28 Jul 2015 00:47:12 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,560,1432623600"; d="scan'208,223";a="614198638" From: "Du, Changbin" To: Andrzej Pietrasiewicz , Felipe Balbi CC: Greg Kroah-Hartman , "linux-usb@vger.kernel.org" , "linux-kernel@vger.kernel.org" Subject: [PATCH v2] usb/gadget: make composite gadget meet usb compliance for vbus draw Thread-Topic: [PATCH v2] usb/gadget: make composite gadget meet usb compliance for vbus draw Thread-Index: AdDI8EFKTv3pvHNGRC2w/fqTmB9+Tw== Date: Tue, 28 Jul 2015 04:46:30 +0000 Message-ID: <0C18FE92A7765D4EB9EE5D38D86A563A01D4E8CF@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: 5225 Lines: 155 >From 08df419517694c4dd9ff328f5644b46a99c2999e Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Thu, 23 Jul 2015 20:08:04 +0800 Subject: [PATCH v2] 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 ++++++++++++++++++++++++++++++++------- drivers/usb/gadget/configfs.c | 2 +- include/linux/usb/composite.h | 1 + include/uapi/linux/usb/ch9.h | 9 +++++++++ 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 4e3447b..b3896e9 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_UNCONF_STATE_VBUS_MAX_DRAW; + else if (g->speed == USB_SPEED_SUPER) + power = USB3_UNCONF_STATE_VBUS_MAX_DRAW; + else + power = USB2_UNCONF_STATE_VBUS_MAX_DRAW; + + 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; } +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_SUSPEND_STATE_VBUS_MAX_DRAW); } 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/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 0495c94..e16335d 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -1449,7 +1449,7 @@ static const struct usb_gadget_driver configfs_driver_template = { .unbind = configfs_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..825ad39 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -506,6 +506,7 @@ extern struct usb_string *usb_gstrings_attach(struct usb_composite_dev *cdev, extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n); +extern void composite_reset(struct usb_gadget *gadget); extern void composite_disconnect(struct usb_gadget *gadget); extern int composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl); diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h index aa33fd1..ab216bf 100644 --- a/include/uapi/linux/usb/ch9.h +++ b/include/uapi/linux/usb/ch9.h @@ -996,4 +996,13 @@ struct usb_set_sel_req { */ #define USB_SELF_POWER_VBUS_MAX_DRAW 100 +/* + * USB2 compliance requires that un-configured current draw less than 100mA, + * while USB3 requires it <= 150mA, and OTG device requires it <= 2.5mA. + */ +#define USB2_UNCONF_STATE_VBUS_MAX_DRAW 100 +#define USB3_UNCONF_STATE_VBUS_MAX_DRAW 150 +#define USB_OTG_UNCONF_STATE_VBUS_MAX_DRAW 2 +#define USB_SUSPEND_STATE_VBUS_MAX_DRAW 2 + #endif /* _UAPI__LINUX_USB_CH9_H */ -- 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/