summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/usbd_core.c57
-rw-r--r--core/usbh_core.c133
2 files changed, 135 insertions, 55 deletions
diff --git a/core/usbd_core.c b/core/usbd_core.c
index b023fefc..c7850e67 100644
--- a/core/usbd_core.c
+++ b/core/usbd_core.c
@@ -29,6 +29,9 @@
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
+#define CONFIG_USBDEV_MAX_EPS 16
+#define CONFIG_USBDEV_MAX_INTERFACES 16
+
struct usbd_tx_rx_msg {
uint8_t ep;
uint8_t ep_type;
@@ -78,12 +81,12 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
usb_osal_mq_t usbd_ep0_mq;
usb_osal_thread_t usbd_ep0_thread;
#endif
- struct usbd_interface *intf[16];
- uint8_t intf_altsetting[16];
+ struct usbd_interface *intf[CONFIG_USBDEV_MAX_INTERFACES];
+ uint8_t intf_altsetting[CONFIG_USBDEV_MAX_INTERFACES];
uint8_t intf_offset;
- struct usbd_tx_rx_msg tx_msg[16];
- struct usbd_tx_rx_msg rx_msg[16];
+ struct usbd_tx_rx_msg tx_msg[CONFIG_USBDEV_MAX_EPS];
+ struct usbd_tx_rx_msg rx_msg[CONFIG_USBDEV_MAX_EPS];
void (*event_handler)(uint8_t busid, uint8_t event);
} g_usbd_core[CONFIG_USBDEV_MAX_BUS];
@@ -532,13 +535,19 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting
break;
case USB_DESCRIPTOR_TYPE_ENDPOINT:
- if (cur_iface == iface) {
+ if (cur_iface == iface && if_desc != NULL) {
ep_desc = (struct usb_endpoint_descriptor *)p;
if (alt_setting == 0) {
ret = usbd_reset_endpoint(busid, ep_desc);
+ if (ret == false) {
+ return ret;
+ }
} else if (cur_alt_setting == alt_setting) {
ret = usbd_set_endpoint(busid, ep_desc);
+ if (ret == false) {
+ return ret;
+ }
if (g_usbd_core[busid].speed >= USB_SPEED_SUPER) {
const uint8_t *ep_comp_desc;
@@ -570,7 +579,9 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting
}
}
- usbd_class_event_notify_handler(busid, USBD_EVENT_SET_INTERFACE, (void *)if_desc);
+ if (if_desc) {
+ usbd_class_event_notify_handler(busid, USBD_EVENT_SET_INTERFACE, (void *)if_desc);
+ }
return ret;
}
@@ -687,9 +698,11 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
ret = false;
break;
case USB_REQUEST_SET_SEL:
+ *len = 0;
break;
case USB_REQUEST_SET_ISOCH_DLY:
g_usbd_core[busid].isoch_delay = value;
+ *len = 0;
break;
default:
@@ -720,6 +733,10 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
uint32_t current_desc_len = 0;
uint8_t cur_iface = 0xFF;
+ if (intf_num >= g_usbd_core[busid].intf_offset) {
+ return false;
+ }
+
p = g_usbd_core[busid].descriptors->config_descriptor_callback(g_usbd_core[busid].speed);
/* Only when device is configured, then interface requests can be valid. */
@@ -791,8 +808,12 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
break;
case USB_REQUEST_SET_INTERFACE:
+ ret = usbd_set_interface(busid, intf_num, setup->wValue);
+ if (ret == false) {
+ break;
+ }
g_usbd_core[busid].intf_altsetting[intf_num] = LO_BYTE(setup->wValue);
- usbd_set_interface(busid, setup->wIndex, setup->wValue);
+
*len = 0;
break;
@@ -825,6 +846,10 @@ static bool usbd_std_endpoint_req_handler(uint8_t busid, struct usb_setup_packet
return false;
}
+ if ((ep & 0x7f) >= CONFIG_USBDEV_MAX_EPS) {
+ return false;
+ }
+
switch (setup->bRequest) {
case USB_REQUEST_GET_STATUS:
usbd_ep_is_stalled(busid, ep, &stalled);
@@ -963,21 +988,19 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
if (setup->bRequest == g_usbd_core[busid].descriptors->msosv1_descriptor->vendor_code) {
switch (setup->wIndex) {
case 0x04:
- desclen = g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[0] +
- (g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[1] << 8) +
- (g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[2] << 16) +
- (g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[3] << 24);
-
+ desclen = GET_LE32(g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id);
*data = (uint8_t *)g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id;
//memcpy(*data, g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id, desclen);
*len = desclen;
return 0;
case 0x05:
- desclen = g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][0] +
- (g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][1] << 8) +
- (g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][2] << 16) +
- (g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][3] << 24);
+ if (g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property == NULL ||
+ setup->wValue >= g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property_count ||
+ g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue] == NULL) {
+ return -1;
+ }
+ desclen = GET_LE32(g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue]);
*data = (uint8_t *)g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue];
//memcpy(*data, g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue], desclen);
*len = desclen;
@@ -1367,6 +1390,8 @@ void usbd_desc_register(uint8_t busid, const struct usb_descriptor *desc)
void usbd_add_interface(uint8_t busid, struct usbd_interface *intf)
{
+ USB_ASSERT_MSG(g_usbd_core[busid].intf_offset < CONFIG_USBDEV_MAX_INTERFACES, "Too many interfaces\r\n");
+
intf->intf_num = g_usbd_core[busid].intf_offset;
g_usbd_core[busid].intf[g_usbd_core[busid].intf_offset] = intf;
g_usbd_core[busid].intf_offset++;
diff --git a/core/usbh_core.c b/core/usbh_core.c
index ba00d8f8..0457a7c5 100644
--- a/core/usbh_core.c
+++ b/core/usbh_core.c
@@ -27,6 +27,7 @@ struct usbh_bus g_usbhost_bus[CONFIG_USBHOST_MAX_BUS];
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
+#define USB_DEV_ADDR_MIN 2
#define USB_DEV_ADDR_MAX 0x7f
#define USB_DEV_ADDR_MARK_OFFSET 5
#define USB_DEV_ADDR_MARK_MASK 0x1f
@@ -43,17 +44,19 @@ static void dummy_event_handler(uint8_t busid, uint8_t hub_index, uint8_t hub_po
static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
{
uint8_t lastaddr = devgen->last;
- uint8_t devaddr = lastaddr;
+ uint8_t devaddr;
int index;
int bitno;
+ if (lastaddr < USB_DEV_ADDR_MIN || lastaddr > USB_DEV_ADDR_MAX) {
+ lastaddr = USB_DEV_ADDR_MAX;
+ }
+ devaddr = lastaddr;
+
for (;;) {
devaddr++;
- if (devaddr > 0x7f) {
- devaddr = 2;
- }
- if (devaddr == lastaddr) {
- return -USB_ERR_NOMEM;
+ if (devaddr > USB_DEV_ADDR_MAX) {
+ devaddr = USB_DEV_ADDR_MIN;
}
index = devaddr >> 5;
@@ -63,6 +66,10 @@ static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
devgen->last = devaddr;
return (int)devaddr;
}
+
+ if (devaddr == lastaddr) {
+ return -USB_ERR_NOMEM;
+ }
}
}
@@ -71,7 +78,7 @@ static int __usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
int index;
int bitno;
- if ((devaddr > 0) && (devaddr < USB_DEV_ADDR_MAX)) {
+ if ((devaddr > 0) && (devaddr <= USB_DEV_ADDR_MAX)) {
index = devaddr >> USB_DEV_ADDR_MARK_OFFSET;
bitno = devaddr & USB_DEV_ADDR_MARK_MASK;
@@ -132,6 +139,10 @@ static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uin
static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device_descriptor *desc, uint16_t length)
{
+ if (length < 8) {
+ return -USB_ERR_INVAL;
+ }
+
if (desc->bLength != USB_SIZEOF_DEVICE_DESC) {
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
return -USB_ERR_INVAL;
@@ -139,6 +150,16 @@ static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device
USB_LOG_ERR("unexpected device descriptor 0x%02x\r\n", desc->bDescriptorType);
return -USB_ERR_INVAL;
} else {
+ if ((hport->speed >= USB_SPEED_SUPER && desc->bMaxPacketSize0 != 9) ||
+ (hport->speed == USB_SPEED_HIGH && desc->bMaxPacketSize0 != 64) ||
+ (hport->speed == USB_SPEED_LOW && desc->bMaxPacketSize0 != 8) ||
+ (hport->speed == USB_SPEED_FULL &&
+ desc->bMaxPacketSize0 != 8 && desc->bMaxPacketSize0 != 16 &&
+ desc->bMaxPacketSize0 != 32 && desc->bMaxPacketSize0 != 64)) {
+ USB_LOG_ERR("invalid bMaxPacketSize0 %d\r\n", desc->bMaxPacketSize0);
+ return -USB_ERR_INVAL;
+ }
+
if (length <= 8) {
return 0;
}
@@ -188,6 +209,9 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
uint32_t desc_len = 0;
uint8_t *p;
+ if (length < USB_SIZEOF_CONFIG_DESC) {
+ return -USB_ERR_INVAL;
+ }
if (desc->bLength != USB_SIZEOF_CONFIG_DESC) {
USB_LOG_ERR("invalid config bLength 0x%02x\r\n", desc->bLength);
return -USB_ERR_INVAL;
@@ -195,9 +219,17 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
USB_LOG_ERR("unexpected config descriptor 0x%02x\r\n", desc->bDescriptorType);
return -USB_ERR_INVAL;
} else {
+ if (desc->bNumInterfaces > CONFIG_USBHOST_MAX_INTERFACES) {
+ return -USB_ERR_NOMEM;
+ }
+
if (length <= USB_SIZEOF_CONFIG_DESC) {
return 0;
}
+
+ if (desc->wTotalLength != length) {
+ return -USB_ERR_INVAL;
+ }
#if 0
USB_LOG_DBG("Config Descriptor:\r\n");
USB_LOG_DBG("bLength: 0x%02x \r\n", desc->bLength);
@@ -225,9 +257,14 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
memset(hport->config.intf, 0, sizeof(struct usbh_interface) * CONFIG_USBHOST_MAX_INTERFACES);
- while (p[DESC_bLength]) {
+ while ((desc_len < length) &&
+ (p[DESC_bLength] >= 2) &&
+ (p[DESC_bLength] <= length - desc_len)) {
switch (p[DESC_bDescriptorType]) {
case USB_DESCRIPTOR_TYPE_INTERFACE:
+ if (cur_ep != cur_ep_num) {
+ return -USB_ERR_INVAL;
+ }
if (p[DESC_bLength] < USB_SIZEOF_INTERFACE_DESC) {
return -USB_ERR_INVAL;
}
@@ -242,16 +279,19 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
return -USB_ERR_NOMEM;
}
- if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) {
- USB_LOG_ERR("Endpoint num %d overflow\r\n", cur_ep_num);
+ if (cur_alt_setting >= CONFIG_USBHOST_MAX_INTF_ALTSETTINGS) {
+ USB_LOG_ERR("Interface altsetting num %d overflow\r\n", cur_alt_setting);
return -USB_ERR_NOMEM;
}
- if (cur_alt_setting >= CONFIG_USBHOST_MAX_INTF_ALTSETTINGS) {
- USB_LOG_ERR("Interface altsetting num %d overflow\r\n", cur_alt_setting);
+ if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) {
+ USB_LOG_ERR("Endpoint num %d overflow\r\n", cur_ep_num);
return -USB_ERR_NOMEM;
}
+ if (cur_alt_setting != hport->config.intf[cur_iface].altsetting_num) {
+ return -USB_ERR_INVAL;
+ }
#if 0
USB_LOG_DBG("Interface Descriptor:\r\n");
USB_LOG_DBG("bLength: 0x%02x \r\n", intf_desc->bLength);
@@ -264,8 +304,9 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
USB_LOG_DBG("bInterfaceProtocol: 0x%02x \r\n", intf_desc->bInterfaceProtocol);
USB_LOG_DBG("iInterface: 0x%02x \r\n", intf_desc->iInterface);
#endif
- memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].intf_desc, intf_desc, 9);
- hport->config.intf[cur_iface].altsetting_num = cur_alt_setting + 1;
+
+ memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].intf_desc, intf_desc, USB_SIZEOF_INTERFACE_DESC);
+ hport->config.intf[cur_iface].altsetting_num++;
break;
case USB_DESCRIPTOR_TYPE_ENDPOINT:
if (p[DESC_bLength] < USB_SIZEOF_ENDPOINT_DESC) {
@@ -273,12 +314,29 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
}
ep_desc = (struct usb_endpoint_descriptor *)p;
- if (cur_ep >= CONFIG_USBHOST_MAX_ENDPOINTS) {
+ if (USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize) == 0) {
+ return -USB_ERR_INVAL;
+ }
+
+ if ((ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT ||
+ (ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
+ if (ep_desc->bInterval == 0 ||
+ (hport->speed >= USB_SPEED_HIGH && ep_desc->bInterval > 16)) {
+ return -USB_ERR_INVAL;
+ }
+ }
+
+ if (cur_iface >= CONFIG_USBHOST_MAX_INTERFACES) {
+ USB_LOG_ERR("Interface num %d overflow\r\n", cur_iface);
+ return -USB_ERR_NOMEM;
+ }
+
+ if (cur_ep >= cur_ep_num) {
USB_LOG_ERR("Endpoint num %d overflow\r\n", cur_ep);
return -USB_ERR_NOMEM;
}
- memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].ep[cur_ep].ep_desc, ep_desc, 7);
+ memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].ep[cur_ep].ep_desc, ep_desc, USB_SIZEOF_ENDPOINT_DESC);
cur_ep++;
break;
@@ -288,10 +346,10 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
/* skip to next descriptor */
desc_len += p[DESC_bLength];
p += p[DESC_bLength];
+ }
- if (desc_len > length) {
- return -USB_ERR_INVAL;
- }
+ if (cur_ep != cur_ep_num) {
+ return -USB_ERR_INVAL;
}
if (desc_len != length) {
@@ -379,8 +437,8 @@ int usbh_enumerate(struct usbh_hubport *hport)
/* Extract the correct max packetsize from the device descriptor */
dev_desc = (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid];
- if (dev_desc->bcdUSB >= USB_3_0) {
- ep_mps = 1 << dev_desc->bMaxPacketSize0;
+ if (hport->speed >= USB_SPEED_SUPER) {
+ ep_mps = 1U << dev_desc->bMaxPacketSize0;
} else {
ep_mps = dev_desc->bMaxPacketSize0;
}
@@ -395,6 +453,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
/* Assign a function address to the device connected to this port */
dev_addr = usbh_allocate_devaddr(&hport->bus->devgen);
if (dev_addr < 0) {
+ ret = dev_addr;
USB_LOG_ERR("Failed to allocate devaddr,errorcode:%d\r\n", ret);
goto errout;
}
@@ -409,6 +468,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
ret = usbh_control_transfer(hport, setup, NULL);
if (ret < 0) {
USB_LOG_ERR("Failed to set devaddr,errorcode:%d\r\n", ret);
+ __usbh_free_devaddr(&hport->bus->devgen, (uint8_t)dev_addr);
goto errout;
}
@@ -431,7 +491,12 @@ int usbh_enumerate(struct usbh_hubport *hport)
goto errout;
}
- parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_DEVICE_DESC);
+ ret = parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_DEVICE_DESC);
+ if (ret < 0) {
+ USB_LOG_ERR("Parse full device descriptor fail\r\n");
+ goto errout;
+ }
+
USB_LOG_INFO("New device found,idVendor:%04x,idProduct:%04x,bcdDevice:%04x\r\n",
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idVendor,
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idProduct,
@@ -748,17 +813,14 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out
struct usb_setup_packet *setup = hport->setup;
int ret;
uint8_t *src;
- uint8_t *dst;
uint16_t len;
- uint16_t i = 2;
- uint16_t j = 0;
/* Get Manufacturer string */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | index);
setup->wIndex = 0x0409;
- setup->wLength = 255;
+ setup->wLength = MIN(255, CONFIG_USBHOST_REQUEST_BUFFER_LEN);
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
@@ -766,26 +828,19 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out
}
src = ep0_request_buffer[hport->bus->busid];
- dst = output;
- len = src[0];
-
- if (ret != len) {
- USB_LOG_ERR("Get string descriptor failed, expect %d, actual %d\r\n", len, ret);
+ if (ret < 2 || src[1] != USB_DESCRIPTOR_TYPE_STRING || src[0] != ret || (src[0] & 1)) {
return -USB_ERR_IO;
}
- memset(output, 0, output_len);
-
- if (((len - 2) / 2) > output_len) {
+ len = (src[0] - 2) / 2;
+ if (len > output_len) {
return -USB_ERR_NOMEM;
}
- while (i < len) {
- dst[j] = src[i];
- i += 2;
- j++;
+ memset(output, 0, output_len);
+ for (uint16_t i = 0; i < len; i++) {
+ output[i] = src[2 + 2 * i];
}
-
return 0;
}