test_hcd_ctrl.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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_IRPS 3
  21. #define TRANSFER_MAX_BYTES 256
  22. #define IRP_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 IRPs (normal completion and early abort)
  25. Purpose:
  26. - Test that a control pipe can be created
  27. - IRPs can be created and enqueued to the control pipe
  28. - Control pipe returns HCD_PIPE_EVENT_IRP_DONE
  29. - Test that IRPs can be aborted when enqueued
  30. Procedure:
  31. - Setup HCD and wait for connection
  32. - Setup default pipe and allocate IRPs
  33. - Enqueue IRPs
  34. - Expect HCD_PIPE_EVENT_IRP_DONE
  35. - Requeue IRPs, but abort them immediately
  36. - Expect IRP to be USB_TRANSFER_STATUS_CANCELED or USB_TRANSFER_STATUS_COMPLETED
  37. - Teardown
  38. */
  39. TEST_CASE("Test HCD control pipe IRPs", "[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 IRPs 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. usb_irp_t *irp_list[NUM_IRPS];
  47. for (int i = 0; i < NUM_IRPS; i++) {
  48. irp_list[i] = test_hcd_alloc_irp(0, IRP_DATA_BUFF_SIZE);
  49. //Initialize with a "Get Config Descriptor request"
  50. irp_list[i]->num_bytes = TRANSFER_MAX_BYTES;
  51. USB_CTRL_REQ_INIT_GET_CFG_DESC((usb_ctrl_req_t *)irp_list[i]->data_buffer, 0, TRANSFER_MAX_BYTES);
  52. irp_list[i]->context = IRP_CONTEXT_VAL;
  53. }
  54. //Enqueue IRPs but immediately suspend the port
  55. printf("Enqueuing IRPs\n");
  56. for (int i = 0; i < NUM_IRPS; i++) {
  57. TEST_ASSERT_EQUAL(ESP_OK, hcd_irp_enqueue(default_pipe, irp_list[i]));
  58. }
  59. //Wait for each done event of each IRP
  60. for (int i = 0; i < NUM_IRPS; i++) {
  61. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_IRP_DONE);
  62. }
  63. //Dequeue IRPs
  64. for (int i = 0; i < NUM_IRPS; i++) {
  65. usb_irp_t *irp = hcd_irp_dequeue(default_pipe);
  66. TEST_ASSERT_EQUAL(irp_list[i], irp);
  67. TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, irp->status);
  68. TEST_ASSERT_EQUAL(IRP_CONTEXT_VAL, irp->context);
  69. }
  70. //Enqueue IRPs again but abort them short after
  71. for (int i = 0; i < NUM_IRPS; i++) {
  72. TEST_ASSERT_EQUAL(ESP_OK, hcd_irp_enqueue(default_pipe, irp_list[i]));
  73. }
  74. for (int i = 0; i < NUM_IRPS; i++) {
  75. TEST_ASSERT_EQUAL(ESP_OK, hcd_irp_abort(irp_list[i]));
  76. }
  77. vTaskDelay(pdMS_TO_TICKS(100)); //Give some time for any inflight transfers to complete
  78. //Wait for the IRPs to complete and dequeue them, then check results
  79. //Dequeue IRPs
  80. for (int i = 0; i < NUM_IRPS; i++) {
  81. usb_irp_t *irp = hcd_irp_dequeue(default_pipe);
  82. //No need to check for IRP pointer address as they may be out of order
  83. TEST_ASSERT(irp->status == USB_TRANSFER_STATUS_COMPLETED || irp->status == USB_TRANSFER_STATUS_CANCELED);
  84. if (irp->status == USB_TRANSFER_STATUS_COMPLETED) {
  85. TEST_ASSERT_GREATER_THAN(0, irp->actual_num_bytes);
  86. } else {
  87. TEST_ASSERT_EQUAL(0, irp->actual_num_bytes);
  88. }
  89. TEST_ASSERT_EQUAL(irp->context, IRP_CONTEXT_VAL);
  90. }
  91. //Free IRP list and pipe
  92. for (int i = 0; i < NUM_IRPS; i++) {
  93. test_hcd_free_irp(irp_list[i]);
  94. }
  95. test_hcd_pipe_free(default_pipe);
  96. //Cleanup
  97. test_hcd_wait_for_disconn(port_hdl, false);
  98. test_hcd_teardown(port_hdl);
  99. }
  100. /*
  101. Test HCD control pipe STALL condition, abort, and clear
  102. Purpose:
  103. - Test that a control pipe can react to a STALL (i.e., a HCD_PIPE_EVENT_HALTED event)
  104. - The HCD_PIPE_CMD_ABORT can retire all IRPs
  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 IRPs
  109. - Corrupt the first IRP so that it will trigger a STALL, then enqueue all the IRPs
  110. - Check that a HCD_PIPE_EVENT_ERROR_STALL event is triggered
  111. - Check that all IRPs can be retired using HCD_PIPE_CMD_ABORT
  112. - Check that the STALL can be cleared by using HCD_PIPE_CMD_CLEAR
  113. - Fix the corrupt first IRP and retry the IRPs
  114. - Dequeue IRPs
  115. - Teardown
  116. */
  117. TEST_CASE("Test HCD control pipe STALL", "[hcd][ignore]")
  118. {
  119. hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
  120. usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
  121. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  122. //Allocate some IRPs and initialize their data buffers with control transfers
  123. 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)
  124. usb_irp_t *irp_list[NUM_IRPS];
  125. for (int i = 0; i < NUM_IRPS; i++) {
  126. irp_list[i] = test_hcd_alloc_irp(0, IRP_DATA_BUFF_SIZE);
  127. //Initialize with a "Get Config Descriptor request"
  128. irp_list[i]->num_bytes = TRANSFER_MAX_BYTES;
  129. USB_CTRL_REQ_INIT_GET_CFG_DESC((usb_ctrl_req_t *)irp_list[i]->data_buffer, 0, TRANSFER_MAX_BYTES);
  130. irp_list[i]->context = IRP_CONTEXT_VAL;
  131. }
  132. //Corrupt the first IRP so that it triggers a STALL
  133. ((usb_ctrl_req_t *)irp_list[0]->data_buffer)->bRequest = 0xAA;
  134. //Enqueue IRPs. A STALL should occur
  135. for (int i = 0; i < NUM_IRPS; i++) {
  136. TEST_ASSERT_EQUAL(ESP_OK, hcd_irp_enqueue(default_pipe, irp_list[i]));
  137. }
  138. printf("Expecting STALL\n");
  139. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_ERROR_STALL);
  140. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe));
  141. //Call the pipe abort command to retire all IRPs then dequeue them all
  142. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_ABORT));
  143. for (int i = 0; i < NUM_IRPS; i++) {
  144. usb_irp_t *irp = hcd_irp_dequeue(default_pipe);
  145. TEST_ASSERT_EQUAL(irp_list[i], irp);
  146. TEST_ASSERT(irp->status == USB_TRANSFER_STATUS_STALL || irp->status == USB_TRANSFER_STATUS_CANCELED);
  147. if (irp->status == USB_TRANSFER_STATUS_COMPLETED) {
  148. TEST_ASSERT_GREATER_THAN(0, irp->actual_num_bytes);
  149. } else {
  150. TEST_ASSERT_EQUAL(0, irp->actual_num_bytes);
  151. }
  152. TEST_ASSERT_EQUAL(IRP_CONTEXT_VAL, irp->context);
  153. }
  154. //Call the clear command to un-stall the pipe
  155. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR));
  156. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe));
  157. printf("Retrying\n");
  158. //Correct first IRP then requeue
  159. USB_CTRL_REQ_INIT_GET_CFG_DESC((usb_ctrl_req_t *)irp_list[0]->data_buffer, 0, TRANSFER_MAX_BYTES);
  160. for (int i = 0; i < NUM_IRPS; i++) {
  161. TEST_ASSERT_EQUAL(ESP_OK, hcd_irp_enqueue(default_pipe, irp_list[i]));
  162. }
  163. //Wait for each IRP to be done, deequeue, and check results
  164. for (int i = 0; i < NUM_IRPS; i++) {
  165. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_IRP_DONE);
  166. //expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_IRP_DONE);
  167. usb_irp_t *irp = hcd_irp_dequeue(default_pipe);
  168. TEST_ASSERT_EQUAL(irp_list[i], irp);
  169. TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, irp->status);
  170. TEST_ASSERT_GREATER_THAN(0, irp->actual_num_bytes);
  171. TEST_ASSERT_EQUAL(IRP_CONTEXT_VAL, irp->context);
  172. }
  173. //Free IRP list and pipe
  174. for (int i = 0; i < NUM_IRPS; i++) {
  175. test_hcd_free_irp(irp_list[i]);
  176. }
  177. test_hcd_pipe_free(default_pipe);
  178. //Cleanup
  179. test_hcd_wait_for_disconn(port_hdl, false);
  180. test_hcd_teardown(port_hdl);
  181. }
  182. /*
  183. Test control pipe run-time halt and clear
  184. Purpose:
  185. - Test that a control pipe can be halted with HCD_PIPE_CMD_HALT whilst there are ongoing IRPs
  186. - Test that a control pipe can be un-halted with a HCD_PIPE_CMD_CLEAR
  187. - Test that enqueued IRPs are resumed when pipe is un-halted
  188. Procedure:
  189. - Setup HCD and wait for connection
  190. - Setup default pipe and allocate IRPs
  191. - Enqqueue IRPs but execute a HCD_PIPE_CMD_HALT command immediately after. Halt command should let on
  192. the current going IRP finish before actually halting the pipe.
  193. - Un-halt the pipe a HCD_PIPE_CMD_HALT command. Enqueued IRPs will be resumed
  194. - Check that all IRPs have completed successfully
  195. - Dequeue IRPs and teardown
  196. */
  197. TEST_CASE("Test HCD control pipe runtime halt and clear", "[hcd][ignore]")
  198. {
  199. hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
  200. usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
  201. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  202. //Allocate some IRPs and initialize their data buffers with control transfers
  203. 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)
  204. usb_irp_t *irp_list[NUM_IRPS];
  205. for (int i = 0; i < NUM_IRPS; i++) {
  206. irp_list[i] = test_hcd_alloc_irp(0, IRP_DATA_BUFF_SIZE);
  207. //Initialize with a "Get Config Descriptor request"
  208. irp_list[i]->num_bytes = TRANSFER_MAX_BYTES;
  209. USB_CTRL_REQ_INIT_GET_CFG_DESC((usb_ctrl_req_t *)irp_list[i]->data_buffer, 0, TRANSFER_MAX_BYTES);
  210. irp_list[i]->context = IRP_CONTEXT_VAL;
  211. }
  212. //Enqueue IRPs but immediately halt the pipe
  213. printf("Enqueuing IRPs\n");
  214. for (int i = 0; i < NUM_IRPS; i++) {
  215. TEST_ASSERT_EQUAL(ESP_OK, hcd_irp_enqueue(default_pipe, irp_list[i]));
  216. }
  217. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT));
  218. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe));
  219. printf("Pipe halted\n");
  220. //Un-halt the pipe
  221. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR));
  222. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe));
  223. printf("Pipe cleared\n");
  224. vTaskDelay(pdMS_TO_TICKS(100)); //Give some time pending for transfers to restart and complete
  225. //Wait for each IRP to be done, dequeue, and check results
  226. for (int i = 0; i < NUM_IRPS; i++) {
  227. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_IRP_DONE);
  228. usb_irp_t *irp = hcd_irp_dequeue(default_pipe);
  229. TEST_ASSERT_EQUAL(irp_list[i], irp);
  230. TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, irp->status);
  231. TEST_ASSERT_GREATER_THAN(0, irp->actual_num_bytes);
  232. TEST_ASSERT_EQUAL(IRP_CONTEXT_VAL, irp->context);
  233. }
  234. //Free IRP list and pipe
  235. for (int i = 0; i < NUM_IRPS; i++) {
  236. test_hcd_free_irp(irp_list[i]);
  237. }
  238. test_hcd_pipe_free(default_pipe);
  239. //Cleanup
  240. test_hcd_wait_for_disconn(port_hdl, false);
  241. test_hcd_teardown(port_hdl);
  242. }