summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2025-03-24 22:55:04 +0700
committerhathach <[email protected]>2025-03-24 22:55:04 +0700
commit9f541a3d961e1a75a9c6441cb3564c726292731b (patch)
treec9f58878416c4516b650dcd7079383405aced207 /src
parente54753814befa26742fa8a9805f5b7beac32a963 (diff)
host: add tuh_enum_descriptor_device_cb() and tuh_enum_descriptor_configuration_cb() callback
host: support device with multiple configurations
Diffstat (limited to 'src')
-rw-r--r--src/host/usbh.c75
-rw-r--r--src/host/usbh.h7
2 files changed, 48 insertions, 34 deletions
diff --git a/src/host/usbh.c b/src/host/usbh.c
index c87f058cd..308916c9b 100644
--- a/src/host/usbh.c
+++ b/src/host/usbh.c
@@ -52,21 +52,25 @@ enum {
// Weak stubs: invoked if no strong implementation is available
//--------------------------------------------------------------------+
TU_ATTR_WEAK bool hcd_deinit(uint8_t rhport) {
- (void) rhport;
- return false;
+ (void) rhport; return false;
}
TU_ATTR_WEAK bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
- (void) rhport;
- (void) cfg_id;
- (void) cfg_param;
+ (void) rhport; (void) cfg_id; (void) cfg_param;
return false;
}
+TU_ATTR_WEAK void tuh_enum_descriptor_device_cb(uint8_t daddr, const tusb_desc_device_t *desc_device) {
+ (void) daddr; (void) desc_device;
+}
+
+TU_ATTR_WEAK bool tuh_enum_descriptor_configuration_cb(uint8_t daddr, uint8_t cfg_index, const tusb_desc_configuration_t *desc_config) {
+ (void) daddr; (void) cfg_index; (void) desc_config;
+ return true;
+}
+
TU_ATTR_WEAK void tuh_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) {
- (void) rhport;
- (void) eventid;
- (void) in_isr;
+ (void) rhport; (void) eventid; (void) in_isr;
}
TU_ATTR_WEAK bool hcd_dcache_clean(const void* addr, uint32_t data_size) {
@@ -126,6 +130,7 @@ typedef struct {
uint8_t i_manufacturer;
uint8_t i_product;
uint8_t i_serial;
+ uint8_t bNumConfigurations;
// Configuration Descriptor
// uint8_t interface_count; // bNumInterfaces alias
@@ -230,7 +235,6 @@ static usbh_class_driver_t const usbh_class_drivers[] = {
};
enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) };
-enum { CONFIG_NUM = 1 }; // default to use configuration 1
// Additional class drivers implemented by application
tu_static usbh_class_driver_t const * _app_driver = NULL;
@@ -1372,8 +1376,8 @@ enum {
ENUM_CONFIG_DRIVER
};
-static bool enum_request_set_addr(void);
-static bool _parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg);
+static bool enum_request_set_addr(tusb_desc_device_t const* desc_device);
+static bool enum_parse_configuration_desc (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg);
static void enum_full_complete(void);
// process device enumeration
@@ -1489,7 +1493,7 @@ static void process_enumeration(tuh_xfer_t* xfer) {
#endif
case ENUM_SET_ADDR:
- enum_request_set_addr();
+ enum_request_set_addr((tusb_desc_device_t*) _usbh_epbuf.ctrl);
break;
case ENUM_GET_DEVICE_DESC: {
@@ -1523,6 +1527,9 @@ static void process_enumeration(tuh_xfer_t* xfer) {
dev->i_manufacturer = desc_device->iManufacturer;
dev->i_product = desc_device->iProduct;
dev->i_serial = desc_device->iSerialNumber;
+ dev->bNumConfigurations = desc_device->bNumConfigurations;
+
+ 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);
@@ -1574,8 +1581,8 @@ static void process_enumeration(tuh_xfer_t* xfer) {
case ENUM_GET_9BYTE_CONFIG_DESC: {
// Get 9-byte for total length
- uint8_t const config_idx = CONFIG_NUM - 1;
- TU_LOG_USBH("Get Configuration[0] Descriptor (9 bytes)\r\n");
+ uint8_t const config_idx = 0;
+ TU_LOG_USBH("Get Configuration[%u] Descriptor (9 bytes)\r\n", config_idx);
TU_ASSERT(tuh_descriptor_get_configuration(daddr, config_idx, _usbh_epbuf.ctrl, 9,
process_enumeration, ENUM_GET_FULL_CONFIG_DESC),);
break;
@@ -1585,25 +1592,32 @@ static void process_enumeration(tuh_xfer_t* xfer) {
uint8_t const* desc_config = _usbh_epbuf.ctrl;
// Use offsetof to avoid pointer to the odd/misaligned address
- uint16_t const total_len = tu_le16toh(
- tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)));
+ uint16_t const total_len = tu_le16toh(tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)));
// TODO not enough buffer to hold configuration descriptor
TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE,);
// Get full configuration descriptor
- uint8_t const config_idx = CONFIG_NUM - 1;
- TU_LOG_USBH("Get Configuration[0] Descriptor\r\n");
+ uint8_t const config_idx = (uint8_t) tu_le16toh(xfer->setup->wIndex);
+ TU_LOG_USBH("Get Configuration[%u] Descriptor\r\n", config_idx);
TU_ASSERT(tuh_descriptor_get_configuration(daddr, config_idx, _usbh_epbuf.ctrl, total_len,
process_enumeration, ENUM_SET_CONFIG),);
break;
}
- case ENUM_SET_CONFIG:
- // tuh_desc_configuration_cb(daddr, CONFIG_NUM-1, (const tusb_desc_configuration_t*) _usbh_epbuf.ctrl);
-
- TU_ASSERT(tuh_configuration_set(daddr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER),);
+ case ENUM_SET_CONFIG: {
+ uint8_t config_idx = (uint8_t) tu_le16toh(xfer->setup->wIndex);
+ if (tuh_enum_descriptor_configuration_cb(daddr, config_idx, (const tusb_desc_configuration_t*) _usbh_epbuf.ctrl)) {
+ TU_ASSERT(tuh_configuration_set(daddr, config_idx+1, process_enumeration, ENUM_CONFIG_DRIVER),);
+ } else {
+ config_idx++;
+ TU_ASSERT(config_idx < dev->bNumConfigurations,);
+ TU_LOG_USBH("Get Configuration[%u] Descriptor (9 bytes)\r\n", config_idx);
+ TU_ASSERT(tuh_descriptor_get_configuration(daddr, config_idx, _usbh_epbuf.ctrl, 9,
+ process_enumeration, ENUM_GET_FULL_CONFIG_DESC),);
+ }
break;
+ }
case ENUM_CONFIG_DRIVER: {
TU_LOG_USBH("Device configured\r\n");
@@ -1613,7 +1627,7 @@ static void process_enumeration(tuh_xfer_t* xfer) {
// Parse configuration & set up drivers
// driver_open() must not make any usb transfer
- TU_ASSERT(_parse_configuration_descriptor(daddr, (tusb_desc_configuration_t*) _usbh_epbuf.ctrl),);
+ TU_ASSERT(enum_parse_configuration_desc(daddr, (tusb_desc_configuration_t*) _usbh_epbuf.ctrl),);
// Start the Set Configuration process for interfaces (itf = TUSB_INDEX_INVALID_8)
// Since driver can perform control transfer within its set_config, this is done asynchronously.
@@ -1624,14 +1638,11 @@ static void process_enumeration(tuh_xfer_t* xfer) {
}
default:
- // stop enumeration if unknown state
- enum_full_complete();
+ enum_full_complete(); // stop enumeration if unknown state
break;
}
}
-
-
static bool enum_new_device(hcd_event_t* event) {
_dev0.rhport = event->rhport;
_dev0.hub_addr = event->connection.hub_addr;
@@ -1701,9 +1712,7 @@ static uint8_t get_new_address(bool is_hub) {
return 0; // invalid address
}
-static bool enum_request_set_addr(void) {
- tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_epbuf.ctrl;
-
+static bool enum_request_set_addr(tusb_desc_device_t const* desc_device) {
// Get new address
uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB);
TU_ASSERT(new_addr != 0);
@@ -1741,7 +1750,7 @@ static bool enum_request_set_addr(void) {
return true;
}
-static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) {
+static bool enum_parse_configuration_desc(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) {
usbh_device_t* dev = get_device(dev_addr);
uint16_t const total_len = tu_le16toh(desc_cfg->wTotalLength);
uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + total_len;
@@ -1858,7 +1867,9 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) {
TU_LOG_USBH("HUB address = %u is mounted\r\n", dev_addr);
}else {
// Invoke callback if available
- if (tuh_mount_cb) tuh_mount_cb(dev_addr);
+ if (tuh_mount_cb) {
+ tuh_mount_cb(dev_addr);
+ }
}
}
}
diff --git a/src/host/usbh.h b/src/host/usbh.h
index 36bb7c9b2..d95bb9b57 100644
--- a/src/host/usbh.h
+++ b/src/host/usbh.h
@@ -100,10 +100,13 @@ typedef union {
//--------------------------------------------------------------------+
// Invoked when enumeration get device descriptor
-// TU_ATTR_WEAK void tuh_descriptor_device_cb(uint8_t daddr, const tusb_desc_device_t *desc_device);
+// Device is not ready to communicate yet, application can copy the descriptor if needed
+void tuh_enum_descriptor_device_cb(uint8_t daddr, const tusb_desc_device_t *desc_device);
// Invoked when enumeration get configuration descriptor
-// TU_ATTR_WEAK void tuh_desc_configuration_cb(uint8_t daddr, uint8_t cfg_index, const tusb_desc_configuration_t *desc_config);
+// For multi-configuration device return false to skip, true to proceed with this configuration (may not be implemented yet)
+// Device is not ready to communicate yet, application can copy the descriptor if needed
+bool tuh_enum_descriptor_configuration_cb(uint8_t daddr, uint8_t cfg_index, const tusb_desc_configuration_t *desc_config);
// Invoked when a device is mounted (configured)
TU_ATTR_WEAK void tuh_mount_cb (uint8_t daddr);