enum For string descriptor (langid, manufacturer product, serila): always get the first 2 bytes to determine the length first. otherwise, some device may have buffer overflow.

This commit is contained in:
hathach 2025-04-14 16:09:32 +07:00
parent edbea218b9
commit e8a84f9076
No known key found for this signature in database
GPG Key ID: 26FAB84F615C3C52
4 changed files with 76 additions and 58 deletions

View File

@ -36,7 +36,7 @@
extern "C" {
#endif
#define NEOPIXEL_PIN 48
#define NEOPIXEL_PIN 38
#define BUTTON_PIN 0
#define BUTTON_STATE_ACTIVE 0

View File

@ -34,6 +34,6 @@ endif ()
set(EXTRA_COMPONENT_DIRS "src" "${CMAKE_CURRENT_LIST_DIR}/boards" "${CMAKE_CURRENT_LIST_DIR}/components")
# set SDKCONFIG for each IDF Target
set(SDKCONFIG ${CMAKE_SOURCE_DIR}/sdkconfig.${IDF_TARGET})
set(SDKCONFIG ${CMAKE_BINARY_DIR}/sdkconfig)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)

View File

@ -108,15 +108,13 @@ typedef struct {
} tu_lookup_table_t;
static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint32_t key) {
tu_static char not_found[11];
for(uint16_t i=0; i<p_table->count; i++) {
if (p_table->items[i].key == key) return p_table->items[i].data;
if (p_table->items[i].key == key) { return p_table->items[i].data; }
}
// not found return the key value in hex
static char not_found[11];
snprintf(not_found, sizeof(not_found), "0x%08lX", (unsigned long) key);
return not_found;
}

View File

