feat(usb/host): Modifiy usb_host_lib example

This commit is contained in:
Peter Marcisovsky
2024-10-18 10:46:53 +02:00
committed by Roman Leonov
parent e62df280e0
commit 8046784118
5 changed files with 210 additions and 69 deletions
@@ -1,4 +1,4 @@
idf_component_register(SRCS "usb_host_lib_main.c" "class_driver.c"
INCLUDE_DIRS "."
PRIV_REQUIRES usb
PRIV_REQUIRES usb driver
)
@@ -0,0 +1,12 @@
menu "Example Configuration"
orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps"
config APP_QUIT_PIN
int "APP Quit button GPIO pin"
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
default 0
help
GPIO pin number to be used as APP_QUIT button.
endmenu
@@ -12,13 +12,16 @@
#define CLIENT_NUM_EVENT_MSG 5
#define ACTION_OPEN_DEV 0x01
#define ACTION_GET_DEV_INFO 0x02
#define ACTION_GET_DEV_DESC 0x04
#define ACTION_GET_CONFIG_DESC 0x08
#define ACTION_GET_STR_DESC 0x10
#define ACTION_CLOSE_DEV 0x20
#define ACTION_EXIT 0x40
typedef enum {
ACTION_OPEN_DEV = 0x01,
ACTION_GET_DEV_INFO = 0x02,
ACTION_GET_DEV_DESC = 0x04,
ACTION_GET_CONFIG_DESC = 0x08,
ACTION_GET_STR_DESC = 0x10,
ACTION_CLOSE_DEV = 0x20,
ACTION_EXIT = 0x40,
ACTION_RECONNECT = 0x80,
} action_t;
typedef struct {
usb_host_client_handle_t client_hdl;
@@ -28,6 +31,7 @@ typedef struct {
} class_driver_t;
static const char *TAG = "CLASS";
static class_driver_t *s_driver_obj;
static void client_event_cb(const usb_host_client_event_msg_t *event_msg, void *arg)
{
@@ -121,24 +125,20 @@ static void action_get_str_desc(class_driver_t *driver_obj)
driver_obj->actions &= ~ACTION_GET_STR_DESC;
}
static void aciton_close_dev(class_driver_t *driver_obj)
static void action_close_dev(class_driver_t *driver_obj)
{
ESP_ERROR_CHECK(usb_host_device_close(driver_obj->client_hdl, driver_obj->dev_hdl));
driver_obj->dev_hdl = NULL;
driver_obj->dev_addr = 0;
//We need to exit the event handler loop
//We need to connect a new device
driver_obj->actions &= ~ACTION_CLOSE_DEV;
driver_obj->actions |= ACTION_EXIT;
driver_obj->actions |= ACTION_RECONNECT;
}
void class_driver_task(void *arg)
{
SemaphoreHandle_t signaling_sem = (SemaphoreHandle_t)arg;
class_driver_t driver_obj = {0};
//Wait until daemon task has installed USB Host Library
xSemaphoreTake(signaling_sem, portMAX_DELAY);
ESP_LOGI(TAG, "Registering Client");
usb_host_client_config_t client_config = {
.is_synchronous = false, //Synchronous clients currently not supported. Set this to false
@@ -149,6 +149,7 @@ void class_driver_task(void *arg)
},
};
ESP_ERROR_CHECK(usb_host_client_register(&client_config, &driver_obj.client_hdl));
s_driver_obj = &driver_obj;
while (1) {
if (driver_obj.actions == 0) {
@@ -170,18 +171,29 @@ void class_driver_task(void *arg)
action_get_str_desc(&driver_obj);
}
if (driver_obj.actions & ACTION_CLOSE_DEV) {
aciton_close_dev(&driver_obj);
action_close_dev(&driver_obj);
}
if (driver_obj.actions & ACTION_EXIT) {
break;
}
if (driver_obj.actions & ACTION_RECONNECT) {
driver_obj.actions = 0;
}
}
}
ESP_LOGI(TAG, "Deregistering Client");
ESP_ERROR_CHECK(usb_host_client_deregister(driver_obj.client_hdl));
//Wait to be deleted
xSemaphoreGive(signaling_sem);
vTaskSuspend(NULL);
}
void class_driver_client_deregister(void)
{
if (s_driver_obj->dev_hdl != NULL) {
s_driver_obj->actions = ACTION_CLOSE_DEV;
}
s_driver_obj->actions |= ACTION_EXIT;
// Unblock, exit the loop and proceed to deregister client
ESP_ERROR_CHECK(usb_host_client_unblock(s_driver_obj->client_hdl));
}
@@ -1,26 +1,78 @@
/*
<<<<<<< HEAD
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
=======
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
>>>>>>> 546b76befa (feat(usb/host): Modifiy usb_host_lib example)
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "freertos/event_groups.h"
#include "esp_log.h"
#include "esp_intr_alloc.h"
#include "usb/usb_host.h"
#include "driver/gpio.h"
#define DAEMON_TASK_PRIORITY 2
#define HOST_LIB_TASK_PRIORITY 2
#define CLASS_TASK_PRIORITY 3
#define APP_QUIT_PIN CONFIG_APP_QUIT_PIN
#ifdef CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK
#define ENABLE_ENUM_FILTER_CALLBACK
#endif // CONFIG_USB_HOST_ENABLE_ENUM_FILTER_CALLBACK
extern void class_driver_task(void *arg);
extern void class_driver_client_deregister(void);
static const char *TAG = "DAEMON";
static const char *TAG = "USB host lib";
QueueHandle_t app_event_queue = NULL;
/**
* @brief APP event group
*
* APP_EVENT - General event, which is APP_QUIT_PIN press event in this example.
*/
typedef enum {
APP_EVENT = 0,
} app_event_group_t;
/**
* @brief APP event queue
*
* This event is used for delivering events from callback to a task.
*/
typedef struct {
app_event_group_t event_group;
} app_event_queue_t;
/**
* @brief BOOT button pressed callback
*
* Signal application to exit the Host lib task
*
* @param[in] arg Unused
*/
static void gpio_cb(void *arg)
{
const app_event_queue_t evt_queue = {
.event_group = APP_EVENT,
};
BaseType_t xTaskWoken = pdFALSE;
if (app_event_queue) {
xQueueSendFromISR(app_event_queue, &evt_queue, &xTaskWoken);
}
if (xTaskWoken == pdTRUE) {
portYIELD_FROM_ISR();
}
}
/**
* @brief Set configuration callback
@@ -51,10 +103,13 @@ static bool set_config_cb(const usb_device_desc_t *dev_desc, uint8_t *bConfigura
}
#endif // ENABLE_ENUM_FILTER_CALLBACK
static void host_lib_daemon_task(void *arg)
/**
* @brief Start USB Host install and handle common USB host library events while app pin not low
*
* @param[in] arg Not used
*/
static void usb_host_lib_task(void *arg)
{
SemaphoreHandle_t signaling_sem = (SemaphoreHandle_t)arg;
ESP_LOGI(TAG, "Installing USB Host Library");
usb_host_config_t host_config = {
.skip_phy_setup = false,
@@ -65,9 +120,8 @@ static void host_lib_daemon_task(void *arg)
};
ESP_ERROR_CHECK(usb_host_install(&host_config));
//Signal to the class driver task that the host library is installed
xSemaphoreGive(signaling_sem);
vTaskDelay(10); //Short delay to let client task spin up
//Signalize the app_main, the USB host library has been installed
xTaskNotifyGive(arg);
bool has_clients = true;
bool has_devices = true;
@@ -75,52 +129,101 @@ static void host_lib_daemon_task(void *arg)
uint32_t event_flags;
ESP_ERROR_CHECK(usb_host_lib_handle_events(portMAX_DELAY, &event_flags));
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
ESP_LOGI(TAG, "No more clients");
has_clients = false;
if (ESP_OK == usb_host_device_free_all()) {
ESP_LOGI(TAG, "All devices marked as free");
} else {
ESP_LOGI(TAG, "Wait for the ALL FREE EVENT");
}
}
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
ESP_LOGI(TAG, "No more devices");
has_devices = false;
}
}
ESP_LOGI(TAG, "No more clients and devices");
//Uninstall the USB Host Library
ESP_ERROR_CHECK(usb_host_uninstall());
//Wait to be deleted
xSemaphoreGive(signaling_sem);
vTaskSuspend(NULL);
}
void app_main(void)
{
SemaphoreHandle_t signaling_sem = xSemaphoreCreateBinary();
ESP_LOGI(TAG, "USB host library example");
TaskHandle_t daemon_task_hdl;
TaskHandle_t class_driver_task_hdl;
//Create daemon task
xTaskCreatePinnedToCore(host_lib_daemon_task,
"daemon",
4096,
(void *)signaling_sem,
DAEMON_TASK_PRIORITY,
&daemon_task_hdl,
0);
//Create the class driver task
xTaskCreatePinnedToCore(class_driver_task,
"class",
4096,
(void *)signaling_sem,
CLASS_TASK_PRIORITY,
&class_driver_task_hdl,
0);
// Init BOOT button: Pressing the button simulates app request to exit
// It will uninstall the class driver and USB Host Lib
const gpio_config_t input_pin = {
.pin_bit_mask = BIT64(APP_QUIT_PIN),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.intr_type = GPIO_INTR_NEGEDGE,
};
ESP_ERROR_CHECK(gpio_config(&input_pin));
ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1));
ESP_ERROR_CHECK(gpio_isr_handler_add(APP_QUIT_PIN, gpio_cb, NULL));
app_event_queue = xQueueCreate(10, sizeof(app_event_queue_t));
app_event_queue_t evt_queue;
TaskHandle_t host_lib_task_hdl, class_driver_task_hdl;
//Create usb host lib task
BaseType_t task_created;
task_created = xTaskCreatePinnedToCore(usb_host_lib_task,
"usb_host",
4096,
xTaskGetCurrentTaskHandle(),
HOST_LIB_TASK_PRIORITY,
&host_lib_task_hdl,
0);
assert(task_created == pdTRUE);
//Wait unit the USB host library is installed
ulTaskNotifyTake(false, 1000);
//Create class driver task
task_created = xTaskCreatePinnedToCore(class_driver_task,
"class",
4096,
NULL,
CLASS_TASK_PRIORITY,
&class_driver_task_hdl,
0);
assert(task_created == pdTRUE);
vTaskDelay(10); //Add a short delay to let the tasks run
//Wait for the tasks to complete
for (int i = 0; i < 2; i++) {
xSemaphoreTake(signaling_sem, portMAX_DELAY);
while (1) {
if (xQueueReceive(app_event_queue, &evt_queue, portMAX_DELAY)) {
if (APP_EVENT == evt_queue.event_group) {
// User pressed button
usb_host_lib_info_t lib_info;
ESP_ERROR_CHECK(usb_host_lib_info(&lib_info));
if (lib_info.num_devices == 0) {
// End while cycle
break;
} else {
ESP_LOGW(TAG, "To shutdown example, remove all USB devices and press button again.");
// Keep polling
}
}
}
}
//Deregister client
class_driver_client_deregister();
vTaskDelay(10);
//Delete the tasks
vTaskDelete(class_driver_task_hdl);
vTaskDelete(daemon_task_hdl);
vTaskDelete(host_lib_task_hdl);
// Delete interrupt and queue
gpio_isr_handler_remove(APP_QUIT_PIN);
xQueueReset(app_event_queue);
vQueueDelete(app_event_queue);
ESP_LOGI(TAG, "End of the example");
}