forked from espressif/esp-idf
feat(usb/host): Modifiy usb_host_lib example
The example keeps handling connections/disconnections indefinitely. Added kconfig.projbuild for GPIO selection. GPIO0 press does terdown/uninstall.
This commit is contained in:
@@ -5,19 +5,21 @@
|
|||||||
|
|
||||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||||
|
|
||||||
This example demonstrates the basic usage of the [USB Host Library API](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/peripherals/usb_host.html) by implementing a pseudo class driver and a Host Library daemon task. The example does the following:
|
This example demonstrates the basic usage of the [USB Host Library API](https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/peripherals/usb_host.html) by implementing a pseudo class driver and a Host Library task. The example does the following:
|
||||||
|
|
||||||
1. Install Host Library and register a client
|
1. Install Host Library and register a client
|
||||||
2. Waits for a device connection
|
2. Waits for a device connection
|
||||||
3. Prints the device's information (such as device/configuration/string descriptors)
|
3. Prints the device's information (such as device/configuration/string descriptors)
|
||||||
4. Waits for the device to disconnect
|
4. Waits for the device to disconnect
|
||||||
5. Deregister the client and uninstall the Host Library
|
5. Repeats steps 2 to 4 until a user pressess a button, which quits the `app`
|
||||||
|
6. If the button has been pressed, while a USB device is still connected, the user will be prompted to remove the device and push the button again to quit the `app`
|
||||||
|
7. Deregister the client, uninstall the Host Library and quit the `app`
|
||||||
|
|
||||||
The example demonstrates the following aspects of the USB Host Library API:
|
The example demonstrates the following aspects of the USB Host Library API:
|
||||||
|
|
||||||
- How to use the Library API to:
|
- How to use the Library API to:
|
||||||
- Install and uninstall the USB Host Library
|
- Install and uninstall the USB Host Library
|
||||||
- Run the library event handler function a daemon task
|
- Run the library event handler function and usb host library task
|
||||||
- How to handle library events
|
- How to handle library events
|
||||||
- How to use the Client API from a client task to:
|
- How to use the Client API from a client task to:
|
||||||
- Register and deregister a client of the USB Host Library
|
- Register and deregister a client of the USB Host Library
|
||||||
@@ -30,7 +32,7 @@ The example demonstrates the following aspects of the USB Host Library API:
|
|||||||
|
|
||||||
### Hardware Required
|
### Hardware Required
|
||||||
|
|
||||||
An ESP board that supports USB-OTG. The example uses the ESP's internal USB PHY, however the internal USB PHY's pins will need to be connected to a USB port (i.e., a USB breakout board) as follows:
|
An ESP board that has a push button and supports USB-OTG. The example uses the ESP's internal USB PHY, however the internal USB PHY's pins will need to be connected to a USB port (i.e., a USB breakout board) as follows:
|
||||||
|
|
||||||
- GND and 5V signals of the ESP board to the GND and 5V lines of the USB port
|
- GND and 5V signals of the ESP board to the GND and 5V lines of the USB port
|
||||||
- GPIO 19 to D-
|
- GPIO 19 to D-
|
||||||
@@ -43,6 +45,7 @@ idf.py menuconfig
|
|||||||
```
|
```
|
||||||
|
|
||||||
* The USB Host Stack has a maximum supported transfer size for control transfer during device enumeration. This size is specified via the USB_HOST_CONTROL_TRANSFER_MAX_SIZE configuration option and has a default value of 256 bytes. Therefore, if devices with length config/string descriptors are used, users may want to increase the size of this configuration.
|
* The USB Host Stack has a maximum supported transfer size for control transfer during device enumeration. This size is specified via the USB_HOST_CONTROL_TRANSFER_MAX_SIZE configuration option and has a default value of 256 bytes. Therefore, if devices with length config/string descriptors are used, users may want to increase the size of this configuration.
|
||||||
|
* Push button GPIO selection
|
||||||
|
|
||||||
### Build and Flash
|
### Build and Flash
|
||||||
|
|
||||||
@@ -61,14 +64,17 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
|
|||||||
## Example Output
|
## Example Output
|
||||||
|
|
||||||
```
|
```
|
||||||
I (261) cpu_start: Starting scheduler on PRO CPU.
|
I (305) main_task: Started on CPU0
|
||||||
I (267) DAEMON: Installing USB Host Library
|
I (315) main_task: Calling app_main()
|
||||||
I (297) CLASS: Registering Client
|
I (315) USB host lib: USB host library example
|
||||||
I (5067) CLASS: Opening device at address 1
|
I (315) gpio: GPIO[0]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:2
|
||||||
I (5067) CLASS: Getting device information
|
I (325) USB host lib: Installing USB Host Library
|
||||||
I (5067) CLASS: Full speed
|
I (365) CLASS: Registering Client
|
||||||
I (5067) CLASS: bConfigurationValue 1
|
I (745) CLASS: Opening device at address 1
|
||||||
I (5067) CLASS: Getting device descriptor
|
I (745) CLASS: Getting device information
|
||||||
|
I (745) CLASS: Full speed
|
||||||
|
I (745) CLASS: bConfigurationValue 1
|
||||||
|
I (745) CLASS: Getting device descriptor
|
||||||
*** Device descriptor ***
|
*** Device descriptor ***
|
||||||
bLength 18
|
bLength 18
|
||||||
bDescriptorType 1
|
bDescriptorType 1
|
||||||
@@ -84,7 +90,7 @@ iManufacturer 1
|
|||||||
iProduct 2
|
iProduct 2
|
||||||
iSerialNumber 3
|
iSerialNumber 3
|
||||||
bNumConfigurations 1
|
bNumConfigurations 1
|
||||||
I (5097) CLASS: Getting config descriptor
|
I (775) CLASS: Getting config descriptor
|
||||||
*** Configuration descriptor ***
|
*** Configuration descriptor ***
|
||||||
bLength 9
|
bLength 9
|
||||||
bDescriptorType 2
|
bDescriptorType 2
|
||||||
@@ -153,12 +159,20 @@ bMaxPower 500mA
|
|||||||
bmAttributes 0x2 BULK
|
bmAttributes 0x2 BULK
|
||||||
wMaxPacketSize 64
|
wMaxPacketSize 64
|
||||||
bInterval 1
|
bInterval 1
|
||||||
I (5227) CLASS: Getting Manufacturer string descriptor
|
I (855) CLASS: Getting Manufacturer string descriptor
|
||||||
Espressif
|
Espressif
|
||||||
I (5237) CLASS: Getting Product string descriptor
|
I (855) CLASS: Getting Product string descriptor
|
||||||
USB JTAG/serial debug unit
|
USB JTAG/serial debug unit
|
||||||
I (5247) CLASS: Getting Serial Number string descriptor
|
I (865) CLASS: Getting Serial Number string descriptor
|
||||||
7C:DF:A1:E0:10:50
|
7C:DF:A1:E0:10:50
|
||||||
|
W (2855) USB host lib: To shutdown example, remove all USB devices and press button again.
|
||||||
|
E (6135) USBH: Device 1 gone
|
||||||
|
I (9545) CLASS: Deregistering Client
|
||||||
|
I (9545) USB host lib: No more clients
|
||||||
|
I (9545) USB host lib: All devices marked as free
|
||||||
|
I (9545) USB host lib: No more clients and devices
|
||||||
|
I (9645) USB host lib: End of the example
|
||||||
|
I (9645) main_task: Returned from app_main()
|
||||||
```
|
```
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
idf_component_register(SRCS "usb_host_lib_main.c" "class_driver.c"
|
idf_component_register(SRCS "usb_host_lib_main.c" "class_driver.c"
|
||||||
INCLUDE_DIRS "."
|
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 CLIENT_NUM_EVENT_MSG 5
|
||||||
|
|
||||||
#define ACTION_OPEN_DEV 0x01
|
typedef enum {
|
||||||
#define ACTION_GET_DEV_INFO 0x02
|
ACTION_OPEN_DEV = 0x01,
|
||||||
#define ACTION_GET_DEV_DESC 0x04
|
ACTION_GET_DEV_INFO = 0x02,
|
||||||
#define ACTION_GET_CONFIG_DESC 0x08
|
ACTION_GET_DEV_DESC = 0x04,
|
||||||
#define ACTION_GET_STR_DESC 0x10
|
ACTION_GET_CONFIG_DESC = 0x08,
|
||||||
#define ACTION_CLOSE_DEV 0x20
|
ACTION_GET_STR_DESC = 0x10,
|
||||||
#define ACTION_EXIT 0x40
|
ACTION_CLOSE_DEV = 0x20,
|
||||||
|
ACTION_EXIT = 0x40,
|
||||||
|
ACTION_RECONNECT = 0x80,
|
||||||
|
} action_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
usb_host_client_handle_t client_hdl;
|
usb_host_client_handle_t client_hdl;
|
||||||
@@ -28,6 +31,7 @@ typedef struct {
|
|||||||
} class_driver_t;
|
} class_driver_t;
|
||||||
|
|
||||||
static const char *TAG = "CLASS";
|
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)
|
static void client_event_cb(const usb_host_client_event_msg_t *event_msg, void *arg)
|
||||||
{
|
{
|
||||||
@@ -122,24 +126,20 @@ static void action_get_str_desc(class_driver_t *driver_obj)
|
|||||||
driver_obj->actions &= ~ACTION_GET_STR_DESC;
|
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));
|
ESP_ERROR_CHECK(usb_host_device_close(driver_obj->client_hdl, driver_obj->dev_hdl));
|
||||||
driver_obj->dev_hdl = NULL;
|
driver_obj->dev_hdl = NULL;
|
||||||
driver_obj->dev_addr = 0;
|
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_CLOSE_DEV;
|
||||||
driver_obj->actions |= ACTION_EXIT;
|
driver_obj->actions |= ACTION_RECONNECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void class_driver_task(void *arg)
|
void class_driver_task(void *arg)
|
||||||
{
|
{
|
||||||
SemaphoreHandle_t signaling_sem = (SemaphoreHandle_t)arg;
|
|
||||||
class_driver_t driver_obj = {0};
|
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");
|
ESP_LOGI(TAG, "Registering Client");
|
||||||
usb_host_client_config_t client_config = {
|
usb_host_client_config_t client_config = {
|
||||||
.is_synchronous = false, //Synchronous clients currently not supported. Set this to false
|
.is_synchronous = false, //Synchronous clients currently not supported. Set this to false
|
||||||
@@ -150,6 +150,7 @@ void class_driver_task(void *arg)
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(usb_host_client_register(&client_config, &driver_obj.client_hdl));
|
ESP_ERROR_CHECK(usb_host_client_register(&client_config, &driver_obj.client_hdl));
|
||||||
|
s_driver_obj = &driver_obj;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (driver_obj.actions == 0) {
|
if (driver_obj.actions == 0) {
|
||||||
@@ -171,18 +172,29 @@ void class_driver_task(void *arg)
|
|||||||
action_get_str_desc(&driver_obj);
|
action_get_str_desc(&driver_obj);
|
||||||
}
|
}
|
||||||
if (driver_obj.actions & ACTION_CLOSE_DEV) {
|
if (driver_obj.actions & ACTION_CLOSE_DEV) {
|
||||||
aciton_close_dev(&driver_obj);
|
action_close_dev(&driver_obj);
|
||||||
}
|
}
|
||||||
if (driver_obj.actions & ACTION_EXIT) {
|
if (driver_obj.actions & ACTION_EXIT) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (driver_obj.actions & ACTION_RECONNECT) {
|
||||||
|
driver_obj.actions = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Deregistering Client");
|
ESP_LOGI(TAG, "Deregistering Client");
|
||||||
ESP_ERROR_CHECK(usb_host_client_deregister(driver_obj.client_hdl));
|
ESP_ERROR_CHECK(usb_host_client_deregister(driver_obj.client_hdl));
|
||||||
|
|
||||||
//Wait to be deleted
|
|
||||||
xSemaphoreGive(signaling_sem);
|
|
||||||
vTaskSuspend(NULL);
|
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,27 +1,78 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/semphr.h"
|
#include "freertos/queue.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
#include "usb/usb_host.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 CLASS_TASK_PRIORITY 3
|
||||||
|
#define APP_QUIT_PIN CONFIG_APP_QUIT_PIN
|
||||||
|
|
||||||
extern void class_driver_task(void *arg);
|
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";
|
||||||
|
|
||||||
static void host_lib_daemon_task(void *arg)
|
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)
|
||||||
{
|
{
|
||||||
SemaphoreHandle_t signaling_sem = (SemaphoreHandle_t)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 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)
|
||||||
|
{
|
||||||
ESP_LOGI(TAG, "Installing USB Host Library");
|
ESP_LOGI(TAG, "Installing USB Host Library");
|
||||||
usb_host_config_t host_config = {
|
usb_host_config_t host_config = {
|
||||||
.skip_phy_setup = false,
|
.skip_phy_setup = false,
|
||||||
@@ -29,9 +80,8 @@ static void host_lib_daemon_task(void *arg)
|
|||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(usb_host_install(&host_config));
|
ESP_ERROR_CHECK(usb_host_install(&host_config));
|
||||||
|
|
||||||
//Signal to the class driver task that the host library is installed
|
//Signalize the app_main, the USB host library has been installed
|
||||||
xSemaphoreGive(signaling_sem);
|
xTaskNotifyGive(arg);
|
||||||
vTaskDelay(10); //Short delay to let client task spin up
|
|
||||||
|
|
||||||
bool has_clients = true;
|
bool has_clients = true;
|
||||||
bool has_devices = true;
|
bool has_devices = true;
|
||||||
@@ -39,52 +89,101 @@ static void host_lib_daemon_task(void *arg)
|
|||||||
uint32_t event_flags;
|
uint32_t event_flags;
|
||||||
ESP_ERROR_CHECK(usb_host_lib_handle_events(portMAX_DELAY, &event_flags));
|
ESP_ERROR_CHECK(usb_host_lib_handle_events(portMAX_DELAY, &event_flags));
|
||||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
|
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
|
||||||
|
ESP_LOGI(TAG, "No more clients");
|
||||||
has_clients = false;
|
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) {
|
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
|
||||||
|
ESP_LOGI(TAG, "No more devices");
|
||||||
has_devices = false;
|
has_devices = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "No more clients and devices");
|
ESP_LOGI(TAG, "No more clients and devices");
|
||||||
|
|
||||||
//Uninstall the USB Host Library
|
//Uninstall the USB Host Library
|
||||||
ESP_ERROR_CHECK(usb_host_uninstall());
|
ESP_ERROR_CHECK(usb_host_uninstall());
|
||||||
//Wait to be deleted
|
|
||||||
xSemaphoreGive(signaling_sem);
|
|
||||||
vTaskSuspend(NULL);
|
vTaskSuspend(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
SemaphoreHandle_t signaling_sem = xSemaphoreCreateBinary();
|
ESP_LOGI(TAG, "USB host library example");
|
||||||
|
|
||||||
TaskHandle_t daemon_task_hdl;
|
// Init BOOT button: Pressing the button simulates app request to exit
|
||||||
TaskHandle_t class_driver_task_hdl;
|
// It will uninstall the class driver and USB Host Lib
|
||||||
//Create daemon task
|
const gpio_config_t input_pin = {
|
||||||
xTaskCreatePinnedToCore(host_lib_daemon_task,
|
.pin_bit_mask = BIT64(APP_QUIT_PIN),
|
||||||
"daemon",
|
.mode = GPIO_MODE_INPUT,
|
||||||
4096,
|
.pull_up_en = GPIO_PULLUP_ENABLE,
|
||||||
(void *)signaling_sem,
|
.intr_type = GPIO_INTR_NEGEDGE,
|
||||||
DAEMON_TASK_PRIORITY,
|
};
|
||||||
&daemon_task_hdl,
|
ESP_ERROR_CHECK(gpio_config(&input_pin));
|
||||||
0);
|
ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1));
|
||||||
//Create the class driver task
|
ESP_ERROR_CHECK(gpio_isr_handler_add(APP_QUIT_PIN, gpio_cb, NULL));
|
||||||
xTaskCreatePinnedToCore(class_driver_task,
|
|
||||||
"class",
|
|
||||||
4096,
|
|
||||||
(void *)signaling_sem,
|
|
||||||
CLASS_TASK_PRIORITY,
|
|
||||||
&class_driver_task_hdl,
|
|
||||||
0);
|
|
||||||
|
|
||||||
|
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
|
vTaskDelay(10); //Add a short delay to let the tasks run
|
||||||
|
|
||||||
//Wait for the tasks to complete
|
while (1) {
|
||||||
for (int i = 0; i < 2; i++) {
|
if (xQueueReceive(app_event_queue, &evt_queue, portMAX_DELAY)) {
|
||||||
xSemaphoreTake(signaling_sem, 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
|
//Delete the tasks
|
||||||
vTaskDelete(class_driver_task_hdl);
|
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");
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user