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