@ -1372,9 +1372,13 @@ enum {
ENUM_HUB_CLEAR_RESET_2,
ENUM_SET_ADDR,
ENUM_GET_DEVICE_DESC,
ENUM_GET_STRING_LANGUAGE_ID_LEN,
ENUM_GET_STRING_LANGUAGE_ID,
ENUM_GET_STRING_MANUFACTURER_LEN,
ENUM_GET_STRING_MANUFACTURER,
ENUM_GET_STRING_PRODUCT_LEN,
ENUM_GET_STRING_PRODUCT,
ENUM_GET_STRING_SERIAL_LEN,
ENUM_GET_STRING_SERIAL,
ENUM_GET_9BYTE_CONFIG_DESC,
ENUM_GET_FULL_CONFIG_DESC,
@ -1416,6 +1420,9 @@ static void process_enumeration(tuh_xfer_t* xfer) {
uint8_t const daddr = xfer->daddr;
uintptr_t const state = xfer->user_data;
usbh_device_t* dev = get_device(daddr);
if (daddr > 0) {
TU_ASSERT(dev,);
}
uint16_t langid = 0x0409; // default is English
switch (state) {
@ -1474,30 +1481,6 @@ static void process_enumeration(tuh_xfer_t* xfer) {
break;
}
#if 0
case ENUM_RESET_2:
// TODO not used by now, but may be needed for some devices !?
// Reset device again before Set Address
TU_LOG_USBH("Port reset2 \r\n");
if (_dev0.hub_addr == 0) {
// connected directly to roothub
hcd_port_reset( _dev0.rhport );
tusb_time_delay_ms_api(RESET_DELAY); // TODO may not work for no-OS on MCU that require reset_end() since
// sof of controller may not running while resetting
hcd_port_reset_end(_dev0.rhport);
// TODO: fall through to SET ADDRESS, refactor later
}
#if CFG_TUH_HUB
else {
// after RESET_DELAY the hub_port_reset() already complete
TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port,
process_enumeration, ENUM_HUB_GET_STATUS_2), );
break;
}
#endif
TU_ATTR_FALLTHROUGH;
#endif
case ENUM_SET_ADDR:
enum_request_set_addr((tusb_desc_device_t*) _usbh_epbuf.ctrl);
break;
@ -1520,14 +1503,15 @@ static void process_enumeration(tuh_xfer_t* xfer) {
// Get full device descriptor
TU_LOG_USBH("Get Device Descriptor\r\n");
TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_epbuf.ctrl, sizeof(tusb_desc_device_t),
process_enumeration, ENUM_GET_STRING_LANGUAGE_ID),);
process_enumeration, ENUM_GET_STRING_LANGUAGE_ID_LEN),);
break;
}
case ENUM_GET_STRING_LANGUAGE_ID: {
// For string descriptor (langid, manufacturer, product, serila): always get the first 2 bytes
// to determine the length first. otherwise, some device may have buffer overflow.
case ENUM_GET_STRING_LANGUAGE_ID_LEN: {
// save the received device descriptor
TU_ASSERT(dev,);
tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_epbuf.ctrl;
tusb_desc_device_t const *desc_device = (tusb_desc_device_t const *) _usbh_epbuf.ctrl;
dev->vid = desc_device->idVendor;
dev->pid = desc_device->idProduct;
dev->i_manufacturer = desc_device->iManufacturer;
@ -1535,50 +1519,88 @@ static void process_enumeration(tuh_xfer_t* xfer) {
dev->i_serial = desc_device->iSerialNumber;
dev->bNumConfigurations = desc_device->bNumConfigurations;
tuh_enum_descriptor_device_cb(daddr, desc_device); // callback
tuh_enum_descriptor_device_cb(daddr, desc_device);// callback
tuh_descriptor_get_string_langid(daddr, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
process_enumeration, ENUM_GET_STRING_MANUFACTURER);
tuh_descriptor_get_string_langid(daddr, _usbh_epbuf.ctrl, 2,
process_enumeration, ENUM_GET_STRING_LANGUAGE_ID);
break;
}
case ENUM_GET_STRING_MANUFACTURER: {
TU_ASSERT(dev,);
const tusb_desc_string_t* desc_langid = (tusb_desc_string_t const*) _usbh_epbuf.ctrl;
case ENUM_GET_STRING_LANGUAGE_ID: {
const uint8_t str_len = xfer->buffer[0];
tuh_descriptor_get_string_langid(daddr, _usbh_epbuf.ctrl, str_len,
process_enumeration, ENUM_GET_STRING_MANUFACTURER_LEN);
break;
}
case ENUM_GET_STRING_MANUFACTURER_LEN: {
const tusb_desc_string_t* desc_langid = (const tusb_desc_string_t *) _usbh_epbuf.ctrl;
if (desc_langid->bLength >= 4) {
langid = tu_le16toh(desc_langid->utf16le[0]);
langid = tu_le16toh(desc_langid->utf16le[0]); // previous request is langid
}
if (dev->i_manufacturer != 0) {
tuh_descriptor_get_string(daddr, dev->i_manufacturer, langid, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
tuh_descriptor_get_string(daddr, dev->i_manufacturer, langid, _usbh_epbuf.ctrl, 2,
process_enumeration, ENUM_GET_STRING_MANUFACTURER);
break;
}else {
TU_ATTR_FALLTHROUGH;
}
}
case ENUM_GET_STRING_MANUFACTURER: {
if (dev->i_manufacturer != 0) {
langid = tu_le16toh(xfer->setup->wIndex); // langid from length's request
const uint8_t str_len = xfer->buffer[0];
tuh_descriptor_get_string(daddr, dev->i_manufacturer, langid, _usbh_epbuf.ctrl, str_len,
process_enumeration, ENUM_GET_STRING_PRODUCT_LEN);
break;
} else {
TU_ATTR_FALLTHROUGH;
}
}
case ENUM_GET_STRING_PRODUCT_LEN:
if (dev->i_product != 0) {
if (state == ENUM_GET_STRING_PRODUCT_LEN) {
langid = tu_le16toh(xfer->setup->wIndex); // get langid from previous setup packet if not fall through
}
tuh_descriptor_get_string(daddr, dev->i_product, langid, _usbh_epbuf.ctrl, 2,
process_enumeration, ENUM_GET_STRING_PRODUCT);
break;
} else {
TU_ATTR_FALLTHROUGH;
}
}
case ENUM_GET_STRING_PRODUCT: {
TU_ASSERT(dev,);
if (state == ENUM_GET_STRING_PRODUCT) {
langid = tu_le16toh(xfer->setup->wIndex); // if not fall through, get langid from previous setup packet
}
if (dev->i_product != 0) {
tuh_descriptor_get_string(daddr, dev->i_product, 0x0409, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
process_enumeration, ENUM_GET_STRING_SERIAL);
langid = tu_le16toh(xfer->setup->wIndex); // langid from length's request
const uint8_t str_len = xfer->buffer[0];
tuh_descriptor_get_string(daddr, dev->i_product, langid, _usbh_epbuf.ctrl, str_len,
process_enumeration, ENUM_GET_STRING_SERIAL_LEN);
break;
} else {
TU_ATTR_FALLTHROUGH;
}
}
case ENUM_GET_STRING_SERIAL: {
TU_ASSERT(dev,);
if (state == ENUM_GET_STRING_SERIAL) {
langid = tu_le16toh(xfer->setup->wIndex); // if not fall through, get langid from previous setup packet
}
case ENUM_GET_STRING_SERIAL_LEN:
if (dev->i_serial != 0) {
tuh_descriptor_get_string(daddr, dev->i_serial, langid, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC);
if (state == ENUM_GET_STRING_SERIAL_LEN) {
langid = tu_le16toh(xfer->setup->wIndex); // get langid from previous setup packet if not fall through
}
tuh_descriptor_get_string(daddr, dev->i_serial, langid, _usbh_epbuf.ctrl, 2,
process_enumeration, ENUM_GET_STRING_SERIAL);
break;
} else {
TU_ATTR_FALLTHROUGH;
}
case ENUM_GET_STRING_SERIAL: {
if (dev->i_serial != 0) {
langid = tu_le16toh(xfer->setup->wIndex); // langid from length's request
const uint8_t str_len = xfer->buffer[0];
tuh_descriptor_get_string(daddr, dev->i_serial, langid, _usbh_epbuf.ctrl, str_len,
process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC);
break;
} else {
TU_ATTR_FALLTHROUGH;
@ -1627,8 +1649,6 @@ static void process_enumeration(tuh_xfer_t* xfer) {
case ENUM_CONFIG_DRIVER: {
TU_LOG_USBH("Device configured\r\n");
TU_ASSERT(dev,);
dev->configured = 1;
// Parse configuration & set up drivers