All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 00/17] usb: gadget: update
@ 2021-01-25 13:43 peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 01/17] usb: gadget: Add ep_config call back to usb_gadget_ops peng.fan at nxp.com
                   ` (16 more replies)
  0 siblings, 17 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Peng Fan <peng.fan@nxp.com>

V2:
 Fix imx6dl_mamoj size SPL exceeded issue

V1:
This patchset is to upstream NXP downstream gadget driver patches
for feature update.

Jun Li (2):
  usb: gadget: set correct usb_configuration for os_desc_config
  usb: gadget: update os_desc_config when add config

Li Jun (13):
  usb: gadget: don't change ep name for dwc3 while ep autoconfig
  usb: gadget: OS String support
  usb: gadget: move utf8_to_utf16le to header file
  usb: gadget: OS Feature Descriptors support
  usb: gadget: add WCID support for mfgtool
  usb: gadget: fastboot: add ext properties for WCID
  usb: gadget: add super speed support
  usb: fastboot: add super speed support
  usb: gadget: dnl: set dnl to be super speed
  usb: composite: force gadget to be USB2 for HS only function
  usb: udc: ci: update speed handling
  usb: gadget: fastboot: use correct max packet size
  usb: gaget: ci: set ep's desc when enable ep

Peng Fan (1):
  usb: gadget: add Kconfig for OS descriptors

Ye Li (1):
  usb: gadget: Add ep_config call back to usb_gadget_ops

 drivers/usb/gadget/Kconfig      |   9 +
 drivers/usb/gadget/ci_udc.c     |   5 +-
 drivers/usb/gadget/composite.c  | 392 +++++++++++++++++++++++++++++---
 drivers/usb/gadget/epautoconf.c |   6 +
 drivers/usb/gadget/f_fastboot.c |  83 ++++++-
 drivers/usb/gadget/g_dnl.c      |   1 +
 drivers/usb/gadget/u_os_desc.h  | 123 ++++++++++
 drivers/usb/gadget/usbstring.c  |  74 +-----
 include/linux/usb/composite.h   |  71 ++++++
 include/linux/usb/gadget.h      |   9 +
 include/linux/utf.h             |  75 ++++++
 11 files changed, 743 insertions(+), 105 deletions(-)
 create mode 100644 drivers/usb/gadget/u_os_desc.h
 create mode 100644 include/linux/utf.h

-- 
2.28.0

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH V2 01/17] usb: gadget: Add ep_config call back to usb_gadget_ops
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 02/17] usb: gadget: don't change ep name for dwc3 while ep autoconfig peng.fan at nxp.com
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Ye Li <ye.li@nxp.com>

Since some new fields in usb_ep structure been moved to usb_ss_ep.
The CDNS3 gadget driver should replies on this operation to bind the
usb_ss_ep with the endpoint descriptor when function layer uses
usb_ep_autoconfig to add endpoint descriptors to gadget. So that
CDNS3 driver can know the EP information and configure the EP once
the set configuration request is received.

Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/epautoconf.c | 4 ++++
 include/linux/usb/gadget.h      | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index e61fe5d114..3f8842976d 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -167,6 +167,10 @@ static int ep_matches(
 			size = 64;
 		put_unaligned(cpu_to_le16(size), &desc->wMaxPacketSize);
 	}
+
+	if (gadget->ops->ep_conf)
+		return gadget->ops->ep_conf(gadget, ep, desc);
+
 	return 1;
 }
 
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 06292ddeb6..8d54b91734 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -470,6 +470,9 @@ struct usb_gadget_ops {
 	struct usb_ep *(*match_ep)(struct usb_gadget *,
 			struct usb_endpoint_descriptor *,
 			struct usb_ss_ep_comp_descriptor *);
+	int   (*ep_conf)(struct usb_gadget *,
+			struct usb_ep *,
+			struct usb_endpoint_descriptor *);
 	void	(*udc_set_speed)(struct usb_gadget *gadget,
 				 enum usb_device_speed);
 };
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 02/17] usb: gadget: don't change ep name for dwc3 while ep autoconfig
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 01/17] usb: gadget: Add ep_config call back to usb_gadget_ops peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 03/17] usb: gadget: OS String support peng.fan at nxp.com
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Li Jun <jun.li@nxp.com>

As the SDP protocol use the predefined ep num for communication, we can't
change its name hence reset its ep num while do ep autoconfig, this is
only apply for SPL.

Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/epautoconf.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 3f8842976d..7da334f5d3 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -262,6 +262,7 @@ struct usb_ep *usb_ep_autoconfig(
 		ep = find_ep(gadget, "ep1-bulk");
 		if (ep && ep_matches(gadget, ep, desc))
 			return ep;
+#ifndef CONFIG_SPL_BUILD
 	} else if (gadget_is_dwc3(gadget)) {
 		const char *name = NULL;
 		/*
@@ -284,6 +285,7 @@ struct usb_ep *usb_ep_autoconfig(
 			ep = find_ep(gadget, name);
 		if (ep && ep_matches(gadget, ep, desc))
 			return ep;
+#endif
 	}
 
 	if (gadget->ops->match_ep)
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 03/17] usb: gadget: OS String support
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 01/17] usb: gadget: Add ep_config call back to usb_gadget_ops peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 02/17] usb: gadget: don't change ep name for dwc3 while ep autoconfig peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 04/17] usb: gadget: move utf8_to_utf16le to header file peng.fan at nxp.com
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Li Jun <jun.li@nxp.com>

This is a porting patch from linux kernel: 19824d5eeece
("usb: gadget: OS String support"), original commit log
see below:

"There is a custom (non-USB IF) extension to the USB standard:

http://msdn.microsoft.com/library/windows/hardware/gg463182

They grant permission to use the specification - there is
"Microsoft OS Descriptor Specification License Agreement"
under the link mentioned above, and its Section 2 "Grant
of License", letter (b) reads:

"Patent license. Microsoft hereby grants to You a nonexclusive,
royalty-free, nontransferable, worldwide license under Microsoft??
patents embodied solely within the Specification and that are owned
or licensable by Microsoft to make, use, import, offer to sell,
sell and distribute directly or indirectly to Your Licensees Your
Implementation. You may sublicense this patent license to Your
Licensees under the same terms and conditions."

The said extension is maintained by Microsoft for Microsoft.

Yet it is fairly common for various devices to use it, and a
popular proprietary operating system expects devices to provide
"OS descriptors", so Linux-based USB gadgets whishing to be able
to talk to a variety of operating systems should be able to provide
the "OS descriptors".

This patch adds optional support for gadgets whishing to expose
the so called "OS String" under index 0xEE of language 0.
The contents of the string is generated based on the qw_sign
array and b_vendor_code.

Interested gadgets need to set the cdev->use_os_string flag,
fill cdev->qw_sign with appropriate values and fill cdev->b_vendor_code
with a value of their choice.

This patch does not however implement responding to any vendor-specific
USB requests."

Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/composite.c | 26 ++++++++++++++++++++++++++
 include/linux/usb/composite.h  | 10 ++++++++++
 2 files changed, 36 insertions(+)

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 91ed7fcec5..63855af52e 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -25,6 +25,22 @@ static inline void le16_add_cpu_packed(__le16_packed *var, u16 val)
 	var->val = cpu_to_le16(le16_to_cpu(var->val) + val);
 }
 
+/**
+ * struct usb_os_string - represents OS String to be reported by a gadget
+ * @bLength: total length of the entire descritor, always 0x12
+ * @bDescriptorType: USB_DT_STRING
+ * @qwSignature: the OS String proper
+ * @bMS_VendorCode: code used by the host for subsequent requests
+ * @bPad: not used, must be zero
+ */
+struct usb_os_string {
+	__u8	bLength;
+	__u8	bDescriptorType;
+	__u8	qwSignature[OS_STRING_QW_SIGN_LEN];
+	__u8	bMS_VendorCode;
+	__u8	bPad;
+} __packed;
+
 /**
  * usb_add_function() - add a function to a configuration
  * @config: the configuration
@@ -577,6 +593,16 @@ static int get_string(struct usb_composite_dev *cdev,
 		return s->bLength;
 	}
 
+	if (cdev->use_os_string && language == 0 && id == OS_STRING_IDX) {
+		struct usb_os_string *b = buf;
+		b->bLength = sizeof(*b);
+		b->bDescriptorType = USB_DT_STRING;
+		memcpy(&b->qwSignature, cdev->qw_sign, sizeof(b->qwSignature));
+		b->bMS_VendorCode = cdev->b_vendor_code;
+		b->bPad = 0;
+		return sizeof(*b);
+	}
+
 	/*
 	 * Otherwise, look up and return a specified string.  String IDs
 	 * are device-scoped, so we look up each string table we're told
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index a49a66f2f8..d4f2a49869 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -284,6 +284,8 @@ struct usb_composite_driver {
 extern int usb_composite_register(struct usb_composite_driver *);
 extern void usb_composite_unregister(struct usb_composite_driver *);
 
+#define OS_STRING_QW_SIGN_LEN		14
+#define OS_STRING_IDX			0xEE
 
 /**
  * struct usb_composite_device - represents one composite usb gadget
@@ -291,6 +293,9 @@ extern void usb_composite_unregister(struct usb_composite_driver *);
  * @req: used for control responses; buffer is pre-allocated
  * @bufsiz: size of buffer pre-allocated in @req
  * @config: the currently active configuration
+ * @qw_sign: qwSignature part of the OS string
+ * @b_vendor_code: bMS_VendorCode part of the OS string
+ * @use_os_string: false by default, interested gadgets set it
  *
  * One of these devices is allocated and initialized before the
  * associated device driver's bind() is called.
@@ -324,6 +329,11 @@ struct usb_composite_dev {
 
 	struct usb_configuration	*config;
 
+	/* OS String is a custom (yet popular) extension to the USB standard. */
+	u8				qw_sign[OS_STRING_QW_SIGN_LEN];
+	u8				b_vendor_code;
+	unsigned int			use_os_string:1;
+
 	/* private: */
 	/* internals */
 	unsigned int			suspended:1;
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 04/17] usb: gadget: move utf8_to_utf16le to header file
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
                   ` (2 preceding siblings ...)
  2021-01-25 13:43 ` [PATCH V2 03/17] usb: gadget: OS String support peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 05/17] usb: gadget: add Kconfig for OS descriptors peng.fan at nxp.com
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Li Jun <jun.li@nxp.com>

As other users may use utf8_to_utf16le() to convert the utf8
to utf16 for usb, so move it to head file.

Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/usbstring.c | 74 +--------------------------------
 include/linux/utf.h            | 75 ++++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+), 73 deletions(-)
 create mode 100644 include/linux/utf.h

diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c
index 83cdd8a259..e2464ad923 100644
--- a/drivers/usb/gadget/usbstring.c
+++ b/drivers/usb/gadget/usbstring.c
@@ -10,79 +10,7 @@
 #include <linux/errno.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
-
-#include <asm/unaligned.h>
-
-
-static int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len)
-{
-	int	count = 0;
-	u8	c;
-	u16	uchar;
-
-	/*
-	 * this insists on correct encodings, though not minimal ones.
-	 * BUT it currently rejects legit 4-byte UTF-8 code points,
-	 * which need surrogate pairs.  (Unicode 3.1 can use them.)
-	 */
-	while (len != 0 && (c = (u8) *s++) != 0) {
-		if ((c & 0x80)) {
-			/*
-			 * 2-byte sequence:
-			 * 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
-			 */
-			if ((c & 0xe0) == 0xc0) {
-				uchar = (c & 0x1f) << 6;
-
-				c = (u8) *s++;
-				if ((c & 0xc0) != 0x80)
-					goto fail;
-				c &= 0x3f;
-				uchar |= c;
-
-			/*
-			 * 3-byte sequence (most CJKV characters):
-			 * zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
-			 */
-			} else if ((c & 0xf0) == 0xe0) {
-				uchar = (c & 0x0f) << 12;
-
-				c = (u8) *s++;
-				if ((c & 0xc0) != 0x80)
-					goto fail;
-				c &= 0x3f;
-				uchar |= c << 6;
-
-				c = (u8) *s++;
-				if ((c & 0xc0) != 0x80)
-					goto fail;
-				c &= 0x3f;
-				uchar |= c;
-
-				/* no bogus surrogates */
-				if (0xd800 <= uchar && uchar <= 0xdfff)
-					goto fail;
-
-			/*
-			 * 4-byte sequence (surrogate pairs, currently rare):
-			 * 11101110wwwwzzzzyy + 110111yyyyxxxxxx
-			 *     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
-			 * (uuuuu = wwww + 1)
-			 * FIXME accept the surrogate code points (only)
-			 */
-			} else
-				goto fail;
-		} else
-			uchar = c;
-		put_unaligned_le16(uchar, cp++);
-		count++;
-		len--;
-	}
-	return count;
-fail:
-	return -1;
-}
-
+#include <linux/utf.h>
 
 /**
  * usb_gadget_get_string - fill out a string descriptor
diff --git a/include/linux/utf.h b/include/linux/utf.h
new file mode 100644
index 0000000000..e1f7d3bd1d
--- /dev/null
+++ b/include/linux/utf.h
@@ -0,0 +1,75 @@
+#ifndef _LINUX_UTF_H
+#define _LINUX_UTF_H
+
+#include <asm/unaligned.h>
+
+static inline int utf8_to_utf16le(const char *s, __le16 *cp, unsigned len)
+{
+	int	count = 0;
+	u8	c;
+	u16	uchar;
+
+	/*
+	 * this insists on correct encodings, though not minimal ones.
+	 * BUT it currently rejects legit 4-byte UTF-8 code points,
+	 * which need surrogate pairs.  (Unicode 3.1 can use them.)
+	 */
+	while (len != 0 && (c = (u8) *s++) != 0) {
+		if ((c & 0x80)) {
+			/*
+			 * 2-byte sequence:
+			 * 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
+			 */
+			if ((c & 0xe0) == 0xc0) {
+				uchar = (c & 0x1f) << 6;
+
+				c = (u8) *s++;
+				if ((c & 0xc0) != 0x80)
+					goto fail;
+				c &= 0x3f;
+				uchar |= c;
+
+			/*
+			 * 3-byte sequence (most CJKV characters):
+			 * zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
+			 */
+			} else if ((c & 0xf0) == 0xe0) {
+				uchar = (c & 0x0f) << 12;
+
+				c = (u8) *s++;
+				if ((c & 0xc0) != 0x80)
+					goto fail;
+				c &= 0x3f;
+				uchar |= c << 6;
+
+				c = (u8) *s++;
+				if ((c & 0xc0) != 0x80)
+					goto fail;
+				c &= 0x3f;
+				uchar |= c;
+
+				/* no bogus surrogates */
+				if (0xd800 <= uchar && uchar <= 0xdfff)
+					goto fail;
+
+			/*
+			 * 4-byte sequence (surrogate pairs, currently rare):
+			 * 11101110wwwwzzzzyy + 110111yyyyxxxxxx
+			 *     = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
+			 * (uuuuu = wwww + 1)
+			 * FIXME accept the surrogate code points (only)
+			 */
+			} else
+				goto fail;
+		} else
+			uchar = c;
+		put_unaligned_le16(uchar, cp++);
+		count++;
+		len--;
+	}
+	return count;
+fail:
+	return -1;
+}
+
+#endif /* _LINUX_UTF_H */
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 05/17] usb: gadget: add Kconfig for OS descriptors
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
                   ` (3 preceding siblings ...)
  2021-01-25 13:43 ` [PATCH V2 04/17] usb: gadget: move utf8_to_utf16le to header file peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 06/17] usb: gadget: OS Feature Descriptors support peng.fan at nxp.com
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Peng Fan <peng.fan@nxp.com>

Add Kconfig for OS descriptors

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/Kconfig | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 7c0df5c264..4a3b22e6de 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -98,6 +98,15 @@ config USB_GADGET_DWC2_OTG_PHY_BUS_WIDTH_8
 
 endif # USB_GADGET_DWC2_OTG
 
+config USB_GADGET_OS_DESCRIPTORS
+	bool "USB OS Feature Descriptors support"
+	help
+	  This is a porting patch from linux kernel: 37a3a533429e
+	  ("usb: gadget: OS Feature Descriptors support"), the original commit
+	  log see below:
+	  There is a custom (non-USB IF) extension to the USB standard:
+	  http://msdn.microsoft.com/library/windows/hardware/gg463182
+
 config CI_UDC
 	bool "ChipIdea device controller"
 	select USB_GADGET_DUALSPEED
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 06/17] usb: gadget: OS Feature Descriptors support
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
                   ` (4 preceding siblings ...)
  2021-01-25 13:43 ` [PATCH V2 05/17] usb: gadget: add Kconfig for OS descriptors peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 07/17] usb: gadget: add WCID support for mfgtool peng.fan at nxp.com
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Li Jun <jun.li@nxp.com>

This is a proting patch from linux kernel: 37a3a533429e
("usb: gadget: OS Feature Descriptors support"), the original commit
log see below:

There is a custom (non-USB IF) extension to the USB standard:

http://msdn.microsoft.com/library/windows/hardware/gg463182

They grant permission to use the specification - there is
"Microsoft OS Descriptor Specification License Agreement"
under the link mentioned above, and its Section 2 "Grant
of License", letter (b) reads:

"Patent license. Microsoft hereby grants to You a nonexclusive,
royalty-free, nontransferable, worldwide license under Microsoft??
patents embodied solely within the Specification and that are owned
or licensable by Microsoft to make, use, import, offer to sell,
sell and distribute directly or indirectly to Your Licensees Your
Implementation. You may sublicense this patent license to Your
Licensees under the same terms and conditions."

The said extension is maintained by Microsoft for Microsoft.

Yet it is fairly common for various devices to use it, and a
popular proprietary operating system expects devices to provide
"OS descriptors", so Linux-based USB gadgets whishing to be able
to talk to a variety of operating systems should be able to provide
the "OS descriptors".

This patch adds optional support for gadgets whishing to expose
the so called "OS Feature Descriptors", that is "Extended Compatibility ID"
and "Extended Properties".

Hosts which do request "OS descriptors" from gadgets do so during
the enumeration phase and before the configuration is set with
SET_CONFIGURATION. What is more, those hosts never ask for configurations
at indices other than 0. Therefore, gadgets whishing to provide
"OS descriptors" must designate one configuration to be used with
this kind of hosts - this is what os_desc_config is added for in
struct usb_composite_dev. There is an additional advantage to it:
if a gadget provides "OS descriptors" and designates one configuration
to be used with such non-USB-compliant hosts it can invoke
"usb_add_config" in any order because the designated configuration
will be reported to be at index 0 anyway.

This patch also adds handling vendor-specific requests addressed
at device or interface and related to handling "OS descriptors"."

Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/composite.c | 252 ++++++++++++++++++++++++++++++++-
 drivers/usb/gadget/u_os_desc.h | 123 ++++++++++++++++
 include/linux/usb/composite.h  |  57 ++++++++
 3 files changed, 431 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/gadget/u_os_desc.h

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 63855af52e..a0c28dbe59 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -12,6 +12,7 @@
 #include <linux/bitops.h>
 #include <linux/bug.h>
 #include <linux/usb/composite.h>
+#include "u_os_desc.h"
 
 #define USB_BUFSIZ	4096
 
@@ -244,6 +245,7 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
 	u8				type = w_value >> 8;
 	int                             hs = 0;
 	struct usb_configuration	*c;
+	struct list_head		*pos;
 
 	if (gadget_is_dualspeed(gadget)) {
 		if (gadget->speed == USB_SPEED_HIGH)
@@ -255,7 +257,20 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
 	}
 
 	w_value &= 0xff;
-	list_for_each_entry(c, &cdev->configs, list) {
+
+	pos = &cdev->configs;
+	c = cdev->os_desc_config;
+	if (c)
+		goto check_config;
+
+	while ((pos = pos->next) !=  &cdev->configs) {
+		c = list_entry(pos, typeof(*c), list);
+
+		/* skip OS Descriptors config which is handled separately */
+		if (c == cdev->os_desc_config)
+			continue;
+
+check_config:
 		if (speed == USB_SPEED_HIGH) {
 			if (!c->highspeed)
 				continue;
@@ -779,6 +794,156 @@ static int bos_desc(struct usb_composite_dev *cdev)
 	return le16_to_cpu(bos->wTotalLength);
 }
 
+static int count_ext_compat(struct usb_configuration *c)
+{
+	int i, res;
+
+	res = 0;
+	for (i = 0; i < c->next_interface_id; ++i) {
+		struct usb_function *f;
+		int j;
+
+		f = c->interface[i];
+		for (j = 0; j < f->os_desc_n; ++j) {
+			struct usb_os_desc *d;
+
+			if (i != f->os_desc_table[j].if_id)
+				continue;
+			d = f->os_desc_table[j].os_desc;
+			if (d && d->ext_compat_id)
+				++res;
+		}
+	}
+	BUG_ON(res > 255);
+	return res;
+}
+
+static void fill_ext_compat(struct usb_configuration *c, u8 *buf)
+{
+	int i, count;
+
+	count = 16;
+	for (i = 0; i < c->next_interface_id; ++i) {
+		struct usb_function *f;
+		int j;
+
+		f = c->interface[i];
+		for (j = 0; j < f->os_desc_n; ++j) {
+			struct usb_os_desc *d;
+
+			if (i != f->os_desc_table[j].if_id)
+				continue;
+			d = f->os_desc_table[j].os_desc;
+			if (d && d->ext_compat_id) {
+				*buf++ = i;
+				*buf++ = 0x01;
+				memcpy(buf, d->ext_compat_id, 16);
+				buf += 22;
+			} else {
+				++buf;
+				*buf = 0x01;
+				buf += 23;
+			}
+			count += 24;
+			if (count >= 4096)
+				return;
+		}
+	}
+}
+
+static int count_ext_prop(struct usb_configuration *c, int interface)
+{
+	struct usb_function *f;
+	int j;
+
+	f = c->interface[interface];
+	for (j = 0; j < f->os_desc_n; ++j) {
+		struct usb_os_desc *d;
+
+		if (interface != f->os_desc_table[j].if_id)
+			continue;
+		d = f->os_desc_table[j].os_desc;
+		if (d && d->ext_compat_id)
+			return d->ext_prop_count;
+	}
+	return 0;
+}
+
+static int len_ext_prop(struct usb_configuration *c, int interface)
+{
+	struct usb_function *f;
+	struct usb_os_desc *d;
+	int j, res;
+
+	res = 10; /* header length */
+	f = c->interface[interface];
+	for (j = 0; j < f->os_desc_n; ++j) {
+		if (interface != f->os_desc_table[j].if_id)
+			continue;
+		d = f->os_desc_table[j].os_desc;
+		if (d)
+			return min(res + d->ext_prop_len, 4096);
+	}
+	return res;
+}
+
+static int fill_ext_prop(struct usb_configuration *c, int interface, u8 *buf)
+{
+	struct usb_function *f;
+	struct usb_os_desc *d;
+	struct usb_os_desc_ext_prop *ext_prop;
+	int j, count, n, ret;
+	u8 *start = buf;
+
+	f = c->interface[interface];
+	for (j = 0; j < f->os_desc_n; ++j) {
+		if (interface != f->os_desc_table[j].if_id)
+			continue;
+		d = f->os_desc_table[j].os_desc;
+		if (d)
+			list_for_each_entry(ext_prop, &d->ext_prop, entry) {
+				/* 4kB minus header length */
+				n = buf - start;
+				if (n >= 4086)
+					return 0;
+
+				count = ext_prop->data_len +
+					ext_prop->name_len + 14;
+				if (count > 4086 - n)
+					return -EINVAL;
+				usb_ext_prop_put_size(buf, count);
+				usb_ext_prop_put_type(buf, ext_prop->type);
+				ret = usb_ext_prop_put_name(buf, ext_prop->name,
+							    ext_prop->name_len);
+				if (ret < 0)
+					return ret;
+				switch (ext_prop->type) {
+				case USB_EXT_PROP_UNICODE:
+				case USB_EXT_PROP_UNICODE_ENV:
+				case USB_EXT_PROP_UNICODE_LINK:
+					usb_ext_prop_put_unicode(buf, ret,
+							 ext_prop->data,
+							 ext_prop->data_len);
+					break;
+				case USB_EXT_PROP_BINARY:
+					usb_ext_prop_put_binary(buf, ret,
+							ext_prop->data,
+							ext_prop->data_len);
+					break;
+				case USB_EXT_PROP_LE32:
+					/* not implemented */
+				case USB_EXT_PROP_BE32:
+					/* not implemented */
+				default:
+					return -EINVAL;
+				}
+				buf += count;
+			}
+	}
+
+	return 0;
+}
+
 /*
  * The setup() callback implements all the ep0 functionality that's
  * not handled lower down, in hardware or the hardware driver(like
@@ -935,6 +1100,91 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 		break;
 	default:
 unknown:
+		/*
+		 * OS descriptors handling
+		 */
+		if (CONFIG_IS_ENABLED(USB_GADGET_OS_DESCRIPTORS) && cdev->use_os_string &&
+		    cdev->os_desc_config && (ctrl->bRequestType & USB_TYPE_VENDOR) &&
+		    ctrl->bRequest == cdev->b_vendor_code) {
+			struct usb_configuration	*os_desc_cfg;
+			u8				*buf;
+			int				interface;
+			int				count = 0;
+
+			buf = req->buf;
+			os_desc_cfg = cdev->os_desc_config;
+			memset(buf, 0, w_length);
+			buf[5] = 0x01;
+			switch (ctrl->bRequestType & USB_RECIP_MASK) {
+			case USB_RECIP_DEVICE:
+				if (w_index != 0x4 || (w_value >> 8))
+					break;
+				buf[6] = w_index;
+				if (w_length == 0x10) {
+					/* Number of ext compat interfaces */
+					count = count_ext_compat(os_desc_cfg);
+					buf[8] = count;
+					count *= 24; /* 24 B/ext compat desc */
+					count += 16; /* header */
+					put_unaligned_le32(count, buf);
+					value = w_length;
+				} else {
+					/* "extended compatibility ID"s */
+					count = count_ext_compat(os_desc_cfg);
+					buf[8] = count;
+					count *= 24; /* 24 B/ext compat desc */
+					count += 16; /* header */
+					put_unaligned_le32(count, buf);
+					buf += 16;
+					fill_ext_compat(os_desc_cfg, buf);
+					value = w_length;
+				}
+				break;
+			case USB_RECIP_INTERFACE:
+				if (w_index != 0x5 || (w_value >> 8))
+					break;
+				interface = w_value & 0xFF;
+				buf[6] = w_index;
+				if (w_length == 0x0A) {
+					count = count_ext_prop(os_desc_cfg,
+						interface);
+					put_unaligned_le16(count, buf + 8);
+					count = len_ext_prop(os_desc_cfg,
+						interface);
+					put_unaligned_le32(count, buf);
+
+					value = w_length;
+				} else {
+					count = count_ext_prop(os_desc_cfg,
+						interface);
+					put_unaligned_le16(count, buf + 8);
+					count = len_ext_prop(os_desc_cfg,
+						interface);
+					put_unaligned_le32(count, buf);
+					buf += 10;
+					value = fill_ext_prop(os_desc_cfg,
+							      interface, buf);
+					if (value < 0)
+						return value;
+
+					value = w_length;
+				}
+				break;
+			}
+
+			if (value >= 0) {
+				req->length = value;
+				req->zero = value < w_length;
+				value = usb_ep_queue(gadget->ep0, req, GFP_KERNEL);
+				if (value < 0) {
+					debug("ep_queue --> %d\n", value);
+					req->status = 0;
+					composite_setup_complete(gadget->ep0, req);
+				}
+			}
+			return value;
+		}
+
 		debug("non-core control req%02x.%02x v%04x i%04x l%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
 			w_value, w_index, w_length);
diff --git a/drivers/usb/gadget/u_os_desc.h b/drivers/usb/gadget/u_os_desc.h
new file mode 100644
index 0000000000..4dab4814a3
--- /dev/null
+++ b/drivers/usb/gadget/u_os_desc.h
@@ -0,0 +1,123 @@
+/*
+ * u_os_desc.h
+ *
+ * Utility definitions for "OS Descriptors" support
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __U_OS_DESC_H__
+#define __U_OS_DESC_H__
+
+#include <linux/utf.h>
+
+#define USB_EXT_PROP_DW_SIZE			0
+#define USB_EXT_PROP_DW_PROPERTY_DATA_TYPE	4
+#define USB_EXT_PROP_W_PROPERTY_NAME_LENGTH	8
+#define USB_EXT_PROP_B_PROPERTY_NAME		10
+#define USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH	10
+#define USB_EXT_PROP_B_PROPERTY_DATA		14
+
+#define USB_EXT_PROP_RESERVED			0
+#define USB_EXT_PROP_UNICODE			1
+#define USB_EXT_PROP_UNICODE_ENV		2
+#define USB_EXT_PROP_BINARY			3
+#define USB_EXT_PROP_LE32			4
+#define USB_EXT_PROP_BE32			5
+#define USB_EXT_PROP_UNICODE_LINK		6
+#define USB_EXT_PROP_UNICODE_MULTI		7
+
+static inline u8 *__usb_ext_prop_ptr(u8 *buf, size_t offset)
+{
+	return buf + offset;
+}
+
+static inline u8 *usb_ext_prop_size_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_DW_SIZE);
+}
+
+static inline u8 *usb_ext_prop_type_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_DW_PROPERTY_DATA_TYPE);
+}
+
+static inline u8 *usb_ext_prop_name_len_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_W_PROPERTY_NAME_LENGTH);
+}
+
+static inline u8 *usb_ext_prop_name_ptr(u8 *buf)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_B_PROPERTY_NAME);
+}
+
+static inline u8 *usb_ext_prop_data_len_ptr(u8 *buf, size_t off)
+{
+	return __usb_ext_prop_ptr(buf,
+				  USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + off);
+}
+
+static inline u8 *usb_ext_prop_data_ptr(u8 *buf, size_t off)
+{
+	return __usb_ext_prop_ptr(buf, USB_EXT_PROP_B_PROPERTY_DATA + off);
+}
+
+static inline void usb_ext_prop_put_size(u8 *buf, int dw_size)
+{
+	put_unaligned_le32(dw_size, usb_ext_prop_size_ptr(buf));
+}
+
+static inline void usb_ext_prop_put_type(u8 *buf, int type)
+{
+	put_unaligned_le32(type, usb_ext_prop_type_ptr(buf));
+}
+
+static inline int usb_ext_prop_put_name(u8 *buf, const char *name, int pnl)
+{
+	int result;
+
+	put_unaligned_le16(pnl, usb_ext_prop_name_len_ptr(buf));
+	memset(usb_ext_prop_name_ptr(buf), 0, 2 * strlen(name));
+	result = utf8_to_utf16le(name, (__le16 *)usb_ext_prop_name_ptr(buf),
+				 strlen(name));
+	if (result < 0)
+		return result;
+
+	put_unaligned_le16(0, &buf[USB_EXT_PROP_B_PROPERTY_NAME + pnl - 2]);
+
+	return pnl;
+}
+
+static inline void usb_ext_prop_put_binary(u8 *buf, int pnl, const char *data,
+					   int data_len)
+{
+	put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl));
+	memcpy(usb_ext_prop_data_ptr(buf, pnl), data, data_len);
+}
+
+static inline int usb_ext_prop_put_unicode(u8 *buf, int pnl, const char *string,
+					   int data_len)
+{
+	int result;
+	put_unaligned_le32(data_len, usb_ext_prop_data_len_ptr(buf, pnl));
+	memset(usb_ext_prop_data_ptr(buf, pnl), 0, 2 * (data_len >> 1));
+	result = utf8_to_utf16le(string, (__le16 *) usb_ext_prop_data_ptr(buf, pnl),
+				 data_len >> 1);
+	if (result < 0)
+		return result;
+
+	put_unaligned_le16(0,
+		&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl + data_len - 2]);
+
+	return data_len;
+}
+
+#endif /* __U_OS_DESC_H__ */
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index d4f2a49869..d75a0bc4c4 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -37,6 +37,53 @@
 
 struct usb_configuration;
 
+/**
+ * struct usb_os_desc_ext_prop - describes one "Extended Property"
+ * @entry: used to keep a list of extended properties
+ * @type: Extended Property type
+ * @name_len: Extended Property unicode name length, including terminating '\0'
+ * @name: Extended Property name
+ * @data_len: Length of Extended Property blob (for unicode store double len)
+ * @data: Extended Property blob
+ */
+struct usb_os_desc_ext_prop {
+	struct list_head	entry;
+	u8			type;
+	int			name_len;
+	char			*name;
+	int			data_len;
+	char			*data;
+};
+
+/**
+ * struct usb_os_desc - describes OS descriptors associated with one interface
+ * @ext_compat_id: 16 bytes of "Compatible ID" and "Subcompatible ID"
+ * @ext_prop: Extended Properties list
+ * @ext_prop_len: Total length of Extended Properties blobs
+ * @ext_prop_count: Number of Extended Properties
+ */
+struct usb_os_desc {
+	char			*ext_compat_id;
+	struct list_head	ext_prop;
+	int			ext_prop_len;
+	int			ext_prop_count;
+};
+
+/**
+ * struct usb_os_desc_table - describes OS descriptors associated with one
+ * interface of a usb_function
+ * @if_id: Interface id
+ * @os_desc: "Extended Compatibility ID" and "Extended Properties" of the
+ *	interface
+ *
+ * Each interface can have at most one "Extended Compatibility ID" and a
+ * number of "Extended Properties".
+ */
+struct usb_os_desc_table {
+	int			if_id;
+	struct usb_os_desc	*os_desc;
+};
+
 /**
  * struct usb_function - describes one function of a configuration
  * @name: For diagnostics, identifies the function.
@@ -50,6 +97,10 @@ struct usb_configuration;
  *	the function will not be available@high speed.
  * @config: assigned when @usb_add_function() is called; this is the
  *	configuration with which this function is associated.
+ * @os_desc_table: Table of (interface id, os descriptors) pairs. The function
+ *	can expose more than one interface. If an interface is a member of
+ *	an IAD, only the first interface of IAD has its entry in the table.
+ * @os_desc_n: Number of entries in os_desc_table
  * @bind: Before the gadget can register, all of its functions bind() to the
  *	available resources including string and interface identifiers used
  *	in interface or class descriptors; endpoints; I/O buffers; and so on.
@@ -98,6 +149,9 @@ struct usb_function {
 
 	struct usb_configuration	*config;
 
+	struct usb_os_desc_table	*os_desc_table;
+	unsigned			os_desc_n;
+
 	/* REVISIT:  bind() functions can be marked __init, which
 	 * makes trouble for section mismatch analysis.  See if
 	 * we can't restructure things to avoid mismatching.
@@ -292,10 +346,12 @@ extern void usb_composite_unregister(struct usb_composite_driver *);
  * @gadget: read-only, abstracts the gadget's usb peripheral controller
  * @req: used for control responses; buffer is pre-allocated
  * @bufsiz: size of buffer pre-allocated in @req
+ * @os_desc_req: used for OS descriptors responses; buffer is pre-allocated
  * @config: the currently active configuration
  * @qw_sign: qwSignature part of the OS string
  * @b_vendor_code: bMS_VendorCode part of the OS string
  * @use_os_string: false by default, interested gadgets set it
+ * @os_desc_config: the configuration to be used with OS descriptors
  *
  * One of these devices is allocated and initialized before the
  * associated device driver's bind() is called.
@@ -332,6 +388,7 @@ struct usb_composite_dev {
 	/* OS String is a custom (yet popular) extension to the USB standard. */
 	u8				qw_sign[OS_STRING_QW_SIGN_LEN];
 	u8				b_vendor_code;
+	struct usb_configuration	*os_desc_config;
 	unsigned int			use_os_string:1;
 
 	/* private: */
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 07/17] usb: gadget: add WCID support for mfgtool
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
                   ` (5 preceding siblings ...)
  2021-01-25 13:43 ` [PATCH V2 06/17] usb: gadget: OS Feature Descriptors support peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 08/17] usb: gadget: fastboot: add ext properties for WCID peng.fan at nxp.com
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Li Jun <jun.li@nxp.com>

Enable WCID(Microsoft Compatible ID Feature Descriptor) for mfgtool.

Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/composite.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index a0c28dbe59..cd61bfec38 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -20,6 +20,10 @@
 typedef struct { __le16 val; } __packed __le16_packed;
 
 static struct usb_composite_driver *composite;
+static struct usb_configuration *os_desc_config;
+
+/* Microsoft OS String Descriptor */
+static char qw_sign_buf[OS_STRING_QW_SIGN_LEN / 2] = {'M', 'S', 'F', 'T', '1', '0', '0'};
 
 static inline void le16_add_cpu_packed(__le16_packed *var, u16 val)
 {
@@ -395,6 +399,10 @@ static int set_config(struct usb_composite_dev *cdev,
 		goto done;
 
 	cdev->config = c;
+	if (cdev->use_os_string) {
+		cdev->os_desc_config = c;
+		os_desc_config = c;
+	}
 
 	/* Initialize all interfaces by setting them to altsetting zero. */
 	for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) {
@@ -1358,6 +1366,18 @@ static int composite_bind(struct usb_gadget *gadget)
 	       sizeof(struct usb_device_descriptor));
 	cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 
+	if (cdev->use_os_string) {
+		/* TODO: Do we want to pass this via platform? */
+		cdev->b_vendor_code = 0x40;
+
+		/* Microsoft OS String Descriptor */
+		utf8_to_utf16le(qw_sign_buf, (__le16 *)cdev->qw_sign,
+				OS_STRING_QW_SIGN_LEN / 2);
+
+		if (os_desc_config)
+			cdev->os_desc_config = os_desc_config;
+	}
+
 	debug("%s: ready\n", composite->name);
 	return 0;
 
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 08/17] usb: gadget: fastboot: add ext properties for WCID
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
                   ` (6 preceding siblings ...)
  2021-01-25 13:43 ` [PATCH V2 07/17] usb: gadget: add WCID support for mfgtool peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 09/17] usb: gadget: set correct usb_configuration for os_desc_config peng.fan at nxp.com
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Li Jun <jun.li@nxp.com>

Add device interface GUID for Microsoft Extended Properties Feature
Descriptor.

Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/f_fastboot.c | 34 +++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index d1d087e12b..e330456390 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -46,6 +46,25 @@ struct f_fastboot {
 	struct usb_request *in_req, *out_req;
 };
 
+static char fb_ext_prop_name[] = "DeviceInterfaceGUID";
+static char fb_ext_prop_data[] = "{4866319A-F4D6-4374-93B9-DC2DEB361BA9}";
+
+static struct usb_os_desc_ext_prop fb_ext_prop = {
+	.type = 1,		/* NUL-terminated Unicode String (REG_SZ) */
+	.name = fb_ext_prop_name,
+	.data = fb_ext_prop_data,
+};
+
+/* 16 bytes of "Compatible ID" and "Subcompatible ID" */
+static char fb_cid[16] = {'W', 'I', 'N', 'U', 'S', 'B'};
+static struct usb_os_desc fb_os_desc = {
+	.ext_compat_id = fb_cid,
+};
+
+static struct usb_os_desc_table fb_os_desc_table = {
+	.os_desc = &fb_os_desc,
+};
+
 static inline struct f_fastboot *func_to_fastboot(struct usb_function *f)
 {
 	return container_of(f, struct f_fastboot, usb_function);
@@ -161,6 +180,19 @@ static int fastboot_bind(struct usb_configuration *c, struct usb_function *f)
 		return id;
 	interface_desc.bInterfaceNumber = id;
 
+	/* Enable OS and Extended Properties Feature Descriptor */
+	c->cdev->use_os_string = 1;
+	f->os_desc_table = &fb_os_desc_table;
+	f->os_desc_n = 1;
+	f->os_desc_table->if_id = id;
+	INIT_LIST_HEAD(&fb_os_desc.ext_prop);
+	fb_ext_prop.name_len = strlen(fb_ext_prop.name) * 2 + 2;
+	fb_os_desc.ext_prop_len = 10 + fb_ext_prop.name_len;
+	fb_os_desc.ext_prop_count = 1;
+	fb_ext_prop.data_len = strlen(fb_ext_prop.data) * 2 + 2;
+	fb_os_desc.ext_prop_len += fb_ext_prop.data_len + 4;
+	list_add_tail(&fb_ext_prop.entry, &fb_os_desc.ext_prop);
+
 	id = usb_string_id(c->cdev);
 	if (id < 0)
 		return id;
@@ -196,6 +228,8 @@ static int fastboot_bind(struct usb_configuration *c, struct usb_function *f)
 
 static void fastboot_unbind(struct usb_configuration *c, struct usb_function *f)
 {
+	f->os_desc_table = NULL;
+	list_del(&fb_os_desc.ext_prop);
 	memset(fastboot_func, 0, sizeof(*fastboot_func));
 }
 
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 09/17] usb: gadget: set correct usb_configuration for os_desc_config
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
                   ` (7 preceding siblings ...)
  2021-01-25 13:43 ` [PATCH V2 08/17] usb: gadget: fastboot: add ext properties for WCID peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 10/17] usb: gadget: update os_desc_config when add config peng.fan at nxp.com
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Jun Li <jun.li@nxp.com>

The current way to set cdev->os_desc_config is wrong if user restart
fastboot, as the old config is not used anymore and new allocated
usb_configuration will be used, so set the os_desc_config while
usb_add_config.

Reviewed-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/composite.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index cd61bfec38..e6fdefd3d0 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -399,10 +399,6 @@ static int set_config(struct usb_composite_dev *cdev,
 		goto done;
 
 	cdev->config = c;
-	if (cdev->use_os_string) {
-		cdev->os_desc_config = c;
-		os_desc_config = c;
-	}
 
 	/* Initialize all interfaces by setting them to altsetting zero. */
 	for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) {
@@ -516,6 +512,9 @@ int usb_add_config(struct usb_composite_dev *cdev,
 
 	usb_ep_autoconfig_reset(cdev->gadget);
 
+	if (os_desc_config)
+		cdev->os_desc_config = os_desc_config;
+
 done:
 	if (status)
 		debug("added config '%s'/%u --> %d\n", config->label,
@@ -1373,9 +1372,6 @@ static int composite_bind(struct usb_gadget *gadget)
 		/* Microsoft OS String Descriptor */
 		utf8_to_utf16le(qw_sign_buf, (__le16 *)cdev->qw_sign,
 				OS_STRING_QW_SIGN_LEN / 2);
-
-		if (os_desc_config)
-			cdev->os_desc_config = os_desc_config;
 	}
 
 	debug("%s: ready\n", composite->name);
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 10/17] usb: gadget: update os_desc_config when add config
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
                   ` (8 preceding siblings ...)
  2021-01-25 13:43 ` [PATCH V2 09/17] usb: gadget: set correct usb_configuration for os_desc_config peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 11/17] usb: gadget: add super speed support peng.fan at nxp.com
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Jun Li <jun.li@nxp.com>

Always use the new added config for os_desc_config to fix cdev->
os_desc_config may miss set in case we restart usb gadget driver.

Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/composite.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index e6fdefd3d0..404da12754 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -512,8 +512,8 @@ int usb_add_config(struct usb_composite_dev *cdev,
 
 	usb_ep_autoconfig_reset(cdev->gadget);
 
-	if (os_desc_config)
-		cdev->os_desc_config = os_desc_config;
+	os_desc_config = config;
+	cdev->os_desc_config = os_desc_config;
 
 done:
 	if (status)
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 11/17] usb: gadget: add super speed support
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
                   ` (9 preceding siblings ...)
  2021-01-25 13:43 ` [PATCH V2 10/17] usb: gadget: update os_desc_config when add config peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 12/17] usb: fastboot: " peng.fan at nxp.com
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Li Jun <jun.li@nxp.com>

This patch is to add usb gadget super speed support in common
driver, including BOS descriptor and select the super speed
descriptor from function driver.

Reviewed-by: Ye Li <ye.li@nxp.com>
Reviewed-by: Peter Chen <peter.chen@nxp.com>
Tested-by: faqiang.zhu <faqiang.zhu@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/composite.c | 85 ++++++++++++++++++++++++----------
 include/linux/usb/composite.h  |  4 ++
 include/linux/usb/gadget.h     |  6 +++
 3 files changed, 70 insertions(+), 25 deletions(-)

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 404da12754..1063c571d8 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -88,6 +88,8 @@ int usb_add_function(struct usb_configuration *config,
 		config->fullspeed = 1;
 	if (!config->highspeed && function->hs_descriptors)
 		config->highspeed = 1;
+	if (!config->superspeed && function->ss_descriptors)
+		config->superspeed = 1;
 
 done:
 	if (value)
@@ -223,7 +225,9 @@ static int config_buf(struct usb_configuration *config,
 
 	/* add each function's descriptors */
 	list_for_each_entry(f, &config->functions, list) {
-		if (speed == USB_SPEED_HIGH)
+		if (speed == USB_SPEED_SUPER)
+			descriptors = f->ss_descriptors;
+		else if (speed == USB_SPEED_HIGH)
 			descriptors = f->hs_descriptors;
 		else
 			descriptors = f->descriptors;
@@ -251,7 +255,9 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
 	struct usb_configuration	*c;
 	struct list_head		*pos;
 
-	if (gadget_is_dualspeed(gadget)) {
+	if (gadget_is_superspeed(gadget)) {
+		speed = gadget->speed;
+	} else if (gadget_is_dualspeed(gadget)) {
 		if (gadget->speed == USB_SPEED_HIGH)
 			hs = 1;
 		if (type == USB_DT_OTHER_SPEED_CONFIG)
@@ -275,7 +281,10 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
 			continue;
 
 check_config:
-		if (speed == USB_SPEED_HIGH) {
+		if (speed == USB_SPEED_SUPER) {
+			if (!c->superspeed)
+				continue;
+		} else if (speed == USB_SPEED_HIGH) {
 			if (!c->highspeed)
 				continue;
 		} else {
@@ -294,8 +303,12 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)
 	struct usb_gadget		*gadget = cdev->gadget;
 	unsigned			count = 0;
 	int				hs = 0;
+	int				ss = 0;
 	struct usb_configuration	*c;
 
+	if (gadget->speed == USB_SPEED_SUPER)
+		ss = 1;
+
 	if (gadget_is_dualspeed(gadget)) {
 		if (gadget->speed == USB_SPEED_HIGH)
 			hs = 1;
@@ -304,7 +317,10 @@ static int count_configs(struct usb_composite_dev *cdev, unsigned type)
 	}
 	list_for_each_entry(c, &cdev->configs, list) {
 		/* ignore configs that won't work at this speed */
-		if (hs) {
+		if (ss) {
+			if (!c->superspeed)
+				continue;
+		} else if (hs) {
 			if (!c->highspeed)
 				continue;
 		} else {
@@ -388,6 +404,9 @@ static int set_config(struct usb_composite_dev *cdev,
 		     case USB_SPEED_HIGH:
 			     speed = "high";
 			     break;
+		     case USB_SPEED_SUPER:
+			     speed = "super";
+			     break;
 		     default:
 			     speed = "?";
 			     break;
@@ -412,7 +431,9 @@ static int set_config(struct usb_composite_dev *cdev,
 		 * function's setup callback instead of the current
 		 * configuration's setup callback.
 		 */
-		if (gadget->speed == USB_SPEED_HIGH)
+		if (gadget->speed == USB_SPEED_SUPER)
+			descriptors = f->ss_descriptors;
+		else if (gadget->speed == USB_SPEED_HIGH)
 			descriptors = f->hs_descriptors;
 		else
 			descriptors = f->descriptors;
@@ -492,8 +513,9 @@ int usb_add_config(struct usb_composite_dev *cdev,
 		list_del(&config->list);
 		config->cdev = NULL;
 	} else {
-		debug("cfg %d/%p speeds:%s%s\n",
+		debug("cfg %d/%p speeds:%s%s%s\n",
 			config->bConfigurationValue, config,
+			config->superspeed ? " super" : "",
 			config->highspeed ? " high" : "",
 			config->fullspeed
 				? (gadget_is_dualspeed(cdev->gadget)
@@ -751,6 +773,7 @@ static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req)
 static int bos_desc(struct usb_composite_dev *cdev)
 {
 	struct usb_ext_cap_descriptor   *usb_ext;
+	struct usb_dcd_config_params	dcd_config_params;
 	struct usb_bos_descriptor       *bos = cdev->req->buf;
 
 	bos->bLength = USB_DT_BOS_SIZE;
@@ -794,9 +817,19 @@ static int bos_desc(struct usb_composite_dev *cdev)
 				    USB_HIGH_SPEED_OPERATION |
 				    USB_5GBPS_OPERATION);
 		ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
-		ss_cap->bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT;
-		ss_cap->bU2DevExitLat =
-			cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
+
+		/* Get Controller configuration */
+		if (cdev->gadget->ops->get_config_params) {
+			cdev->gadget->ops->get_config_params(
+				&dcd_config_params);
+		} else {
+			dcd_config_params.bU1devExitLat =
+				USB_DEFAULT_U1_DEV_EXIT_LAT;
+			dcd_config_params.bU2DevExitLat =
+				cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
+		}
+		ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
+		ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
 	}
 	return le16_to_cpu(bos->wTotalLength);
 }
@@ -999,32 +1032,28 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 			cdev->desc.bNumConfigurations =
 				count_configs(cdev, USB_DT_DEVICE);
 
-			/*
-			 * If the speed is Super speed, then the supported
-			 * max packet size is 512 and it should be sent as
-			 * exponent of 2. So, 9(2^9=512) should be filled in
-			 * bMaxPacketSize0. Also fill USB version as 3.0
-			 * if speed is Super speed.
-			 */
-			if (cdev->gadget->speed == USB_SPEED_SUPER) {
+			cdev->desc.bMaxPacketSize0 =
+				cdev->gadget->ep0->maxpacket;
+			if (gadget->speed >= USB_SPEED_SUPER) {
+				cdev->desc.bcdUSB = cpu_to_le16(0x0310);
 				cdev->desc.bMaxPacketSize0 = 9;
-				cdev->desc.bcdUSB = cpu_to_le16(0x0300);
 			} else {
-				cdev->desc.bMaxPacketSize0 =
-					cdev->gadget->ep0->maxpacket;
+				cdev->desc.bcdUSB = cpu_to_le16(0x0200);
 			}
 			value = min(w_length, (u16) sizeof cdev->desc);
 			memcpy(req->buf, &cdev->desc, value);
 			break;
 		case USB_DT_DEVICE_QUALIFIER:
-			if (!gadget_is_dualspeed(gadget))
+			if (!gadget_is_dualspeed(gadget) ||
+			    gadget->speed >= USB_SPEED_SUPER)
 				break;
 			device_qual(cdev);
 			value = min_t(int, w_length,
 				      sizeof(struct usb_qualifier_descriptor));
 			break;
 		case USB_DT_OTHER_SPEED_CONFIG:
-			if (!gadget_is_dualspeed(gadget))
+			if (!gadget_is_dualspeed(gadget) ||
+			    gadget->speed >= USB_SPEED_SUPER)
 				break;
 
 		case USB_DT_CONFIG:
@@ -1039,10 +1068,16 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
 				value = min(w_length, (u16) value);
 			break;
 		case USB_DT_BOS:
-			if (gadget_is_superspeed(cdev->gadget))
+			/*
+			 * Super speed connection should support BOS, and
+			 * USB compliance test (USB 2.0 Command Verifier)
+			 * also issues this request, return for now for
+			 * USB 2.0 connection.
+			 */
+			if (gadget->speed >= USB_SPEED_SUPER) {
 				value = bos_desc(cdev);
-			if (value >= 0)
 				value = min(w_length, (u16)value);
+			}
 			break;
 		default:
 			goto unknown;
@@ -1421,7 +1456,7 @@ composite_resume(struct usb_gadget *gadget)
 }
 
 static struct usb_gadget_driver composite_driver = {
-	.speed		= USB_SPEED_HIGH,
+	.speed		= USB_SPEED_SUPER,
 
 	.bind		= composite_bind,
 	.unbind         = composite_unbind,
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index d75a0bc4c4..935e5c0cbb 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -146,6 +146,7 @@ struct usb_function {
 	struct usb_gadget_strings	**strings;
 	struct usb_descriptor_header	**descriptors;
 	struct usb_descriptor_header	**hs_descriptors;
+	struct usb_descriptor_header    **ss_descriptors;
 
 	struct usb_configuration	*config;
 
@@ -279,6 +280,7 @@ struct usb_configuration {
 	u8			next_interface_id;
 	unsigned		highspeed:1;
 	unsigned		fullspeed:1;
+	unsigned		superspeed:1;
 	struct usb_function	*interface[MAX_CONFIG_INTERFACES];
 };
 
@@ -292,6 +294,7 @@ int usb_add_config(struct usb_composite_dev *,
  *	identifiers.
  * @strings: tables of strings, keyed by identifiers assigned during bind()
  *	and language IDs provided in control requests
+ * @max_speed: Highest speed the driver supports.
  * @bind: (REQUIRED) Used to allocate resources that are shared across the
  *	whole device, such as string IDs, and add its configurations using
  *	@usb_add_config().  This may fail by returning a negative errno
@@ -319,6 +322,7 @@ struct usb_composite_driver {
 	const char				*name;
 	const struct usb_device_descriptor	*dev;
 	struct usb_gadget_strings		**strings;
+	enum usb_device_speed			max_speed;
 
 	/* REVISIT:  bind() functions can be marked __init, which
 	 * makes trouble for section mismatch analysis.  See if
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 8d54b91734..7e6d329e54 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -449,6 +449,11 @@ static inline void usb_ep_fifo_flush(struct usb_ep *ep)
 
 /*-------------------------------------------------------------------------*/
 
+struct usb_dcd_config_params {
+	__u8  bU1devExitLat;	/* U1 Device exit Latency */
+	__le16 bU2DevExitLat;	/* U2 Device exit Latency */
+};
+
 struct usb_gadget;
 struct usb_gadget_driver;
 
@@ -464,6 +469,7 @@ struct usb_gadget_ops {
 	int	(*pullup) (struct usb_gadget *, int is_on);
 	int	(*ioctl)(struct usb_gadget *,
 				unsigned code, unsigned long param);
+	void	(*get_config_params)(struct usb_dcd_config_params *);
 	int	(*udc_start)(struct usb_gadget *,
 			     struct usb_gadget_driver *);
 	int	(*udc_stop)(struct usb_gadget *);
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 12/17] usb: fastboot: add super speed support
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
                   ` (10 preceding siblings ...)
  2021-01-25 13:43 ` [PATCH V2 11/17] usb: gadget: add super speed support peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 13/17] usb: gadget: dnl: set dnl to be super speed peng.fan at nxp.com
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Li Jun <jun.li@nxp.com>

Add super speed EP config.

Reviewed-by: Ye Li <ye.li@nxp.com>
Reviewed-by: Peter Chen <peter.chen@nxp.com>
Tested-by: faqiang.zhu <faqiang.zhu@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/f_fastboot.c | 47 ++++++++++++++++++++++++++++++---
 1 file changed, 44 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index e330456390..c2abdd66a8 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -128,10 +128,45 @@ static struct usb_descriptor_header *fb_hs_function[] = {
 	NULL,
 };
 
+/* Super speed */
+static struct usb_endpoint_descriptor ss_ep_in = {
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
+	.bEndpointAddress	= USB_DIR_IN,
+	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize		= cpu_to_le16(1024),
+};
+
+static struct usb_endpoint_descriptor ss_ep_out = {
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
+	.bEndpointAddress	= USB_DIR_OUT,
+	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize		= cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor fb_ss_bulk_comp_desc = {
+	.bLength =		sizeof(fb_ss_bulk_comp_desc),
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+};
+
+static struct usb_descriptor_header *fb_ss_function[] = {
+	(struct usb_descriptor_header *)&interface_desc,
+	(struct usb_descriptor_header *)&ss_ep_in,
+	(struct usb_descriptor_header *)&fb_ss_bulk_comp_desc,
+	(struct usb_descriptor_header *)&ss_ep_out,
+	(struct usb_descriptor_header *)&fb_ss_bulk_comp_desc,
+	NULL,
+};
+
 static struct usb_endpoint_descriptor *
 fb_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
-	    struct usb_endpoint_descriptor *hs)
+	    struct usb_endpoint_descriptor *hs,
+	    struct usb_endpoint_descriptor *ss)
 {
+	if (gadget_is_superspeed(g) && g->speed >= USB_SPEED_SUPER)
+		return ss;
+
 	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
 		return hs;
 	return fs;
@@ -219,6 +254,12 @@ static int fastboot_bind(struct usb_configuration *c, struct usb_function *f)
 		f->hs_descriptors = fb_hs_function;
 	}
 
+	if (gadget_is_superspeed(gadget)) {
+		ss_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress;
+		ss_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress;
+		f->ss_descriptors = fb_ss_function;
+	}
+
 	s = env_get("serial#");
 	if (s)
 		g_dnl_set_serialnumber((char *)s);
@@ -283,7 +324,7 @@ static int fastboot_set_alt(struct usb_function *f,
 	debug("%s: func: %s intf: %d alt: %d\n",
 	      __func__, f->name, interface, alt);
 
-	d = fb_ep_desc(gadget, &fs_ep_out, &hs_ep_out);
+	d = fb_ep_desc(gadget, &fs_ep_out, &hs_ep_out, &ss_ep_out);
 	ret = usb_ep_enable(f_fb->out_ep, d);
 	if (ret) {
 		puts("failed to enable out ep\n");
@@ -298,7 +339,7 @@ static int fastboot_set_alt(struct usb_function *f,
 	}
 	f_fb->out_req->complete = rx_handler_command;
 
-	d = fb_ep_desc(gadget, &fs_ep_in, &hs_ep_in);
+	d = fb_ep_desc(gadget, &fs_ep_in, &hs_ep_in, &ss_ep_in);
 	ret = usb_ep_enable(f_fb->in_ep, d);
 	if (ret) {
 		puts("failed to enable in ep\n");
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 13/17] usb: gadget: dnl: set dnl to be super speed
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
                   ` (11 preceding siblings ...)
  2021-01-25 13:43 ` [PATCH V2 12/17] usb: fastboot: " peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 14/17] usb: composite: force gadget to be USB2 for HS only function peng.fan at nxp.com
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Li Jun <jun.li@nxp.com>

Set its max_speed to be super speed.

Reviewed-by: Ye Li <ye.li@nxp.com>
Reviewed-by: Peter Chen <peter.chen@nxp.com>
Tested-by: faqiang.zhu <faqiang.zhu@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/g_dnl.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
index 86fdd16b01..afb7b74f30 100644
--- a/drivers/usb/gadget/g_dnl.c
+++ b/drivers/usb/gadget/g_dnl.c
@@ -286,6 +286,7 @@ static struct usb_composite_driver g_dnl_driver = {
 	.name = NULL,
 	.dev = &device_desc,
 	.strings = g_dnl_composite_strings,
+	.max_speed = USB_SPEED_SUPER,
 
 	.bind = g_dnl_bind,
 	.unbind = g_dnl_unbind,
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 14/17] usb: composite: force gadget to be USB2 for HS only function
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
                   ` (12 preceding siblings ...)
  2021-01-25 13:43 ` [PATCH V2 13/17] usb: gadget: dnl: set dnl to be super speed peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 15/17] usb: udc: ci: update speed handling peng.fan at nxp.com
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Li Jun <jun.li@nxp.com>

If one of functions is not super speed capable, we need force the udc
to be high speed, this is an equivalent implementation of
usb_gadget_udc_set_speed() in kernel but simple, which set the gadget
max_speed to be high speed, so afterwards when start gadget duc can
set the HW to be USB 2.0 mode.

Reviewed-by: Ye Li <ye.li@nxp.com>
Reviewed-by: Peter Chen <peter.chen@nxp.com>
Tested-by: faqiang.zhu <faqiang.zhu@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/composite.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 1063c571d8..2a309e624e 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -532,6 +532,19 @@ int usb_add_config(struct usb_composite_dev *cdev,
 		}
 	}
 
+	/*
+	 * If one function of config is not super speed capable,
+	 * force the gadget to be high speed so controller driver
+	 * can init HW to be USB 2.0
+	 */
+	if (gadget_is_superspeed(cdev->gadget)) {
+		list_for_each_entry(f, &config->functions, list) {
+			if (!f->ss_descriptors)
+				cdev->gadget->max_speed =
+					USB_SPEED_HIGH;
+		}
+	}
+
 	usb_ep_autoconfig_reset(cdev->gadget);
 
 	os_desc_config = config;
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 15/17] usb: udc: ci: update speed handling
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
                   ` (13 preceding siblings ...)
  2021-01-25 13:43 ` [PATCH V2 14/17] usb: composite: force gadget to be USB2 for HS only function peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-01-25 13:43 ` [PATCH V2 16/17] usb: gadget: fastboot: use correct max packet size peng.fan at nxp.com
  2021-01-25 13:44 ` [PATCH V2 17/17] usb: gaget: ci: set ep's desc when enable ep peng.fan at nxp.com
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Li Jun <jun.li@nxp.com>

Remove the gadget driver speed check, and set its max_speed to
be USB_SPEED_HIGH.

Reviewed-by: Ye Li <ye.li@nxp.com>
Reviewed-by: Peter Chen <peter.chen@nxp.com>
Tested-by: faqiang.zhu <faqiang.zhu@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/ci_udc.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index cdb8f6fb3d..b64e4bb605 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -145,6 +145,7 @@ static struct ci_drv controller = {
 		.name	= "ci_udc",
 		.ops	= &ci_udc_ops,
 		.is_dualspeed = 1,
+		.max_speed = USB_SPEED_HIGH,
 	},
 };
 
@@ -1015,8 +1016,6 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
 		return -EINVAL;
 	if (!driver->bind || !driver->setup || !driver->disconnect)
 		return -EINVAL;
-	if (driver->speed != USB_SPEED_FULL && driver->speed != USB_SPEED_HIGH)
-		return -EINVAL;
 
 #if CONFIG_IS_ENABLED(DM_USB)
 	ret = usb_setup_ehci_gadget(&controller.ctrl);
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 16/17] usb: gadget: fastboot: use correct max packet size
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
                   ` (14 preceding siblings ...)
  2021-01-25 13:43 ` [PATCH V2 15/17] usb: udc: ci: update speed handling peng.fan at nxp.com
@ 2021-01-25 13:43 ` peng.fan at nxp.com
  2021-06-23 10:15   ` Maxime Ripard
  2021-01-25 13:44 ` [PATCH V2 17/17] usb: gaget: ci: set ep's desc when enable ep peng.fan at nxp.com
  16 siblings, 1 reply; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:43 UTC (permalink / raw)
  To: u-boot

