Skip to content

Commit

Permalink
feat(esp_tinyusb): Added qualifier descritpor handling, implmented ot…
Browse files Browse the repository at this point in the history
…her speed and qualifier callbacks
  • Loading branch information
roma-jam committed Feb 13, 2024
1 parent 59337ef commit 2e21557
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 24 deletions.
104 changes: 93 additions & 11 deletions device/esp_tinyusb/descriptors_control.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,53 @@ uint8_t const *tud_descriptor_configuration_cb(uint8_t index)
assert(s_desc_cfg->cfg);

#if (TUD_OPT_HIGH_SPEED)
// HINT: cfg and hs_cfg are the same, no need to assert(hs_cfg)
assert(s_desc_cfg->fs_cfg);
// Return configuration descriptor based on Host speed
return (tud_speed_get() == TUSB_SPEED_HIGH)
? s_desc_cfg->cfg
return (TUSB_SPEED_HIGH == tud_speed_get())
? s_desc_cfg->hs_cfg
: s_desc_cfg->fs_cfg;
#else
return s_desc_cfg->cfg;
#endif //
#endif // TUD_OPT_HIGH_SPEED
}

#if (TUD_OPT_HIGH_SPEED)
/**
* @brief Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
* Descriptor contents must exist long enough for transfer to complete
* If not highspeed capable stall this request
*/
uint8_t const *tud_descriptor_device_qualifier_cb(void)
{
assert(s_desc_cfg);
assert(s_desc_cfg->qualifier);
return (uint8_t const *)s_desc_cfg->qualifier;
}


/**
* @brief Invoked when received GET OTHER SPEED CONFIGURATION DESCRIPTOR request
* Descriptor contents must exist long enough for transfer to complete
* Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa
*/
uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index)
{
assert(s_desc_cfg);
assert(s_desc_cfg->other_speed);

const uint8_t *other_speed = (TUSB_SPEED_HIGH == tud_speed_get())
? s_desc_cfg->fs_cfg
: s_desc_cfg->hs_cfg;

memcpy(s_desc_cfg->other_speed,
other_speed,
((tusb_desc_configuration_t *)other_speed)->wTotalLength);

((tusb_desc_configuration_t *)s_desc_cfg->other_speed)->bDescriptorType = TUSB_DESC_OTHER_SPEED_CONFIG;
return s_desc_cfg->other_speed;
}
#endif // TUD_OPT_HIGH_SPEED

