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 
9 #include "ux_host_class_dpump.h"
10 #include "ux_device_class_dpump.h"
11 
12 #include "ux_host_stack.h"
13 
14 /* Define USBX demo constants.  */
15 
16 #define UX_DEMO_STACK_SIZE      4096
17 #define UX_DEMO_BUFFER_SIZE     2048
18 #define UX_DEMO_RUN             1
19 #define UX_DEMO_MEMORY_SIZE     (64*1024)
20 
21 
22 /* Define the counters used in the demo application...  */
23 
24 static ULONG                           thread_0_counter;
25 static ULONG                           thread_1_counter;
26 static ULONG                           error_counter;
27 
28 static UCHAR                           test_sim_entry;
29 static ULONG                           test_sim_query_usage;
30 static ULONG                           test_sim_query_count;
31 static ULONG                           test_sim_activate_count;
32 
33 /* Define USBX demo global variables.  */
34 
35 static unsigned char                   host_out_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
36 static unsigned char                   host_in_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
37 static unsigned char                   slave_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
38 
39 static UX_HOST_CLASS                   *class_driver;
40 static UX_HOST_CLASS_DPUMP             *dpump;
41 static UX_SLAVE_CLASS_DPUMP            *dpump_slave;
42 
43 
44 static UCHAR device_framework_full_speed[] = {
45 
46     /* Device descriptor */
47     0x12, 0x01, 0x10, 0x01,
48     0x00, 0x00, 0x00, /* bDeviceClass, bDeviceSubClass, bDeviceProtocol */
49     0x08, /* bMaxPacketSize0 */
50     0xec, 0x08, 0x10, 0x00, /* idVendor, idProduct */
51     0x00, 0x00,
52     0x00, 0x00, 0x00,
53     0x01, /* bNumConfigurations */
54 
55     /* Configuration descriptor */
56     0x09, 0x02,
57     0x20, 0x00, /* wTotalLength */
58     0x01, 0x01, /* bNumInterfaces, bConfigurationValue */
59     0x00,
60     0xc0, 0x32, /* bmAttributes, bMaxPower */
61 
62     /* Interface descriptor */
63     0x09, 0x04,
64     0x00, 0x00, 0x02, /* bInterfaceNumber, bAlternateSetting, bNumEndpoints */
65     0x99, 0x99, 0x99, /* bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol */
66     0x00,
67 
68     /* Endpoint descriptor (Bulk Out) */
69     0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00,
70 
71     /* Endpoint descriptor (Bulk In) */
72     0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00
73 };
74 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
75 
76 
77 static UCHAR device_framework_high_speed[] = {
78 
79     /* Device descriptor */
80     0x12, 0x01, 0x00, 0x02,
81     0x00, 0x00, 0x00, /* bDeviceClass, bDeviceSubClass, bDeviceProtocol */
82     0x40, /* bMaxPacketSize0 */
83     0x0a, 0x07, /* idVendor */
84     0x25, 0x40, /* idProduct */
85     0x01, 0x00,
86     0x01, 0x02, 0x03,
87     0x01, /* bNumConfigurations */
88 
89     /* Device qualifier descriptor */
90     0x0a, 0x06, 0x00, 0x02,
91     0x00, 0x00, 0x00, /* bDeviceClass, bDeviceSubClass, bDeviceProtocol */
92     0x40, /* bMaxPacketSize0 */
93     0x01, /* bNumConfigurations */
94     0x00,
95 
96     /* Configuration descriptor */
97     0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
98     0x32,
99 
100     /* Interface descriptor */
101     0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99,
102     0x00,
103 
104     /* Endpoint descriptor (Bulk Out) */
105     0x07, 0x05, 0x01, 0x02, 0x00, 0x02, 0x00,
106 
107     /* Endpoint descriptor (Bulk In) */
108     0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00
109 };
110 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
111 
112 /* String Device Framework :
113     Byte 0 and 1 : Word containing the language ID : 0x0904 for US
114     Byte 2       : Byte containing the index of the descriptor
115     Byte 3       : Byte containing the length of the descriptor string
116 */
117 static UCHAR string_framework[] = {
118 
119     /* Manufacturer string descriptor : Index 1 */
120     0x09, 0x04, 0x01, 0x0c,
121     0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
122     0x6f, 0x67, 0x69, 0x63,
123 
124     /* Product string descriptor : Index 2 */
125     0x09, 0x04, 0x02, 0x0c,
126     0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
127     0x44, 0x65, 0x6d, 0x6f,
128 
129     /* Serial Number string descriptor : Index 3 */
130     0x09, 0x04, 0x03, 0x04,
131     0x30, 0x30, 0x30, 0x31
132 };
133 #define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
134 
135 /* Multiple languages are supported on the device, to add
136     a language besides English, the unicode language code must
137     be appended to the language_id_framework array and the length
138     adjusted accordingly. */
139 static UCHAR language_id_framework[] = {
140 
141     /* English. */
142     0x09, 0x04
143 };
144 #define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
145 
146 
147 /* Define prototypes for external Host Controller's (HCDs), classes and clients.  */
148 
149 static VOID                tx_demo_instance_activate(VOID  *dpump_instance);
150 static VOID                tx_demo_instance_deactivate(VOID *dpump_instance);
151 
152 UINT                       _ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command);
153 UINT                       ux_hcd_sim_initialize(UX_HCD *hcd);
154 UINT                       _ux_host_class_dpump_write(UX_HOST_CLASS_DPUMP *dpump, UCHAR * data_pointer,
155                                     ULONG requested_length, ULONG *actual_length);
156 UINT                       _ux_host_class_dpump_read (UX_HOST_CLASS_DPUMP *dpump, UCHAR *data_pointer,
157                                     ULONG requested_length, ULONG *actual_length);
158 
159 static TX_THREAD           tx_demo_thread_host_simulation;
160 static TX_THREAD           tx_demo_thread_slave_simulation;
161 static void                tx_demo_thread_host_simulation_entry(ULONG);
162 static void                tx_demo_thread_slave_simulation_entry(ULONG);
163 
test_ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND * command)164 static UINT test_ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command)
165 {
166     if (test_sim_entry)
167     {
168 
169         switch (command -> ux_host_class_command_request)
170         {
171         case UX_HOST_CLASS_COMMAND_QUERY:
172             test_sim_query_count ++;
173             if (command -> ux_host_class_command_usage != test_sim_query_usage)
174                 return UX_NO_CLASS_MATCH;
175             break;
176 
177         case UX_HOST_CLASS_COMMAND_ACTIVATE:
178             test_sim_activate_count ++;
179             break;
180 
181         default:
182             break;
183         }
184         return UX_SUCCESS;
185     }
186     return ux_host_class_dpump_entry(command);
187 }
188 
189 
190 /* Define the ISR dispatch.  */
191 
192 extern VOID    (*test_isr_dispatch)(void);
193 
194 
195 /* Prototype for test control return.  */
196 
197 void  test_control_return(UINT status);
198 
199 
200 /* Define the ISR dispatch routine.  */
201 
test_isr(void)202 static void    test_isr(void)
203 {
204 
205     /* For further expansion of interrupt-level testing.  */
206 }
207 
208 
error_callback(UINT system_level,UINT system_context,UINT error_code)209 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
210 {
211 
212     /* Failed test.  */
213     printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
214     test_control_return(1);
215 }
216 
217 /* Define what the initial system looks like.  */
218 
219 #ifdef CTEST
test_application_define(void * first_unused_memory)220 void test_application_define(void *first_unused_memory)
221 #else
222 void    usbx_ux_host_stack_class_device_scan_test_application_define(void *first_unused_memory)
223 #endif
224 {
225 
226 UINT status;
227 CHAR                            *stack_pointer;
228 CHAR                            *memory_pointer;
229 UX_SLAVE_CLASS_DPUMP_PARAMETER  parameter;
230 
231 
232     /* Initialize the free memory pointer.  */
233     stack_pointer = (CHAR *) first_unused_memory;
234     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
235 
236     /* Initialize USBX Memory.  */
237     status =  ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
238 
239     /* Check for error.  */
240     if (status != UX_SUCCESS)
241     {
242 
243         printf("Running ux_host_stack_class_device_scan Test........................ ERROR #1\n");
244         test_control_return(1);
245     }
246 
247     /* Register the error callback. */
248     _ux_utility_error_callback_register(error_callback);
249 
250     /* The code below is required for installing the host portion of USBX.  */
251     status =  ux_host_stack_initialize(UX_NULL);
252 
253     /* Check for error.  */
254     if (status != UX_SUCCESS)
255     {
256 
257         printf("Running ux_host_stack_class_device_scan Test........................ ERROR #2\n");
258         test_control_return(1);
259     }
260 
261     /* Register all the host class drivers for this USBX implementation.  */
262     status =  ux_host_stack_class_register(_ux_system_host_class_dpump_name, test_ux_host_class_dpump_entry);
263 
264     /* Check for error.  */
265     if (status != UX_SUCCESS)
266     {
267 
268         printf("Running ux_host_stack_class_device_scan Test........................ ERROR #3\n");
269         test_control_return(1);
270     }
271 
272     /* The code below is required for installing the device portion of USBX */
273     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
274                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
275                                        string_framework, STRING_FRAMEWORK_LENGTH,
276                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
277 
278     /* Check for error.  */
279     if (status != UX_SUCCESS)
280     {
281 
282         printf("Running ux_host_stack_class_device_scan Test........................ ERROR #5\n");
283         test_control_return(1);
284     }
285 
286     /* Set the parameters for callback when insertion/extraction of a Data Pump device.  */
287     parameter.ux_slave_class_dpump_instance_activate   =  tx_demo_instance_activate;
288     parameter.ux_slave_class_dpump_instance_deactivate =  tx_demo_instance_deactivate;
289 
290     /* Initialize the device dpump class. The class is connected with interface 0 */
291     status  = ux_device_stack_class_register(_ux_system_slave_class_dpump_name, _ux_device_class_dpump_entry,
292                                               1, 0, &parameter);
293 
294     /* Check for error.  */
295     if (status != UX_SUCCESS)
296     {
297 
298         printf("Running ux_host_stack_class_device_scan Test........................ ERROR #6\n");
299         test_control_return(1);
300     }
301 
302     /* Initialize the simulated device controller.  */
303     status =  _ux_dcd_sim_slave_initialize();
304 
305     /* Check for error.  */
306     if (status != UX_SUCCESS)
307     {
308 
309         printf("Running ux_host_stack_class_device_scan Test........................ ERROR #7\n");
310         test_control_return(1);
311     }
312 
313     /* Register all the USB host controllers available in this system */
314     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, ux_hcd_sim_host_initialize,0,0);
315 
316     /* Check for error.  */
317     if (status != UX_SUCCESS)
318     {
319 
320         printf("Running ux_host_stack_class_device_scan Test........................ ERROR #4\n");
321         test_control_return(1);
322     }
323 
324     /* Create the main host simulation thread.  */
325     status =  tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
326             stack_pointer, UX_DEMO_STACK_SIZE,
327             20, 20, 1, TX_AUTO_START);
328 
329     /* Check for error.  */
330     if (status != TX_SUCCESS)
331     {
332 
333         printf("Running ux_host_stack_class_device_scan Test........................ ERROR #8\n");
334         test_control_return(1);
335     }
336 
337     /* Create the main demo thread.  */
338     status =  tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
339             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
340             20, 20, 1, TX_AUTO_START);
341 
342     /* Check for error.  */
343     if (status != TX_SUCCESS)
344     {
345 
346         printf("Running ux_host_stack_class_device_scan Test........................ ERROR #9\n");
347         test_control_return(1);
348     }
349 }
350 
351 
tx_demo_thread_host_simulation_entry(ULONG arg)352 static void  tx_demo_thread_host_simulation_entry(ULONG arg)
353 {
354 
355 UINT status;
356 UX_HOST_CLASS   *class;
357 UX_DEVICE       *device;
358 
359 
360     /* Inform user.  */
361     printf("Running ux_host_stack_class_device_scan Test........................ ");
362 
363     /* Find the main data pump container.  */
364     status =  ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class);
365 
366     /* Check for error.  */
367     if (status != UX_SUCCESS)
368     {
369 
370         /* DPUMP basic test error.  */
371         printf("ERROR #10\n");
372         test_control_return(1);
373     }
374 
375     /* We get the first instance of the data pump device.  */
376     do
377     {
378 
379         status =  ux_host_stack_class_instance_get(class, 0, (VOID **) &dpump);
380         tx_thread_relinquish();
381     } while (status != UX_SUCCESS);
382 
383     /* We still need to wait for the data pump status to be live.  */
384     while (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE)
385     {
386 
387         tx_thread_relinquish();
388     }
389 
390     status = ux_host_stack_device_get(0, &device);
391     if (status != UX_SUCCESS)
392     {
393 
394         printf("ERROR #%d: fail to get device instance\n", __LINE__);
395         test_control_return(1);
396     }
397 
398 #if !defined(UX_HOST_STACK_DEVICE_DRIVER_SCAN_DISABLE)
399     /* Simulate class device scan, query and activate should happen. */
400     test_sim_entry = UX_TRUE;
401 
402     /* Query fail case */
403     test_sim_query_usage = 0xFF; /* UX_HOST_CLASS_COMMAND_USAGE_PIDVID, UX_HOST_CLASS_COMMAND_USAGE_CSP */
404     test_sim_activate_count = 0;
405     test_sim_query_count = 0;
406     status = _ux_host_stack_class_device_scan(device);
407     if (status == UX_SUCCESS)
408     {
409 
410         printf("ERROR #%d: Queries should fail\n", __LINE__);
411         error_counter ++;
412     }
413     if (test_sim_query_count != 2)
414     {
415 
416         printf("ERROR #%d: Queries tried must be 2\n", __LINE__);
417         error_counter ++;
418     }
419     if (test_sim_activate_count > 0)
420     {
421 
422         printf("ERROR #%d: No activate should be done\n", __LINE__);
423         error_counter ++;
424     }
425 
426 #if !defined(UX_HOST_STACK_DEVICE_DRIVER_SCAN_VIDPID_DISABLE)
427     /* VIDPID success case */
428     test_sim_query_usage = UX_HOST_CLASS_COMMAND_USAGE_PIDVID; /* UX_HOST_CLASS_COMMAND_USAGE_PIDVID, UX_HOST_CLASS_COMMAND_USAGE_DCSP */
429     test_sim_activate_count = 0;
430     test_sim_query_count = 0;
431     status = _ux_host_stack_class_device_scan(device);
432     if (status != UX_SUCCESS)
433     {
434 
435         printf("ERROR #%d: Queries should pass\n", __LINE__);
436         error_counter ++;
437     }
438     if (test_sim_query_count == 0)
439     {
440 
441         printf("ERROR #%d: There should be at least 1 query\n", __LINE__);
442         error_counter ++;
443     }
444     if (test_sim_activate_count != 1)
445     {
446 
447         printf("ERROR #%d: There must be 1 activate\n", __LINE__);
448         error_counter ++;
449     }
450 #endif /* !defined(UX_HOST_STACK_DEVICE_DRIVER_SCAN_DCSP_DISABLE) */
451 
452 #if !defined(UX_HOST_STACK_DEVICE_DRIVER_SCAN_DCSP_DISABLE)
453     /* Class/SubClass/Protocol success case */
454     test_sim_query_usage = UX_HOST_CLASS_COMMAND_USAGE_DCSP; /* UX_HOST_CLASS_COMMAND_USAGE_PIDVID, UX_HOST_CLASS_COMMAND_USAGE_DCSP */
455     test_sim_activate_count = 0;
456     test_sim_query_count = 0;
457     status = _ux_host_stack_class_device_scan(device);
458     if (status != UX_SUCCESS)
459     {
460 
461         printf("ERROR #%d: Queries should pass\n", __LINE__);
462         error_counter ++;
463     }
464     if (test_sim_query_count == 0)
465     {
466 
467         printf("ERROR #%d: There should be at least 1 query\n", __LINE__);
468         error_counter ++;
469     }
470     if (test_sim_activate_count != 1)
471     {
472 
473         printf("ERROR #%d: There must be 1 activate\n", __LINE__);
474         error_counter ++;
475     }
476 #endif /* !defined(UX_HOST_STACK_DEVICE_DRIVER_SCAN_DCSP_DISABLE) */
477 
478 #endif /* !defined(UX_HOST_STACK_DEVICE_DRIVER_SCAN_DISABLE) */
479 
480     /* Sleep for a tick to make sure everything is complete.  */
481     tx_thread_sleep(1);
482 
483     /* Check for errors from other threads.  */
484     if (error_counter)
485     {
486 
487         /* DPUMP error.  */
488         printf("ERROR #14\n");
489         test_control_return(1);
490     }
491     else
492     {
493 
494         /* Successful test.  */
495         printf("SUCCESS!\n");
496         test_control_return(0);
497     }
498 }
499 
500 
tx_demo_thread_slave_simulation_entry(ULONG arg)501 static void  tx_demo_thread_slave_simulation_entry(ULONG arg)
502 {
503 
504     while(1)
505     {
506 
507         /* Ensure the dpump class on the device is still alive.  */
508         if (dpump_slave != UX_NULL)
509         {
510 
511             /* Increment thread counter.  */
512             thread_1_counter++;
513         }
514 
515         /* Let other thread run.  */
516         tx_thread_sleep(10);
517     }
518 }
519 
tx_demo_instance_activate(VOID * dpump_instance)520 static VOID  tx_demo_instance_activate(VOID *dpump_instance)
521 {
522 
523     /* Save the DPUMP instance.  */
524     dpump_slave = (UX_SLAVE_CLASS_DPUMP *) dpump_instance;
525 }
526 
tx_demo_instance_deactivate(VOID * dpump_instance)527 static VOID  tx_demo_instance_deactivate(VOID *dpump_instance)
528 {
529 
530     /* Reset the DPUMP instance.  */
531     dpump_slave = UX_NULL;
532 }
533 
534