1 /* This test is designed to test the simple dpump host/device class operation.  */
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 #include "ux_host_class_dummy.h"
9 #include "ux_device_class_dummy.h"
10 #include "ux_test.h"
11 
12 
13 /* Define USBX demo constants.  */
14 
15 #define UX_DEMO_STACK_SIZE      4096
16 #define UX_DEMO_BUFFER_SIZE     2048
17 #define UX_DEMO_RUN             1
18 #define UX_DEMO_MEMORY_SIZE     (64*1024)
19 
20 
21 /* Define the counters used in the demo application...  */
22 
23 static ULONG                           thread_0_counter;
24 static ULONG                           thread_1_counter;
25 static ULONG                           error_counter;
26 
27 
28 /* Define USBX demo global variables.  */
29 
30 static UX_HOST_CLASS                   *class_driver;
31 static UX_HOST_CLASS_DUMMY             *dummy;
32 static UX_DEVICE_CLASS_DUMMY           *dummy_slave;
33 
34 static UINT                             expected_error;
35 
36 #define _W0(w)      ( (w)       & 0xFF)
37 #define _W1(w)      (((w) >> 8) & 0xFF)
38 
39 #define _DEVICE_DESCRIPTOR(cls, sub, protocol, pktsize, vid, pid, n_cfg)        \
40     0x12, 0x01, 0x10, 0x01,                                                     \
41     (cls), (sub), (protocol), (pktsize),                                        \
42     _W0(vid), _W1(vid), _W0(pid), _W1(pid),                                     \
43     0x00, 0x00, 0x00, 0x00, 0x00, (n_cfg),
44 
45 #define _QUALIFIER_DESCRIPTOR(cls, sub, protocol, n_cfg)                        \
46     0x0a, 0x06, 0x00, 0x02,                                                     \
47     (cls), (sub), (protocol), 0x40, (n_cfg), 0x00,
48 
49 #define _CONFIGURATION_DESCRIPTOR(total_len, n_ifc, cfg_val)                    \
50     0x09, 0x02, _W0(total_len), _W1(total_len), (n_ifc), (cfg_val),             \
51     0x00, 0xc0, 0x32,
52 
53 #define _INTERFACE_DESCRIPTOR(ifc_n, alt, n_ep, cls, sub, protocol)             \
54     0x09, 0x04, (ifc_n), (alt), (n_ep), (cls), (sub), (protocol), 0x00,
55 
56 #define _ENDPOINT_DESCRIPTOR(addr, attr, pktsize, interval)                     \
57     0x07, 0x05, (addr), (attr), _W0(pktsize), _W1(pktsize), (interval),
58 
59 #define _CONFIGURATION_TOTAL_LENGTH (9+9+9+2*7)
60 #define _CONFIGURATION_DESCRIPTORS(hs)                                          \
61     _CONFIGURATION_DESCRIPTOR(_CONFIGURATION_TOTAL_LENGTH, 1, 1)                \
62     _INTERFACE_DESCRIPTOR(0, 0, 0, 0x99, 0x99, 0x99)                            \
63     _INTERFACE_DESCRIPTOR(0, 1, 2, 0x99, 0x99, 0x99)                            \
64     _ENDPOINT_DESCRIPTOR(0x01, 0x02, (hs) ? 512 : 64, 0x00)                     \
65     _ENDPOINT_DESCRIPTOR(0x82, 0x02, (hs) ? 512 : 64, 0x00)
66 
67 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
68 static UCHAR device_framework_full_speed[] = {
69     _DEVICE_DESCRIPTOR(0x00, 0x00, 0x00, 8, 0x08EC, 0x0001, 1)
70     _CONFIGURATION_DESCRIPTORS(0)
71 };
72 
73 
74 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
75 static UCHAR device_framework_high_speed[] = {
76     _DEVICE_DESCRIPTOR(0x00, 0x00, 0x00, 64, 0x08EC, 0x0001, 1)
77     _QUALIFIER_DESCRIPTOR(0, 0, 0, 1)
78     _CONFIGURATION_DESCRIPTORS(1)
79 };
80 
81 /* String Device Framework :
82     Byte 0 and 1 : Word containing the language ID : 0x0904 for US
83     Byte 2       : Byte containing the index of the descriptor
84     Byte 3       : Byte containing the length of the descriptor string
85 */
86 #define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
87 static UCHAR string_framework[] = {
88 
89     /* Manufacturer string descriptor : Index 1 */
90     0x09, 0x04, 0x01, 0x0c,
91     0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
92     0x6f, 0x67, 0x69, 0x63,
93 
94     /* Product string descriptor : Index 2 */
95     0x09, 0x04, 0x02, 0x0c,
96     0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
97     0x44, 0x65, 0x6d, 0x6f,
98 
99     /* Serial Number string descriptor : Index 3 */
100     0x09, 0x04, 0x03, 0x04,
101     0x30, 0x30, 0x30, 0x31
102 };
103 
104 
105 /* Multiple languages are supported on the device, to add
106     a language besides English, the unicode language code must
107     be appended to the language_id_framework array and the length
108     adjusted accordingly. */
109 #define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
110 static UCHAR language_id_framework[] = {
111 
112     /* English. */
113     0x09, 0x04
114 };
115 
116 
117 /* Define prototypes for external Host Controller's (HCDs), classes and clients.  */
118 
119 static VOID                tx_demo_instance_activate(VOID  *dummy_instance);
120 static VOID                tx_demo_instance_deactivate(VOID *dummy_instance);
121 static VOID                tx_demo_instance_change(UX_DEVICE_CLASS_DUMMY *dummy_instance);
122 
123 #if defined(UX_HOST_STANDALONE)
124 static UINT                tx_demo_host_change_function(ULONG e, UX_HOST_CLASS *c, VOID *p);
125 #else
126 #define                     tx_demo_host_change_function UX_NULL
127 #endif
128 
129 UINT                       ux_hcd_sim_initialize(UX_HCD *hcd);
130 
131 static TX_THREAD           tx_demo_thread_host_simulation;
132 static TX_THREAD           tx_demo_thread_slave_simulation;
133 static void                tx_demo_thread_host_simulation_entry(ULONG);
134 static void                tx_demo_thread_slave_simulation_entry(ULONG);
135 
136 
137 /* Define the ISR dispatch.  */
138 
139 extern VOID    (*test_isr_dispatch)(void);
140 
141 
142 /* Prototype for test control return.  */
143 
144 void  test_control_return(UINT status);
145 
146 
147 /* Define the ISR dispatch routine.  */
148 
test_isr(void)149 static void    test_isr(void)
150 {
151 
152     /* For further expansion of interrupt-level testing.  */
153 }
154 
155 
error_callback(UINT system_level,UINT system_context,UINT error_code)156 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
157 {
158     if (expected_error == 0 || error_code != expected_error)
159     {
160         /* Failed test.  */
161         printf("Error on line %d, system_level: %d, system_context: %d, error code: %x\n", __LINE__, system_level, system_context, error_code);
162         // test_control_return(1);
163     }
164 }
165 
166 /* Define what the initial system looks like.  */
167 
168 #ifdef CTEST
test_application_define(void * first_unused_memory)169 void test_application_define(void *first_unused_memory)
170 #else
171 void    usbx_class_interface_enumeration_test_application_define(void *first_unused_memory)
172 #endif
173 {
174 
175 UINT status;
176 CHAR                            *stack_pointer;
177 CHAR                            *memory_pointer;
178 UX_DEVICE_CLASS_DUMMY_PARAMETER  parameter;
179 
180 
181     printf("Running Basic Interface Class Enumeration Test...................... ");
182 
183     /* Initialize the free memory pointer.  */
184     stack_pointer = (CHAR *) first_unused_memory;
185     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
186 
187     /* Initialize USBX Memory.  */
188     status =  ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
189 
190     /* Check for error.  */
191     if (status != UX_SUCCESS)
192     {
193 
194         printf("ERROR #%d\n", __LINE__);
195         test_control_return(1);
196     }
197 
198     /* Register the error callback. */
199     _ux_utility_error_callback_register(error_callback);
200 
201     /* The code below is required for installing the host portion of USBX.  */
202     status =  ux_host_stack_initialize(tx_demo_host_change_function);
203 
204     /* Check for error.  */
205     if (status != UX_SUCCESS)
206     {
207 
208         printf("ERROR #%d\n", __LINE__);
209         test_control_return(1);
210     }
211 
212     /* Register all the host class drivers for this USBX implementation.  */
213     status =  ux_host_stack_class_register(_ux_host_class_dummy_name, _ux_host_class_dummy_entry);
214 
215     /* Check for error.  */
216     if (status != UX_SUCCESS)
217     {
218 
219         printf("ERROR #%d\n", __LINE__);
220         test_control_return(1);
221     }
222 
223     /* The code below is required for installing the device portion of USBX */
224     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
225                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
226                                        string_framework, STRING_FRAMEWORK_LENGTH,
227                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
228 
229     /* Check for error.  */
230     if (status != UX_SUCCESS)
231     {
232 
233         printf("ERROR #%d\n", __LINE__);
234         test_control_return(1);
235     }
236 
237     /* Set the parameters for callback when insertion/extraction of a Data Pump device.  */
238     _ux_utility_memory_set((void *)&parameter, 0x00, sizeof(parameter));
239     parameter.ux_device_class_dummy_parameter_callbacks.ux_device_class_dummy_instance_activate   =  tx_demo_instance_activate;
240     parameter.ux_device_class_dummy_parameter_callbacks.ux_device_class_dummy_instance_deactivate =  tx_demo_instance_deactivate;
241     parameter.ux_device_class_dummy_parameter_callbacks.ux_device_class_dummy_change              =  tx_demo_instance_change;
242 
243     /* Initialize the device dpump class. The class is connected with interface 0 */
244     status =  ux_device_stack_class_register(_ux_device_class_dummy_name, _ux_device_class_dummy_entry,
245                                               1, 0, &parameter);
246 
247     /* Check for error.  */
248     if (status != UX_SUCCESS)
249     {
250 
251         printf("ERROR #%d\n", __LINE__);
252         test_control_return(1);
253     }
254 
255     /* Initialize the simulated device controller.  */
256     status =  _ux_dcd_sim_slave_initialize();
257 
258     /* Check for error.  */
259     if (status != UX_SUCCESS)
260     {
261 
262         printf("ERROR #%d\n", __LINE__);
263         test_control_return(1);
264     }
265 
266     /* Register all the USB host controllers available in this system */
267     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, ux_hcd_sim_host_initialize,0,0);
268 
269     /* Check for error.  */
270     if (status != UX_SUCCESS)
271     {
272 
273         printf("ERROR #%d\n", __LINE__);
274         test_control_return(1);
275     }
276 
277     /* Create the main host simulation thread.  */
278     status =  tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
279             stack_pointer, UX_DEMO_STACK_SIZE,
280             20, 20, 1, TX_AUTO_START);
281 
282     /* Check for error.  */
283     if (status != TX_SUCCESS)
284     {
285 
286         printf("ERROR #%d\n", __LINE__);
287         test_control_return(1);
288     }
289 
290     /* Create the main demo thread.  */
291     status =  tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
292             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
293             20, 20, 1, TX_AUTO_START);
294 
295     /* Check for error.  */
296     if (status != TX_SUCCESS)
297     {
298 
299         printf("ERROR #%d\n", __LINE__);
300         test_control_return(1);
301     }
302 }
303 
ux_demo_dummy_instance_check(VOID)304 static UINT ux_demo_dummy_instance_check(VOID)
305 {
306 UINT            status;
307 UX_HOST_CLASS   *cls;
308     status = ux_host_stack_class_get(_ux_host_class_dummy_name, &cls);
309     if (status != UX_SUCCESS)
310         return(status);
311     status =  ux_host_stack_class_instance_get(cls, 0, (VOID **) &dummy);
312     if (status != UX_SUCCESS)
313         return(status);
314     if (dummy -> ux_host_class_dummy_state != UX_HOST_CLASS_INSTANCE_LIVE)
315         return(UX_NO_CLASS_MATCH);
316     return(UX_SUCCESS);
317 }
318 
ux_demo_dummy_instance_connect_wait(ULONG wait_ticks)319 static UINT ux_demo_dummy_instance_connect_wait(ULONG wait_ticks)
320 {
321 ULONG   t0 = tx_time_get(), t1;
322     while(1)
323     {
324 #if defined(UX_HOST_STANDALONE)
325         ux_system_tasks_run();
326 #endif
327         if (UX_SUCCESS == ux_demo_dummy_instance_check())
328             return(UX_SUCCESS);
329         tx_thread_relinquish();
330 
331         /* Wait forever.  */
332         if (wait_ticks == 0xFFFFFFFFul)
333             continue;
334 
335         /* No wait.  */
336         if (wait_ticks == 0)
337             break;
338 
339         /* Check timeout.  */
340         t1 = tx_time_get();
341         if (t1 >= t0)
342             t1 = t1 - t0;
343         else
344             t1 = 0xFFFFFFFFul - t0 + t1;
345         if (t1 > wait_ticks)
346             break;
347     }
348     return(UX_ERROR);
349 }
350 
ux_demo_dummy_instance_remove_wait(ULONG wait_ticks)351 static UINT ux_demo_dummy_instance_remove_wait(ULONG wait_ticks)
352 {
353 ULONG   t0 = tx_time_get(), t1;
354     while(1)
355     {
356 #if defined(UX_HOST_STANDALONE)
357         ux_system_tasks_run();
358 #endif
359         if (UX_SUCCESS != ux_demo_dummy_instance_check())
360         {
361             dummy = UX_NULL;
362             return(UX_SUCCESS);
363         }
364         tx_thread_relinquish();
365 
366         /* Wait forever.  */
367         if (wait_ticks == 0xFFFFFFFFul)
368             continue;
369 
370         /* No wait.  */
371         if (wait_ticks == 0)
372             break;
373 
374         /* Check timeout.  */
375         t1 = tx_time_get();
376         if (t1 >= t0)
377             t1 = t1 - t0;
378         else
379             t1 = 0xFFFFFFFFul - t0 + t1;
380         if (t1 > wait_ticks)
381             break;
382     }
383     return(UX_ERROR);
384 }
385 
tx_demo_thread_host_simulation_entry(ULONG arg)386 static void  tx_demo_thread_host_simulation_entry(ULONG arg)
387 {
388 UINT                status;
389 UX_DEVICE           *device;
390 UX_CONFIGURATION    *configuration;
391 UX_INTERFACE        *interface;
392 
393     stepinfo(">>>> Dummy Class Connection Wait\n");
394     status = ux_demo_dummy_instance_connect_wait(1000);
395     if (status != UX_SUCCESS)
396     {
397         printf("ERROR #%d\n", __LINE__);
398         test_control_return(1);
399     }
400 
401     stepinfo(">>>> Dummy Class Configuration Deactivate\n");
402     interface = dummy -> ux_host_class_dummy_interface;
403     configuration = interface -> ux_interface_configuration;
404     device = configuration -> ux_configuration_device;
405     status = ux_host_stack_device_configuration_deactivate(device);
406     if (status != UX_SUCCESS)
407     {
408         printf("ERROR #%d\n", __LINE__);
409         test_control_return(1);
410     }
411     status = ux_demo_dummy_instance_remove_wait(10);
412     if (status != UX_SUCCESS)
413     {
414         printf("ERROR #%d\n", __LINE__);
415         test_control_return(1);
416     }
417 
418     stepinfo(">>>> Dummy Class Configuration Activate\n");
419     status = ux_host_stack_device_configuration_activate(configuration);
420     if (status != UX_SUCCESS)
421     {
422         printf("ERROR #%d\n", __LINE__);
423         test_control_return(1);
424     }
425     status = ux_demo_dummy_instance_connect_wait(1000);
426     if (status != UX_SUCCESS)
427     {
428         printf("ERROR #%d\n", __LINE__);
429         test_control_return(1);
430     }
431 
432 #if UX_TEST_MULTI_ALT_ON
433     stepinfo(">>>> Dummy Class Interface Change\n");
434     status = _ux_host_class_dummy_select_interface(dummy, 0, 1);
435     if (status != UX_SUCCESS)
436     {
437         printf("ERROR #%d, 0x%x\n", __LINE__, status);
438         test_control_return(1);
439     }
440     status = _ux_host_class_dummy_select_interface(dummy, 0, 0);
441     if (status != UX_SUCCESS)
442     {
443         printf("ERROR #%d, 0x%x\n", __LINE__, status);
444         test_control_return(1);
445     }
446 #endif
447 
448     expected_error = 0;
449 
450     /* Sleep for a tick to make sure everything is complete.  */
451     tx_thread_sleep(1);
452 
453     /* Check for errors from other threads.  */
454     if (error_counter)
455     {
456 
457         /* DPUMP error.  */
458         printf("ERROR #%d: total %ld errors\n", __LINE__, error_counter);
459         test_control_return(1);
460     }
461     else
462     {
463 
464         /* Successful test.  */
465         printf("SUCCESS!\n");
466         test_control_return(0);
467     }
468 }
469 
470 
tx_demo_thread_slave_simulation_entry(ULONG arg)471 static void  tx_demo_thread_slave_simulation_entry(ULONG arg)
472 {
473 
474 UINT    status;
475 ULONG   actual_length;
476 
477 
478     while(1)
479     {
480 #if defined(UX_DEVICE_STANDALONE)
481 
482         /* Run device tasks.  */
483         ux_system_tasks_run();
484 #endif
485         /* Increment thread counter.  */
486         thread_1_counter++;
487 
488         /* Relinquish to other thread.  */
489         tx_thread_relinquish();
490     }
491 }
492 
tx_demo_instance_activate(VOID * inst)493 static VOID  tx_demo_instance_activate(VOID *inst)
494 {
495     dummy_slave = (UX_DEVICE_CLASS_DUMMY *)inst;
496 }
497 
tx_demo_instance_deactivate(VOID * inst)498 static VOID  tx_demo_instance_deactivate(VOID *inst)
499 {
500     dummy_slave = UX_NULL;
501 }
502 
tx_demo_instance_change(UX_DEVICE_CLASS_DUMMY * dummy)503 static VOID  tx_demo_instance_change(UX_DEVICE_CLASS_DUMMY *dummy)
504 {
505     UX_PARAMETER_NOT_USED(dummy);
506 }
507 
508 #if defined(UX_HOST_STANDALONE)
tx_demo_host_change_function(ULONG e,UX_HOST_CLASS * c,VOID * p)509 static UINT  tx_demo_host_change_function(ULONG e, UX_HOST_CLASS *c, VOID *p)
510 {
511     if (e == UX_STANDALONE_WAIT_BACKGROUND_TASK)
512     {
513         tx_thread_relinquish();
514     }
515 }
516 #endif
517