From: Li Jun <jun.li@nxp.com>

Change to use wMaxPacketSize of current speed EP desc for request
length wrap up.

Reviewed-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/f_fastboot.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index c2abdd66a8..2ef75a1388 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -427,7 +427,7 @@ static unsigned int rx_bytes_expected(struct usb_ep *ep)
 {
 	int rx_remain = fastboot_data_remaining();
 	unsigned int rem;
-	unsigned int maxpacket = ep->maxpacket;
+	unsigned int maxpacket = usb_endpoint_maxp(ep->desc);
 
 	if (rx_remain <= 0)
 		return 0;
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH V2 17/17] usb: gaget: ci: set ep's desc when enable ep
  2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
                   ` (15 preceding siblings ...)
  2021-01-25 13:43 ` [PATCH V2 16/17] usb: gadget: fastboot: use correct max packet size peng.fan at nxp.com
@ 2021-01-25 13:44 ` peng.fan at nxp.com
  16 siblings, 0 replies; 19+ messages in thread
From: peng.fan at nxp.com @ 2021-01-25 13:44 UTC (permalink / raw)
  To: u-boot

From: Li Jun <jun.li@nxp.com>

As we need standard usb_ep's desc, so set it when enable ep.

Reviewed-by: Peter Chen <peter.chen@nxp.com>
Signed-off-by: Li Jun <jun.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/usb/gadget/ci_udc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index b64e4bb605..226a9e6d67 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -336,6 +336,7 @@ static int ci_ep_enable(struct usb_ep *ep,
 	num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
 	in = (desc->bEndpointAddress & USB_DIR_IN) != 0;
 	ci_ep->desc = desc;
+	ep->desc = desc;
 
 	if (num) {
 		int max = get_unaligned_le16(&desc->wMaxPacketSize);
@@ -358,6 +359,7 @@ static int ci_ep_disable(struct usb_ep *ep)
 	struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep);
 
 	ci_ep->desc = NULL;
+	ep->desc = NULL;
 	return 0;
 }
 
-- 
2.28.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH V2 16/17] usb: gadget: fastboot: use correct max packet size
  2021-01-25 13:43 ` [PATCH V2 16/17] usb: gadget: fastboot: use correct max packet size peng.fan at nxp.com
