[PATCH v4 04/13] usb: dwc2: Rework roothub interface

Jules Maselbas jmaselbas at kalray.eu
Tue Aug 11 11:16:28 EDT 2020


Roothub requests are now decoded in one place.

Signed-off-by: Jules Maselbas <jmaselbas at kalray.eu>
---
 drivers/usb/dwc2/dwc2.h |   2 +-
 drivers/usb/dwc2/host.c |   4 +-
 drivers/usb/dwc2/rhub.c | 519 +++++++++++++++++++---------------------
 3 files changed, 245 insertions(+), 280 deletions(-)

diff --git a/drivers/usb/dwc2/dwc2.h b/drivers/usb/dwc2/dwc2.h
index d18b10cbf..c10385475 100644
--- a/drivers/usb/dwc2/dwc2.h
+++ b/drivers/usb/dwc2/dwc2.h
@@ -28,7 +28,7 @@ void dwc2_core_init(struct dwc2 *dwc2);
 
 /* Host functions */
 #ifdef CONFIG_USB_DWC2_HOST
-int dwc2_submit_rh_msg(struct dwc2 *dwc2, struct usb_device *dev,
+int dwc2_submit_roothub(struct dwc2 *dwc2, struct usb_device *dev,
 		unsigned long pipe, void *buf, int len,
 		struct devrequest *setup);
 int dwc2_register_host(struct dwc2 *dwc2);
diff --git a/drivers/usb/dwc2/host.c b/drivers/usb/dwc2/host.c
index a678e98fd..7eaa7c31c 100644
--- a/drivers/usb/dwc2/host.c
+++ b/drivers/usb/dwc2/host.c
@@ -326,9 +326,9 @@ static int dwc2_submit_control_msg(struct usb_device *udev,
 	int status_direction;
 
 	if (devnum == dwc2->root_hub_devnum) {
-		udev->status = 0;
 		udev->speed = USB_SPEED_HIGH;
-		return dwc2_submit_rh_msg(dwc2, udev, pipe, buffer, len, setup);
+		ret = dwc2_submit_roothub(dwc2, udev, pipe, buffer, len, setup);
+		return ret;
 	}
 
 	/* SETUP stage */
diff --git a/drivers/usb/dwc2/rhub.c b/drivers/usb/dwc2/rhub.c
index 01c938943..356071444 100644
--- a/drivers/usb/dwc2/rhub.c
+++ b/drivers/usb/dwc2/rhub.c
@@ -7,7 +7,7 @@ static struct descriptor {
 	struct usb_config_descriptor config;
 	struct usb_interface_descriptor interface;
 	struct usb_endpoint_descriptor endpoint;
-}  __attribute__ ((packed)) descriptor = {
+}  __packed descriptor = {
 	.hub = {
 		.bLength		= USB_DT_HUB_NONVAR_SIZE +
 					  ((USB_MAXCHILDREN + 1 + 7) / 8),
@@ -22,7 +22,7 @@ static struct descriptor {
 	.device = {
 		.bLength		= USB_DT_DEVICE_SIZE,
 		.bDescriptorType	= USB_DT_DEVICE,
-		.bcdUSB			= __constant_cpu_to_le16(2), /* v2.0 */
+		.bcdUSB			= cpu_to_le16(2), /* v2.0 */
 		.bDeviceClass		= USB_CLASS_HUB,
 		.bDeviceSubClass	= 0,
 		.bDeviceProtocol	= USB_HUB_PR_HS_NO_TT,
@@ -38,7 +38,7 @@ static struct descriptor {
 	.config = {
 		.bLength		= USB_DT_CONFIG_SIZE,
 		.bDescriptorType	= USB_DT_CONFIG,
-		.wTotalLength		= __constant_cpu_to_le16(
+		.wTotalLength		= cpu_to_le16(
 						USB_DT_CONFIG_SIZE +
 						USB_DT_INTERFACE_SIZE +
 						USB_DT_ENDPOINT_SIZE),
@@ -64,356 +64,321 @@ static struct descriptor {
 		.bDescriptorType	= USB_DT_ENDPOINT,
 		.bEndpointAddress	= 1 | USB_DIR_IN, /* 0x81 */
 		.bmAttributes		= USB_ENDPOINT_XFER_INT,
-		.wMaxPacketSize		= __constant_cpu_to_le16(
+		.wMaxPacketSize		= cpu_to_le16(
 						(USB_MAXCHILDREN + 1 + 7) / 8),
 		.bInterval		= 255
 	},
 };
 
-static char *language_string = "\x09\x04";
-static char *vendor_string = "u-boot";
-static char *product_string = "DWC2 root hub";
-
-/*
- * DWC2 to USB API interface
- */
-static int dwc2_submit_rh_msg_in_status(struct dwc2 *dwc2,
-					   struct usb_device *dev, void *buffer,
-					   int txlen, struct devrequest *cmd)
+static int dwc2_get_port_status(struct dwc2 *dwc2, struct usb_device *dev,
+		void *buf, int len)
 {
 	struct usb_port_status *portsts;
-	uint32_t hprt0 = 0;
-	uint32_t port_status = 0;
-	uint32_t port_change = 0;
-	int len = 0;
+	uint32_t hprt0;
+	uint32_t status = 0;
+	uint32_t change = 0;
 	int speed;
 
-	switch (cmd->requesttype & (USB_TYPE_MASK | USB_RECIP_MASK)) {
-	case USB_TYPE_STANDARD | USB_RECIP_DEVICE:
-		*(uint16_t *)buffer = cpu_to_le16(1);
-		len = 2;
-		break;
-	case USB_TYPE_STANDARD | USB_RECIP_INTERFACE:
-	case USB_TYPE_STANDARD | USB_RECIP_ENDPOINT:
-		*(uint16_t *)buffer = cpu_to_le16(0);
-		len = 2;
-		break;
-	case USB_RT_HUB:	/* USB_TYPE_CLASS | USB_RECIP_DEVICE */
-		*(uint32_t *)buffer = cpu_to_le32(0);
-		len = 4;
-		break;
-	case USB_RT_PORT:	/* USB_TYPE_CLASS | USB_RECIP_OTHER */
-		hprt0 = dwc2_readl(dwc2, HPRT0);
+	if (!buf || len < sizeof(*portsts))
+		return -1;
 
-		if (hprt0 & HPRT0_CONNSTS)
-			port_status |= USB_PORT_STAT_CONNECTION;
-		if (hprt0 & HPRT0_ENA)
-			port_status |= USB_PORT_STAT_ENABLE;
-		if (hprt0 & HPRT0_SUSP)
-			port_status |= USB_PORT_STAT_SUSPEND;
-		if (hprt0 & HPRT0_OVRCURRACT)
-			port_status |= USB_PORT_STAT_OVERCURRENT;
-		if (hprt0 & HPRT0_RST)
-			port_status |= USB_PORT_STAT_RESET;
-		if (hprt0 & HPRT0_PWR)
-			port_status |= USB_PORT_STAT_POWER;
-
-		speed = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT;
-		if (speed == HPRT0_SPD_HIGH_SPEED)
-			port_status |= USB_PORT_STAT_HIGH_SPEED;
-		else if (speed == HPRT0_SPD_LOW_SPEED)
-			port_status |= USB_PORT_STAT_LOW_SPEED;
-
-		if (hprt0 & HPRT0_ENACHG)
-			port_change |= USB_PORT_STAT_C_ENABLE;
-		if (hprt0 & HPRT0_CONNDET)
-			port_change |= USB_PORT_STAT_C_CONNECTION;
-		if (hprt0 & HPRT0_OVRCURRCHG)
-			port_change |= USB_PORT_STAT_C_OVERCURRENT;
-
-		portsts = buffer;
-		portsts->wPortStatus = cpu_to_le16(port_status);
-		portsts->wPortChange = cpu_to_le16(port_change);
-		len = sizeof(*portsts);
+	hprt0 = dwc2_readl(dwc2, HPRT0);
+
+	if (hprt0 & HPRT0_CONNSTS)
+		status |= USB_PORT_STAT_CONNECTION;
+	if (hprt0 & HPRT0_ENA)
+		status |= USB_PORT_STAT_ENABLE;
+	if (hprt0 & HPRT0_SUSP)
+		status |= USB_PORT_STAT_SUSPEND;
+	if (hprt0 & HPRT0_OVRCURRACT)
+		status |= USB_PORT_STAT_OVERCURRENT;
+	if (hprt0 & HPRT0_RST)
+		status |= USB_PORT_STAT_RESET;
+	if (hprt0 & HPRT0_PWR)
+		status |= USB_PORT_STAT_POWER;
+
+	speed = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT;
+	if (speed == HPRT0_SPD_HIGH_SPEED)
+		status |= USB_PORT_STAT_HIGH_SPEED;
+	else if (speed == HPRT0_SPD_LOW_SPEED)
+		status |= USB_PORT_STAT_LOW_SPEED;
+
+	if (hprt0 & HPRT0_ENACHG)
+		change |= USB_PORT_STAT_C_ENABLE;
+	if (hprt0 & HPRT0_CONNDET)
+		change |= USB_PORT_STAT_C_CONNECTION;
+	if (hprt0 & HPRT0_OVRCURRCHG)
+		change |= USB_PORT_STAT_C_OVERCURRENT;
+
+	portsts = buf;
+	portsts->wPortStatus = cpu_to_le16(status);
+	portsts->wPortChange = cpu_to_le16(change);
+
+	dev->act_len = sizeof(*portsts);
+	dev->status = 0;
 
-		break;
-	default:
-		goto unknown;
-	}
+	return 0;
+}
 
-	dev->act_len = min(len, txlen);
-	dev->status = 0;
+static int dwc2_get_hub_status(struct dwc2 *dwc2, struct usb_device *dev,
+		void *buf, int len)
+{
+	if (!buf || len < 4)
+		return -1;
+
+	*(uint32_t *)buf = 0;
+	dev->act_len = 4;
+	dev->status  = 0;
 
 	return 0;
+}
 
-unknown:
-	dev->act_len = 0;
-	dev->status = USB_ST_STALLED;
+static int dwc2_get_hub_descriptor(struct dwc2 *dwc2, struct usb_device *dev,
+		void *buf, int len)
+{
+	if (!buf)
+		return -1;
+
+	dev->act_len = min_t(int, len, descriptor.hub.bLength);
+	dev->status = 0;
+	memcpy(buf, &descriptor.hub, dev->act_len);
 
-	return -1;
+	return 0;
 }
 
-static void strtodesc(char *dest, char *src, size_t n)
+static void strle16(__le16 *dest, char *src, size_t n)
 {
 	unsigned int i;
 
-	dest[0] = n;
-	dest[1] = 0x3;
-	for (i = 2; i < n && *src != '\0'; i += 2) {
-		dest[i] = *(src++);
-		dest[i + 1] = 0;
-	}
+	for (i = 0; i < n && *src != '\0'; i++, src++)
+		dest[i] = cpu_to_le16(*src);
 }
 
-/* Direction: In ; Request: Descriptor */
-static int dwc2_submit_rh_msg_in_descriptor(struct usb_device *dev,
-					       void *buffer, int txlen,
-					       struct devrequest *cmd)
+static int dwc2_get_string_descriptor(struct dwc2 *dwc2, struct usb_device *dev,
+			       void *buf, int len, int index)
 {
-	int len = 0;
-	char *src;
-	uint16_t wValue = le16_to_cpu(cmd->value);
-	uint16_t wLength = le16_to_cpu(cmd->length);
-
-	switch (cmd->requesttype & (USB_TYPE_MASK | USB_RECIP_MASK)) {
-	case USB_TYPE_STANDARD | USB_RECIP_DEVICE:
-		switch (wValue >> 8) {
-		case USB_DT_DEVICE:
-			debug("USB_DT_DEVICE request\n");
-			len = min3(txlen, (int)descriptor.device.bLength, (int)wLength);
-			memcpy(buffer, &descriptor.device, len);
-			break;
-		case USB_DT_CONFIG:
-			debug("USB_DT_CONFIG config\n");
-			len = min3(txlen, (int)descriptor.config.wTotalLength, (int)wLength);
-			memcpy(buffer, &descriptor.config, len);
-			break;
-		case USB_DT_STRING:
-			debug("USB_DT_STRING: %#x\n", wValue);
-			switch (wValue & 0xff) {
-			case 0: /* Language */
-				src = language_string;
-				len = strlen(src) + 2;
-				((char *)buffer)[0] = len;
-				((char *)buffer)[1] = 0x03;
-				memcpy(buffer + 2, src, strlen(src));
-				break;
-			case 1: /* Vendor */
-				src = vendor_string;
-				len = 2 * strlen(src) + 2;
-				strtodesc(buffer, src, len);
-				break;
-			case 2: /* Product */
-				src = product_string;
-				len = 2 * strlen(src) + 2;
-				strtodesc(buffer, src, len);
-				break;
-			default:
-				debug("%s(): unknown string index 0x%x\n", __func__, wValue & 0xff);
-				goto unknown;
-			}
-			len = min3(txlen, len, (int)wLength);
-			break;
-		default:
-			debug("%s(): unknown requesttype: 0x%x\n", __func__,
-			       cmd->requesttype & (USB_TYPE_MASK | USB_RECIP_MASK));
-			goto unknown;
-		}
-		break;
+	char *src, *str = buf;
+	__le16 *le16 = (__le16 *)(str + 2);
+	int size;
+
+	if (!buf || len < 2)
+		return -1;
 
-	case USB_RT_HUB:	/* USB_TYPE_CLASS | USB_RECIP_DEVICE */
-		debug("USB_RT_HUB\n");
+	switch (index) {
+	case 0: /* Language */
+		src = "\x09\x04";
+		size = strlen(src) + 2;
+		len = min_t(int, len, size);
 
-		len = min3(txlen, (int)descriptor.hub.bLength, (int)wLength);
-		memcpy(buffer, &descriptor.hub, len);
+		str[0] = size;
+		str[1] = 0x03;
+		memcpy(str + 2, src, len - 2);
+		break;
+	case 1: /* Vendor */
+		src = "u-boot";
+		size = 2 * strlen(src) + 2;
+		len = min_t(int, len, size);
+
+		str[0] = size;
+		str[1] = 0x03;
+		strle16(le16, src, (len - 2) / 2);
+		break;
+	case 2: /* Product */
+		src = "DWC2 root hub";
+		size = 2 * strlen(src) + 2;
+		len = min_t(int, len, size);
+
+		str[0] = size;
+		str[1] = 0x03;
+		strle16(le16, src, (len - 2) / 2);
 		break;
 	default:
-		goto unknown;
+		dwc2_err(dwc2, "roothub: unknown string descriptor: 0x%x\n",
+				index);
+		return -1;
 	}
 
 	dev->act_len = len;
 	dev->status = 0;
 
 	return 0;
-
-unknown:
-	dev->act_len = 0;
-	dev->status = USB_ST_STALLED;
-
-	return -1;
 }
 
-/* Direction: In ; Request: Configuration */
-static int dwc2_submit_rh_msg_in_configuration(struct usb_device *dev,
-					       void *buffer, int txlen,
-					       struct devrequest *cmd)
+static int dwc2_get_descriptor(struct dwc2 *dwc2, struct usb_device *dev,
+			       void *buf, int len, int value)
 {
-	int len = 0;
+	int index = value >> 8;
+
+	if (!buf || len < 0)
+		return -1;
 
-	switch (cmd->requesttype & (USB_TYPE_MASK | USB_RECIP_MASK)) {
-	case USB_TYPE_STANDARD | USB_RECIP_DEVICE:
-		*(uint8_t *)buffer = 0x01;
-		len = min(txlen, 1);
+	switch (index) {
+	case USB_DT_DEVICE:
+		len = min(len, (int)descriptor.device.bLength);
+		memcpy(buf, &descriptor.device, len);
 		break;
+	case USB_DT_CONFIG:
+		len = min(len, (int)descriptor.config.wTotalLength);
+		memcpy(buf, &descriptor.config, len);
+		break;
+	case USB_DT_STRING:
+		value &= 0xff;
+		return dwc2_get_string_descriptor(dwc2, dev, buf, len, value);
 	default:
-		goto unknown;
+		dwc2_err(dwc2, "roothub: unknown descriptor: 0x%x\n", index);
+		return -1;
 	}
 
 	dev->act_len = len;
 	dev->status = 0;
 
 	return 0;
-
-unknown:
-	dev->act_len = 0;
-	dev->status = USB_ST_STALLED;
-
-	return -1;
 }
 
-/* Direction: In */
-static int dwc2_submit_rh_msg_in(struct dwc2 *dwc2,
-				 struct usb_device *dev, void *buffer,
-				 int txlen, struct devrequest *cmd)
+static int dwc2_set_port_feature(struct dwc2 *dwc2, struct usb_device *dev,
+		int feature)
 {
-	switch (cmd->request) {
-	case USB_REQ_GET_STATUS:
-		return dwc2_submit_rh_msg_in_status(dwc2, dev, buffer,
-						       txlen, cmd);
-	case USB_REQ_GET_DESCRIPTOR:
-		return dwc2_submit_rh_msg_in_descriptor(dev, buffer,
-							   txlen, cmd);
-	case USB_REQ_GET_CONFIGURATION:
-		return dwc2_submit_rh_msg_in_configuration(dev, buffer,
-							      txlen, cmd);
-	default:
-		dev->act_len = 0;
-		dev->status = USB_ST_STALLED;
+	uint32_t hprt0;
+
+	hprt0 = dwc2_readl(dwc2, HPRT0);
+	hprt0 &= ~(HPRT0_ENA | HPRT0_CONNDET | HPRT0_ENACHG | HPRT0_OVRCURRCHG);
+
+	switch (feature) {
+	case USB_PORT_FEAT_SUSPEND:
+		break;
+	case USB_PORT_FEAT_RESET:
+		hprt0 |= HPRT0_RST;
+		dwc2_writel(dwc2, hprt0, HPRT0);
+
+		mdelay(60);
 
+		hprt0 = dwc2_readl(dwc2, HPRT0);
+		hprt0 &= ~HPRT0_RST;
+		dwc2_writel(dwc2, hprt0, HPRT0);
+		break;
+	case USB_PORT_FEAT_POWER:
+		break;
+	case USB_PORT_FEAT_ENABLE:
+		/* Set by the core after a reset */
+		break;
+	default:
+		dwc2_dbg(dwc2, "roothub: unsupported set port feature 0x%x\n",
+				feature);
 		return -1;
 	}
+
+	dev->act_len = 0;
+	dev->status = 0;
+
+	return 0;
 }
 
-/* Direction: Out */
-static int dwc2_submit_rh_msg_out(struct dwc2 *dwc2,
-				  struct usb_device *dev,
-				  void *buffer, int txlen,
-				  struct devrequest *cmd)
+static int dwc2_clear_port_feature(struct dwc2 *dwc2, struct usb_device *dev,
+		int feature)
 {
-	uint16_t wValue = le16_to_cpu(cmd->value);
 	uint32_t hprt0;
 
-	switch (cmd->requesttype & (USB_TYPE_MASK | USB_RECIP_MASK)) {
-	case USB_TYPE_STANDARD | USB_RECIP_DEVICE:
-		switch (cmd->request) {
-		case USB_REQ_SET_ADDRESS:
-			dwc2_dbg(dwc2, "set root hub addr %d\n", wValue);
-			dwc2->root_hub_devnum = wValue;
-			break;
-		case USB_REQ_SET_CONFIGURATION:
-			break;
-		default:
-			goto unknown;
-		}
+	hprt0 = dwc2_readl(dwc2, HPRT0);
+	hprt0 &= ~(HPRT0_ENA | HPRT0_CONNDET | HPRT0_ENACHG | HPRT0_OVRCURRCHG);
+
+	switch (feature) {
+	case USB_PORT_FEAT_ENABLE:
+		hprt0 |= HPRT0_ENA;
+		break;
+	case USB_PORT_FEAT_SUSPEND:
+		break;
+	case USB_PORT_FEAT_POWER:
 		break;
-	case USB_TYPE_STANDARD | USB_RECIP_ENDPOINT:
-	case USB_RT_HUB:	/* USB_TYPE_CLASS | USB_RECIP_DEVICE */
-		switch (cmd->request) {
-		case USB_REQ_CLEAR_FEATURE:
-			break;
-		}
+	case USB_PORT_FEAT_C_CONNECTION:
+		hprt0 |= HPRT0_CONNDET;
 		break;
-	case USB_RT_PORT:	/* USB_TYPE_CLASS | USB_RECIP_OTHER */
-		switch (cmd->request) {
-		case USB_REQ_CLEAR_FEATURE:
-			hprt0 = dwc2_readl(dwc2, HPRT0);
-			hprt0 &= ~(HPRT0_ENA | HPRT0_CONNDET
-				   | HPRT0_ENACHG | HPRT0_OVRCURRCHG);
-			switch (wValue) {
-			case USB_PORT_FEAT_ENABLE:
-				hprt0 |= HPRT0_ENA;
-				break;
-			case USB_PORT_FEAT_SUSPEND:
-				break;
-			case USB_PORT_FEAT_POWER:
-				break;
-			case USB_PORT_FEAT_C_CONNECTION:
-				hprt0 |= HPRT0_CONNDET;
-				break;
-			case USB_PORT_FEAT_C_ENABLE:
-				hprt0 |= HPRT0_ENACHG;
-				break;
-			case USB_PORT_FEAT_C_OVER_CURRENT:
-				hprt0 |= HPRT0_OVRCURRCHG;
-				break;
-			default:
-				dwc2_dbg(dwc2, "unknown feature 0x%x\n", wValue);
-				goto unknown;
-			}
-			dwc2_writel(dwc2, hprt0, HPRT0);
-			break;
-		case USB_REQ_SET_FEATURE:
-			hprt0 = dwc2_readl(dwc2, HPRT0);
-			hprt0 &= ~(HPRT0_ENA | HPRT0_CONNDET
-				   | HPRT0_ENACHG | HPRT0_OVRCURRCHG);
-			switch (wValue) {
-			case USB_PORT_FEAT_SUSPEND:
-				break;
-			case USB_PORT_FEAT_RESET:
-				hprt0 |= HPRT0_RST;
-				dwc2_writel(dwc2, hprt0, HPRT0);
-
-				mdelay(60);
-
-				hprt0 = dwc2_readl(dwc2, HPRT0);
-				hprt0 &= ~HPRT0_RST;
-				dwc2_writel(dwc2, hprt0, HPRT0);
-				break;
-			case USB_PORT_FEAT_POWER:
-				break;
-			case USB_PORT_FEAT_ENABLE:
-				/* Set by the core after a reset */
-				break;
-			default:
-				dwc2_dbg(dwc2, "unknown feature 0x%x\n", wValue);
-				goto unknown;
-			}
-			break;
-		default: goto unknown;
-		}
+	case USB_PORT_FEAT_C_ENABLE:
+		hprt0 |= HPRT0_ENACHG;
+		break;
+	case USB_PORT_FEAT_C_OVER_CURRENT:
+		hprt0 |= HPRT0_OVRCURRCHG;
 		break;
 	default:
-		goto unknown;
+		dwc2_dbg(dwc2, "roothub: unsupported clear port feature 0x%x\n",
+				feature);
+		return -1;
 	}
 
+	dwc2_writel(dwc2, hprt0, HPRT0);
+
 	dev->act_len = 0;
 	dev->status = 0;
 
 	return 0;
+}
+
+static int dwc2_set_address(struct dwc2 *dwc2, struct usb_device *dev, int addr)
+{
+	dwc2_dbg(dwc2, "roothub: set address to %d\n", addr);
+	dwc2->root_hub_devnum = addr;
 
-unknown:
 	dev->act_len = 0;
-	dev->status = USB_ST_STALLED;
-	return -1;
+	dev->status = 0;
+
+	return 0;
 }
 
-int
-dwc2_submit_rh_msg(struct dwc2 *dwc2, struct usb_device *dev,
-				 unsigned long pipe, void *buffer, int txlen,
-				 struct devrequest *cmd)
+int dwc2_submit_roothub(struct dwc2 *dwc2, struct usb_device *dev,
+		unsigned long pipe, void *buf, int len,
+		struct devrequest *setup)
 {
-	int stat = 0;
+	unsigned char reqtype = setup->requesttype;
+	unsigned char request = setup->request;
+	unsigned short value = le16_to_cpu(setup->value);
+	unsigned short size  = le16_to_cpu(setup->length);
+	int minlen = min_t(int, len, size);
 
 	if (usb_pipeint(pipe)) {
-		dwc2_err(dwc2, "Root-Hub submit IRQ: NOT implemented\n");
+		dwc2_err(dwc2, "roothub: submit IRQ NOT implemented\n");
 		return 0;
 	}
 
-	if (cmd->requesttype & USB_DIR_IN)
-		stat = dwc2_submit_rh_msg_in(dwc2, dev, buffer, txlen, cmd);
-	else
-		stat = dwc2_submit_rh_msg_out(dwc2, dev, buffer, txlen, cmd);
+	dev->act_len = 0;
+	dev->status = USB_ST_STALLED;
+
+#define REQ(l, u) ((l) | ((u) << 8))
+
+	switch (REQ(request, reqtype)) {
+	case REQ(USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB):
+		return dwc2_get_hub_descriptor(dwc2, dev, buf, minlen);
+
+	case REQ(USB_REQ_GET_DESCRIPTOR, USB_DIR_IN):
+		return dwc2_get_descriptor(dwc2, dev, buf, minlen, value);
+
+	case REQ(USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB):
+		return dwc2_get_hub_status(dwc2, dev, buf, len);
+
+	case REQ(USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT):
+		return dwc2_get_port_status(dwc2, dev, buf, len);
 
-	mdelay(1);
-	return stat;
+	case REQ(USB_REQ_SET_FEATURE, USB_DIR_OUT | USB_RT_PORT):
+		return dwc2_set_port_feature(dwc2, dev, value);
+
+	case REQ(USB_REQ_CLEAR_FEATURE, USB_DIR_OUT | USB_RT_PORT):
+		return dwc2_clear_port_feature(dwc2, dev, value);
+
+	case REQ(USB_REQ_SET_ADDRESS, USB_DIR_OUT):
+		return dwc2_set_address(dwc2, dev, value);
+
+	case REQ(USB_REQ_SET_CONFIGURATION, USB_DIR_OUT):
+		dev->act_len = 0;
+		dev->status = 0;
+		return 0;
+
+	case REQ(USB_REQ_GET_CONFIGURATION, USB_DIR_IN):
+		*(char *)buf = 1;
+		dev->act_len = 1;
+		dev->status = 0;
+		return 0;
+	}
+
+	dwc2_err(dwc2, "roothub: unsupported request 0x%x requesttype 0x%x\n",
+		 request, reqtype);
+
+	return 0;
 }
-- 
2.17.1




More information about the barebox mailing list