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_dpump.h"
9 #include "ux_device_class_dpump.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 unsigned char                   host_out_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
31 static unsigned char                   host_in_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
32 static unsigned char                   slave_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
33 
34 static UX_HOST_CLASS                   *class_driver;
35 static UX_HOST_CLASS_DPUMP             *dpump;
36 static UX_SLAVE_CLASS_DPUMP            *dpump_slave;
37 
38 static UINT                             ignore_errors;
39 
40 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 50
41 static UCHAR device_framework_full_speed[] = {
42 
43     /* Device descriptor */
44     0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
45     0xec, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
46     0x00, 0x01,
47 
48     /* Configuration descriptor */
49     0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
50     0x32,
51 
52     /* Interface descriptor */
53     0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99,
54     0x00,
55 
56     /* Endpoint descriptor (Bulk Out) */
57     0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00,
58 
59     /* Endpoint descriptor (Bulk In) */
60     0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00
61 };
62 
63 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 60
64 static UCHAR device_framework_high_speed[] = {
65 
66     /* Device descriptor */
67     0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
68     0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
69     0x03, 0x01,
70 
71     /* Device qualifier descriptor */
72     0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
73     0x01, 0x00,
74 
75     /* Configuration descriptor */
76     0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
77     0x32,
78 
79     /* Interface descriptor */
80     0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99,
81     0x00,
82 
83     /* Endpoint descriptor (Bulk Out) */
84     0x07, 0x05, 0x01, 0x02, 0x00, 0x02, 0x00,
85 
86     /* Endpoint descriptor (Bulk In) */
87     0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00
88 };
89 
90 /* String Device Framework :
91     Byte 0 and 1 : Word containing the language ID : 0x0904 for US
92     Byte 2       : Byte containing the index of the descriptor
93     Byte 3       : Byte containing the length of the descriptor string
94 */
95 #define STRING_FRAMEWORK_LENGTH 38
96 static UCHAR string_framework[] = {
97 
98     /* Manufacturer string descriptor : Index 1 */
99     0x09, 0x04, 0x01, 0x0c,
100     0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x20, 0x4c,
101     0x6f, 0x67, 0x69, 0x63,
102 
103     /* Product string descriptor : Index 2 */
104     0x09, 0x04, 0x02, 0x0c,
105     0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
106     0x44, 0x65, 0x6d, 0x6f,
107 
108     /* Serial Number string descriptor : Index 3 */
109     0x09, 0x04, 0x03, 0x04,
110     0x30, 0x30, 0x30, 0x31
111 };
112 
113 
114 /* Multiple languages are supported on the device, to add
115     a language besides English, the unicode language code must
116     be appended to the language_id_framework array and the length
117     adjusted accordingly. */
118 #define LANGUAGE_ID_FRAMEWORK_LENGTH 2
119 static UCHAR language_id_framework[] = {
120 
121     /* English. */
122     0x09, 0x04
123 };
124 
125 
126 /* Define prototypes for external Host Controller's (HCDs), classes and clients.  */
127 
128 static VOID                tx_demo_instance_activate(VOID  *dpump_instance);
129 static VOID                tx_demo_instance_deactivate(VOID *dpump_instance);
130 
131 UINT                       _ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command);
132 UINT                       ux_hcd_sim_initialize(UX_HCD *hcd);
133 UINT                       _ux_host_class_dpump_write(UX_HOST_CLASS_DPUMP *dpump, UCHAR * data_pointer,
134                                     ULONG requested_length, ULONG *actual_length);
135 UINT                       _ux_host_class_dpump_read (UX_HOST_CLASS_DPUMP *dpump, UCHAR *data_pointer,
136                                     ULONG requested_length, ULONG *actual_length);
137 
138 static TX_THREAD           tx_demo_thread_host_simulation;
139 static TX_THREAD           tx_demo_thread_test_simulation;
140 static void                tx_demo_thread_host_simulation_entry(ULONG);
141 static void                tx_demo_thread_test_simulation_entry(ULONG);
142 
143 
144 /* Define the ISR dispatch.  */
145 
146 extern VOID    (*test_isr_dispatch)(void);
147 
148 
149 /* Prototype for test control return.  */
150 
151 void  test_control_return(UINT status);
152 
153 
154 /* Define the ISR dispatch routine.  */
155 
test_isr(void)156 static void    test_isr(void)
157 {
158 
159     /* For further expansion of interrupt-level testing.  */
160 }
161 
162 
error_callback(UINT system_level,UINT system_context,UINT error_code)163 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
164 {
165     if (!ignore_errors)
166     {
167         /* Failed test.  */
168         printf("Error on line %d, system_level: %d, system_context: %d, error code: 0x%x(%d)\n",
169             __LINE__, system_level, system_context, error_code, error_code);
170         test_control_return(1);
171     }
172 }
173 
174 /* Define what the initial system looks like.  */
175 
176 #ifdef CTEST
test_application_define(void * first_unused_memory)177 void test_application_define(void *first_unused_memory)
178 #else
179 void    usbx_ux_host_stack_device_string_get_test_application_define(void *first_unused_memory)
180 #endif
181 {
182 
183 UINT                            status;
184 CHAR                            *stack_pointer;
185 CHAR                            *memory_pointer;
186 UX_SLAVE_CLASS_DPUMP_PARAMETER  parameter;
187 
188     printf("Running ux_host_stack_device_string_get Test........................ ");
189     stepinfo("\n");
190 
191     /* Initialize the free memory pointer.  */
192     stack_pointer = (CHAR *) first_unused_memory;
193     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
194 
195     /* Initialize USBX Memory.  */
196     status =  ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
197 
198     /* Check for error.  */
199     if (status != UX_SUCCESS)
200     {
201 
202         printf("ERROR #%d:0x%x\n", __LINE__, status);
203         test_control_return(1);
204     }
205 
206     /* Register the error callback. */
207     _ux_utility_error_callback_register(error_callback);
208 
209     /* The code below is required for installing the host portion of USBX.  */
210     status =  ux_host_stack_initialize(UX_NULL);
211 
212     /* Check for error.  */
213     if (status != UX_SUCCESS)
214     {
215 
216         printf("ERROR #%d:0x%x\n", __LINE__, status);
217         test_control_return(1);
218     }
219 
220     /* Register all the host class drivers for this USBX implementation.  */
221     status =  ux_host_stack_class_register(_ux_system_host_class_dpump_name, ux_host_class_dpump_entry);
222 
223     /* Check for error.  */
224     if (status != UX_SUCCESS)
225     {
226 
227         printf("ERROR #%d:0x%x\n", __LINE__, status);
228         test_control_return(1);
229     }
230 
231     /* The code below is required for installing the device portion of USBX */
232     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
233                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
234                                        string_framework, STRING_FRAMEWORK_LENGTH,
235                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
236 
237     /* Check for error.  */
238     if (status != UX_SUCCESS)
239     {
240 
241         printf("ERROR #%d:0x%x\n", __LINE__, status);
242         test_control_return(1);
243     }
244 
245     /* Set the parameters for callback when insertion/extraction of a Data Pump device.  */
246     parameter.ux_slave_class_dpump_instance_activate   =  tx_demo_instance_activate;
247     parameter.ux_slave_class_dpump_instance_deactivate =  tx_demo_instance_deactivate;
248 
249     /* Initialize the device dpump class. The class is connected with interface 0 */
250     status =  ux_device_stack_class_register(_ux_system_slave_class_dpump_name, _ux_device_class_dpump_entry,
251                                                1, 0, &parameter);
252 
253     /* Check for error.  */
254     if (status != UX_SUCCESS)
255     {
256 
257         printf("ERROR #%d:0x%x\n", __LINE__, status);
258         test_control_return(1);
259     }
260 
261     /* Initialize the simulated device controller.  */
262     status =  _ux_dcd_sim_slave_initialize();
263 
264     /* Check for error.  */
265     if (status != UX_SUCCESS)
266     {
267 
268         printf("ERROR #%d:0x%x\n", __LINE__, status);
269         test_control_return(1);
270     }
271 
272     /* Register all the USB host controllers available in this system */
273     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, ux_hcd_sim_host_initialize,0,0);
274 
275     /* Check for error.  */
276     if (status != UX_SUCCESS)
277     {
278 
279         printf("ERROR #%d:0x%x\n", __LINE__, status);
280         test_control_return(1);
281     }
282 
283     /* Create the main host simulation thread.  */
284     status =  tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
285             stack_pointer, UX_DEMO_STACK_SIZE,
286             20, 20, 1, TX_AUTO_START);
287 
288     /* Check for error.  */
289     if (status != TX_SUCCESS)
290     {
291 
292         printf("ERROR #%d:0x%x\n", __LINE__, status);
293         test_control_return(1);
294     }
295 
296     /* Create the main demo thread.  */
297     status =  tx_thread_create(&tx_demo_thread_test_simulation, "tx demo test simulation", tx_demo_thread_test_simulation_entry, 0,
298             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
299             20, 20, 1, TX_DONT_START);
300 
301     /* Check for error.  */
302     if (status != TX_SUCCESS)
303     {
304 
305         printf("ERROR #%d:0x%x\n", __LINE__, status);
306         test_control_return(1);
307     }
308 }
309 
310 
tx_demo_dpump_get(void)311 static UINT  tx_demo_dpump_get(void)
312 {
313 UINT            status;
314 UX_HOST_CLASS   *class_inst;
315 
316 #if defined(UX_HOST_STANDALONE)
317     ux_system_tasks_run();
318 #endif
319 
320     status =  ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class_inst);
321     if (status != UX_SUCCESS)
322         return(UX_ERROR);
323     status =  ux_host_stack_class_instance_get(class_inst, 0, (VOID **) &dpump);
324     if (status != UX_SUCCESS)
325         return(UX_ERROR);
326     if (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE)
327         return(UX_ERROR);
328     return(UX_SUCCESS);
329 }
330 
331 
tx_demo_thread_host_simulation_entry(ULONG arg)332 static void  tx_demo_thread_host_simulation_entry(ULONG arg)
333 {
334 UINT            status;
335 INT             i;
336 UX_DEVICE       *device;
337 ULONG           temp;
338 
339     /* Wait a while before instances are ready.  */
340     for (i = 0; i < 1000;i ++)
341     {
342         if (tx_demo_dpump_get() == UX_SUCCESS &&
343             dpump_slave != UX_NULL)
344             break;
345         tx_thread_sleep(1);
346     }
347     if (dpump == UX_NULL || dpump_slave == UX_NULL)
348     {
349         printf("ERROR #%d: Enumeration fail %p %p\n", __LINE__, dpump, dpump_slave);
350         test_control_return(1);
351     }
352     device = dpump -> ux_host_class_dpump_device;
353 
354     ignore_errors = UX_TRUE;
355 
356     /* >>>>> Test case, device instance error.  */
357     temp = device -> ux_device_handle;
358     device -> ux_device_handle = 0;
359     status = ux_host_stack_device_string_get(device, host_in_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, 0, 0);
360     if (status != UX_DEVICE_HANDLE_UNKNOWN)
361     {
362         printf("ERROR #%d:0x%x\n", __LINE__, status);
363         test_control_return(1);
364     }
365     device -> ux_device_handle = temp;
366 
367 #if !defined(UX_HOST_STANDALONE)
368     /* >>>>> Test case, semaphore get error.  */
369     _ux_utility_semaphore_delete(&device -> ux_device_protection_semaphore);
370     status = ux_host_stack_device_string_get(device, host_in_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, 0, 0);
371     if (status != UX_SEMAPHORE_ERROR)
372     {
373         printf("ERROR #%d:0x%x\n", __LINE__, status);
374         test_control_return(1);
375     }
376     _ux_utility_semaphore_create(&device -> ux_device_protection_semaphore, "ux_device_protection_semaphore", 1);
377 #endif
378 
379     ignore_errors = UX_FALSE;
380 
381     /* >>>>> Test case, semaphore get after a while.  */
382     /* Return a LANG ID.  */
383     tx_thread_resume(&tx_demo_thread_test_simulation);
384     status = ux_host_stack_device_string_get(device, host_in_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, 0, 0);
385     if (status != UX_SUCCESS)
386     {
387         printf("ERROR #%d:0x%x\n", __LINE__, status);
388         test_control_return(1);
389     }
390     UX_TEST_ASSERT(host_in_buffer[0] == 4);
391     UX_TEST_ASSERT(host_in_buffer[1] == UX_STRING_DESCRIPTOR_ITEM);
392     UX_TEST_ASSERT(host_in_buffer[2] == 0x09);
393     UX_TEST_ASSERT(host_in_buffer[3] == 0x04);
394 
395     /* >>>>> Test case, string get (0x30, 0x30, 0x30, 0x31).  */
396     status = ux_host_stack_device_string_get(device, host_in_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, 0x0409, 3);
397     if (status != UX_SUCCESS)
398     {
399         printf("ERROR #%d:0x%x\n", __LINE__, status);
400         test_control_return(1);
401     }
402     UX_TEST_ASSERT(host_in_buffer[0] >= 10);
403     UX_TEST_ASSERT(host_in_buffer[1] == UX_STRING_DESCRIPTOR_ITEM);
404     UX_TEST_ASSERT(host_in_buffer[2] == 0x30);
405     UX_TEST_ASSERT(host_in_buffer[3] == 0x00);
406     UX_TEST_ASSERT(host_in_buffer[4] == 0x30);
407     UX_TEST_ASSERT(host_in_buffer[5] == 0x00);
408     UX_TEST_ASSERT(host_in_buffer[6] == 0x30);
409     UX_TEST_ASSERT(host_in_buffer[7] == 0x00);
410     UX_TEST_ASSERT(host_in_buffer[8] == 0x31);
411     UX_TEST_ASSERT(host_in_buffer[9] == 0x00);
412 
413     /* Sleep for a tick to make sure everything is complete.  */
414     tx_thread_sleep(1);
415 
416     /* Check for errors from other threads.  */
417     if (error_counter)
418     {
419 
420         /* DPUMP error.  */
421         printf("ERROR count %ld\n", error_counter);
422         test_control_return(1);
423     }
424     else
425     {
426 
427         /* Successful test.  */
428         printf("SUCCESS!\n");
429         test_control_return(0);
430     }
431 }
432 
433 
tx_demo_thread_test_simulation_entry(ULONG arg)434 static void  tx_demo_thread_test_simulation_entry(ULONG arg)
435 {
436 UINT                    status;
437 UX_DEVICE               *device;
438 
439     while(1)
440     {
441 
442 #if defined(UX_DEVICE_STANDALONE)
443         ux_system_tasks_run();
444 #endif
445 
446 #if !defined(UX_HOST_STANDALONE)
447         if (dpump && dpump -> ux_host_class_dpump_device)
448         {
449             /* Get control semaphore for a while.  */
450             device = dpump -> ux_host_class_dpump_device;
451             status =  tx_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER);
452             if (status != TX_SUCCESS)
453             {
454                 printf("ERROR #%d:0x%x\n", __LINE__, status);
455                 test_control_return(1);
456             }
457             tx_thread_sleep(20);
458             status = tx_semaphore_put(&device -> ux_device_protection_semaphore);
459             if (status != TX_SUCCESS)
460             {
461                 printf("ERROR #%d:0x%x\n", __LINE__, status);
462                 test_control_return(1);
463             }
464         }
465         tx_thread_suspend(&tx_demo_thread_test_simulation);
466 #endif
467 
468     }
469 }
470 
tx_demo_instance_activate(VOID * dpump_instance)471 static VOID  tx_demo_instance_activate(VOID *dpump_instance)
472 {
473 
474     /* Save the DPUMP instance.  */
475     dpump_slave = (UX_SLAVE_CLASS_DPUMP *) dpump_instance;
476 }
477 
tx_demo_instance_deactivate(VOID * dpump_instance)478 static VOID  tx_demo_instance_deactivate(VOID *dpump_instance)
479 {
480 
481     /* Reset the DPUMP instance.  */
482     dpump_slave = UX_NULL;
483 }
484 
485