@ 2021-06-23 10:15   ` Maxime Ripard
  0 siblings, 0 replies; 19+ messages in thread
From: Maxime Ripard @ 2021-06-23 10:15 UTC (permalink / raw)
  To: peng.fan at nxp.com; +Cc: u-boot, Lukasz Majewski, Marek Vasut, Andre Przywara

[-- Attachment #1: Type: text/plain, Size: 1414 bytes --]

Hi,

Adding Andre, Lukasz and Marek in Cc

On Mon, Jan 25, 2021 at 09:43:59PM +0800, peng.fan at nxp.com wrote:
> From: Li Jun <jun.li@nxp.com>
> 
> Change to use wMaxPacketSize of current speed EP desc for request
> length wrap up.
> 
> Reviewed-by: Peter Chen <peter.chen@nxp.com>
> Signed-off-by: Li Jun <jun.li@nxp.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
>  drivers/usb/gadget/f_fastboot.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
> index c2abdd66a8..2ef75a1388 100644
> --- a/drivers/usb/gadget/f_fastboot.c
> +++ b/drivers/usb/gadget/f_fastboot.c
> @@ -427,7 +427,7 @@ static unsigned int rx_bytes_expected(struct usb_ep *ep)
>  {
>  	int rx_remain = fastboot_data_remaining();
>  	unsigned int rem;
> -	unsigned int maxpacket = ep->maxpacket;
> +	unsigned int maxpacket = usb_endpoint_maxp(ep->desc);

Unfortunately this introduces a regression on sunxi, where a fastboot
flash command will stall on the download part forever.

Interestingly, this occurs on the last packet of the download and only
if the packet size is a power of two, and over 512.

This can be easily tested using

dd if=/dev/random of=test-custom.bin bs=1 count=512
fastboot flash uboot test-custom.bin

However, 511, 513 (or any other size, really) will work just fine.

Maxime

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2021-06-23 10:16 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-25 13:43 [PATCH V2 00/17] usb: gadget: update peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 01/17] usb: gadget: Add ep_config call back to usb_gadget_ops peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 02/17] usb: gadget: don't change ep name for dwc3 while ep autoconfig peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 03/17] usb: gadget: OS String support peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 04/17] usb: gadget: move utf8_to_utf16le to header file peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 05/17] usb: gadget: add Kconfig for OS descriptors peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 06/17] usb: gadget: OS Feature Descriptors support peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 07/17] usb: gadget: add WCID support for mfgtool peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 08/17] usb: gadget: fastboot: add ext properties for WCID peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 09/17] usb: gadget: set correct usb_configuration for os_desc_config peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 10/17] usb: gadget: update os_desc_config when add config peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 11/17] usb: gadget: add super speed support peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 12/17] usb: fastboot: " peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 13/17] usb: gadget: dnl: set dnl to be super speed peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 14/17] usb: composite: force gadget to be USB2 for HS only function peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 15/17] usb: udc: ci: update speed handling peng.fan at nxp.com
2021-01-25 13:43 ` [PATCH V2 16/17] usb: gadget: fastboot: use correct max packet size peng.fan at nxp.com
2021-06-23 10:15   ` Maxime Ripard
2021-01-25 13:44 ` [PATCH V2 17/17] usb: gaget: ci: set ep's desc when enable ep peng.fan at nxp.com

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.