/**
* @brief Invoked when received GET STRING DESCRIPTOR request
Expand Down Expand Up @@ -106,8 +144,9 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid)
// =============================================================================
esp_err_t tinyusb_set_descriptors(const tinyusb_config_t *config)
{
esp_err_t ret = ESP_FAIL;
assert(config);
const char **string_descriptor;
const char **pstr_desc;
// Create descriptor struct
s_desc_cfg = calloc(1, sizeof(tinyusb_descriptor_config_t));
assert(s_desc_cfg);
Expand All @@ -126,7 +165,7 @@ esp_err_t tinyusb_set_descriptors(const tinyusb_config_t *config)
if (NULL == config->hs_cfg_desc) {
// Default configuration descriptor is provided only for CDC, MSC and NCM classes
#if (CFG_TUD_HID > 0 || CFG_TUD_MIDI > 0 || CFG_TUD_CUSTOM_CLASS > 0 || CFG_TUD_ECM_RNDIS > 0 || CFG_TUD_DFU > 0 || CFG_TUD_DFU_RUNTIME > 0 || CFG_TUD_BTH > 0)
ESP_RETURN_ON_FALSE(config->hs_cfg_desc, ESP_ERR_INVALID_ARG, TAG, "Configuration descriptor must be provided for this device");
ESP_GOTO_ON_FALSE(config->hs_cfg_desc, ESP_ERR_INVALID_ARG, fail, TAG, "Configuration descriptor must be provided for this device");
#else
ESP_LOGW(TAG, "The device's HS configuration descriptor is not provided by user, using default.");
#endif
Expand All @@ -139,19 +178,50 @@ esp_err_t tinyusb_set_descriptors(const tinyusb_config_t *config)
if (NULL == config->fs_cfg_desc) {
// Default configuration descriptor is provided only for CDC, MSC and NCM classes
#if (CFG_TUD_HID > 0 || CFG_TUD_MIDI > 0 || CFG_TUD_CUSTOM_CLASS > 0 || CFG_TUD_ECM_RNDIS > 0 || CFG_TUD_DFU > 0 || CFG_TUD_DFU_RUNTIME > 0 || CFG_TUD_BTH > 0)
ESP_RETURN_ON_FALSE(config->fs_cfg_desc, ESP_ERR_INVALID_ARG, TAG, "Configuration descriptor must be provided for this device");
ESP_GOTO_ON_FALSE(config->fs_cfg_desc, ESP_ERR_INVALID_ARG, fail, TAG, "Configuration descriptor must be provided for this device");
#else
ESP_LOGW(TAG, "The device's FS configuration descriptor is not provided by user, using default.");
#endif
}
s_desc_cfg->fs_cfg = config->fs_cfg_desc
? config->fs_cfg_desc
: descriptor_fs_cfg_kconfig;

// HS and FS cfg desc should be equal length
ESP_GOTO_ON_FALSE(((tusb_desc_configuration_t *)s_desc_cfg->hs_cfg)->wTotalLength ==
((tusb_desc_configuration_t *)s_desc_cfg->fs_cfg)->wTotalLength,
ESP_ERR_INVALID_ARG, fail, TAG, "HS and FS Configuration descriptors must be same length");

// Qualifier Descriptor
if (NULL == config->qualifier_desc) {
ESP_LOGW(TAG, "Qualifier descriptor must be provided for HighSpeed device. Create one with current Device Descriptor.");
s_desc_cfg->qualifier = calloc(1, sizeof (tusb_desc_device_qualifier_t));

// Fill up with values from Device descriptor
s_desc_cfg->qualifier->bLength = s_desc_cfg->dev->bLength;
s_desc_cfg->qualifier->bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER;
s_desc_cfg->qualifier->bcdUSB = s_desc_cfg->dev->bcdUSB;
s_desc_cfg->qualifier->bDeviceClass = s_desc_cfg->dev->bDeviceClass;
s_desc_cfg->qualifier->bDeviceSubClass = s_desc_cfg->dev->bDeviceSubClass;
s_desc_cfg->qualifier->bDeviceProtocol = s_desc_cfg->dev->bDeviceProtocol;
s_desc_cfg->qualifier->bMaxPacketSize0 = s_desc_cfg->dev->bMaxPacketSize0;
s_desc_cfg->qualifier->bNumConfigurations = s_desc_cfg->dev->bNumConfigurations;
s_desc_cfg->qualifier->bReserved = 0;

s_desc_cfg->qualifier_alloc_internally = true;
} else {
s_desc_cfg->qualifier = config->qualifier_desc;
s_desc_cfg->qualifier_alloc_internally = false;
}

// Other Speed buffer allocate
s_desc_cfg->other_speed = calloc(1, ((tusb_desc_configuration_t *)s_desc_cfg->hs_cfg)->wTotalLength);
ESP_GOTO_ON_FALSE(s_desc_cfg->other_speed, ESP_ERR_NO_MEM, fail, TAG, "Other speed memory allocation error");
#else
if (NULL == config->configuration_descriptor) {
// Default configuration descriptor is provided only for CDC, MSC and NCM classes
#if (CFG_TUD_HID > 0 || CFG_TUD_MIDI > 0 || CFG_TUD_CUSTOM_CLASS > 0 || CFG_TUD_ECM_RNDIS > 0 || CFG_TUD_DFU > 0 || CFG_TUD_DFU_RUNTIME > 0 || CFG_TUD_BTH > 0)
ESP_RETURN_ON_FALSE(config->configuration_descriptor, ESP_ERR_INVALID_ARG, TAG, "Configuration descriptor must be provided for this device");
ESP_GOTO_ON_FALSE(config->configuration_descriptor, ESP_ERR_INVALID_ARG, fail, TAG, "Configuration descriptor must be provided for this device");
#else
ESP_LOGW(TAG, "The device's configuration descriptor is not provided by user, using default.");
#endif
Expand All @@ -163,18 +233,18 @@ esp_err_t tinyusb_set_descriptors(const tinyusb_config_t *config)

// Select String Descriptors and count them
if (config->string_descriptor) {
string_descriptor = config->string_descriptor;
pstr_desc = config->string_descriptor;
s_desc_cfg->str_count = (config->string_descriptor_count != 0)
? config->string_descriptor_count
: 8; // '8' is for backward compatibility with esp_tinyusb v1.0.0. Do NOT remove!
} else {
string_descriptor = descriptor_str_kconfig;
pstr_desc = descriptor_str_kconfig;
while (descriptor_str_kconfig[++s_desc_cfg->str_count] != NULL);
ESP_LOGW(TAG, "The device's string descriptor is not provided by user, using default.");
}

assert(s_desc_cfg->str_count <= USB_STRING_DESCRIPTOR_ARRAY_SIZE);
memcpy(s_desc_cfg->str, string_descriptor, s_desc_cfg->str_count * sizeof(string_descriptor[0]));
ESP_GOTO_ON_FALSE(s_desc_cfg->str_count <= USB_STRING_DESCRIPTOR_ARRAY_SIZE, ESP_ERR_NOT_SUPPORTED, fail, TAG, "String descriptors exceed limit");
memcpy(s_desc_cfg->str, pstr_desc, s_desc_cfg->str_count * sizeof(pstr_desc[0]));

ESP_LOGI(TAG, "\n"
"┌─────────────────────────────────┐\n"
Expand Down Expand Up @@ -207,7 +277,12 @@ esp_err_t tinyusb_set_descriptors(const tinyusb_config_t *config)
s_desc_cfg->dev->idVendor, s_desc_cfg->dev->idProduct, s_desc_cfg->dev->bcdDevice,
s_desc_cfg->dev->iManufacturer, s_desc_cfg->dev->iProduct, s_desc_cfg->dev->iSerialNumber,
s_desc_cfg->dev->bNumConfigurations);

return ESP_OK;

fail:
free(s_desc_cfg);
return ret;
}

void tinyusb_set_str_descriptor(const char *str, int str_idx)
Expand All @@ -220,5 +295,12 @@ void tinyusb_set_str_descriptor(const char *str, int str_idx)
void tinyusb_free_desctiptors(void)
{
assert(s_desc_cfg);
#if (TUD_OPT_HIGH_SPEED)
assert(s_desc_cfg->other_speed);
free(s_desc_cfg->other_speed);
if (s_desc_cfg->qualifier_alloc_internally) {
free(s_desc_cfg->qualifier);
}
#endif // TUD_OPT_HIGH_SPEED
free(s_desc_cfg);
}
4 changes: 3 additions & 1 deletion device/esp_tinyusb/include/tinyusb.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ typedef struct {
union {
struct {
const uint8_t *configuration_descriptor; /*!< Pointer to a configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */
const uint8_t *reserved; /*!< For backward compatibility */
const uint8_t *reserved1; /*!< For backward compatibility */
const uint8_t *reserved2; /*!< For backward compatibility */
};
#if (TUD_OPT_HIGH_SPEED)
struct {
const uint8_t *hs_cfg_desc; /*!< Pointer to a HS configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */
const uint8_t *fs_cfg_desc; /*!< Pointer to a FS configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */
tusb_desc_device_qualifier_t *qualifier_desc; /*!< Pointer to a qualifier descriptor */
};
#endif // TUD_OPT_HIGH_SPEED
};
Expand Down
10 changes: 8 additions & 2 deletions device/esp_tinyusb/include_private/descriptors_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ extern "C" {
*/
typedef struct {
const tusb_desc_device_t *dev; /*!< Pointer to device descriptor */
const uint8_t *cfg; /*!< Pointer to HS configuration descriptor */
union {
const uint8_t *cfg; /*!< Pointer to FS configuration descriptor when device one-speed only */
const uint8_t *hs_cfg; /*!< Pointer to HS configuration descriptor when device one-speed only */
};
#if (TUD_OPT_HIGH_SPEED)
const uint8_t *fs_cfg; /*!< Pointer to FS configuration descriptor */
const uint8_t *fs_cfg; /*!< Pointer to FS configuration descriptor when device support HS */
tusb_desc_device_qualifier_t *qualifier; /*!< Pointer to Qualifier descriptor */
bool qualifier_alloc_internally; /*!< Qualifier descriptor was allocated internally */
uint8_t *other_speed; /*!< Pointer for other speed configuration descriptor */
#endif // TUD_OPT_HIGH_SPEED
const char *str[USB_STRING_DESCRIPTOR_ARRAY_SIZE]; /*!< Pointer to array of UTF-8 strings */
int str_count; /*!< Number of descriptors in str */
Expand Down
2 changes: 1 addition & 1 deletion device/esp_tinyusb/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
idf_component_register(SRCS "test_esp_tinyusb.c"
idf_component_register(SRCS "test_esp_tinyusb.c" "test_bvalid_sig.c"
INCLUDE_DIRS "."
REQUIRES unity esp_tinyusb
)
9 changes: 0 additions & 9 deletions device/esp_tinyusb/test/test_bvalid_sig.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,7 @@ static uint8_t const test_configuration_descriptor[] = {
TUD_CONFIG_DESCRIPTOR(1, 0, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_SELF_POWERED | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
};

<<<<<<< HEAD
static const tusb_desc_device_t test_device_descriptor = {
=======
static tusb_desc_device_t test_device_descriptor = {
>>>>>>> 288fb6e (ref(esp_tinyusb): Update CHANGELOG.md)
.bLength = sizeof(test_device_descriptor),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0200,
Expand Down Expand Up @@ -92,13 +88,8 @@ TEST_CASE("bvalid_signal", "[esp_tinyusb]")
}

// Verify
<<<<<<< HEAD
TEST_ASSERT_EQUAL(dev_umounted, dev_mounted);
TEST_ASSERT_EQUAL(DEVICE_DETACH_TEST_ROUNDS, dev_mounted);
=======
TEST_ASSERT_EQUAL(dev_mounted, dev_umounted);
TEST_ASSERT_EQUAL(dev_mounted, DEVICE_DETACH_TEST_ROUNDS);
>>>>>>> 288fb6e (ref(esp_tinyusb): Update CHANGELOG.md)

tinyusb_driver_uninstall();
}
Expand Down

0 comments on commit 2e21557

Please sign in to comment.