test_hcd_ctrl.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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_setup_packet_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 = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES;
  51. USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_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, check, and print
  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. //We must have transmitted at least the setup packet, but device may return less than bytes requested
  70. TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes);
  71. TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes);
  72. usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t));
  73. TEST_ASSERT_EQUAL(USB_B_DESCRIPTOR_TYPE_CONFIGURATION , config_desc->bDescriptorType);
  74. printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength);
  75. }
  76. //Enqueue URBs again but abort them short after
  77. for (int i = 0; i < NUM_URBS; i++) {
  78. TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i]));
  79. }
  80. for (int i = 0; i < NUM_URBS; i++) {
  81. TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_abort(urb_list[i]));
  82. }
  83. vTaskDelay(pdMS_TO_TICKS(100)); //Give some time for any inflight transfers to complete
  84. //Wait for the URBs to complete and dequeue them, then check results
  85. //Dequeue URBs
  86. for (int i = 0; i < NUM_URBS; i++) {
  87. urb_t *urb = hcd_urb_dequeue(default_pipe);
  88. //No need to check for URB pointer address as they may be out of order
  89. TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED);
  90. if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) {
  91. //We must have transmitted at least the setup packet, but device may return less than bytes requested
  92. TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes);
  93. TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes);
  94. } else {
  95. //A failed transfer should 0 actual number of bytes transmitted
  96. TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes);
  97. }
  98. TEST_ASSERT_EQUAL(urb->transfer.context, URB_CONTEXT_VAL);
  99. }
  100. //Free URB list and pipe
  101. for (int i = 0; i < NUM_URBS; i++) {
  102. test_hcd_free_urb(urb_list[i]);
  103. }
  104. test_hcd_pipe_free(default_pipe);
  105. //Cleanup
  106. test_hcd_wait_for_disconn(port_hdl, false);
  107. test_hcd_teardown(port_hdl);
  108. }
  109. /*
  110. Test HCD control pipe STALL condition, abort, and clear
  111. Purpose:
  112. - Test that a control pipe can react to a STALL (i.e., a HCD_PIPE_EVENT_ERROR_STALL event)
  113. - The HCD_PIPE_CMD_FLUSH can retire all URBs
  114. - Pipe clear command can return the pipe to being active
  115. Procedure:
  116. - Setup HCD and wait for connection
  117. - Setup default pipe and allocate URBs
  118. - Corrupt the first URB so that it will trigger a STALL, then enqueue all the URBs
  119. - Check that a HCD_PIPE_EVENT_ERROR_STALL event is triggered
  120. - Check that all URBs can be retired using HCD_PIPE_CMD_FLUSH, a HCD_PIPE_EVENT_URB_DONE event should be generated
  121. - Check that the STALL can be cleared by using HCD_PIPE_CMD_CLEAR
  122. - Fix the corrupt first URB and retry the URBs
  123. - Dequeue URBs
  124. - Teardown
  125. */
  126. TEST_CASE("Test HCD control pipe STALL", "[hcd][ignore]")
  127. {
  128. hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
  129. usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
  130. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  131. //Allocate some URBs and initialize their data buffers with control transfers
  132. 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)
  133. urb_t *urb_list[NUM_URBS];
  134. for (int i = 0; i < NUM_URBS; i++) {
  135. urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE);
  136. //Initialize with a "Get Config Descriptor request"
  137. urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES;
  138. USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES);
  139. urb_list[i]->transfer.context = URB_CONTEXT_VAL;
  140. }
  141. //Corrupt the first URB so that it triggers a STALL
  142. ((usb_setup_packet_t *)urb_list[0]->transfer.data_buffer)->bRequest = 0xAA;
  143. //Enqueue URBs. A STALL should occur
  144. int num_enqueued = 0;
  145. for (int i = 0; i < NUM_URBS; i++) {
  146. if (hcd_urb_enqueue(default_pipe, urb_list[i]) != ESP_OK) {
  147. //STALL may occur before we are done enqueing
  148. break;
  149. }
  150. num_enqueued++;
  151. }
  152. TEST_ASSERT_GREATER_THAN(0, num_enqueued);
  153. printf("Expecting STALL\n");
  154. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_ERROR_STALL);
  155. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe));
  156. //Call the pipe abort command to retire all URBs then dequeue them all
  157. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_FLUSH));
  158. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE);
  159. for (int i = 0; i < num_enqueued; i++) {
  160. urb_t *urb = hcd_urb_dequeue(default_pipe);
  161. TEST_ASSERT_EQUAL(urb_list[i], urb);
  162. TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_STALL || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED);
  163. if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) {
  164. //We must have transmitted at least the setup packet, but device may return less than bytes requested
  165. TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes);
  166. TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes);
  167. } else {
  168. //A failed transfer should 0 actual number of bytes transmitted
  169. TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes);
  170. }
  171. TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
  172. }
  173. //Call the clear command to un-stall the pipe
  174. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR));
  175. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe));
  176. printf("Retrying\n");
  177. //Correct first URB then requeue
  178. USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[0]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES);
  179. for (int i = 0; i < NUM_URBS; i++) {
  180. TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i]));
  181. }
  182. //Wait for each URB to be done, deequeue, and check results
  183. for (int i = 0; i < NUM_URBS; i++) {
  184. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE);
  185. //expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_URB_DONE);
  186. urb_t *urb = hcd_urb_dequeue(default_pipe);
  187. TEST_ASSERT_EQUAL(urb_list[i], urb);
  188. TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, urb->transfer.status);
  189. TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
  190. //We must have transmitted at least the setup packet, but device may return less than bytes requested
  191. TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes);
  192. TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes);
  193. usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t));
  194. TEST_ASSERT_EQUAL(USB_B_DESCRIPTOR_TYPE_CONFIGURATION , config_desc->bDescriptorType);
  195. printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength);
  196. }
  197. //Free URB list and pipe
  198. for (int i = 0; i < NUM_URBS; i++) {
  199. test_hcd_free_urb(urb_list[i]);
  200. }
  201. test_hcd_pipe_free(default_pipe);
  202. //Cleanup
  203. test_hcd_wait_for_disconn(port_hdl, false);
  204. test_hcd_teardown(port_hdl);
  205. }
  206. /*
  207. Test control pipe run-time halt and clear
  208. Purpose:
  209. - Test that a control pipe can be halted with HCD_PIPE_CMD_HALT whilst there are ongoing URBs
  210. - Test that a control pipe can be un-halted with a HCD_PIPE_CMD_CLEAR
  211. - Test that enqueued URBs are resumed when pipe is un-halted
  212. Procedure:
  213. - Setup HCD and wait for connection
  214. - Setup default pipe and allocate URBs
  215. - Enqqueue URBs but execute a HCD_PIPE_CMD_HALT command immediately after.
  216. - Halt command should immediately halt the current URB and generate a HCD_PIPE_EVENT_URB_DONE
  217. - Other pending URBs should be untouched.
  218. - Un-halt the pipe using a HCD_PIPE_CMD_CLEAR command. Enqueued URBs will be resumed
  219. - Check that all URBs have completed successfully
  220. - Dequeue URBs and teardown
  221. */
  222. TEST_CASE("Test HCD control pipe runtime halt and clear", "[hcd][ignore]")
  223. {
  224. hcd_port_handle_t port_hdl = test_hcd_setup(); //Setup the HCD and port
  225. usb_speed_t port_speed = test_hcd_wait_for_conn(port_hdl); //Trigger a connection
  226. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  227. //Allocate some URBs and initialize their data buffers with control transfers
  228. 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)
  229. urb_t *urb_list[NUM_URBS];
  230. for (int i = 0; i < NUM_URBS; i++) {
  231. urb_list[i] = test_hcd_alloc_urb(0, URB_DATA_BUFF_SIZE);
  232. //Initialize with a "Get Config Descriptor request"
  233. urb_list[i]->transfer.num_bytes = sizeof(usb_setup_packet_t) + TRANSFER_MAX_BYTES;
  234. USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)urb_list[i]->transfer.data_buffer, 0, TRANSFER_MAX_BYTES);
  235. urb_list[i]->transfer.context = URB_CONTEXT_VAL;
  236. }
  237. //Enqueue URBs but immediately halt the pipe
  238. printf("Enqueuing URBs\n");
  239. for (int i = 0; i < NUM_URBS; i++) {
  240. TEST_ASSERT_EQUAL(ESP_OK, hcd_urb_enqueue(default_pipe, urb_list[i]));
  241. }
  242. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT));
  243. test_hcd_expect_pipe_event(default_pipe, HCD_PIPE_EVENT_URB_DONE);
  244. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe));
  245. printf("Pipe halted\n");
  246. //Un-halt the pipe
  247. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR));
  248. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe));
  249. printf("Pipe cleared\n");
  250. vTaskDelay(pdMS_TO_TICKS(100)); //Give some time pending for transfers to restart and complete
  251. //Wait for each URB to be done, dequeue, and check results
  252. for (int i = 0; i < NUM_URBS; i++) {
  253. urb_t *urb = hcd_urb_dequeue(default_pipe);
  254. TEST_ASSERT_EQUAL(urb_list[i], urb);
  255. TEST_ASSERT(urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED || urb->transfer.status == USB_TRANSFER_STATUS_CANCELED);
  256. if (urb->transfer.status == USB_TRANSFER_STATUS_COMPLETED) {
  257. //We must have transmitted at least the setup packet, but device may return less than bytes requested
  258. TEST_ASSERT_GREATER_OR_EQUAL(sizeof(usb_setup_packet_t), urb->transfer.actual_num_bytes);
  259. TEST_ASSERT_LESS_OR_EQUAL(urb->transfer.num_bytes, urb->transfer.actual_num_bytes);
  260. usb_config_desc_t *config_desc = (usb_config_desc_t *)(urb->transfer.data_buffer + sizeof(usb_setup_packet_t));
  261. TEST_ASSERT_EQUAL(USB_B_DESCRIPTOR_TYPE_CONFIGURATION , config_desc->bDescriptorType);
  262. printf("Config Desc wTotalLength %d\n", config_desc->wTotalLength);
  263. } else {
  264. //A failed transfer should 0 actual number of bytes transmitted
  265. TEST_ASSERT_EQUAL(0, urb->transfer.actual_num_bytes);
  266. }
  267. TEST_ASSERT_EQUAL(URB_CONTEXT_VAL, urb->transfer.context);
  268. }
  269. //Free URB list and pipe
  270. for (int i = 0; i < NUM_URBS; i++) {
  271. test_hcd_free_urb(urb_list[i]);
  272. }
  273. test_hcd_pipe_free(default_pipe);
  274. //Cleanup
  275. test_hcd_wait_for_disconn(port_hdl, false);
  276. test_hcd_teardown(port_hdl);
  277. }