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