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