test_hcd_ctrl.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. // Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include <stdio.h>
  14. #include "freertos/FreeRTOS.h"
  15. #include "freertos/semphr.h"
  16. #include "unity.h"
  17. #include "test_utils.h"
  18. #include "test_hcd_common.h"
  19. #define TEST_DEV_ADDR 0
  20. #define NUM_URBS 3
  21. #define TRANSFER_MAX_BYTES 256
  22. #define URB_DATA_BUFF_SIZE (sizeof(usb_ctrl_req_t) + TRANSFER_MAX_BYTES) //256 is worst case size for configuration descriptors
  23. /*
  24. Test HCD control pipe URBs (normal completion and early abort)
  25. Purpose:
  26. - Test that a control pipe can be created
  27. - URBs can be created and enqueued to the control pipe
  28. - Control pipe returns HCD_PIPE_EVENT_URB_DONE
  29. - Test that URBs can be aborted when enqueued
  30. Procedure:
  31. - Setup HCD and wait for connection
  32. - Setup default pipe and allocate URBs
  33. - Enqueue URBs
  34. - Expect HCD_PIPE_EVENT_URB_DONE
  35. - Requeue URBs, but abort them immediately
  36. - Expect URB to be USB_TRANSFER_STATUS_CANCELED or USB_TRANSFER_STATUS_COMPLETED
  37. - Teardown
  38. */
  39. TEST_CASE("Test HCD control pipe URBs", "[hcd][ignore]")
  40. {
  41. hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
  42. usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
  43. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  44. //Allocate some URBs and initialize their data buffers with control transfers
  45. 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)
  46. urb_t *urb_list[NUM_URBS];
  47. for (int i = 0; i < NUM_URBS; i++) {
  48. urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE);
  49. //Initialize with a "Get Config Descriptor request"
  50. urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES;
  51. USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES);
  52. urb_list[i]->transfer.context = URB_CONTEXT_VAL;
  53. }
  54. //Enqueue URBs but immediately suspend the port
  55. printf("Enqueuing URBs\n");
  56. for (int i = 0; i < NUM_URBS; i++) {
  57. TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i]));
  58. }
  59. //Wait for each done event of each URB
  60. for (int i = 0; i < NUM_URBS; i++) {
  61. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE);
  62. }
  63. //Dequeue URBs
  64. for (int i = 0; i < NUM_URBS; i++) {
  65. urb_t *urb = hcd_urb_dequeue(default_pipe);
  66. TEST_ASSERT_EQUAL(urb_list[i], urb);
  67. TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status);
  68. TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
  69. }
  70. //Print config desc
  71. for (int i = 0; i < urb_list[0]->transfer.actual_num_bytes; i++) {
  72. printf("%d\t0x%x\n", i, urb_list[0]->transfer.data_buffer[sizeof(usb_ctrl_req_t) + i]);
  73. }
  74. //Enqueue URBs again but abort them short after
  75. for (int i = 0; i < NUM_URBS; i++) {
  76. TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i]));
  77. }
  78. for (int i = 0; i < NUM_URBS; i++) {
  79. TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_abort(urb_list[i]));
  80. }
  81. vTaskDelay(pdMS_TO_TICKS(100)); //Give some time for any inflight transfers to complete
  82. //Wait for the URBs to complete and dequeue them, then check results
  83. //Dequeue URBs
  84. for (int i = 0; i < NUM_URBS; i++) {
  85. urb_t *urb = hcd_urb_dequeue(default_pipe);
  86. //No need to check for URB pointer address as they may be out of order
  87. TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED);
  88. if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) {
  89. TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes);
  90. } else {
  91. TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes);
  92. }
  93. TEST_ASSERT_EQUAL(urb->transfer.context, URB_CONTEXT_VAL);
  94. }
  95. //Free URB list and pipe
  96. for (int i = 0; i < NUM_URBS; i++) {
  97. test_hcd_free_urb(urb_list[i]);
  98. }
  99. test_hcd_pipe_free(default_pipe);
  100. //Cleanup
  101. test_hcd_wait_for_disconn(port_hdl, false);
  102. test_hcd_teardown(port_hdl);
  103. }
  104. /*
  105. Test HCD control pipe STALL condition, abort, and clear
  106. Purpose:
  107. - Test that a control pipe can react to a STALL (i.e., a HCD_PIPE_EVENT_HALTED event)
  108. - The HCD_PIPE_CMD_ABORT can retire all URBs
  109. - Pipe clear command can return the pipe to being active
  110. Procedure:
  111. - Setup HCD and wait for connection
  112. - Setup default pipe and allocate URBs
  113. - Corrupt the first URB so that it will trigger a STALL, then enqueue all the URBs
  114. - Check that a HCD_PIPE_EVENT_ERROR_STALL event is triggered
  115. - Check that all URBs can be retired using HCD_PIPE_CMD_ABORT
  116. - Check that the STALL can be cleared by using HCD_PIPE_CMD_CLEAR
  117. - Fix the corrupt first URB and retry the URBs
  118. - Dequeue URBs
  119. - Teardown
  120. */
  121. TEST_CASE("Test HCD control pipe STALL", "[hcd][ignore]")
  122. {
  123. hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
  124. usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
  125. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  126. //Allocate some URBs and initialize their data buffers with control transfers
  127. 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)
  128. urb_t *urb_list[NUM_URBS];
  129. for (int i = 0; i < NUM_URBS; i++) {
  130. urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE);
  131. //Initialize with a "Get Config Descriptor request"
  132. urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES;
  133. USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES);
  134. urb_list[i]->transfer.context = URB_CONTEXT_VAL;
  135. }
  136. //Corrupt the first URB so that it triggers a STALL
  137. ((usb_ctrl_req_t *)urb_list[0]->transfer.data_buffer)->bRequest = 0xAA;
  138. //Enqueue URBs. A STALL should occur
  139. int num_enqueued = 0;
  140. for (int i = 0; i < NUM_URBS; i++) {
  141. if (hcd_urb_enqueue(default_pipe, urb_list[i]) != ESP_OK) {
  142. //STALL may occur before we are done enqueing
  143. break;
  144. }
  145. num_enqueued++;
  146. }
  147. TEST_ASSERT_GREATER_THAN(0, num_enqueued);
  148. printf("Expecting STALL\n");
  149. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_ERROR_STALL);
  150. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe));
  151. //Call the pipe abort command to retire all URBs then dequeue them all
  152. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_ABORT));
  153. for (int i = 0; i < num_enqueued; i++) {
  154. urb_t *urb = hcd_urb_dequeue(default_pipe);
  155. TEST_ASSERT_EQUAL(urb_list[i], urb);
  156. TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_STALL || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED);
  157. if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) {
  158. TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes);
  159. } else {
  160. TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes);
  161. }
  162. TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
  163. }
  164. //Call the clear command to un-stall the pipe
  165. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR));
  166. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe));
  167. printf("Retrying\n");
  168. //Correct first URB then requeue
  169. USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[0]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES);
  170. for (int i = 0; i < NUM_URBS; i++) {
  171. TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i]));
  172. }
  173. //Wait for each URB to be done, deequeue, and check results
  174. for (int i = 0; i < NUM_URBS; i++) {
  175. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE);
  176. //expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_URB_DONE);
  177. urb_t *urb = hcd_urb_dequeue(default_pipe);
  178. TEST_ASSERT_EQUAL(urb_list[i], urb);
  179. TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status);
  180. TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes);
  181. TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
  182. }
  183. //Free URB list and pipe
  184. for (int i = 0; i < NUM_URBS; i++) {
  185. test_hcd_free_urb(urb_list[i]);
  186. }
  187. test_hcd_pipe_free(default_pipe);
  188. //Cleanup
  189. test_hcd_wait_for_disconn(port_hdl, false);
  190. test_hcd_teardown(port_hdl);
  191. }
  192. /*
  193. Test control pipe run-time halt and clear
  194. Purpose:
  195. - Test that a control pipe can be halted with HCD_PIPE_CMD_HALT whilst there are ongoing URBs
  196. - Test that a control pipe can be un-halted with a HCD_PIPE_CMD_CLEAR
  197. - Test that enqueued URBs are resumed when pipe is un-halted
  198. Procedure:
  199. - Setup HCD and wait for connection
  200. - Setup default pipe and allocate URBs
  201. - Enqqueue URBs but execute a HCD_PIPE_CMD_HALT command immediately after. Halt command should let on
  202. the current going URB finish before actually halting the pipe.
  203. - Un-halt the pipe a HCD_PIPE_CMD_HALT command. Enqueued URBs will be resumed
  204. - Check that all URBs have completed successfully
  205. - Dequeue URBs and teardown
  206. */
  207. TEST_CASE("Test HCD control pipe runtime halt and clear", "[hcd][ignore]")
  208. {
  209. hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
  210. usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
  211. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  212. //Allocate some URBs and initialize their data buffers with control transfers
  213. 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)
  214. urb_t *urb_list[NUM_URBS];
  215. for (int i = 0; i < NUM_URBS; i++) {
  216. urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE);
  217. //Initialize with a "Get Config Descriptor request"
  218. urb_list[i]->transfer.num_bytes = TRANSFER_MAX_BYTES;
  219. USB_CTRL_REQ_INIT_GET_CONFIG_DESC((usb_ctrl_req_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES);
  220. urb_list[i]->transfer.context = URB_CONTEXT_VAL;
  221. }
  222. //Enqueue URBs but immediately halt the pipe
  223. printf("Enqueuing URBs\n");
  224. for (int i = 0; i < NUM_URBS; i++) {
  225. TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i]));
  226. }
  227. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT));
  228. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe));
  229. printf("Pipe halted\n");
  230. //Un-halt the pipe
  231. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR));
  232. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe));
  233. printf("Pipe cleared\n");
  234. vTaskDelay(pdMS_TO_TICKS(100)); //Give some time pending for transfers to restart and complete
  235. //Wait for each URB to be done, dequeue, and check results
  236. for (int i = 0; i < NUM_URBS; i++) {
  237. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE);
  238. urb_t *urb = hcd_urb_dequeue(default_pipe);
  239. TEST_ASSERT_EQUAL(urb_list[i], urb);
  240. TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status);
  241. TEST_ASSERT_GREATER_THAN(0, urb->transfer.actual_num_bytes);
  242. TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
  243. }
  244. //Free URB list and pipe
  245. for (int i = 0; i < NUM_URBS; i++) {
  246. test_hcd_free_urb(urb_list[i]);
  247. }
  248. test_hcd_pipe_free(default_pipe);
  249. //Cleanup
  250. test_hcd_wait_for_disconn(port_hdl, false);
  251. test_hcd_teardown(port_hdl);
  252. }