-
Notifications
You must be signed in to change notification settings - Fork 7.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feature/usb_host_multi_configuration' into 'master'
USB Host multiconfiguration support pt1 (getting the configuration descriptor) Closes IDFGH-11532 and IDF-8732 See merge request espressif/esp-idf!26760
- Loading branch information
Showing
6 changed files
with
437 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <stdint.h> | ||
|
||
typedef struct { | ||
SemaphoreHandle_t dev_open_smp; | ||
uint8_t bConfigurationValue; | ||
} multiconf_client_test_param_t; | ||
|
||
/** | ||
* @brief Multiconfiguration client task | ||
*/ | ||
void multiconf_client_async_task(void *arg); | ||
|
||
/** | ||
* @brief Get configuration descriptor | ||
*/ | ||
void multiconf_client_get_conf_desc(void); |
179 changes: 179 additions & 0 deletions
179
components/usb/test_apps/usb_host/main/multiconf_client_async.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <stdint.h> | ||
#include <string.h> | ||
#include "freertos/FreeRTOS.h" | ||
#include "freertos/task.h" | ||
#include "freertos/semphr.h" | ||
#include "esp_err.h" | ||
#include "esp_log.h" | ||
#include "test_usb_common.h" | ||
#include "multiconf_client.h" | ||
#include "mock_msc.h" | ||
#include "dev_msc.h" | ||
#include "usb/usb_host.h" | ||
#include "unity.h" | ||
|
||
/* | ||
Implementation of a multi-configuration client used for USB Host Tests. | ||
- The multi-configuration client will: | ||
- Register itself as a client | ||
- Receive USB_HOST_CLIENT_EVENT_NEW_DEV event message, and open the device | ||
- Get active configuration descriptor | ||
- Start handling client events | ||
- Wait for a request from main task to read a configuration descriptor | ||
- Compare the obtained configuration descriptor with the active configuration descriptor | ||
- Free the memory used for storing the configuration descriptor | ||
- Close the device | ||
- Deregister control client | ||
*/ | ||
|
||
const char *MULTICONF_CLIENT_TAG = "Multi config Client"; | ||
|
||
#define CLIENT_NUM_EVENT_MSG 5 | ||
|
||
typedef enum { | ||
TEST_STAGE_WAIT_CONN, | ||
TEST_STAGE_DEV_OPEN, | ||
TEST_STAGE_WAIT, | ||
TEST_STAGE_CHECK_CONFIG_DESC, | ||
TEST_STAGE_DEV_CLOSE, | ||
} test_stage_t; | ||
|
||
typedef struct { | ||
// Test parameters | ||
multiconf_client_test_param_t test_param; | ||
// device info | ||
uint8_t dev_addr; | ||
usb_speed_t dev_speed; | ||
// Client variables | ||
usb_host_client_handle_t client_hdl; | ||
usb_device_handle_t dev_hdl; | ||
// Test state | ||
test_stage_t cur_stage; | ||
test_stage_t next_stage; | ||
const usb_config_desc_t *config_desc_cached; | ||
} multiconf_client_obj_t; | ||
|
||
static multiconf_client_obj_t *s_multiconf_obj; | ||
|
||
static void multiconf_client_event_cb(const usb_host_client_event_msg_t *event_msg, void *arg) | ||
{ | ||
multiconf_client_obj_t *multiconf_obj = (multiconf_client_obj_t *)arg; | ||
switch (event_msg->event) { | ||
case USB_HOST_CLIENT_EVENT_NEW_DEV: | ||
TEST_ASSERT_EQUAL(TEST_STAGE_WAIT_CONN, multiconf_obj->cur_stage); | ||
multiconf_obj->next_stage = TEST_STAGE_DEV_OPEN; | ||
multiconf_obj->dev_addr = event_msg->new_dev.address; | ||
break; | ||
default: | ||
abort(); // Should never occur in this test | ||
break; | ||
} | ||
} | ||
|
||
void multiconf_client_async_task(void *arg) | ||
{ | ||
multiconf_client_obj_t multiconf_obj; | ||
// Initialize test params | ||
memcpy(&multiconf_obj.test_param, arg, sizeof(multiconf_client_test_param_t)); | ||
// Initialize client variables | ||
multiconf_obj.client_hdl = NULL; | ||
multiconf_obj.dev_hdl = NULL; | ||
// Initialize test stage | ||
multiconf_obj.cur_stage = TEST_STAGE_WAIT_CONN; | ||
multiconf_obj.next_stage = TEST_STAGE_WAIT_CONN; | ||
multiconf_obj.dev_addr = 0; | ||
|
||
// Register client | ||
usb_host_client_config_t client_config = { | ||
.is_synchronous = false, | ||
.max_num_event_msg = CLIENT_NUM_EVENT_MSG, | ||
.async = { | ||
.client_event_callback = multiconf_client_event_cb, | ||
.callback_arg = (void *) &multiconf_obj, | ||
}, | ||
}; | ||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_register(&client_config, &multiconf_obj.client_hdl)); | ||
s_multiconf_obj = &multiconf_obj; | ||
|
||
// Wait to be started by main thread | ||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); | ||
ESP_LOGD(MULTICONF_CLIENT_TAG, "Starting"); | ||
|
||
bool exit_loop = false; | ||
bool skip_event_handling = false; | ||
while (!exit_loop) { | ||
if (!skip_event_handling) { | ||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_handle_events(multiconf_obj.client_hdl, portMAX_DELAY)); | ||
} | ||
skip_event_handling = false; | ||
if (multiconf_obj.cur_stage == multiconf_obj.next_stage) { | ||
continue; | ||
} | ||
multiconf_obj.cur_stage = multiconf_obj.next_stage; | ||
|
||
switch (multiconf_obj.next_stage) { | ||
case TEST_STAGE_DEV_OPEN: { | ||
ESP_LOGD(MULTICONF_CLIENT_TAG, "Open"); | ||
// Open the device | ||
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_host_device_open(multiconf_obj.client_hdl, multiconf_obj.dev_addr, &multiconf_obj.dev_hdl), "Failed to open the device"); | ||
|
||
// Get device info to get it's speed | ||
usb_device_info_t dev_info; | ||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_info(multiconf_obj.dev_hdl, &dev_info)); | ||
multiconf_obj.dev_speed = dev_info.speed; | ||
|
||
multiconf_obj.next_stage = TEST_STAGE_WAIT; | ||
skip_event_handling = true; | ||
break; | ||
} | ||
case TEST_STAGE_WAIT: { | ||
// Give semaphore signalizing that the device has been opened | ||
xSemaphoreGive(multiconf_obj.test_param.dev_open_smp); | ||
break; | ||
} | ||
case TEST_STAGE_CHECK_CONFIG_DESC: { | ||
ESP_LOGD(MULTICONF_CLIENT_TAG, "Check config descriptors"); | ||
// Get mocked config descriptor | ||
const usb_config_desc_t *config_desc_ref = dev_msc_get_config_desc(multiconf_obj.dev_speed); | ||
TEST_ASSERT_EQUAL_MESSAGE(multiconf_obj.config_desc_cached->wTotalLength, config_desc_ref->wTotalLength, "Incorrect length of CFG descriptor"); | ||
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(config_desc_ref, multiconf_obj.config_desc_cached, sizeof(usb_config_desc_t), "Configuration descriptors do not match"); | ||
|
||
// Free the memory used to store the config descriptor | ||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_config_desc_free(multiconf_obj.config_desc_cached)); | ||
multiconf_obj.next_stage = TEST_STAGE_DEV_CLOSE; | ||
skip_event_handling = true; | ||
break; | ||
} | ||
case TEST_STAGE_DEV_CLOSE: { | ||
ESP_LOGD(MULTICONF_CLIENT_TAG, "Close"); | ||
vTaskDelay(10); // Give USB Host Lib some time to process all transfers | ||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_device_close(multiconf_obj.client_hdl, multiconf_obj.dev_hdl)); | ||
exit_loop = true; | ||
break; | ||
} | ||
default: | ||
abort(); | ||
break; | ||
} | ||
} | ||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_client_deregister(multiconf_obj.client_hdl)); | ||
ESP_LOGD(MULTICONF_CLIENT_TAG, "Done"); | ||
vTaskDelete(NULL); | ||
} | ||
|
||
void multiconf_client_get_conf_desc(void) | ||
{ | ||
// Get configuration descriptor, ctrl transfer is sent to the device to get the config descriptor | ||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_get_config_desc(s_multiconf_obj->client_hdl, s_multiconf_obj->dev_hdl, s_multiconf_obj->test_param.bConfigurationValue, &s_multiconf_obj->config_desc_cached)); | ||
|
||
// Go to next stage | ||
s_multiconf_obj->next_stage = TEST_STAGE_CHECK_CONFIG_DESC; | ||
ESP_ERROR_CHECK(usb_host_client_unblock(s_multiconf_obj->client_hdl)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.