test_hcd.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  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 "esp_intr_alloc.h"
  19. #include "esp_err.h"
  20. #include "esp_attr.h"
  21. #include "esp_rom_gpio.h"
  22. #include "soc/gpio_pins.h"
  23. #include "soc/gpio_sig_map.h"
  24. #include "hal/usbh_ll.h"
  25. #include "hcd.h"
  26. // -------------------------------------------------- PHY Control ------------------------------------------------------
  27. static void phy_force_conn_state(bool connected, TickType_t delay_ticks)
  28. {
  29. vTaskDelay(delay_ticks);
  30. usb_wrap_dev_t *wrap = &USB_WRAP;
  31. if (connected) {
  32. //Swap back to internal PHY that is connected to a devicee
  33. wrap->otg_conf.phy_sel = 0;
  34. } else {
  35. //Set externa PHY input signals to fixed voltage levels mimicing a disconnected state
  36. esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_EXTPHY_VP_IDX, false);
  37. esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_EXTPHY_VM_IDX, false);
  38. esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_EXTPHY_RCV_IDX, false);
  39. //Swap to the external PHY
  40. wrap->otg_conf.phy_sel = 1;
  41. }
  42. }
  43. // ------------------------------------------------ Helper Functions ---------------------------------------------------
  44. #define EVENT_QUEUE_LEN 5
  45. #define NUM_XFER_REQS 3
  46. #define XFER_DATA_MAX_LEN 256 //Just assume that will only IN/OUT 256 bytes for now
  47. #define PORT_NUM 1
  48. typedef struct {
  49. hcd_port_handle_t port_hdl;
  50. hcd_port_event_t port_event;
  51. } port_event_msg_t;
  52. typedef struct {
  53. hcd_pipe_handle_t pipe_hdl;
  54. hcd_pipe_event_t pipe_event;
  55. } pipe_event_msg_t;
  56. static bool port_callback(hcd_port_handle_t port_hdl, hcd_port_event_t port_event, void *user_arg, bool in_isr)
  57. {
  58. QueueHandle_t port_evt_queue = (QueueHandle_t)user_arg;
  59. TEST_ASSERT(in_isr); //Current HCD implementation should never call a port callback in a task context
  60. port_event_msg_t msg = {
  61. .port_hdl = port_hdl,
  62. .port_event = port_event,
  63. };
  64. BaseType_t xTaskWoken = pdFALSE;
  65. xQueueSendFromISR(port_evt_queue, &msg, &xTaskWoken);
  66. return (xTaskWoken == pdTRUE);
  67. }
  68. static bool pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_event, void *user_arg, bool in_isr)
  69. {
  70. QueueHandle_t pipe_evt_queue = (QueueHandle_t)user_arg;
  71. pipe_event_msg_t msg = {
  72. .pipe_hdl = pipe_hdl,
  73. .pipe_event = pipe_event,
  74. };
  75. if (in_isr) {
  76. BaseType_t xTaskWoken = pdFALSE;
  77. xQueueSendFromISR(pipe_evt_queue, &msg, &xTaskWoken);
  78. return (xTaskWoken == pdTRUE);
  79. } else {
  80. xQueueSend(pipe_evt_queue, &msg, portMAX_DELAY);
  81. return false;
  82. }
  83. }
  84. static void expect_port_event(QueueHandle_t port_evt_queue, hcd_port_handle_t expected_hdl, hcd_port_event_t expected_event)
  85. {
  86. port_event_msg_t msg;
  87. xQueueReceive(port_evt_queue, &msg, portMAX_DELAY);
  88. TEST_ASSERT_EQUAL(expected_hdl, msg.port_hdl);
  89. TEST_ASSERT_EQUAL(expected_event, msg.port_event);
  90. printf("\t-> Port event\n");
  91. }
  92. static void expect_pipe_event(QueueHandle_t pipe_evt_queue, hcd_pipe_handle_t expected_hdl, hcd_pipe_event_t expected_event)
  93. {
  94. pipe_event_msg_t msg;
  95. xQueueReceive(pipe_evt_queue, &msg, portMAX_DELAY);
  96. TEST_ASSERT_EQUAL(expected_hdl, msg.pipe_hdl);
  97. TEST_ASSERT_EQUAL(expected_event, msg.pipe_event);
  98. }
  99. /**
  100. * @brief Creates port and pipe event queues. Sets up the HCD, and initializes a port.
  101. *
  102. * @param[out] port_evt_queue Port event queue
  103. * @param[out] pipe_evt_queue Pipe event queue
  104. * @param[out] port_hdl Port handle
  105. */
  106. static void setup(QueueHandle_t *port_evt_queue, QueueHandle_t *pipe_evt_queue, hcd_port_handle_t *port_hdl)
  107. {
  108. *port_evt_queue = xQueueCreate(EVENT_QUEUE_LEN, sizeof(port_event_msg_t));
  109. *pipe_evt_queue = xQueueCreate(EVENT_QUEUE_LEN, sizeof(pipe_event_msg_t));
  110. TEST_ASSERT_NOT_EQUAL(NULL, *port_evt_queue);
  111. TEST_ASSERT_NOT_EQUAL(NULL, *pipe_evt_queue);
  112. //Install HCD
  113. hcd_config_t config = {
  114. .intr_flags = ESP_INTR_FLAG_LEVEL1,
  115. };
  116. TEST_ASSERT_EQUAL(ESP_OK, hcd_install(&config));
  117. //Initialize a port
  118. hcd_port_config_t port_config = {
  119. .callback = port_callback,
  120. .callback_arg = (void *)*port_evt_queue,
  121. .context = NULL,
  122. };
  123. TEST_ASSERT_EQUAL(ESP_OK, hcd_port_init(PORT_NUM, &port_config, port_hdl));
  124. TEST_ASSERT_NOT_EQUAL(NULL, *port_hdl);
  125. TEST_ASSERT_EQUAL(HCD_PORT_STATE_NOT_POWERED, hcd_port_get_state(*port_hdl));
  126. phy_force_conn_state(false, 0); //Force disconnected state on PHY
  127. }
  128. /**
  129. * @brief Deinitializes the port, uninstalls HCD, and frees port and pipe event queues
  130. *
  131. * @param[in] port_evt_queue Port event queue
  132. * @param[in] pipe_evt_queue Pipe event semaphore
  133. * @param[in] port_hdl Port handle
  134. */
  135. static void teardown(QueueHandle_t port_evt_queue, QueueHandle_t pipe_evt_queue, hcd_port_handle_t port_hdl)
  136. {
  137. //Deinitialize a port
  138. TEST_ASSERT_EQUAL(ESP_OK, hcd_port_deinit(port_hdl));
  139. //Uninstall the HCD
  140. TEST_ASSERT_EQUAL(ESP_OK, hcd_uninstall());
  141. vQueueDelete(port_evt_queue);
  142. vQueueDelete(pipe_evt_queue);
  143. }
  144. /**
  145. * @brief Powers ON a port and waits for a connection, then resets the connected device
  146. *
  147. * @param port_hdl Port handle
  148. * @param port_evt_queue Port event queue
  149. */
  150. static void wait_for_connection(hcd_port_handle_t port_hdl, QueueHandle_t port_evt_queue)
  151. {
  152. //Power ON the port
  153. TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_POWER_ON));
  154. TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISCONNECTED, hcd_port_get_state(port_hdl));
  155. //Wait for connection event
  156. printf("Waiting for conenction\n");
  157. phy_force_conn_state(true, pdMS_TO_TICKS(100)); //Allow for connected state on PHY
  158. expect_port_event(port_evt_queue, port_hdl, HCD_PORT_EVENT_CONNECTION);
  159. TEST_ASSERT_EQUAL(HCD_PORT_EVENT_CONNECTION, hcd_port_handle_event(port_hdl));
  160. TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISABLED, hcd_port_get_state(port_hdl));
  161. //Reset newly connected device
  162. printf("Resetting\n");
  163. TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_RESET));
  164. TEST_ASSERT_EQUAL(HCD_PORT_STATE_ENABLED, hcd_port_get_state(port_hdl));
  165. //Get speed of conencted
  166. usb_speed_t port_speed;
  167. TEST_ASSERT_EQUAL(ESP_OK, hcd_port_get_speed(port_hdl, &port_speed));
  168. if (port_speed == USB_SPEED_FULL) {
  169. printf("Full speed enabled\n");
  170. } else {
  171. printf("Low speed enabled\n");
  172. }
  173. }
  174. /**
  175. * @brief Disables the port, waits for a disconnection, then powers OFF the port
  176. *
  177. * @param port_hdl Port handle
  178. * @param port_evt_queue Port event queue
  179. * @param already_disabled If the port is already disabled, it will skip disabling the port
  180. */
  181. static void wait_for_disconnection(hcd_port_handle_t port_hdl, QueueHandle_t port_evt_queue, bool already_disabled)
  182. {
  183. if (!already_disabled) {
  184. //Disable the device
  185. printf("Disabling\n");
  186. TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_DISABLE));
  187. TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISABLED, hcd_port_get_state(port_hdl));
  188. }
  189. //Wait for a safe disconnect
  190. printf("Waiting for disconnection\n");
  191. phy_force_conn_state(false, pdMS_TO_TICKS(100)); //Force disconnected state on PHY
  192. expect_port_event(port_evt_queue, port_hdl, HCD_PORT_EVENT_DISCONNECTION);
  193. TEST_ASSERT_EQUAL(HCD_PORT_EVENT_DISCONNECTION, hcd_port_handle_event(port_hdl));
  194. TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISCONNECTED, hcd_port_get_state(port_hdl));
  195. //Power down the port
  196. TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_POWER_OFF));
  197. TEST_ASSERT_EQUAL(HCD_PORT_STATE_NOT_POWERED, hcd_port_get_state(port_hdl));
  198. }
  199. static void alloc_pipe_and_xfer_reqs(hcd_port_handle_t port_hdl,
  200. QueueHandle_t pipe_evt_queue,
  201. hcd_pipe_handle_t *pipe_hdl,
  202. hcd_xfer_req_handle_t *req_hdls,
  203. uint8_t **data_buffers,
  204. usb_irp_t **irps,
  205. int num_xfers)
  206. {
  207. //We don't support hubs yet. Just get the speed of the port to determine the speed of the device
  208. usb_speed_t port_speed;
  209. TEST_ASSERT_EQUAL(ESP_OK, hcd_port_get_speed(port_hdl, &port_speed));
  210. //Create default pipe
  211. printf("Creating default pipe\n");
  212. hcd_pipe_config_t config = {
  213. .callback = pipe_callback,
  214. .callback_arg = (void *)pipe_evt_queue,
  215. .context = NULL,
  216. .ep_desc = NULL, //NULL EP descriptor to create a default pipe
  217. .dev_addr = 0,
  218. .dev_speed = port_speed,
  219. };
  220. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_alloc(port_hdl, &config, pipe_hdl));
  221. TEST_ASSERT_NOT_EQUAL(NULL, *pipe_hdl);
  222. //Create transfer requests (and other required objects such as IRPs and data buffers)
  223. printf("Creating transfer requests\n");
  224. for (int i = 0; i < num_xfers; i++) {
  225. //Allocate transfer request object
  226. req_hdls[i] = hcd_xfer_req_alloc();
  227. TEST_ASSERT_NOT_EQUAL(NULL, req_hdls[i]);
  228. //Allocate data buffers
  229. data_buffers[i] = heap_caps_malloc(sizeof(usb_ctrl_req_t) + XFER_DATA_MAX_LEN, MALLOC_CAP_DMA);
  230. TEST_ASSERT_NOT_EQUAL(NULL, data_buffers[i]);
  231. //Allocate IRP object
  232. irps[i] = heap_caps_malloc(sizeof(usb_irp_t), MALLOC_CAP_DEFAULT);
  233. TEST_ASSERT_NOT_EQUAL(NULL, irps[i]);
  234. //Set the transfer request's target
  235. hcd_xfer_req_set_target(req_hdls[i], *pipe_hdl, irps[i], NULL);
  236. }
  237. }
  238. static void free_pipe_and_xfer_reqs(hcd_pipe_handle_t pipe_hdl,
  239. hcd_xfer_req_handle_t *req_hdls,
  240. uint8_t **data_buffers,
  241. usb_irp_t **irps,
  242. int num_xfers)
  243. {
  244. printf("Freeing transfer requets\n");
  245. //Free transfer requests (and their associated objects such as IRPs and data buffers)
  246. for (int i = 0; i < num_xfers; i++) {
  247. heap_caps_free(irps[i]);
  248. heap_caps_free(data_buffers[i]);
  249. hcd_xfer_req_free(req_hdls[i]);
  250. }
  251. printf("Freeing default pipe\n");
  252. //Delete the pipe
  253. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_free(pipe_hdl));
  254. }
  255. // ------------------------------------------------ Host Port Tests ----------------------------------------------------
  256. /*
  257. Test a port sudden disconnect and port recovery
  258. Purpose: Test that when sudden disconnection happens on an HCD port, the port will
  259. - Generate the HCD_PORT_EVENT_SUDDEN_DISCONN and be put into the HCD_PORT_STATE_RECOVERY state
  260. - Ongoing transfers requests and pipes are handled correctly
  261. Procedure:
  262. - Setup HCD, a default pipe, and multiple transfer requests
  263. - Start transfers but immediately trigger a disconnect
  264. - Check that HCD_PORT_EVENT_SUDDEN_DISCONN event is generated
  265. - Check that default pipe is invalid and transfer requests can be dequeued
  266. - Recover the port and try to connect then disconnect again (to make sure the port works port recovery)
  267. - Teardown HCD
  268. */
  269. TEST_CASE("Test HCD port sudden disconnect", "[hcd][ignore]")
  270. {
  271. QueueHandle_t port_evt_queue;
  272. QueueHandle_t pipe_evt_queue;
  273. hcd_port_handle_t port_hdl;
  274. setup(&port_evt_queue, &pipe_evt_queue, &port_hdl);
  275. wait_for_connection(port_hdl, port_evt_queue);
  276. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  277. //Allocate transfer requests
  278. hcd_pipe_handle_t default_pipe;
  279. hcd_xfer_req_handle_t req_hdls[NUM_XFER_REQS];
  280. uint8_t *data_buffers[NUM_XFER_REQS];
  281. usb_irp_t *irps[NUM_XFER_REQS];
  282. alloc_pipe_and_xfer_reqs(port_hdl, pipe_evt_queue, &default_pipe, req_hdls, data_buffers, irps, NUM_XFER_REQS);
  283. //Initialize transfer requests to send a "Get Device Descriptor" request
  284. for (int i = 0; i < NUM_XFER_REQS; i++) {
  285. irps[i]->num_bytes = 64; //1 worst case MPS
  286. USB_CTRL_REQ_INIT_GET_CFG_DESC((usb_ctrl_req_t *) data_buffers[i], 0, XFER_DATA_MAX_LEN);
  287. irps[i]->data_buffer = data_buffers[i];
  288. irps[i]->num_iso_packets = 0;
  289. }
  290. //Enqueue those transfer requests
  291. for (int i = 0; i < NUM_XFER_REQS; i++) {
  292. TEST_ASSERT_EQUAL(ESP_OK, hcd_xfer_req_enqueue(req_hdls[i]));
  293. }
  294. phy_force_conn_state(false, 0); //Force disconnected state on PHY
  295. expect_port_event(port_evt_queue, port_hdl, HCD_PORT_EVENT_SUDDEN_DISCONN);
  296. TEST_ASSERT_EQUAL(HCD_PORT_EVENT_SUDDEN_DISCONN, hcd_port_handle_event(port_hdl));
  297. TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl));
  298. printf("Sudden disconnect\n");
  299. //Handling the disconenction event should have invalidated all pipes.
  300. //Pipe should have received (zero or more HCD_PIPE_EVENT_XFER_REQ_DONE) followed by a HCD_PIPE_EVENT_INVALID (MUST OCCUR)
  301. int num_pipe_events = EVENT_QUEUE_LEN - uxQueueSpacesAvailable(pipe_evt_queue);
  302. for (int i = 0; i < num_pipe_events - 1; i++) {
  303. expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_XFER_REQ_DONE);
  304. }
  305. expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_INVALID);
  306. TEST_ASSERT_EQUAL(hcd_pipe_get_state(default_pipe), HCD_PIPE_STATE_INVALID);
  307. //Dequeue transfer requests
  308. for (int i = 0; i < NUM_XFER_REQS; i++) {
  309. hcd_xfer_req_handle_t req_hdl = hcd_xfer_req_dequeue(default_pipe);
  310. hcd_pipe_handle_t pipe_hdl;
  311. usb_irp_t *irp;
  312. void *context;
  313. hcd_xfer_req_get_target(req_hdl, &pipe_hdl, &irp, &context);
  314. TEST_ASSERT_EQUAL(default_pipe, pipe_hdl);
  315. TEST_ASSERT_EQUAL(irps[i], irp);
  316. TEST_ASSERT(irp->status == USB_TRANSFER_STATUS_COMPLETED || irp->status == USB_TRANSFER_STATUS_NO_DEVICE);
  317. TEST_ASSERT_EQUAL(NULL, context);
  318. }
  319. //Free transfer requests
  320. free_pipe_and_xfer_reqs(default_pipe, req_hdls, data_buffers, irps, NUM_XFER_REQS);
  321. //Recover the port should return to the to NOT POWERED state
  322. TEST_ASSERT_EQUAL(ESP_OK, hcd_port_recover(port_hdl));
  323. TEST_ASSERT_EQUAL(HCD_PORT_STATE_NOT_POWERED, hcd_port_get_state(port_hdl));
  324. //Recovered port should be able to connect and disconenct again
  325. wait_for_connection(port_hdl, port_evt_queue);
  326. wait_for_disconnection(port_hdl, port_evt_queue, false);
  327. teardown(port_evt_queue, pipe_evt_queue, port_hdl);
  328. }
  329. /*
  330. Test port suspend and resume with active pipes
  331. Purpose:
  332. - Test p[ort suspend and resume commands work correctly whilst there are active pipes with ongoing transfers
  333. - When suspending, the pipes should be allowed to finish their current ongoing transfer before the bus is suspended.
  334. - When resuming, pipes with pending transfer should be started after the bus is resumed.
  335. Procedure:
  336. - Setup HCD, a port, a default pipe, and multiple transfer requests
  337. - Start transfers but immediately suspend the port
  338. - Resume the port
  339. - Check all transfer requests have also be resumed and completed on port resume
  340. - Teardown
  341. */
  342. TEST_CASE("Test HCD port suspend and resume", "[hcd][ignore]")
  343. {
  344. QueueHandle_t port_evt_queue;
  345. QueueHandle_t pipe_evt_queue;
  346. hcd_port_handle_t port_hdl;
  347. setup(&port_evt_queue, &pipe_evt_queue, &port_hdl);
  348. wait_for_connection(port_hdl, port_evt_queue);
  349. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  350. //Allocate transfer requests
  351. hcd_pipe_handle_t default_pipe;
  352. hcd_xfer_req_handle_t req_hdls[NUM_XFER_REQS];
  353. uint8_t *data_buffers[NUM_XFER_REQS];
  354. usb_irp_t *irps[NUM_XFER_REQS];
  355. alloc_pipe_and_xfer_reqs(port_hdl, pipe_evt_queue, &default_pipe, req_hdls, data_buffers, irps, NUM_XFER_REQS);
  356. //Initialize transfer requests to send a "Get Device Descriptor" request
  357. for (int i = 0; i < NUM_XFER_REQS; i++) {
  358. irps[i]->num_bytes = 64; //1 worst case MPS
  359. USB_CTRL_REQ_INIT_GET_CFG_DESC((usb_ctrl_req_t *) data_buffers[i], 0, XFER_DATA_MAX_LEN);
  360. irps[i]->data_buffer = data_buffers[i];
  361. irps[i]->num_iso_packets = 0;
  362. }
  363. //Enqueue those transfer requests
  364. for (int i = 0; i < NUM_XFER_REQS; i++) {
  365. TEST_ASSERT_EQUAL(ESP_OK, hcd_xfer_req_enqueue(req_hdls[i]));
  366. }
  367. //Immediately suspend the bus whilst pies are active
  368. TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_SUSPEND));
  369. TEST_ASSERT_EQUAL(HCD_PORT_STATE_SUSPENDED, hcd_port_get_state(port_hdl));
  370. printf("Suspended\n");
  371. vTaskDelay(pdMS_TO_TICKS(100));
  372. TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_RESUME));
  373. TEST_ASSERT_EQUAL(HCD_PORT_STATE_ENABLED, hcd_port_get_state(port_hdl));
  374. vTaskDelay(pdMS_TO_TICKS(100)); //Give some time for resumed transfers to complete
  375. expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_XFER_REQ_DONE);
  376. //Dequeue transfer requests
  377. for (int i = 0; i < NUM_XFER_REQS; i++) {
  378. hcd_xfer_req_handle_t req_hdl = hcd_xfer_req_dequeue(default_pipe);
  379. hcd_pipe_handle_t pipe_hdl;
  380. usb_irp_t *irp;
  381. void *context;
  382. hcd_xfer_req_get_target(req_hdl, &pipe_hdl, &irp, &context);
  383. TEST_ASSERT_EQUAL(default_pipe, pipe_hdl);
  384. TEST_ASSERT_EQUAL(irps[i], irp);
  385. TEST_ASSERT(irp->status == USB_TRANSFER_STATUS_COMPLETED);
  386. TEST_ASSERT_EQUAL(NULL, context);
  387. }
  388. //Free transfer requests
  389. free_pipe_and_xfer_reqs(default_pipe, req_hdls, data_buffers, irps, NUM_XFER_REQS);
  390. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  391. wait_for_disconnection(port_hdl, port_evt_queue, false);
  392. teardown(port_evt_queue, pipe_evt_queue, port_hdl);
  393. }
  394. /*
  395. Test HCD port disable with active pipes
  396. Purpose:
  397. - Test that the port disable command works correctly with active pipes
  398. - Pipes should be to finish their current ongoing transfer before port is disabled
  399. - After disabling the port, all pipes should become invalid.
  400. Procedure:
  401. - Setup HCD, a default pipe, and multiple transfer requests
  402. - Start transfers but immediately disable the port
  403. - Check pipe received invalid event
  404. - Check that transfer are either done or not executed
  405. - Teardown
  406. */
  407. TEST_CASE("Test HCD port disable", "[hcd][ignore]")
  408. {
  409. QueueHandle_t port_evt_queue;
  410. QueueHandle_t pipe_evt_queue;
  411. hcd_port_handle_t port_hdl;
  412. setup(&port_evt_queue, &pipe_evt_queue, &port_hdl);
  413. wait_for_connection(port_hdl, port_evt_queue);
  414. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  415. //Allocate transfer requests
  416. hcd_pipe_handle_t default_pipe;
  417. hcd_xfer_req_handle_t req_hdls[NUM_XFER_REQS];
  418. uint8_t *data_buffers[NUM_XFER_REQS];
  419. usb_irp_t *irps[NUM_XFER_REQS];
  420. alloc_pipe_and_xfer_reqs(port_hdl, pipe_evt_queue, &default_pipe, req_hdls, data_buffers, irps, NUM_XFER_REQS);
  421. //Initialize transfer requests to send a "Get Device Descriptor" request
  422. for (int i = 0; i < NUM_XFER_REQS; i++) {
  423. irps[i]->num_bytes = 64; //1 worst case MPS
  424. USB_CTRL_REQ_INIT_GET_CFG_DESC((usb_ctrl_req_t *) data_buffers[i], 0, XFER_DATA_MAX_LEN);
  425. irps[i]->data_buffer = data_buffers[i];
  426. irps[i]->num_iso_packets = 0;
  427. }
  428. //Enqueue those transfer requests
  429. for (int i = 0; i < NUM_XFER_REQS; i++) {
  430. TEST_ASSERT_EQUAL(ESP_OK, hcd_xfer_req_enqueue(req_hdls[i]));
  431. }
  432. //Immediately disable port
  433. TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_DISABLE));
  434. TEST_ASSERT_EQUAL(HCD_PORT_STATE_DISABLED, hcd_port_get_state(port_hdl));
  435. printf("Disabled\n");
  436. //Pipe should have received (zero or more HCD_PIPE_EVENT_XFER_REQ_DONE) followed by a HCD_PIPE_EVENT_INVALID (MUST OCCUR)
  437. int num_pipe_events = EVENT_QUEUE_LEN - uxQueueSpacesAvailable(pipe_evt_queue);
  438. for (int i = 0; i < num_pipe_events - 1; i++) {
  439. expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_XFER_REQ_DONE);
  440. }
  441. expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_INVALID);
  442. for (int i = 0; i < NUM_XFER_REQS; i++) {
  443. hcd_xfer_req_handle_t req_hdl = hcd_xfer_req_dequeue(default_pipe);
  444. hcd_pipe_handle_t pipe_hdl;
  445. usb_irp_t *irp;
  446. void *context;
  447. hcd_xfer_req_get_target(req_hdl, &pipe_hdl, &irp, &context);
  448. TEST_ASSERT_EQUAL(default_pipe, pipe_hdl);
  449. TEST_ASSERT_EQUAL(irps[i], irp);
  450. TEST_ASSERT(irp->status == USB_TRANSFER_STATUS_COMPLETED || irp->status == USB_TRANSFER_STATUS_NO_DEVICE);
  451. TEST_ASSERT_EQUAL(NULL, context);
  452. }
  453. //Free transfer requests
  454. free_pipe_and_xfer_reqs(default_pipe, req_hdls, data_buffers, irps, NUM_XFER_REQS);
  455. //Already disabled. Disconnect and teardown
  456. wait_for_disconnection(port_hdl, port_evt_queue, true);
  457. teardown(port_evt_queue, pipe_evt_queue, port_hdl);
  458. }
  459. /*
  460. Test HCD port command bailout
  461. Purpose:
  462. - Test that if the a port's state changes whilst a command is being executed, the port command should return
  463. ESP_ERR_INVALID_RESPONSE
  464. Procedure:
  465. - Setup HCD and wait for connection
  466. - Suspend the port
  467. - Resume the port but trigger a disconnect from another thread during the resume command
  468. - Check that port command returns ESP_ERR_INVALID_RESPONSE
  469. */
  470. static void concurrent_task(void *arg)
  471. {
  472. SemaphoreHandle_t sync_sem = (SemaphoreHandle_t) arg;
  473. xSemaphoreTake(sync_sem, portMAX_DELAY);
  474. vTaskDelay(pdMS_TO_TICKS(10)); //Give a short delay let reset command start in main thread
  475. //Forcibly a disconenction
  476. phy_force_conn_state(false, 0);
  477. vTaskDelay(portMAX_DELAY); //Block forever and wait to be deleted
  478. }
  479. TEST_CASE("Test HCD port command bailout", "[hcd][ignore]")
  480. {
  481. QueueHandle_t port_evt_queue;
  482. QueueHandle_t pipe_evt_queue;
  483. hcd_port_handle_t port_hdl;
  484. setup(&port_evt_queue, &pipe_evt_queue, &port_hdl);
  485. wait_for_connection(port_hdl, port_evt_queue);
  486. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  487. //Create task to run commands concurrently
  488. SemaphoreHandle_t sync_sem = xSemaphoreCreateBinary();
  489. TaskHandle_t task_handle;
  490. TEST_ASSERT_NOT_EQUAL(NULL, sync_sem);
  491. TEST_ASSERT_EQUAL(pdTRUE, xTaskCreatePinnedToCore(concurrent_task, "tsk", 4096, (void *) sync_sem, UNITY_FREERTOS_PRIORITY + 1, &task_handle, 0));
  492. //Suspend the device
  493. printf("Suspending\n");
  494. TEST_ASSERT_EQUAL(ESP_OK, hcd_port_command(port_hdl, HCD_PORT_CMD_SUSPEND));
  495. vTaskDelay(pdMS_TO_TICKS(20)); //Short delay for device to enter suspend state
  496. printf("Attempting to resume\n");
  497. xSemaphoreGive(sync_sem); //Trigger concurrent task
  498. //Attempt to resume the port. But the concurrent task should override this with a disconnection event
  499. TEST_ASSERT_EQUAL(ESP_ERR_INVALID_RESPONSE, hcd_port_command(port_hdl, HCD_PORT_CMD_RESUME));
  500. //Check that concurrent task triggered a sudden disconnection
  501. expect_port_event(port_evt_queue, port_hdl, HCD_PORT_EVENT_SUDDEN_DISCONN);
  502. TEST_ASSERT_EQUAL(HCD_PORT_EVENT_SUDDEN_DISCONN, hcd_port_handle_event(port_hdl));
  503. TEST_ASSERT_EQUAL(HCD_PORT_STATE_RECOVERY, hcd_port_get_state(port_hdl));
  504. vTaskDelay(pdMS_TO_TICKS(10)); //Short delay for concurrent task finish running
  505. vTaskDelete(task_handle);
  506. vSemaphoreDelete(sync_sem);
  507. //Directly teardown the port without recovery
  508. teardown(port_evt_queue, pipe_evt_queue, port_hdl);
  509. }
  510. // --------------------------------------------------- Pipe Tests ------------------------------------------------------
  511. /*
  512. Test HCD Transfer Requests (normal completion and early abort)
  513. Purpose:
  514. - Test that pipes can be created
  515. - Transfer requests can be created and enqueued
  516. - Pipe returns HCD_PIPE_EVENT_XFER_REQ_DONE
  517. - Test that transfer requests can be aborted when enqueued
  518. Procedure:
  519. - Setup
  520. - Allocate transfer requests. Initialize as Get Device Descriptor request
  521. - Enqueue transfer requests
  522. - Expect HCD_PIPE_EVENT_XFER_REQ_DONE. Deallocate transfer requests
  523. - Requeue transfer requests, but abort them immediately
  524. - Teardown
  525. */
  526. TEST_CASE("Test HCD pipe transfer request", "[hcd][ignore]")
  527. {
  528. QueueHandle_t port_evt_queue;
  529. QueueHandle_t pipe_evt_queue;
  530. hcd_port_handle_t port_hdl;
  531. setup(&port_evt_queue, &pipe_evt_queue, &port_hdl);
  532. wait_for_connection(port_hdl, port_evt_queue);
  533. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  534. //Allocate transfer requests
  535. hcd_pipe_handle_t default_pipe;
  536. hcd_xfer_req_handle_t req_hdls[NUM_XFER_REQS];
  537. uint8_t *data_buffers[NUM_XFER_REQS];
  538. usb_irp_t *irps[NUM_XFER_REQS];
  539. alloc_pipe_and_xfer_reqs(port_hdl, pipe_evt_queue, &default_pipe, req_hdls, data_buffers, irps, NUM_XFER_REQS);
  540. //Initialize transfer requests to send a "Get Device Descriptor" request
  541. for (int i = 0; i < NUM_XFER_REQS; i++) {
  542. irps[i]->num_bytes = 64; //1 worst case MPS
  543. USB_CTRL_REQ_INIT_GET_DEVC_DESC((usb_ctrl_req_t *) data_buffers[i]);
  544. irps[i]->data_buffer = data_buffers[i];
  545. irps[i]->num_iso_packets = 0;
  546. }
  547. //Enqueue those transfer requests
  548. for (int i = 0; i < NUM_XFER_REQS; i++) {
  549. TEST_ASSERT_EQUAL(ESP_OK, hcd_xfer_req_enqueue(req_hdls[i]));
  550. }
  551. //Wait for each done event of each transfer request
  552. for (int i = 0; i < NUM_XFER_REQS; i++) {
  553. expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_XFER_REQ_DONE);
  554. }
  555. //Dequeue transfer requests and check results.
  556. for (int i = 0; i < NUM_XFER_REQS; i++) {
  557. hcd_xfer_req_handle_t req_hdl = hcd_xfer_req_dequeue(default_pipe);
  558. TEST_ASSERT_EQUAL(req_hdls[i], req_hdl);
  559. hcd_pipe_handle_t pipe_hdl;
  560. usb_irp_t *irp;
  561. void *context;
  562. hcd_xfer_req_get_target(req_hdl, &pipe_hdl, &irp, &context);
  563. TEST_ASSERT_EQUAL(default_pipe, pipe_hdl);
  564. TEST_ASSERT_EQUAL(irp, irps[i]);
  565. TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, irp->status);
  566. TEST_ASSERT_EQUAL(NULL, context);
  567. }
  568. //Enqueue them again but abort them short after
  569. for (int i = 0; i < NUM_XFER_REQS; i++) {
  570. TEST_ASSERT_EQUAL(ESP_OK, hcd_xfer_req_enqueue(req_hdls[i]));
  571. }
  572. for (int i = 0; i < NUM_XFER_REQS; i++) {
  573. hcd_xfer_req_abort(req_hdls[i]);
  574. }
  575. vTaskDelay(pdMS_TO_TICKS(100)); //Give some time for any inflight transfers to complete
  576. expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_XFER_REQ_DONE);
  577. //Dequeue transfer rqeuests and check results of aborted transfer request
  578. for (int i = 0; i < NUM_XFER_REQS; i++) {
  579. hcd_xfer_req_handle_t req_hdl = hcd_xfer_req_dequeue(default_pipe);
  580. hcd_pipe_handle_t pipe_hdl;
  581. usb_irp_t *irp;
  582. void *context;
  583. hcd_xfer_req_get_target(req_hdl, &pipe_hdl, &irp, &context);
  584. TEST_ASSERT_EQUAL(default_pipe, pipe_hdl);
  585. //No need to check req_hdl or IRP order as abort will cause them to dequeu out of order
  586. TEST_ASSERT(irp->status == USB_TRANSFER_STATUS_COMPLETED || irp->status == USB_TRANSFER_STATUS_CANCELLED);
  587. TEST_ASSERT_EQUAL(NULL, context);
  588. }
  589. //Free transfer requests
  590. free_pipe_and_xfer_reqs(default_pipe, req_hdls, data_buffers, irps, NUM_XFER_REQS);
  591. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  592. wait_for_disconnection(port_hdl, port_evt_queue, false);
  593. teardown(port_evt_queue, pipe_evt_queue, port_hdl);
  594. }
  595. /*
  596. Test HCD pipe STALL condition, abort, and clear
  597. Purpose:
  598. - Test that a pipe can react to a STALL (i.e., a HCD_PIPE_EVENT_HALTED event)
  599. - The HCD_PIPE_CMD_ABORT can retire all transfer requests
  600. - Pipe clear command can return the pipe to being active
  601. Procedure:
  602. - Setup HCD and a port, a default pipe, and multiple transfer requests
  603. - Corrupt the first transfer request, then enqueue all of them.
  604. - The corrupted transfer request should trigger a STALL response from the endpoint
  605. - Check that the correct pipe event, error, and state is returned from the pipe
  606. - Check that the other transfers can be retired using the abort command
  607. - Check that the halt can be cleared by using the clear command
  608. - Requeue correct transfers to check that pipe still works after being cleared
  609. - Teardown
  610. */
  611. TEST_CASE("Test HCD pipe STALL", "[hcd][ignore]")
  612. {
  613. QueueHandle_t port_evt_queue;
  614. QueueHandle_t pipe_evt_queue;
  615. hcd_port_handle_t port_hdl;
  616. setup(&port_evt_queue, &pipe_evt_queue, &port_hdl);
  617. wait_for_connection(port_hdl, port_evt_queue);
  618. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  619. //Allocate transfer requests
  620. hcd_pipe_handle_t default_pipe;
  621. hcd_xfer_req_handle_t req_hdls[NUM_XFER_REQS];
  622. uint8_t *data_buffers[NUM_XFER_REQS];
  623. usb_irp_t *irps[NUM_XFER_REQS];
  624. alloc_pipe_and_xfer_reqs(port_hdl, pipe_evt_queue, &default_pipe, req_hdls, data_buffers, irps, NUM_XFER_REQS);
  625. //Initialize transfer requests to send a "Get Device Descriptor" request
  626. for (int i = 0; i < NUM_XFER_REQS; i++) {
  627. irps[i]->num_bytes = 64; //1 worst case MPS
  628. USB_CTRL_REQ_INIT_GET_CFG_DESC((usb_ctrl_req_t *) data_buffers[i], 0, XFER_DATA_MAX_LEN);
  629. irps[i]->data_buffer = data_buffers[i];
  630. irps[i]->num_iso_packets = 0;
  631. }
  632. //Corrupt first transfer so that it triggers a STALL
  633. ((usb_ctrl_req_t *) data_buffers[0])->bRequest = 0xAA;
  634. //Enqueue those transfer requests
  635. for (int i = 0; i < NUM_XFER_REQS; i++) {
  636. TEST_ASSERT_EQUAL(ESP_OK, hcd_xfer_req_enqueue(req_hdls[i]));
  637. }
  638. vTaskDelay(pdMS_TO_TICKS(100)); //Give some time for transfers to complete
  639. //Check that pipe has been stalled
  640. printf("Expecting STALL\n");
  641. expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_ERROR_STALL);
  642. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe));
  643. //Call the pipe abort command to retire all transfers then dequeue all transfers
  644. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_ABORT));
  645. for (int i = 0; i < NUM_XFER_REQS; i++) {
  646. hcd_xfer_req_handle_t req_hdl = hcd_xfer_req_dequeue(default_pipe);
  647. hcd_pipe_handle_t pipe_hdl;
  648. usb_irp_t *irp;
  649. void *context;
  650. hcd_xfer_req_get_target(req_hdl, &pipe_hdl, &irp, &context);
  651. TEST_ASSERT_EQUAL(default_pipe, pipe_hdl);
  652. TEST_ASSERT_EQUAL(irp, irps[i]);
  653. TEST_ASSERT(irp->status == USB_TRANSFER_STATUS_STALL || irp->status == USB_TRANSFER_STATUS_CANCELLED);
  654. TEST_ASSERT_EQUAL(NULL, context);
  655. }
  656. //Call the clear command to un-stall the pipe
  657. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR));
  658. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe));
  659. //Correct first transfer then requeue
  660. USB_CTRL_REQ_INIT_GET_CFG_DESC((usb_ctrl_req_t *) data_buffers[0], 0, XFER_DATA_MAX_LEN);
  661. for (int i = 0; i < NUM_XFER_REQS; i++) {
  662. TEST_ASSERT_EQUAL(ESP_OK, hcd_xfer_req_enqueue(req_hdls[i]));
  663. }
  664. vTaskDelay(pdMS_TO_TICKS(100)); //Give some time for transfers to complete
  665. expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_XFER_REQ_DONE);
  666. //Dequeue transfer requests and check results.
  667. for (int i = 0; i < NUM_XFER_REQS; i++) {
  668. hcd_xfer_req_handle_t req_hdl = hcd_xfer_req_dequeue(default_pipe);
  669. TEST_ASSERT_EQUAL(req_hdls[i], req_hdl);
  670. hcd_pipe_handle_t pipe_hdl;
  671. usb_irp_t *irp;
  672. void *context;
  673. hcd_xfer_req_get_target(req_hdl, &pipe_hdl, &irp, &context);
  674. TEST_ASSERT_EQUAL(default_pipe, pipe_hdl);
  675. TEST_ASSERT_EQUAL(irp, irps[i]);
  676. TEST_ASSERT_EQUAL(USB_TRANSFER_STATUS_COMPLETED, irp->status);
  677. TEST_ASSERT_EQUAL(NULL, context);
  678. }
  679. //Free transfer requests
  680. free_pipe_and_xfer_reqs(default_pipe, req_hdls, data_buffers, irps, NUM_XFER_REQS);
  681. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  682. wait_for_disconnection(port_hdl, port_evt_queue, false);
  683. teardown(port_evt_queue, pipe_evt_queue, port_hdl);
  684. }
  685. /*
  686. Test Pipe runtime halt and clear
  687. Purpose:
  688. - Test that a pipe can be halted with a command whilst there are ongoing transfer requests
  689. - Test that a pipe can be un-halted with a HCD_PIPE_CMD_CLEAR
  690. - Test that enqueued transfer requests are resumed when pipe is cleared
  691. Procedure:
  692. - Setup HCD, a default pipe, and multiple transfer requests
  693. - Enqueue transfer requests but execute a HCD_PIPE_CMD_HALT command immediately after. Halt command should let on
  694. the current going transfer request finish before actually halting the pipe.
  695. - Clear the pipe halt using a HCD_PIPE_CMD_HALT command. Enqueued transfer requests will be resumed
  696. - Check that all transfer requests have completed successfully.
  697. - Teardown
  698. */
  699. TEST_CASE("Test HCD pipe runtime halt and clear", "[hcd][ignore]")
  700. {
  701. QueueHandle_t port_evt_queue;
  702. QueueHandle_t pipe_evt_queue;
  703. hcd_port_handle_t port_hdl;
  704. setup(&port_evt_queue, &pipe_evt_queue, &port_hdl);
  705. wait_for_connection(port_hdl, port_evt_queue);
  706. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  707. //Allocate transfer requests
  708. hcd_pipe_handle_t default_pipe;
  709. hcd_xfer_req_handle_t req_hdls[NUM_XFER_REQS];
  710. uint8_t *data_buffers[NUM_XFER_REQS];
  711. usb_irp_t *irps[NUM_XFER_REQS];
  712. alloc_pipe_and_xfer_reqs(port_hdl, pipe_evt_queue, &default_pipe, req_hdls, data_buffers, irps, NUM_XFER_REQS);
  713. //Initialize transfer requests to send a "Get Device Descriptor" request
  714. for (int i = 0; i < NUM_XFER_REQS; i++) {
  715. irps[i]->num_bytes = 64; //1 worst case MPS
  716. USB_CTRL_REQ_INIT_GET_CFG_DESC((usb_ctrl_req_t *) data_buffers[i], 0, XFER_DATA_MAX_LEN);
  717. irps[i]->data_buffer = data_buffers[i];
  718. irps[i]->num_iso_packets = 0;
  719. }
  720. printf("Enqueuing transfer requests\n");
  721. //Enqueue those transfer requests
  722. for (int i = 0; i < NUM_XFER_REQS; i++) {
  723. TEST_ASSERT_EQUAL(ESP_OK, hcd_xfer_req_enqueue(req_hdls[i]));
  724. }
  725. //Halt the pipe immediately
  726. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_HALT));
  727. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_HALTED, hcd_pipe_get_state(default_pipe));
  728. printf("Pipe halted\n");
  729. vTaskDelay(pdMS_TO_TICKS(100)); //Give some time for current inflight transfer to complete
  730. //Clear command to un-halt the pipe
  731. TEST_ASSERT_EQUAL(ESP_OK, hcd_pipe_command(default_pipe, HCD_PIPE_CMD_CLEAR));
  732. TEST_ASSERT_EQUAL(HCD_PIPE_STATE_ACTIVE, hcd_pipe_get_state(default_pipe));
  733. printf("Pipe cleared\n");
  734. vTaskDelay(pdMS_TO_TICKS(100)); //Give some time pending for transfers to restart and complete
  735. expect_pipe_event(pipe_evt_queue, default_pipe, HCD_PIPE_EVENT_XFER_REQ_DONE);
  736. for (int i = 0; i < NUM_XFER_REQS; i++) {
  737. hcd_xfer_req_handle_t req_hdl = hcd_xfer_req_dequeue(default_pipe);
  738. TEST_ASSERT_EQUAL(req_hdls[i], req_hdl);
  739. hcd_pipe_handle_t pipe_hdl;
  740. usb_irp_t *irp;
  741. void *context;
  742. hcd_xfer_req_get_target(req_hdl, &pipe_hdl, &irp, &context);
  743. TEST_ASSERT_EQUAL(default_pipe, pipe_hdl);
  744. TEST_ASSERT_EQUAL(irp, irps[i]);
  745. TEST_ASSERT(irp->status == USB_TRANSFER_STATUS_COMPLETED);
  746. TEST_ASSERT_EQUAL(NULL, context);
  747. }
  748. //Free transfer requests
  749. free_pipe_and_xfer_reqs(default_pipe, req_hdls, data_buffers, irps, NUM_XFER_REQS);
  750. vTaskDelay(pdMS_TO_TICKS(100)); //Short delay send of SOF (for FS) or EOPs (for LS)
  751. wait_for_disconnection(port_hdl, port_evt_queue, false);
  752. teardown(port_evt_queue, pipe_evt_queue, port_hdl);
  753. }