test_usb_host_plugging.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdio.h>
  7. #include "freertos/FreeRTOS.h"
  8. #include "freertos/task.h"
  9. #include "esp_err.h"
  10. #include "esp_intr_alloc.h"
  11. #include "test_usb_common.h"
  12. #include "test_usb_mock_classes.h"
  13. #include "msc_client.h"
  14. #include "ctrl_client.h"
  15. #include "usb/usb_host.h"
  16. #include "unity.h"
  17. #include "test_utils.h"
  18. // --------------------------------------------------- Test Cases ------------------------------------------------------
  19. /*
  20. Test USB Host Library Sudden Disconnection Handling (no clients)
  21. Purpose:
  22. - Test that sudden disconnections are handled properly when there are no clients
  23. - Test that devices can reconnect after a sudden disconnection has been handled by the USB Host Library
  24. Procedure:
  25. - Install USB Host Library
  26. - Wait for connection (and enumeration) to occur
  27. - Force a disconnection, then wait for disconnection to be handled (USB_HOST_LIB_EVENT_FLAGS_ALL_FREE)
  28. - Allow connections again, and repeat test for multiple iterations
  29. */
  30. #define TEST_DCONN_NO_CLIENT_ITERATIONS 3
  31. TEST_CASE("Test USB Host sudden disconnection (no client)", "[usb_host][ignore]")
  32. {
  33. test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
  34. //Install USB Host Library
  35. usb_host_config_t host_config = {
  36. .skip_phy_setup = true, //test_usb_init_phy() will already have setup the internal USB PHY for us
  37. .intr_flags = ESP_INTR_FLAG_LEVEL1,
  38. };
  39. ESP_ERROR_CHECK(usb_host_install(&host_config));
  40. printf("Installed\n");
  41. bool connected = false;
  42. int dconn_iter = 0;
  43. while (1) {
  44. //Start handling system events
  45. uint32_t event_flags;
  46. usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
  47. if (!connected) {
  48. usb_host_lib_info_t lib_info;
  49. TEST_ASSERT_EQUAL(ESP_OK, usb_host_lib_info(&lib_info));
  50. if (lib_info.num_devices == 1) {
  51. //We've just connected. Trigger a disconnect
  52. connected = true;
  53. printf("Forcing Sudden Disconnect\n");
  54. test_usb_set_phy_state(false, 0);
  55. }
  56. }
  57. if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
  58. //The device has disconnected and it's disconnection has been handled
  59. printf("Dconn iter %d done\n", dconn_iter);
  60. if (++dconn_iter < TEST_DCONN_NO_CLIENT_ITERATIONS) {
  61. //Start next iteration
  62. connected = false;
  63. test_usb_set_phy_state(true, 0);
  64. } else {
  65. break;
  66. }
  67. }
  68. }
  69. //Clean up USB Host
  70. ESP_ERROR_CHECK(usb_host_uninstall());
  71. test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing
  72. }
  73. /*
  74. Test USB Host Library Sudden Disconnection Handling (with client)
  75. Purpose:
  76. - Test that sudden disconnections are handled properly when there are registered clients
  77. - Test that devices can reconnect after a sudden disconnection has been handled by the USB Host Library
  78. Procedure:
  79. - Install USB Host Library
  80. - Create a task to run an MSC client
  81. - Start the MSC disconnect client task. It will open the device then force a disconnect for multiple iterations
  82. - Wait for USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS and USB_HOST_LIB_EVENT_FLAGS_ALL_FREE before uninstalling
  83. */
  84. #define TEST_FORCE_DCONN_NUM_TRANSFERS 3
  85. #define TEST_MSC_SCSI_TAG 0xDEADBEEF
  86. TEST_CASE("Test USB Host sudden disconnection (single client)", "[usb_host][ignore]")
  87. {
  88. test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
  89. //Install USB Host
  90. usb_host_config_t host_config = {
  91. .skip_phy_setup = true, //test_usb_init_phy() will already have setup the internal USB PHY for us
  92. .intr_flags = ESP_INTR_FLAG_LEVEL1,
  93. };
  94. ESP_ERROR_CHECK(usb_host_install(&host_config));
  95. printf("Installed\n");
  96. //Create task to run client that communicates with MSC SCSI interface
  97. msc_client_test_param_t params = {
  98. .num_sectors_to_read = 1, //Unused by disconnect MSC client
  99. .num_sectors_per_xfer = TEST_FORCE_DCONN_NUM_TRANSFERS * MOCK_MSC_SCSI_SECTOR_SIZE,
  100. .msc_scsi_xfer_tag = TEST_MSC_SCSI_TAG,
  101. .idVendor = MOCK_MSC_SCSI_DEV_ID_VENDOR,
  102. .idProduct = MOCK_MSC_SCSI_DEV_ID_PRODUCT,
  103. };
  104. TaskHandle_t task_hdl;
  105. xTaskCreatePinnedToCore(msc_client_async_dconn_task, "async", 4096, (void *)&params, 2, &task_hdl, 0);
  106. //Start the task
  107. xTaskNotifyGive(task_hdl);
  108. bool all_clients_gone = false;
  109. bool all_dev_free = false;
  110. while (!all_clients_gone || !all_dev_free) {
  111. //Start handling system events
  112. uint32_t event_flags;
  113. usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
  114. if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
  115. printf("No more clients\n");
  116. all_clients_gone = true;
  117. }
  118. if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
  119. printf("All device's freed\n");
  120. all_dev_free = true;
  121. }
  122. }
  123. //Short delay to allow task to be cleaned up
  124. vTaskDelay(10);
  125. //Clean up USB Host
  126. ESP_ERROR_CHECK(usb_host_uninstall());
  127. test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing
  128. }
  129. /*
  130. Test USB Host Library Enumeration
  131. Purpose:
  132. - Test that the USB Host Library enumerates device correctly
  133. Procedure:
  134. - Install USB Host Library
  135. - Create a task to run an MSC client
  136. - Start the MSC enumeration client task. It will:
  137. - Wait for device connection
  138. - Open the device
  139. - Check details of the device's enumeration
  140. - Disconnect the device, and repeat the steps above for multiple iterations.
  141. - Wait for USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS and USB_HOST_LIB_EVENT_FLAGS_ALL_FREE before uninstalling
  142. */
  143. #define TEST_ENUM_ITERATIONS 3
  144. TEST_CASE("Test USB Host enumeration", "[usb_host][ignore]")
  145. {
  146. test_usb_init_phy(); //Initialize the internal USB PHY and USB Controller for testing
  147. //Install USB Host
  148. usb_host_config_t host_config = {
  149. .skip_phy_setup = true, //test_usb_init_phy() will already have setup the internal USB PHY for us
  150. .intr_flags = ESP_INTR_FLAG_LEVEL1,
  151. };
  152. ESP_ERROR_CHECK(usb_host_install(&host_config));
  153. printf("Installed\n");
  154. //Create task to run client that checks the enumeration of the device
  155. TaskHandle_t task_hdl;
  156. xTaskCreatePinnedToCore(msc_client_async_enum_task, "async", 6144, NULL, 2, &task_hdl, 0);
  157. //Start the task
  158. xTaskNotifyGive(task_hdl);
  159. bool all_clients_gone = false;
  160. bool all_dev_free = false;
  161. while (!all_clients_gone || !all_dev_free) {
  162. //Start handling system events
  163. uint32_t event_flags;
  164. usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
  165. if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
  166. printf("No more clients\n");
  167. TEST_ASSERT_EQUAL(ESP_ERR_NOT_FINISHED, usb_host_device_free_all());
  168. all_clients_gone = true;
  169. }
  170. if (all_clients_gone && event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
  171. all_dev_free = true;
  172. }
  173. }
  174. //Short delay to allow task to be cleaned up
  175. vTaskDelay(10);
  176. //Clean up USB Host
  177. ESP_ERROR_CHECK(usb_host_uninstall());
  178. test_usb_deinit_phy(); //Deinitialize the internal USB PHY after testing
  179. }