1 /* This test is designed to test the ux_host_stack_transfer_request.  */
2 
3 #include <stdio.h>
4 #include "tx_api.h"
5 #include "ux_api.h"
6 #include "ux_system.h"
7 #include "ux_utility.h"
8 
9 #include "ux_host_stack.h"
10 #include "ux_device_stack.h"
11 
12 #include "ux_device_class_cdc_acm.h"
13 #include "ux_host_class_cdc_acm.h"
14 
15 #include "ux_host_class_dpump.h"
16 #include "ux_device_class_dpump.h"
17 
18 #include "ux_host_class_hid.h"
19 #include "ux_device_class_hid.h"
20 
21 #include "ux_host_class_storage.h"
22 #include "ux_device_class_storage.h"
23 
24 #include "ux_test_dcd_sim_slave.h"
25 #include "ux_test_hcd_sim_host.h"
26 #include "ux_test_utility_sim.h"
27 
28 
29 /* Define USBX test constants.  */
30 
31 #define UX_TEST_STACK_SIZE      4096
32 #define UX_TEST_BUFFER_SIZE     2048
33 #define UX_TEST_RUN             1
34 #define UX_TEST_MEMORY_SIZE     (64*1024)
35 
36 #define     LSB(x) ( (x) & 0x00ff)
37 #define     MSB(x) (((x) & 0xff00) >> 8)
38 
39 /* Configuration descriptor 9 bytes */
40 #define CFG_DESC(wTotalLength, bNumInterfaces, bConfigurationValue)\
41     /* Configuration 1 descriptor 9 bytes */\
42     0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\
43     (bNumInterfaces), (bConfigurationValue), 0x00,\
44     0x40, 0x00,
45 #define CFG_DESC_LEN 9
46 
47 /* DPUMP interface descriptors. */
48 #define DPUMP_IFC_DESC(ifc, alt, nb_ep) \
49     /* Interface descriptor */\
50     0x09, 0x04, (ifc), (alt), (nb_ep), 0x99, 0x99, 0x99, 0x00,
51 
52 #define DPUMP_IFC_EP_DESC(epaddr, eptype, epsize) \
53     /* Endpoint descriptor */\
54     0x07, 0x05, (epaddr), (eptype), LSB(epsize), MSB(epsize), 0x01,
55 
56 #define DPUMP_IFC_DESC_ALL_LEN(nb_ep) (9 + (nb_ep) * 7)
57 
58 #define CFG_DESC_ALL_LEN (CFG_DESC_LEN + DPUMP_IFC_DESC_ALL_LEN(4))
59 
60 #define CFG_DESC_ALL \
61     CFG_DESC(CFG_DESC_ALL_LEN, 1, 1)\
62     DPUMP_IFC_DESC(0, 0, 4)\
63     DPUMP_IFC_EP_DESC(0x81, 2, 64)\
64     DPUMP_IFC_EP_DESC(0x02, 2, 64)\
65     DPUMP_IFC_EP_DESC(0x83, 1, 64)\
66     DPUMP_IFC_EP_DESC(0x84, 3, 64)\
67 
68 /* Define the counters used in the test application...  */
69 
70 static ULONG                           thread_0_counter;
71 static ULONG                           thread_1_counter;
72 static ULONG                           error_counter;
73 
74 static UCHAR                           error_callback_ignore = UX_FALSE;
75 static ULONG                           error_callback_counter;
76 
77 static UCHAR                           buffer[UX_TEST_BUFFER_SIZE];
78 
79 static UCHAR                           thread_1_state;
80 
81 /* Define USBX test global variables.  */
82 
83 static UX_HOST_CLASS                   *class_driver;
84 static UX_HOST_CLASS_DPUMP             *dpump;
85 static UX_SLAVE_CLASS_DPUMP            *dpump_slave = UX_NULL;
86 
87 static UCHAR device_framework_full_speed[] = {
88 
89     /* Device descriptor 18 bytes */
90     0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
91     0xec, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
92     0x00, 0x01,
93 
94     CFG_DESC_ALL
95 };
96 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
97 
98 static UCHAR device_framework_high_speed[] = {
99 
100     /* Device descriptor */
101     0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
102     0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
103     0x03, 0x01,
104 
105     /* Device qualifier descriptor */
106     0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
107     0x01, 0x00,
108 
109     CFG_DESC_ALL
110 };
111 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
112 
113 /* String Device Framework :
114     Byte 0 and 1 : Word containing the language ID : 0x0904 for US
115     Byte 2       : Byte containing the index of the descriptor
116     Byte 3       : Byte containing the length of the descriptor string
117 */
118 
119 static UCHAR string_framework[] = {
120 
121     /* Manufacturer string descriptor : Index 1 */
122     0x09, 0x04, 0x01, 0x0c,
123     0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
124     0x6f, 0x67, 0x69, 0x63,
125 
126     /* Product string descriptor : Index 2 */
127     0x09, 0x04, 0x02, 0x0c,
128     0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
129     0x44, 0x65, 0x6d, 0x6f,
130 
131     /* Serial Number string descriptor : Index 3 */
132     0x09, 0x04, 0x03, 0x04,
133     0x30, 0x30, 0x30, 0x31
134 };
135 #define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
136 
137     /* Multiple languages are supported on the device, to add
138        a language besides English, the unicode language code must
139        be appended to the language_id_framework array and the length
140        adjusted accordingly. */
141 static UCHAR language_id_framework[] = {
142 
143 /* English. */
144     0x09, 0x04
145 };
146 #define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
147 
148 /* Define prototypes for external Host Controller's (HCDs), classes and clients.  */
149 
150 static VOID                ux_test_instance_activate(VOID  *dpump_instance);
151 static VOID                ux_test_instance_deactivate(VOID *dpump_instance);
152 
153 UINT                       _ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command);
154 UINT                       ux_hcd_sim_initialize(UX_HCD *hcd);
155 UINT                       _ux_host_class_dpump_write(UX_HOST_CLASS_DPUMP *dpump, UCHAR * data_pointer,
156                                     ULONG requested_length, ULONG *actual_length);
157 UINT                       _ux_host_class_dpump_read (UX_HOST_CLASS_DPUMP *dpump, UCHAR *data_pointer,
158                                     ULONG requested_length, ULONG *actual_length);
159 
160 static TX_THREAD           ux_test_thread_simulation_0;
161 static TX_THREAD           ux_test_thread_simulation_1;
162 static void                ux_test_thread_simulation_0_entry(ULONG);
163 static void                ux_test_thread_simulation_1_entry(ULONG);
164 
165 
166 /* Define the ISR dispatch.  */
167 
168 extern VOID    (*test_isr_dispatch)(void);
169 
170 
171 /* Prototype for test control return.  */
172 
173 void  test_control_return(UINT status);
174 
175 /* Simulator actions. */
176 
177 static UX_TEST_HCD_SIM_ACTION endpoint0x83_create_del_skip[] = {
178 /* function, request to match,
179    port action, port status,
180    request action, request EP, request data, request actual length, request status,
181    status, additional callback,
182    no_return */
183 {   UX_HCD_CREATE_ENDPOINT, NULL,
184         UX_FALSE, 0,
185         UX_TEST_MATCH_EP, 0x83, UX_NULL, 0, 0,
186         UX_SUCCESS},
187 {   UX_HCD_CREATE_ENDPOINT, NULL,
188         UX_FALSE, 0,
189         UX_TEST_MATCH_EP, 0x83, UX_NULL, 0, 0,
190         UX_SUCCESS},
191 {   0   }
192 };
193 
test_action_abort(UX_TEST_ACTION * action,VOID * params)194 static VOID test_action_abort(UX_TEST_ACTION *action, VOID *params)
195 {
196 
197     ux_host_stack_transfer_request_abort(&dpump->ux_host_class_dpump_bulk_in_endpoint->ux_endpoint_transfer_request);
198 }
199 
200 static UX_TEST_HCD_SIM_ACTION preempt_abort_on_abort[] = {
201 /* function, request to match,
202    port action, port status,
203    request action, request EP, request data, request actual length, request status,
204    status, additional callback,
205    no_return */
206 {   UX_HCD_TRANSFER_ABORT, NULL,
207         UX_FALSE, 0,
208         UX_TEST_MATCH_EP, 0x81, UX_NULL, 0, 0,
209         UX_SUCCESS, test_action_abort,
210         UX_TRUE},
211 {   0   }
212 };
213 
214 /* Define the ISR dispatch routine.  */
215 
test_isr(void)216 static void    test_isr(void)
217 {
218 
219     /* For further expansion of interrupt-level testing.  */
220 }
221 
222 
error_callback(UINT system_level,UINT system_context,UINT error_code)223 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
224 {
225 
226     error_callback_counter ++;
227 
228     if (!error_callback_ignore)
229     {
230         {
231             /* Failed test.  */
232             printf("Error #%d, system_level: %d, system_context: %d, error_code: 0x%x\n", __LINE__, system_level, system_context, error_code);
233             // test_control_return(1);
234         }
235     }
236 }
237 
break_on_dpump_ready(VOID)238 static UINT break_on_dpump_ready(VOID)
239 {
240 
241 UINT             status;
242 UX_HOST_CLASS   *class;
243 
244     /* Find the main data pump container.  */
245     status =  ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class);
246     if (status != UX_SUCCESS)
247         /* Do not break. */
248         return UX_SUCCESS;
249 
250     /* Find the instance. */
251     status =  ux_host_stack_class_instance_get(class, 0, (VOID **) &dpump);
252     if (status != UX_SUCCESS)
253         /* Do not break. */
254         return UX_SUCCESS;
255 
256     if (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE)
257         /* Do not break. */
258         return UX_SUCCESS;
259 
260     return 1;
261 }
262 
break_on_removal(VOID)263 static UINT break_on_removal(VOID)
264 {
265 
266 UINT                     status;
267 UX_DEVICE               *device;
268 
269     status = ux_host_stack_device_get(0, &device);
270     if (status == UX_SUCCESS)
271         /* Do not break. */
272         return UX_SUCCESS;
273 
274     return 1;
275 }
276 
277 
test_ux_device_class_dpump_entry(UX_SLAVE_CLASS_COMMAND * command)278 static UINT test_ux_device_class_dpump_entry(UX_SLAVE_CLASS_COMMAND *command)
279 {
280     switch(command->ux_slave_class_command_request)
281     {
282         case UX_SLAVE_CLASS_COMMAND_INITIALIZE:
283         case UX_SLAVE_CLASS_COMMAND_QUERY:
284         case UX_SLAVE_CLASS_COMMAND_CHANGE:
285             return UX_SUCCESS;
286 
287         default:
288             return UX_NO_CLASS_MATCH;
289     }
290 }
291 
test_ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND * command)292 static UINT test_ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command)
293 {
294     switch (command -> ux_host_class_command_request)
295     {
296         case UX_HOST_CLASS_COMMAND_QUERY:
297         default:
298             return _ux_host_class_dpump_entry(command);
299     }
300 }
301 
302 /* Define what the initial system looks like.  */
303 
304 #ifdef CTEST
test_application_define(void * first_unused_memory)305 void test_application_define(void *first_unused_memory)
306 #else
307 void    usbx_ux_host_stack_transfer_request_test_application_define(void *first_unused_memory)
308 #endif
309 {
310 
311 UINT                            status;
312 CHAR                            *stack_pointer;
313 CHAR                            *memory_pointer;
314 UX_SLAVE_CLASS_DPUMP_PARAMETER  parameter;
315 
316     /* Initialize the free memory pointer.  */
317     stack_pointer = (CHAR *) first_unused_memory;
318     memory_pointer = stack_pointer + (UX_TEST_STACK_SIZE * 2);
319 
320     /* Initialize USBX Memory.  */
321     status =  ux_system_initialize(memory_pointer, UX_TEST_MEMORY_SIZE, UX_NULL, 0);
322 
323     /* Check for error.  */
324     if (status != UX_SUCCESS)
325     {
326 
327         printf("Running ux_host_stack_transfer_request Test......................... ERROR #1\n");
328         test_control_return(1);
329     }
330 
331     /* Register the error callback. */
332     _ux_utility_error_callback_register(error_callback);
333 
334     /* The code below is required for installing the host portion of USBX.  */
335     status =  ux_host_stack_initialize(UX_NULL);
336 
337     /* Check for error.  */
338     if (status != UX_SUCCESS)
339     {
340 
341         printf("Running ux_host_stack_transfer_request Test......................... ERROR #2\n");
342         test_control_return(1);
343     }
344 
345     /* Register all the host class drivers for this USBX implementation.  */
346     status =  ux_host_stack_class_register(_ux_system_host_class_dpump_name, test_ux_host_class_dpump_entry);
347 
348     /* Check for error.  */
349     if (status != UX_SUCCESS)
350     {
351 
352         printf("Running ux_host_stack_transfer_request Test......................... ERROR #3\n");
353         test_control_return(1);
354     }
355 
356     /* The code below is required for installing the device portion of USBX */
357     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
358                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
359                                        string_framework, STRING_FRAMEWORK_LENGTH,
360                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
361 
362     /* Check for error.  */
363     if (status != UX_SUCCESS)
364     {
365 
366         printf("Running ux_host_stack_transfer_request Test......................... ERROR #5\n");
367         test_control_return(1);
368     }
369 
370     /* Set the parameters for callback when insertion/extraction of a Data Pump device.  */
371     parameter.ux_slave_class_dpump_instance_activate   =  UX_NULL;
372     parameter.ux_slave_class_dpump_instance_deactivate =  UX_NULL;
373 
374     /* Initialize the device dpump class. The class is connected with interface 0 */
375     status =  ux_device_stack_class_register(_ux_system_slave_class_dpump_name, test_ux_device_class_dpump_entry,
376                                               1, 0, &parameter);
377 
378     /* Check for error.  */
379     if (status != UX_SUCCESS)
380     {
381 
382         printf("Running ux_host_stack_transfer_request Test......................... ERROR #6\n");
383         test_control_return(1);
384     }
385 
386     /* Initialize the simulated device controller.  */
387     status =  _ux_test_dcd_sim_slave_initialize();
388 
389     /* Check for error.  */
390     if (status != UX_SUCCESS)
391     {
392 
393         printf("Running ux_host_stack_transfer_request Test......................... ERROR #7\n");
394         test_control_return(1);
395     }
396 
397     /* Register all the USB host controllers available in this system */
398     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
399 
400     /* Check for error.  */
401     if (status != UX_SUCCESS)
402     {
403 
404         printf("Running ux_host_stack_transfer_request Test......................... ERROR #4\n");
405         test_control_return(1);
406     }
407 
408     /* Create the main simulation thread.  */
409     status =  tx_thread_create(&ux_test_thread_simulation_0, "test simulation 0", ux_test_thread_simulation_0_entry, 0,
410             stack_pointer, UX_TEST_STACK_SIZE,
411             20, 20, 1, TX_AUTO_START);
412 
413     /* Check for error.  */
414     if (status != TX_SUCCESS)
415     {
416 
417         printf("Running ux_host_stack_transfer_request Test......................... ERROR #8\n");
418         test_control_return(1);
419     }
420 
421     /* Create the test simulation thread.  */
422     status =  tx_thread_create(&ux_test_thread_simulation_1, "test simulation 1", ux_test_thread_simulation_1_entry, 0,
423             stack_pointer + UX_TEST_STACK_SIZE, UX_TEST_STACK_SIZE,
424             20, 20, 1, TX_NO_ACTIVATE);
425 
426     /* Check for error.  */
427     if (status != TX_SUCCESS)
428     {
429 
430         printf("Running ux_host_stack_transfer_request Test......................... ERROR #8\n");
431         test_control_return(1);
432     }
433 }
434 
435 
ux_test_thread_simulation_0_entry(ULONG arg)436 static void  ux_test_thread_simulation_0_entry(ULONG arg)
437 {
438 UINT                                                status;
439 UX_DEVICE                                          *device;
440 UX_ENDPOINT                                        *control_endpoint;
441 UX_TRANSFER                                        *transfer_request;
442 INT                                                 i;
443 
444     /* Inform user.  */
445     printf("Running ux_host_stack_transfer_request Test......................... ");
446 
447     /* Skip ISO EP create/delete. */
448     ux_test_hcd_sim_host_set_actions(endpoint0x83_create_del_skip);
449 
450     /* Connect. */
451     ux_test_hcd_sim_host_connect(UX_HIGH_SPEED_DEVICE);
452     ux_test_breakable_sleep(100, break_on_dpump_ready);
453 
454     if (dpump == UX_NULL || dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE)
455     {
456 
457         printf("ERROR #%d: dpump not ready\n", __LINE__);
458         error_counter ++;
459     }
460 
461     status = ux_host_stack_device_get(0, &device);
462     if (status != UX_SUCCESS)
463     {
464 
465         printf("ERROR #%d: device_get fail\n", __LINE__);
466         test_control_return(1);
467     }
468     control_endpoint = &device->ux_device_control_endpoint;
469     transfer_request = &control_endpoint->ux_endpoint_transfer_request;
470 
471     /* Send transfer request when device is not addressed. */
472 
473     transfer_request -> ux_transfer_request_data_pointer =      buffer;
474     transfer_request -> ux_transfer_request_requested_length =  64;
475     transfer_request -> ux_transfer_request_index =             0;
476 
477     /* SetAddress(0). */
478     transfer_request -> ux_transfer_request_function =          UX_SET_ADDRESS;
479     transfer_request -> ux_transfer_request_type =              UX_REQUEST_OUT | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
480     transfer_request -> ux_transfer_request_value =             0;
481     status = ux_host_stack_transfer_request(transfer_request);
482     if (status != UX_SUCCESS)
483     {
484 
485         printf("ERROR #%d: SetAddress(0) code 0x%x\n", __LINE__, status);
486         test_control_return(1);
487     }
488     device->ux_device_state = UX_DEVICE_ATTACHED;
489 
490     /* GetDeviceDescriptor. */
491     transfer_request -> ux_transfer_request_function =          UX_GET_DESCRIPTOR;
492     transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
493     transfer_request -> ux_transfer_request_value =             UX_DEVICE_DESCRIPTOR_ITEM << 8;
494     status = ux_host_stack_transfer_request(transfer_request);
495     if (status != UX_SUCCESS)
496     {
497 
498         printf("ERROR #%d: GetDeviceDescriptor() code 0x%x\n", __LINE__, status);
499         test_control_return(1);
500     }
501 
502     /* SetAddress(x). */
503     transfer_request -> ux_transfer_request_function =          UX_SET_ADDRESS;
504     transfer_request -> ux_transfer_request_type =              UX_REQUEST_OUT | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
505     transfer_request -> ux_transfer_request_value =             device->ux_device_address;
506     status = ux_host_stack_transfer_request(transfer_request);
507     if (status != UX_SUCCESS)
508     {
509 
510         printf("ERROR #%d: SetAddress(x) code 0x%x\n", __LINE__, status);
511         test_control_return(1);
512     }
513     device->ux_device_state = UX_DEVICE_ADDRESSED;
514 
515     /* SetConfigure(1). */
516     transfer_request -> ux_transfer_request_function =          UX_SET_CONFIGURATION;
517     transfer_request -> ux_transfer_request_type =              UX_REQUEST_OUT | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
518     transfer_request -> ux_transfer_request_value =             1;
519     status = ux_host_stack_transfer_request(transfer_request);
520     if (status != UX_SUCCESS)
521     {
522 
523         printf("ERROR #%d: SetConfigure(1) code 0x%x\n", __LINE__, status);
524         test_control_return(1);
525     }
526     device->ux_device_state = UX_DEVICE_CONFIGURED;
527 
528     /* Simulate semaphore error. */
529     ux_test_utility_sim_sem_get_error_generation_start(0);
530     /* GetDeviceDescriptor. */
531     transfer_request -> ux_transfer_request_function =          UX_GET_DESCRIPTOR;
532     transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
533     transfer_request -> ux_transfer_request_value =             UX_DEVICE_DESCRIPTOR_ITEM << 8;
534     status = ux_host_stack_transfer_request(transfer_request);
535     if (status == UX_SUCCESS)
536     {
537 
538         printf("ERROR #%d: GetDeviceDescriptor() code 0x%x\n", __LINE__, status);
539         test_control_return(1);
540     }
541     ux_test_utility_sim_sem_get_error_generation_stop();
542 
543     /* Start transfer in another thread and abort it.  */
544     thread_1_state = 0;
545 
546     tx_thread_resume(&ux_test_thread_simulation_1);
547     for (i = 0; i < 20; i ++)
548     {
549         if (thread_1_state > 0)
550             break;
551         tx_thread_sleep(1);
552     }
553     if (thread_1_state == 0)
554     {
555         printf("ERROR #%d: fail to resume thread\n", __LINE__);
556         test_control_return(1);
557     }
558 
559     /* Transfer started, check if it's pending.  */
560     for (i = 0; i < 20; i ++)
561     {
562         if (thread_1_state > 1)
563             break;
564         tx_thread_sleep(1);
565     }
566     if (thread_1_state > 1)
567     {
568         printf("ERROR #%d: thread not pending\n", __LINE__);
569         test_control_return(1);
570     }
571     if (dpump->ux_host_class_dpump_bulk_in_endpoint->ux_endpoint_transfer_request.ux_transfer_request_completion_code != UX_TRANSFER_STATUS_PENDING)
572     {
573         printf("ERROR #%d: transfer request status not UX_TRANSFER_STATUS_PENDING but 0x%x\n", __LINE__, dpump->ux_host_class_dpump_bulk_in_endpoint->ux_endpoint_transfer_request.ux_transfer_request_completion_code);
574         error_counter ++;
575     }
576 
577     /* Abort it.  */
578     status = ux_host_stack_transfer_request_abort(&dpump->ux_host_class_dpump_bulk_in_endpoint->ux_endpoint_transfer_request);
579     if (status != UX_SUCCESS)
580     {
581         printf("ERROR #%d: abort error\n", __LINE__);
582         error_counter ++;
583     }
584     else
585     {
586         for (i = 0; i < 20; i ++)
587         {
588             if (thread_1_state > 1)
589                 break;
590             tx_thread_sleep(1);
591         }
592         if (thread_1_state == 0)
593         {
594             printf("ERROR #%d: thread not progressing\n", __LINE__);
595             error_counter ++;
596         }
597     }
598 
599     /* Disconnect on transfer abort.  */
600     ux_test_hcd_sim_host_set_actions(preempt_abort_on_abort);
601     thread_1_state = 0;
602     tx_thread_resume(&ux_test_thread_simulation_1);
603     for (i = 0; i < 20; i ++)
604     {
605         if (thread_1_state > 0)
606             break;
607         tx_thread_sleep(1);
608     }
609     status = ux_host_stack_transfer_request_abort(&dpump->ux_host_class_dpump_bulk_in_endpoint->ux_endpoint_transfer_request);
610     if (status != UX_SUCCESS)
611     {
612         printf("ERROR #%d: abort error\n", __LINE__);
613         error_counter ++;
614     }
615 
616     /* Disconnect. */
617     ux_test_hcd_sim_host_disconnect();
618     ux_test_breakable_sleep(100, break_on_removal);
619 
620     /* Simulate transfer request when device is disconnected.  */
621     status = ux_host_stack_transfer_request(transfer_request);
622     if (status == UX_SUCCESS)
623     {
624 
625         printf("ERROR #%d: GetDeviceDescriptor() should fail\n", __LINE__);
626         test_control_return(1);
627     }
628 
629     /* Sleep for a tick to make sure everything is complete.  */
630     tx_thread_sleep(1);
631 
632     /* Check for errors from other threads.  */
633     if (error_counter)
634     {
635 
636         /* Test error.  */
637         printf("ERROR #%d: total %ld errors\n", __LINE__, error_counter);
638         test_control_return(1);
639     }
640     else
641     {
642 
643         /* Successful test.  */
644         printf("SUCCESS!\n");
645         test_control_return(0);
646     }
647 }
648 
ux_test_thread_simulation_1_entry(ULONG arg)649 static void  ux_test_thread_simulation_1_entry(ULONG arg)
650 {
651 UINT  status;
652 ULONG actual_length;
653 
654     while(1)
655     {
656         thread_1_state ++;
657 
658         /* Start transfer. */
659         status = ux_host_class_dpump_read(dpump, buffer, 128, &actual_length);
660 
661         thread_1_state ++;
662 
663         if (dpump->ux_host_class_dpump_bulk_in_endpoint->ux_endpoint_transfer_request.ux_transfer_request_completion_code != UX_TRANSFER_STATUS_ABORT)
664         {
665             printf("ERROR #%d: expect UX_TRANSFER_STATUS_ABORT but got 0x%x\n", __LINE__, dpump->ux_host_class_dpump_bulk_in_endpoint->ux_endpoint_transfer_request.ux_transfer_request_completion_code);
666             error_counter ++;
667         }
668 
669         tx_thread_suspend(&ux_test_thread_simulation_1);
670     }
671 }