test_hcd_ctrl.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*
  2. * SPDX-FileCopyrightText: 2021-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/semphr.h"
  9. #include "unity.h"
  10. #include "test_hcd_common.h"
  11. #define TEST_DEV_ADDR 0
  12. #define NUM_URBS 3
  13. #define TRANSFER_MAX_BYTES 256
  14. #define URB_DATA_BUFF_SIZE (sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES) //256 is worst case size for configuration descriptors
  15. /*
  16. Test HCD control pipe URBs (normal completion and early abort)
  17. Purpose:
  18. - Test that a control pipe can be created
  19. - URBs can be created and enqueued to the control pipe
  20. - Control pipe returns HCD_PIPE_EVENT_URB_DONE
  21. - Test that URBs can be aborted when enqueued
  22. Procedure:
  23. - Setup HCD and wait for connection
  24. - Setup default pipe and allocate URBs
  25. - Enqueue URBs
  26. - Expect HCD_PIPE_EVENT_URB_DONE
  27. - Requeue URBs, but abort them immediately
  28. - Expect URB to be USB_TRANSFER_STATUS_CANCELED or USB_TRANSFER_STATUS_COMPLETED
  29. - Teardown
  30. */
  31. TEST_CASE("Test HCD control pipe URBs", "[ctrl][low_speed][full_speed]")
  32. {
  33. usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
  34. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  35. //Allocate some URBs and initialize their data buffers with control transfers
  36. hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); //Create a default pipe (using a NULL EP descriptor)
  37. urb_t *urb_list[NUM_URBS];
  38. for (int i = 0; i < NUM_URBS; i++) {
  39. urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE);
  40. //Initialize with a "Get Config Descriptor request"
  41. urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES;
  42. USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES);
  43. urb_list[i]->transfer.context = URB_CONTEXT_VAL;
  44. }
  45. //Enqueue URBs but immediately suspend the port
  46. printf("Enqueuing URBs\n");
  47. for (int i = 0; i < NUM_URBS; i++) {
  48. TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i]));
  49. }
  50. //Wait for each done event of each URB
  51. for (int i = 0; i < NUM_URBS; i++) {
  52. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE);
  53. }
  54. //Dequeue URBs, check, and print
  55. for (int i = 0; i < NUM_URBS; i++) {
  56. urb_t *urb = hcd_urb_dequeue(default_pipe);
  57. TEST_ASSERT_EQUAL(urb_list[i], urb);
  58. TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status, "Transfer NOT completed");
  59. TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
  60. //We must have transmitted at least the setup packet, but device may return less than bytes requested
  61. TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes);
  62. TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes);
  63. usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t));
  64. TEST_ASSERT_EQUAL(USB_B_DESCRIPTOR_TYPE_CONFIGURATION , config_desc->bDescriptorType);
  65. printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength);
  66. }
  67. //Enqueue URBs again but abort them short after
  68. for (int i = 0; i < NUM_URBS; i++) {
  69. TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i]));
  70. }
  71. for (int i = 0; i < NUM_URBS; i++) {
  72. TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_abort(urb_list[i]));
  73. }
  74. vTaskDelay(pdMS_TO_TICKS(100)); //Give some time for any inflight transfers to complete
  75. //Wait for the URBs to complete and dequeue them, then check results
  76. //Dequeue URBs
  77. for (int i = 0; i < NUM_URBS; i++) {
  78. urb_t *urb = hcd_urb_dequeue(default_pipe);
  79. //No need to check for URB pointer address as they may be out of order
  80. TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED);
  81. if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) {
  82. //We must have transmitted at least the setup packet, but device may return less than bytes requested
  83. TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes);
  84. TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes);
  85. } else {
  86. //A failed transfer should 0 actual number of bytes transmitted
  87. TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes);
  88. }
  89. TEST_ASSERT_EQUAL(urb->transfer.context, URB_CONTEXT_VAL);
  90. }
  91. //Free URB list and pipe
  92. for (int i = 0; i < NUM_URBS; i++) {
  93. test_hcd_free_urb(urb_list[i]);
  94. }
  95. test_hcd_pipe_free(default_pipe);
  96. //Cleanup
  97. test_hcd_wait_for_disconn(port_hdl, false);
  98. }
  99. /*
  100. Test HCD control pipe STALL condition, abort, and clear
  101. @todo this test is not passing with low-speed: test with bus analyzer
  102. Purpose:
  103. - Test that a control pipe can react to a STALL (i.e., a HCD_PIPE_EVENT_ERROR_STALL event)
  104. - The HCD_PIPE_CMD_FLUSH can retire all URBs
  105. - Pipe clear command can return the pipe to being active
  106. Procedure:
  107. - Setup HCD and wait for connection
  108. - Setup default pipe and allocate URBs
  109. - Corrupt the first URB so that it will trigger a STALL, then enqueue all the URBs
  110. - Check that a HCD_PIPE_EVENT_ERROR_STALL event is triggered
  111. - Check that all URBs can be retired using HCD_PIPE_CMD_FLUSH, a HCD_PIPE_EVENT_URB_DONE event should be generated
  112. - Check that the STALL can be cleared by using HCD_PIPE_CMD_CLEAR
  113. - Fix the corrupt first URB and retry the URBs
  114. - Dequeue URBs
  115. - Teardown
  116. */
  117. TEST_CASE("Test HCD control pipe STALL", "[ctrl][full_speed]")
  118. {
  119. usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
  120. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  121. //Allocate some URBs and initialize their data buffers with control transfers
  122. hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); //Create a default pipe (using a NULL EP descriptor)
  123. urb_t *urb_list[NUM_URBS];
  124. for (int i = 0; i < NUM_URBS; i++) {
  125. urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE);
  126. //Initialize with a "Get Config Descriptor request"
  127. urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES;
  128. USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES);
  129. urb_list[i]->transfer.context = URB_CONTEXT_VAL;
  130. }
  131. //Corrupt the first URB so that it triggers a STALL
  132. ((usb_setup_packet_t *)urb_list[0]->transfer.data_buffer)->bRequest = 0xAA;
  133. //Enqueue URBs. A STALL should occur
  134. int num_enqueued = 0;
  135. for (int i = 0; i < NUM_URBS; i++) {
  136. if (hcd_urb_enqueue(default_pipe, urb_list[i]) != ESP_OK) {
  137. //STALL may occur before we are done enqueing
  138. break;
  139. }
  140. num_enqueued++;
  141. }
  142. TEST_ASSERT_GREATER_THAN(0, num_enqueued);
  143. printf("Expecting STALL\n");
  144. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_ERROR_STALL);
  145. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe));
  146. //Call the pipe abort command to retire all URBs then dequeue them all
  147. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_FLUSH));
  148. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE);
  149. for (int i = 0; i < num_enqueued; i++) {
  150. urb_t *urb = hcd_urb_dequeue(default_pipe);
  151. TEST_ASSERT_EQUAL(urb_list[i], urb);
  152. TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_STALL || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED);
  153. if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) {
  154. //We must have transmitted at least the setup packet, but device may return less than bytes requested
  155. TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes);
  156. TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes);
  157. } else {
  158. //A failed transfer should 0 actual number of bytes transmitted
  159. TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes);
  160. }
  161. TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
  162. }
  163. //Call the clear command to un-stall the pipe
  164. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR));
  165. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe));
  166. printf("Retrying\n");
  167. //Correct first URB then requeue
  168. USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[0]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES);
  169. for (int i = 0; i < NUM_URBS; i++) {
  170. TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i]));
  171. }
  172. //Wait for each URB to be done, deequeue, and check results
  173. for (int i = 0; i < NUM_URBS; i++) {
  174. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE);
  175. //expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_URB_DONE);
  176. urb_t *urb = hcd_urb_dequeue(default_pipe);
  177. TEST_ASSERT_EQUAL(urb_list[i], urb);
  178. TEST_ASSERT_EQUAL_MESSAGE(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status, "Transfer NOT completed");
  179. TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
  180. //We must have transmitted at least the setup packet, but device may return less than bytes requested
  181. TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes);
  182. TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes);
  183. usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t));
  184. TEST_ASSERT_EQUAL(USB_B_DESCRIPTOR_TYPE_CONFIGURATION , config_desc->bDescriptorType);
  185. printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength);
  186. }
  187. //Free URB list and pipe
  188. for (int i = 0; i < NUM_URBS; i++) {
  189. test_hcd_free_urb(urb_list[i]);
  190. }
  191. test_hcd_pipe_free(default_pipe);
  192. //Cleanup
  193. test_hcd_wait_for_disconn(port_hdl, false);
  194. }
  195. /*
  196. Test control pipe run-time halt and clear
  197. Purpose:
  198. - Test that a control pipe can be halted with HCD_PIPE_CMD_HALT whilst there are ongoing URBs
  199. - Test that a control pipe can be un-halted with a HCD_PIPE_CMD_CLEAR
  200. - Test that enqueued URBs are resumed when pipe is un-halted
  201. Procedure:
  202. - Setup HCD and wait for connection
  203. - Setup default pipe and allocate URBs
  204. - Enqqueue URBs but execute a HCD_PIPE_CMD_HALT command immediately after.
  205. - Halt command should immediately halt the current URB and generate a HCD_PIPE_EVENT_URB_DONE
  206. - Other pending URBs should be untouched.
  207. - Un-halt the pipe using a HCD_PIPE_CMD_CLEAR command. Enqueued URBs will be resumed
  208. - Check that all URBs have completed successfully
  209. - Dequeue URBs and teardown
  210. */
  211. TEST_CASE("Test HCD control pipe runtime halt and clear", "[ctrl][low_speed][full_speed]")
  212. {
  213. usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
  214. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  215. //Allocate some URBs and initialize their data buffers with control transfers
  216. hcd_pipe_handle_t default_pipe = test_hcd_pipe_alloc(port_hdl, NULL, TEST_DEV_ADDR, port_speed); //Create a default pipe (using a NULL EP descriptor)
  217. urb_t *urb_list[NUM_URBS];
  218. for (int i = 0; i < NUM_URBS; i++) {
  219. urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE);
  220. //Initialize with a "Get Config Descriptor request"
  221. urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES;
  222. USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES);
  223. urb_list[i]->transfer.context = URB_CONTEXT_VAL;
  224. }
  225. //Enqueue URBs but immediately halt the pipe
  226. printf("Enqueuing URBs\n");
  227. for (int i = 0; i < NUM_URBS; i++) {
  228. TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i]));
  229. }
  230. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT));
  231. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE);
  232. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe));
  233. printf("Pipe halted\n");
  234. //Un-halt the pipe
  235. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR));
  236. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe));
  237. printf("Pipe cleared\n");
  238. vTaskDelay(pdMS_TO_TICKS(100)); //Give some time pending for transfers to restart and complete
  239. //Wait for each URB to be done, dequeue, and check results
  240. for (int i = 0; i < NUM_URBS; i++) {
  241. urb_t *urb = hcd_urb_dequeue(default_pipe);
  242. TEST_ASSERT_EQUAL_PTR(urb_list[i], urb);
  243. TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED);
  244. if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) {
  245. //We must have transmitted at least the setup packet, but device may return less than bytes requested
  246. TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes);
  247. TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes);
  248. usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t));
  249. TEST_ASSERT_EQUAL(USB_B_DESCRIPTOR_TYPE_CONFIGURATION , config_desc->bDescriptorType);
  250. printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength);
  251. } else {
  252. //A failed transfer should 0 actual number of bytes transmitted
  253. TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes);
  254. }
  255. TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
  256. }
  257. //Free URB list and pipe
  258. for (int i = 0; i < NUM_URBS; i++) {
  259. test_hcd_free_urb(urb_list[i]);
  260. }
  261. test_hcd_pipe_free(default_pipe);
  262. //Cleanup
  263. test_hcd_wait_for_disconn(port_hdl, false);
  264. }