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, 0x00, /* wTotalLength */
56     0x01, 0x01, /* bNumInterfaces, bConfigurationValue */
57     0x00,
58     0xc0, 0x32, /* bmAttributes, bMaxPower */
59 
60     /* Interface descriptor */
61     0x09, 0x04,
62     0x00, 0x00, 0x02, /* bInterfaceNumber, bAlternateSetting, bNumEndpoints */
63     0x99, 0x99, 0x99, /* bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol */
64     0x00,
65 
66     /* Endpoint descriptor (Bulk Out) */
67     0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00,
68 
69     /* Endpoint descriptor (Bulk In) */
70     0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00
71 };
72 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
73 
74 
75 static UCHAR device_framework_high_speed[] = {
76 
77     /* Device descriptor */
78     0x12, 0x01, 0x00, 0x02,
79     0x00, 0x00, 0x00, /* bDeviceClass, bDeviceSubClass, bDeviceProtocol */
80     0x40, /* bMaxPacketSize0 */
81     0x0a, 0x07, /* idVendor */
82     0x25, 0x40, /* idProduct */
83     0x01, 0x00,
84     0x01, 0x02, 0x03,
85     0x01, /* bNumConfigurations */
86 
87     /* Device qualifier descriptor */
88     0x0a, 0x06, 0x00, 0x02,
89     0x00, 0x00, 0x00, /* bDeviceClass, bDeviceSubClass, bDeviceProtocol */
90     0x40, /* bMaxPacketSize0 */
91     0x01, /* bNumConfigurations */
92     0x00,
93 
94     /* Configuration descriptor */
95     0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
96     0x32,
97 
98     /* Interface descriptor */
99     0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99,
100     0x00,
101 
102     /* Endpoint descriptor (Bulk Out) */
103     0x07, 0x05, 0x01, 0x02, 0x00, 0x02, 0x00,
104 
105     /* Endpoint descriptor (Bulk In) */
106     0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00
107 };
108 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
109 
110 /* String Device Framework :
111     Byte 0 and 1 : Word containing the language ID : 0x0904 for US
112     Byte 2       : Byte containing the index of the descriptor
113     Byte 3       : Byte containing the length of the descriptor string
114 */
115 static UCHAR string_framework[] = {
116 
117     /* Manufacturer string descriptor : Index 1 */
118     0x09, 0x04, 0x01, 0x0c,
119     0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
120     0x6f, 0x67, 0x69, 0x63,
121 
122     /* Product string descriptor : Index 2 */
123     0x09, 0x04, 0x02, 0x0c,
124     0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
125     0x44, 0x65, 0x6d, 0x6f,
126 
127     /* Serial Number string descriptor : Index 3 */
128     0x09, 0x04, 0x03, 0x04,
129     0x30, 0x30, 0x30, 0x31
130 };
131 #define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
132 
133 /* Multiple languages are supported on the device, to add
134     a language besides English, the unicode language code must
135     be appended to the language_id_framework array and the length
136     adjusted accordingly. */
137 static UCHAR language_id_framework[] = {
138 
139     /* English. */
140     0x09, 0x04
141 };
142 #define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
143 
144 static UCHAR iso_ep_desc[] =
145 {
146     /* Endpoint descriptor (ISO) */
147     0x07, 0x05, 0x01, 0x01, 0x00, 0x01, 0x00,
148 };
149 
150 
151 /* Define prototypes for external Host Controller's (HCDs), classes and clients.  */
152 
153 static VOID                tx_test_instance_activate(VOID  *dpump_instance);
154 static VOID                tx_test_instance_deactivate(VOID *dpump_instance);
155 
156 UINT                       _ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command);
157 UINT                       ux_hcd_sim_initialize(UX_HCD *hcd);
158 UINT                       _ux_host_class_dpump_write(UX_HOST_CLASS_DPUMP *dpump, UCHAR * data_pointer,
159                                     ULONG requested_length, ULONG *actual_length);
160 UINT                       _ux_host_class_dpump_read (UX_HOST_CLASS_DPUMP *dpump, UCHAR *data_pointer,
161                                     ULONG requested_length, ULONG *actual_length);
162 
163 static TX_THREAD           tx_test_thread_host_simulation;
164 static TX_THREAD           tx_test_thread_slave_simulation;
165 static void                tx_test_thread_host_simulation_entry(ULONG);
166 static void                tx_test_thread_slave_simulation_entry(ULONG);
167 
168 static VOID                ux_test_hcd_entry_invoked(UX_TEST_ACTION *action, VOID *params);
169 
170 /* Define the ISR dispatch.  */
171 
172 extern VOID    (*test_isr_dispatch)(void);
173 
174 
175 /* Prototype for test control return.  */
176 
177 void  test_control_return(UINT status);
178 
179 /* Simulation */
180 
181 static UX_TEST_HCD_SIM_ACTION endpoint_create_fail[] = {
182 /* function, request to match,
183    port action, port status,
184    request action, request EP, request data, request actual length, request status,
185    status, additional callback,
186    no_return */
187 {   UX_HCD_CREATE_ENDPOINT, NULL,
188         UX_FALSE, 0,
189         0         , 0, UX_NULL, 0, 0,
190         UX_ERROR, ux_test_hcd_entry_invoked},
191 {   0   }
192 };
193 
194 /* Define the ISR dispatch routine.  */
195 
test_isr(void)196 static void    test_isr(void)
197 {
198 
199     /* For further expansion of interrupt-level testing.  */
200 }
201 
202 
error_callback(UINT system_level,UINT system_context,UINT error_code)203 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
204 {
205 
206     test_error_counter ++;
207 
208     /* Failed test.  */
209     if (!test_error_cases)
210     {
211 
212         printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
213         test_control_return(1);
214     }
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_endpoint_instance_create_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_endpoint_instance_create 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_endpoint_instance_create 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, _ux_host_class_dpump_entry);
263 
264     /* Check for error.  */
265     if (status != UX_SUCCESS)
266     {
267 
268         printf("Running ux_host_stack_endpoint_instance_create 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_endpoint_instance_create 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_test_instance_activate;
288     parameter.ux_slave_class_dpump_instance_deactivate =  tx_test_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_endpoint_instance_create Test................. ERROR #6\n");
299         test_control_return(1);
300     }
301 
302     /* Initialize the simulated device controller.  */
303     status =  _ux_test_dcd_sim_slave_initialize();
304 
305     /* Check for error.  */
306     if (status != UX_SUCCESS)
307     {
308 
309         printf("Running ux_host_stack_endpoint_instance_create 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_test_hcd_sim_host_initialize,0,0);
315 
316     /* Check for error.  */
317     if (status != UX_SUCCESS)
318     {
319 
320         printf("Running ux_host_stack_endpoint_instance_create Test................. ERROR #4\n");
321         test_control_return(1);
322     }
323 
324     /* Create the main host simulation thread.  */
325     status =  tx_thread_create(&tx_test_thread_host_simulation, "tx demo host simulation", tx_test_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_endpoint_instance_create Test................. ERROR #8\n");
334         test_control_return(1);
335     }
336 
337     /* Create the main demo thread.  */
338     status =  tx_thread_create(&tx_test_thread_slave_simulation, "tx demo slave simulation", tx_test_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_endpoint_instance_create Test................. ERROR #9\n");
347         test_control_return(1);
348     }
349 }
350 
351 
tx_test_thread_host_simulation_entry(ULONG arg)352 static void  tx_test_thread_host_simulation_entry(ULONG arg)
353 {
354 
355 UINT status;
356 UX_HOST_CLASS   *class;
357 UX_DEVICE       *device;
358 UX_ENDPOINT      endpoint;
359 UX_HCD          *hcd;
360 
361     /* Inform user.  */
362     printf("Running ux_host_stack_endpoint_instance_create Test................. ");
363 
364     /* Find the main data pump container.  */
365     status =  ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class);
366 
367     /* Check for error.  */
368     if (status != UX_SUCCESS)
369     {
370 
371         /* DPUMP basic test error.  */
372         printf("ERROR #10\n");
373         test_control_return(1);
374     }
375 
376     /* We get the first instance of the data pump device.  */
377     do
378     {
379 
380         status =  ux_host_stack_class_instance_get(class, 0, (VOID **) &dpump);
381         tx_thread_relinquish();
382     } while (status != UX_SUCCESS);
383 
384     /* We still need to wait for the data pump status to be live.  */
385     while (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE)
386     {
387 
388         tx_thread_relinquish();
389     }
390 
391     status = ux_host_stack_device_get(0, &device);
392     if (status != UX_SUCCESS)
393     {
394 
395         printf("ERROR #%d: fail to get device instance\n", __LINE__);
396         test_control_return(1);
397     }
398 
399     /* Simulate _ux_host_stack_endpoint_instance_create error cases. */
400     hcd =  &_ux_system_host -> ux_system_host_hcd_array[0];
401     endpoint.ux_endpoint_device = device;
402 
403     _ux_utility_descriptor_parse(iso_ep_desc, _ux_system_endpoint_descriptor_structure,
404                                  UX_ENDPOINT_DESCRIPTOR_ENTRIES, (UCHAR *) &endpoint.ux_endpoint_descriptor);
405 
406     test_error_cases = UX_TRUE;
407 
408     /* Simulate endpoint creation error. */
409     ux_test_hcd_sim_host_set_actions(endpoint_create_fail);
410     status = _ux_host_stack_endpoint_instance_create(&endpoint);
411     if (status == UX_SUCCESS)
412     {
413 
414         printf("ERROR #%d: expect error\n", __LINE__);
415         error_counter ++;
416     }
417 #if UX_MAX_DEVICES > 1
418     /* Simulate bandwidth error: available bandwidth is 0. */
419     hcd -> ux_hcd_available_bandwidth = 0;
420 
421     status = _ux_host_stack_endpoint_instance_create(&endpoint);
422     if (status != UX_NO_BANDWIDTH_AVAILABLE)
423     {
424 
425         printf("ERROR #%d: expect UX_NO_BANDWIDTH_AVAILABLE but got %x\n", __LINE__, status);
426         error_counter ++;
427     }
428 #endif
429     test_error_cases = UX_FALSE;
430 
431     /* Sleep for a tick to make sure everything is complete.  */
432     tx_thread_sleep(1);
433 
434     /* Check for errors from other threads.  */
435     if (error_counter)
436     {
437 
438         /* DPUMP error.  */
439         printf("ERROR #14\n");
440         test_control_return(1);
441     }
442     else
443     {
444 
445         /* Successful test.  */
446         printf("SUCCESS!\n");
447         test_control_return(0);
448     }
449 }
450 
451 
tx_test_thread_slave_simulation_entry(ULONG arg)452 static void  tx_test_thread_slave_simulation_entry(ULONG arg)
453 {
454 
455     while(1)
456     {
457 
458         /* Ensure the dpump class on the device is still alive.  */
459         if (dpump_slave != UX_NULL)
460         {
461 
462             /* Increment thread counter.  */
463             thread_1_counter++;
464         }
465 
466         /* Let other thread run.  */
467         tx_thread_sleep(10);
468     }
469 }
470 
tx_test_instance_activate(VOID * dpump_instance)471 static VOID  tx_test_instance_activate(VOID *dpump_instance)
472 {
473 
474     /* Save the DPUMP instance.  */
475     dpump_slave = (UX_SLAVE_CLASS_DPUMP *) dpump_instance;
476 }
477 
tx_test_instance_deactivate(VOID * dpump_instance)478 static VOID  tx_test_instance_deactivate(VOID *dpump_instance)
479 {
480 
481     /* Reset the DPUMP instance.  */
482     dpump_slave = UX_NULL;
483 }
484 
ux_test_hcd_entry_invoked(UX_TEST_ACTION * action,VOID * params)485 static VOID ux_test_hcd_entry_invoked(UX_TEST_ACTION *action, VOID *params)
486 {
487 
488     test_error_counter ++;
489 }