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, ¶meter);
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 }