| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- /*
- * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Unlicense OR CC0-1.0
- */
- #include <stdlib.h>
- #include "freertos/FreeRTOS.h"
- #include "freertos/semphr.h"
- #include "esp_log.h"
- #include "usb/usb_host.h"
- #define CLIENT_NUM_EVENT_MSG 5
- 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;
- uint8_t dev_addr;
- usb_device_handle_t dev_hdl;
- uint32_t actions;
- } 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)
- {
- class_driver_t *driver_obj = (class_driver_t *)arg;
- switch (event_msg->event) {
- case USB_HOST_CLIENT_EVENT_NEW_DEV:
- if (driver_obj->dev_addr == 0) {
- driver_obj->dev_addr = event_msg->new_dev.address;
- //Open the device next
- driver_obj->actions |= ACTION_OPEN_DEV;
- }
- break;
- case USB_HOST_CLIENT_EVENT_DEV_GONE:
- if (driver_obj->dev_hdl != NULL) {
- //Cancel any other actions and close the device next
- driver_obj->actions = ACTION_CLOSE_DEV;
- }
- break;
- default:
- //Should never occur
- abort();
- }
- }
- static void action_open_dev(class_driver_t *driver_obj)
- {
- assert(driver_obj->dev_addr != 0);
- ESP_LOGI(TAG, "Opening device at address %d", driver_obj->dev_addr);
- ESP_ERROR_CHECK(usb_host_device_open(driver_obj->client_hdl, driver_obj->dev_addr, &driver_obj->dev_hdl));
- //Get the device's information next
- driver_obj->actions &= ~ACTION_OPEN_DEV;
- driver_obj->actions |= ACTION_GET_DEV_INFO;
- }
- static void action_get_info(class_driver_t *driver_obj)
- {
- assert(driver_obj->dev_hdl != NULL);
- ESP_LOGI(TAG, "Getting device information");
- usb_device_info_t dev_info;
- ESP_ERROR_CHECK(usb_host_device_info(driver_obj->dev_hdl, &dev_info));
- ESP_LOGI(TAG, "\t%s speed", (dev_info.speed == USB_SPEED_LOW) ? "Low" : "Full");
- ESP_LOGI(TAG, "\tbConfigurationValue %d", dev_info.bConfigurationValue);
- //Todo: Print string descriptors
- //Get the device descriptor next
- driver_obj->actions &= ~ACTION_GET_DEV_INFO;
- driver_obj->actions |= ACTION_GET_DEV_DESC;
- }
- static void action_get_dev_desc(class_driver_t *driver_obj)
- {
- assert(driver_obj->dev_hdl != NULL);
- ESP_LOGI(TAG, "Getting device descriptor");
- const usb_device_desc_t *dev_desc;
- ESP_ERROR_CHECK(usb_host_get_device_descriptor(driver_obj->dev_hdl, &dev_desc));
- usb_print_device_descriptor(dev_desc);
- //Get the device's config descriptor next
- driver_obj->actions &= ~ACTION_GET_DEV_DESC;
- driver_obj->actions |= ACTION_GET_CONFIG_DESC;
- }
- static void action_get_config_desc(class_driver_t *driver_obj)
- {
- assert(driver_obj->dev_hdl != NULL);
- ESP_LOGI(TAG, "Getting config descriptor");
- const usb_config_desc_t *config_desc;
- ESP_ERROR_CHECK(usb_host_get_active_config_descriptor(driver_obj->dev_hdl, &config_desc));
- usb_print_config_descriptor(config_desc, NULL);
- //Get the device's string descriptors next
- driver_obj->actions &= ~ACTION_GET_CONFIG_DESC;
- driver_obj->actions |= ACTION_GET_STR_DESC;
- }
- static void action_get_str_desc(class_driver_t *driver_obj)
- {
- assert(driver_obj->dev_hdl != NULL);
- usb_device_info_t dev_info;
- ESP_ERROR_CHECK(usb_host_device_info(driver_obj->dev_hdl, &dev_info));
- if (dev_info.str_desc_manufacturer) {
- ESP_LOGI(TAG, "Getting Manufacturer string descriptor");
- usb_print_string_descriptor(dev_info.str_desc_manufacturer);
- }
- if (dev_info.str_desc_product) {
- ESP_LOGI(TAG, "Getting Product string descriptor");
- usb_print_string_descriptor(dev_info.str_desc_product);
- }
- if (dev_info.str_desc_serial_num) {
- ESP_LOGI(TAG, "Getting Serial Number string descriptor");
- usb_print_string_descriptor(dev_info.str_desc_serial_num);
- }
- //Nothing to do until the device disconnects
- driver_obj->actions &= ~ACTION_GET_STR_DESC;
- }
- 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 connect a new device
- driver_obj->actions &= ~ACTION_CLOSE_DEV;
- driver_obj->actions |= ACTION_RECONNECT;
- }
- void class_driver_task(void *arg)
- {
- class_driver_t driver_obj = {0};
- ESP_LOGI(TAG, "Registering Client");
- usb_host_client_config_t client_config = {
- .is_synchronous = false, //Synchronous clients currently not supported. Set this to false
- .max_num_event_msg = CLIENT_NUM_EVENT_MSG,
- .async = {
- .client_event_callback = client_event_cb,
- .callback_arg = (void *) &driver_obj,
- },
- };
- 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) {
- usb_host_client_handle_events(driver_obj.client_hdl, portMAX_DELAY);
- } else {
- if (driver_obj.actions & ACTION_OPEN_DEV) {
- action_open_dev(&driver_obj);
- }
- if (driver_obj.actions & ACTION_GET_DEV_INFO) {
- action_get_info(&driver_obj);
- }
- if (driver_obj.actions & ACTION_GET_DEV_DESC) {
- action_get_dev_desc(&driver_obj);
- }
- if (driver_obj.actions & ACTION_GET_CONFIG_DESC) {
- action_get_config_desc(&driver_obj);
- }
- if (driver_obj.actions & ACTION_GET_STR_DESC) {
- action_get_str_desc(&driver_obj);
- }
- if (driver_obj.actions & ACTION_CLOSE_DEV) {
- 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));
- 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));
- }
|