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 _SetAddress = UX_TEST_SETUP_SetAddress;
181 
182 static UX_TEST_HCD_SIM_ACTION set_address_request[] = {
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, &_SetAddress,
189         UX_FALSE, 0,
190         UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, UX_SUCCESS,
191         UX_SUCCESS, ux_test_hcd_entry_invoked},
192 {   UX_HCD_TRANSFER_REQUEST, &_SetAddress,
193         UX_FALSE, 0,
194         UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, UX_SUCCESS,
195         UX_SUCCESS, ux_test_hcd_entry_invoked},
196 {   UX_HCD_TRANSFER_REQUEST, &_SetAddress,
197         UX_FALSE, 0,
198         UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, UX_SUCCESS,
199         UX_SUCCESS, ux_test_hcd_entry_invoked},
200 {   0   }
201 };
202 
203 /* Define the ISR dispatch routine.  */
204 
test_isr(void)205 static void    test_isr(void)
206 {
207 
208     /* For further expansion of interrupt-level testing.  */
209 }
210 
211 
error_callback(UINT system_level,UINT system_context,UINT error_code)212 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
213 {
214 
215     test_error_counter ++;
216 
217     /* Failed test.  */
218     if (!test_error_cases)
219     {
220 
221         printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
222         test_control_return(1);
223     }
224 }
225 
226 /* Define what the initial system looks like.  */
227 
228 #ifdef CTEST
test_application_define(void * first_unused_memory)229 void test_application_define(void *first_unused_memory)
230 #else
231 void    usbx_ux_host_stack_device_address_set_test_application_define(void *first_unused_memory)
232 #endif
233 {
234 
235 UINT status;
236 CHAR                            *stack_pointer;
237 CHAR                            *memory_pointer;
238 UX_SLAVE_CLASS_DPUMP_PARAMETER  parameter;
239 
240 
241     /* Initialize the free memory pointer.  */
242     stack_pointer = (CHAR *) first_unused_memory;
243     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
244 
245     /* Initialize USBX Memory.  */
246     status =  ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
247 
248     /* Check for error.  */
249     if (status != UX_SUCCESS)
250     {
251 
252         printf("Running ux_host_stack_device_address_set Test....................... ERROR #1\n");
253         test_control_return(1);
254     }
255 
256     /* Register the error callback. */
257     _ux_utility_error_callback_register(error_callback);
258 
259     /* The code below is required for installing the host portion of USBX.  */
260     status =  ux_host_stack_initialize(UX_NULL);
261 
262     /* Check for error.  */
263     if (status != UX_SUCCESS)
264     {
265 
266         printf("Running ux_host_stack_device_address_set Test....................... ERROR #2\n");
267         test_control_return(1);
268     }
269 
270     /* Register all the host class drivers for this USBX implementation.  */
271     status =  ux_host_stack_class_register(_ux_system_host_class_dpump_name, _ux_host_class_dpump_entry);
272 
273     /* Check for error.  */
274     if (status != UX_SUCCESS)
275     {
276 
277         printf("Running ux_host_stack_device_address_set Test....................... ERROR #3\n");
278         test_control_return(1);
279     }
280 
281     /* The code below is required for installing the device portion of USBX */
282     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
283                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
284                                        string_framework, STRING_FRAMEWORK_LENGTH,
285                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
286 
287     /* Check for error.  */
288     if (status != UX_SUCCESS)
289     {
290 
291         printf("Running ux_host_stack_device_address_set Test....................... ERROR #5\n");
292         test_control_return(1);
293     }
294 
295     /* Set the parameters for callback when insertion/extraction of a Data Pump device.  */
296     parameter.ux_slave_class_dpump_instance_activate   =  tx_test_instance_activate;
297     parameter.ux_slave_class_dpump_instance_deactivate =  tx_test_instance_deactivate;
298 
299     /* Initialize the device dpump class. The class is connected with interface 0 */
300     status  = ux_device_stack_class_register(_ux_system_slave_class_dpump_name, _ux_device_class_dpump_entry,
301                                               1, 0, &parameter);
302 
303     /* Check for error.  */
304     if (status != UX_SUCCESS)
305     {
306 
307         printf("Running ux_host_stack_device_address_set Test....................... ERROR #6\n");
308         test_control_return(1);
309     }
310 
311     /* Initialize the simulated device controller.  */
312     status =  _ux_test_dcd_sim_slave_initialize();
313 
314     /* Check for error.  */
315     if (status != UX_SUCCESS)
316     {
317 
318         printf("Running ux_host_stack_device_address_set Test....................... ERROR #7\n");
319         test_control_return(1);
320     }
321 
322     /* Register all the USB host controllers available in this system */
323     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
324 
325     /* Check for error.  */
326     if (status != UX_SUCCESS)
327     {
328 
329         printf("Running ux_host_stack_device_address_set Test....................... ERROR #4\n");
330         test_control_return(1);
331     }
332 
333     /* Create the main host simulation thread.  */
334     status =  tx_thread_create(&tx_test_thread_host_simulation, "tx demo host simulation", tx_test_thread_host_simulation_entry, 0,
335             stack_pointer, UX_DEMO_STACK_SIZE,
336             20, 20, 1, TX_AUTO_START);
337 
338     /* Check for error.  */
339     if (status != TX_SUCCESS)
340     {
341 
342         printf("Running ux_host_stack_device_address_set Test....................... ERROR #8\n");
343         test_control_return(1);
344     }
345 
346     /* Create the main demo thread.  */
347     status =  tx_thread_create(&tx_test_thread_slave_simulation, "tx demo slave simulation", tx_test_thread_slave_simulation_entry, 0,
348             stack_pointer + UX_DEMO_STACK_SIZE, 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_device_address_set Test....................... ERROR #9\n");
356         test_control_return(1);
357     }
358 }
359 
360 
tx_test_thread_host_simulation_entry(ULONG arg)361 static void  tx_test_thread_host_simulation_entry(ULONG arg)
362 {
363 
364 UINT             status;
365 UX_DEVICE        *device;
366 UX_CONFIGURATION *configuration;
367 UX_HCD           *hcd;
368 UX_DEVICE        device_back;
369 
370     /* Inform user.  */
371     printf("Running ux_host_stack_device_address_set Test....................... ");
372 
373     /* Connect. */
374     ux_test_hcd_sim_host_connect(UX_HIGH_SPEED_DEVICE);
375 
376     /* Check device connection. */
377     status = ux_host_stack_device_get(0, &device);
378     if (status != UX_SUCCESS)
379     {
380 
381         printf("ERROR #%d: fail to get device instance\n", __LINE__);
382         test_control_return(1);
383     }
384 
385     /* Get configuration. */
386     status = ux_host_stack_device_configuration_get(device, 0, &configuration);
387     if (status != UX_SUCCESS)
388     {
389 
390         printf("ERROR #%d: fail to get device configuration\n", __LINE__);
391         test_control_return(1);
392     }
393 
394 #if UX_MAX_DEVICES > 1
395     /* Simulate address set error. */
396 
397     /* Backup device instance. */
398     ux_utility_memory_copy(&device_back, device, sizeof(UX_DEVICE));
399 
400     /* Modify address usage map. */
401     hcd = UX_DEVICE_HCD_GET(device);
402     ux_utility_memory_set(hcd->ux_hcd_address, 0xFF, 16);
403 
404     /* Set address, expect error since all device address used. */
405     test_error_counter = 0;
406     ux_test_hcd_sim_host_set_actions(set_address_request);
407     status = _ux_host_stack_device_address_set(device);
408     if (status == UX_SUCCESS)
409     {
410 
411         printf("ERROR #%d: expect error\n", __LINE__);
412         error_counter ++;
413     }
414     if (test_error_counter)
415     {
416 
417         printf("ERROR #%d: expect no call of SetAddress\n", __LINE__);
418         error_counter ++;
419     }
420 
421     /* Set address, expect address 1.  */
422     ux_utility_memory_set(hcd->ux_hcd_address, 0x00, 16);
423     hcd->ux_hcd_address[0] = 1;
424     hcd->ux_hcd_address[1] = 1;
425     /* Set address, expect no error since all device address used. */
426     test_error_counter = 0;
427     ux_test_hcd_sim_host_set_actions(set_address_request);
428     status = _ux_host_stack_device_address_set(device);
429     if (status != UX_SUCCESS)
430     {
431 
432         printf("ERROR #%d: expect no error 0x%x\n", __LINE__, status);
433         error_counter ++;
434     }
435     if (test_error_counter != 1)
436     {
437 
438         printf("ERROR #%d: expect 1 call of SetAddress but not %ld\n", __LINE__, test_error_counter);
439         error_counter ++;
440     }
441     if (hcd->ux_hcd_address[0] != 0x03 || hcd->ux_hcd_address[1] != 0x01)
442     {
443         printf("ERROR #%d: expect address map 0x03 0x01 but not 0x%x 0x%x\n", __LINE__, hcd->ux_hcd_address[0], hcd->ux_hcd_address[1]);
444         error_counter ++;
445     }
446 
447     /* Set address, expect address 1.  */
448     ux_utility_memory_set(hcd->ux_hcd_address, 0x00, 16);
449     hcd->ux_hcd_address[0] = 0xFF;
450     hcd->ux_hcd_address[1] = 1;
451     /* Set address, expect no error since all device address used. */
452     test_error_counter = 0;
453     ux_test_hcd_sim_host_set_actions(set_address_request);
454     status = _ux_host_stack_device_address_set(device);
455     if (status != UX_SUCCESS)
456     {
457 
458         printf("ERROR #%d: expect no error 0x%x\n", __LINE__, status);
459         error_counter ++;
460     }
461     if (test_error_counter != 1)
462     {
463 
464         printf("ERROR #%d: expect 1 call of SetAddress but not %ld\n", __LINE__, test_error_counter);
465         error_counter ++;
466     }
467     if (hcd->ux_hcd_address[0] != 0xFF || hcd->ux_hcd_address[1] != 0x03)
468     {
469         printf("ERROR #%d: expect address map 0xFF 0x03 but not 0x%x 0x%x\n", __LINE__, hcd->ux_hcd_address[0], hcd->ux_hcd_address[1]);
470         error_counter ++;
471     }
472 
473 #endif
474 
475     /* Sleep for a tick to make sure everything is complete.  */
476     tx_thread_sleep(1);
477 
478     /* Check for errors from other threads.  */
479     if (error_counter)
480     {
481 
482         /* DPUMP error.  */
483         printf("ERROR #14\n");
484         test_control_return(1);
485     }
486     else
487     {
488 
489         /* Successful test.  */
490         printf("SUCCESS!\n");
491         test_control_return(0);
492     }
493 }
494 
495 
tx_test_thread_slave_simulation_entry(ULONG arg)496 static void  tx_test_thread_slave_simulation_entry(ULONG arg)
497 {
498 
499     while(1)
500     {
501 
502         /* Ensure the dpump class on the device is still alive.  */
503         if (dpump_slave != UX_NULL)
504         {
505 
506             /* Increment thread counter.  */
507             thread_1_counter++;
508         }
509 
510         /* Let other thread run.  */
511         tx_thread_sleep(10);
512     }
513 }
514 
tx_test_instance_activate(VOID * dpump_instance)515 static VOID  tx_test_instance_activate(VOID *dpump_instance)
516 {
517 
518     /* Save the DPUMP instance.  */
519     dpump_slave = (UX_SLAVE_CLASS_DPUMP *) dpump_instance;
520 }
521 
tx_test_instance_deactivate(VOID * dpump_instance)522 static VOID  tx_test_instance_deactivate(VOID *dpump_instance)
523 {
524 
525     /* Reset the DPUMP instance.  */
526     dpump_slave = UX_NULL;
527 }
528 
ux_test_hcd_entry_invoked(UX_TEST_ACTION * action,VOID * params)529 static VOID ux_test_hcd_entry_invoked(UX_TEST_ACTION *action, VOID *params)
530 {
531 
532     test_error_counter ++;
533 }