class_driver.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Unlicense OR CC0-1.0
  5. */
  6. #include <stdlib.h>
  7. #include "freertos/FreeRTOS.h"
  8. #include "freertos/semphr.h"
  9. #include "esp_log.h"
  10. #include "usb/usb_host.h"
  11. #define CLIENT_NUM_EVENT_MSG 5
  12. #define ACTION_OPEN_DEV 0x01
  13. #define ACTION_GET_DEV_INFO 0x02
  14. #define ACTION_GET_DEV_DESC 0x04
  15. #define ACTION_GET_CONFIG_DESC 0x08
  16. #define ACTION_GET_STR_DESC 0x10
  17. #define ACTION_CLOSE_DEV 0x20
  18. #define ACTION_EXIT 0x40
  19. typedef struct {
  20. usb_host_client_handle_t client_hdl;
  21. uint8_t dev_addr;
  22. usb_device_handle_t dev_hdl;
  23. uint32_t actions;
  24. } class_driver_t;
  25. static const char *TAG = "CLASS";
  26. static void client_event_cb(const usb_host_client_event_msg_t *event_msg, void *arg)
  27. {
  28. class_driver_t *driver_obj = (class_driver_t *)arg;
  29. switch (event_msg->event) {
  30. case USB_HOST_CLIENT_EVENT_NEW_DEV:
  31. if (driver_obj->dev_addr == 0) {
  32. driver_obj->dev_addr = event_msg->new_dev.address;
  33. //Open the device next
  34. driver_obj->actions |= ACTION_OPEN_DEV;
  35. }
  36. break;
  37. case USB_HOST_CLIENT_EVENT_DEV_GONE:
  38. if (driver_obj->dev_hdl != NULL) {
  39. //Cancel any other actions and close the device next
  40. driver_obj->actions = ACTION_CLOSE_DEV;
  41. }
  42. break;
  43. default:
  44. //Should never occur
  45. abort();
  46. }
  47. }
  48. static void action_open_dev(class_driver_t *driver_obj)
  49. {
  50. assert(driver_obj->dev_addr != 0);
  51. ESP_LOGI(TAG, "Opening device at address %d", driver_obj->dev_addr);
  52. ESP_ERROR_CHECK(usb_host_device_open(driver_obj->client_hdl, driver_obj->dev_addr, &driver_obj->dev_hdl));
  53. //Get the device's information next
  54. driver_obj->actions &= ~ACTION_OPEN_DEV;
  55. driver_obj->actions |= ACTION_GET_DEV_INFO;
  56. }
  57. static void action_get_info(class_driver_t *driver_obj)
  58. {
  59. assert(driver_obj->dev_hdl != NULL);
  60. ESP_LOGI(TAG, "Getting device information");
  61. usb_device_info_t dev_info;
  62. ESP_ERROR_CHECK(usb_host_device_info(driver_obj->dev_hdl, &dev_info));
  63. ESP_LOGI(TAG, "\t%s speed", (dev_info.speed == USB_SPEED_LOW) ? "Low" : "Full");
  64. ESP_LOGI(TAG, "\tbConfigurationValue %d", dev_info.bConfigurationValue);
  65. //Todo: Print string descriptors
  66. //Get the device descriptor next
  67. driver_obj->actions &= ~ACTION_GET_DEV_INFO;
  68. driver_obj->actions |= ACTION_GET_DEV_DESC;
  69. }
  70. static void action_get_dev_desc(class_driver_t *driver_obj)
  71. {
  72. assert(driver_obj->dev_hdl != NULL);
  73. ESP_LOGI(TAG, "Getting device descriptor");
  74. const usb_device_desc_t *dev_desc;
  75. ESP_ERROR_CHECK(usb_host_get_device_descriptor(driver_obj->dev_hdl, &dev_desc));
  76. usb_print_device_descriptor(dev_desc);
  77. //Get the device's config descriptor next
  78. driver_obj->actions &= ~ACTION_GET_DEV_DESC;
  79. driver_obj->actions |= ACTION_GET_CONFIG_DESC;
  80. }
  81. static void action_get_config_desc(class_driver_t *driver_obj)
  82. {
  83. assert(driver_obj->dev_hdl != NULL);
  84. ESP_LOGI(TAG, "Getting config descriptor");
  85. const usb_config_desc_t *config_desc;
  86. ESP_ERROR_CHECK(usb_host_get_active_config_descriptor(driver_obj->dev_hdl, &config_desc));
  87. usb_print_config_descriptor(config_desc, NULL);
  88. //Get the device's string descriptors next
  89. driver_obj->actions &= ~ACTION_GET_CONFIG_DESC;
  90. driver_obj->actions |= ACTION_GET_STR_DESC;
  91. }
  92. static void action_get_str_desc(class_driver_t *driver_obj)
  93. {
  94. assert(driver_obj->dev_hdl != NULL);
  95. usb_device_info_t dev_info;
  96. ESP_ERROR_CHECK(usb_host_device_info(driver_obj->dev_hdl, &dev_info));
  97. if (dev_info.str_desc_manufacturer) {
  98. ESP_LOGI(TAG, "Getting Manufacturer string descriptor");
  99. usb_print_string_descriptor(dev_info.str_desc_manufacturer);
  100. }
  101. if (dev_info.str_desc_product) {
  102. ESP_LOGI(TAG, "Getting Product string descriptor");
  103. usb_print_string_descriptor(dev_info.str_desc_product);
  104. }
  105. if (dev_info.str_desc_serial_num) {
  106. ESP_LOGI(TAG, "Getting Serial Number string descriptor");
  107. usb_print_string_descriptor(dev_info.str_desc_serial_num);
  108. }
  109. //Nothing to do until the device disconnects
  110. driver_obj->actions &= ~ACTION_GET_STR_DESC;
  111. }
  112. static void aciton_close_dev(class_driver_t *driver_obj)
  113. {
  114. ESP_ERROR_CHECK(usb_host_device_close(driver_obj->client_hdl, driver_obj->dev_hdl));
  115. driver_obj->dev_hdl = NULL;
  116. driver_obj->dev_addr = 0;
  117. //We need to exit the event handler loop
  118. driver_obj->actions &= ~ACTION_CLOSE_DEV;
  119. driver_obj->actions |= ACTION_EXIT;
  120. }
  121. void class_driver_task(void *arg)
  122. {
  123. SemaphoreHandle_t signaling_sem = (SemaphoreHandle_t)arg;
  124. class_driver_t driver_obj = {0};
  125. //Wait until daemon task has installed USB Host Library
  126. xSemaphoreTake(signaling_sem, portMAX_DELAY);
  127. ESP_LOGI(TAG, "Registering Client");
  128. usb_host_client_config_t client_config = {
  129. .is_synchronous = false, //Synchronous clients currently not supported. Set this to false
  130. .max_num_event_msg = CLIENT_NUM_EVENT_MSG,
  131. .async = {
  132. .client_event_callback = client_event_cb,
  133. .callback_arg = (void *)&driver_obj,
  134. },
  135. };
  136. ESP_ERROR_CHECK(usb_host_client_register(&client_config, &driver_obj.client_hdl));
  137. while (1) {
  138. if (driver_obj.actions == 0) {
  139. usb_host_client_handle_events(driver_obj.client_hdl, portMAX_DELAY);
  140. } else {
  141. if (driver_obj.actions & ACTION_OPEN_DEV) {
  142. action_open_dev(&driver_obj);
  143. }
  144. if (driver_obj.actions & ACTION_GET_DEV_INFO) {
  145. action_get_info(&driver_obj);
  146. }
  147. if (driver_obj.actions & ACTION_GET_DEV_DESC) {
  148. action_get_dev_desc(&driver_obj);
  149. }
  150. if (driver_obj.actions & ACTION_GET_CONFIG_DESC) {
  151. action_get_config_desc(&driver_obj);
  152. }
  153. if (driver_obj.actions & ACTION_GET_STR_DESC) {
  154. action_get_str_desc(&driver_obj);
  155. }
  156. if (driver_obj.actions & ACTION_CLOSE_DEV) {
  157. aciton_close_dev(&driver_obj);
  158. }
  159. if (driver_obj.actions & ACTION_EXIT) {
  160. break;
  161. }
  162. }
  163. }
  164. ESP_LOGI(TAG, "Deregistering Client");
  165. ESP_ERROR_CHECK(usb_host_client_deregister(driver_obj.client_hdl));
  166. //Wait to be deleted
  167. xSemaphoreGive(signaling_sem);
  168. vTaskSuspend(NULL);
  169. }