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_utility_sim.h"
16 
17 /* Define USBX demo constants.  */
18 
19 #define UX_DEMO_STACK_SIZE      4096
20 #define UX_DEMO_BUFFER_SIZE     2048
21 #define UX_DEMO_RUN             1
22 #define UX_DEMO_MEMORY_SIZE     (64*1024)
23 
24 
25 /* Define the counters used in the demo application...  */
26 
27 static ULONG                           test_error_cases = UX_FALSE;
28 
29 static ULONG                           thread_0_counter;
30 static ULONG                           thread_1_counter;
31 static ULONG                           error_counter;
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 
164 /* Action simulator */
165 
166 static UX_TEST_HCD_SIM_ACTION enable_port_error[] = {
167 /* function, request to match,
168    port action, port status,
169    request action, request EP, request data, request actual length, request status,
170    status, additional callback,
171    no_return */
172 {   UX_HCD_ENABLE_PORT, NULL,
173         UX_FALSE, 0,
174         0         , 0, UX_NULL, 0, 0,
175         UX_PORT_INDEX_UNKNOWN},
176 {   0   }
177 };
178 
179 static UX_TEST_HCD_SIM_ACTION reset_port_error[] = {
180 /* function, request to match,
181    port action, port status,
182    request action, request EP, request data, request actual length, request status,
183    status, additional callback,
184    no_return */
185 {   UX_HCD_RESET_PORT, NULL,
186         UX_FALSE, 0,
187         0         , 0, UX_NULL, 0, 0,
188         UX_PORT_INDEX_UNKNOWN},
189 {   UX_HCD_RESET_PORT, NULL,
190         UX_FALSE, 0,
191         0         , 0, UX_NULL, 0, 0,
192         UX_PORT_INDEX_UNKNOWN},
193 {   UX_HCD_RESET_PORT, NULL,
194         UX_FALSE, 0,
195         0         , 0, UX_NULL, 0, 0,
196         UX_PORT_INDEX_UNKNOWN},
197 {   0   }
198 };
199 
200 static UX_TEST_HCD_SIM_ACTION get_port_status_error[] = {
201 /* function, request to match,
202    port action, port status,
203    request action, request EP, request data, request actual length, request status,
204    status, additional callback,
205    no_return */
206 {   UX_HCD_GET_PORT_STATUS, NULL,
207         UX_FALSE, 0,
208         0         , 0, UX_NULL, 0, 0,
209         UX_PORT_INDEX_UNKNOWN},
210 {   UX_HCD_GET_PORT_STATUS, NULL,
211         UX_FALSE, 0,
212         0         , 0, UX_NULL, 0, 0,
213         UX_PORT_INDEX_UNKNOWN},
214 {   UX_HCD_GET_PORT_STATUS, NULL,
215         UX_FALSE, 0,
216         0         , 0, UX_NULL, 0, 0,
217         UX_PORT_INDEX_UNKNOWN},
218 {   0   }
219 };
220 
221 /* Define the ISR dispatch.  */
222 
223 extern VOID    (*test_isr_dispatch)(void);
224 
225 
226 /* Prototype for test control return.  */
227 
228 void  test_control_return(UINT status);
229 
230 
231 /* Define the ISR dispatch routine.  */
232 
test_isr(void)233 static void    test_isr(void)
234 {
235 
236     /* For further expansion of interrupt-level testing.  */
237 }
238 
239 
error_callback(UINT system_level,UINT system_context,UINT error_code)240 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
241 {
242 
243     /* Failed test.  */
244     if (!test_error_cases)
245     {
246 
247         printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
248         test_control_return(1);
249     }
250 }
251 
252 /* Define what the initial system looks like.  */
253 
254 #ifdef CTEST
test_application_define(void * first_unused_memory)255 void test_application_define(void *first_unused_memory)
256 #else
257 void    usbx_ux_host_stack_rh_device_insertion_test_application_define(void *first_unused_memory)
258 #endif
259 {
260 
261 UINT                            status;
262 CHAR                            *stack_pointer;
263 CHAR                            *memory_pointer;
264 UX_SLAVE_CLASS_DPUMP_PARAMETER  parameter;
265 
266 
267     /* Initialize the free memory pointer.  */
268     stack_pointer = (CHAR *) first_unused_memory;
269     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
270 
271     /* Initialize USBX Memory.  */
272     status =  ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
273 
274     /* Check for error.  */
275     if (status != UX_SUCCESS)
276     {
277 
278         printf("Running ux_host_stack_rh_device_insertion Test...................... ERROR #1\n");
279         test_control_return(1);
280     }
281 
282     /* Register the error callback. */
283     _ux_utility_error_callback_register(error_callback);
284 
285     /* The code below is required for installing the host portion of USBX.  */
286     status =  ux_host_stack_initialize(UX_NULL);
287 
288     /* Check for error.  */
289     if (status != UX_SUCCESS)
290     {
291 
292         printf("Running ux_host_stack_rh_device_insertion Test...................... ERROR #2\n");
293         test_control_return(1);
294     }
295 
296     /* Register all the host class drivers for this USBX implementation.  */
297     status =  ux_host_stack_class_register(_ux_system_host_class_dpump_name, _ux_host_class_dpump_entry);
298 
299     /* Check for error.  */
300     if (status != UX_SUCCESS)
301     {
302 
303         printf("Running ux_host_stack_rh_device_insertion Test...................... ERROR #3\n");
304         test_control_return(1);
305     }
306 
307     /* The code below is required for installing the device portion of USBX */
308     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
309                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
310                                        string_framework, STRING_FRAMEWORK_LENGTH,
311                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
312 
313     /* Check for error.  */
314     if (status != UX_SUCCESS)
315     {
316 
317         printf("Running ux_host_stack_rh_device_insertion Test...................... ERROR #5\n");
318         test_control_return(1);
319     }
320 
321     /* Set the parameters for callback when insertion/extraction of a Data Pump device.  */
322     parameter.ux_slave_class_dpump_instance_activate   =  tx_demo_instance_activate;
323     parameter.ux_slave_class_dpump_instance_deactivate =  tx_demo_instance_deactivate;
324 
325     /* Initialize the device dpump class. The class is connected with interface 0 */
326     status  = ux_device_stack_class_register(_ux_system_slave_class_dpump_name, _ux_device_class_dpump_entry,
327                                               1, 0, &parameter);
328 
329     /* Check for error.  */
330     if (status != UX_SUCCESS)
331     {
332 
333         printf("Running ux_host_stack_rh_device_insertion Test...................... ERROR #6\n");
334         test_control_return(1);
335     }
336 
337     /* Initialize the simulated device controller.  */
338     status =  _ux_dcd_sim_slave_initialize();
339 
340     /* Check for error.  */
341     if (status != UX_SUCCESS)
342     {
343 
344         printf("Running ux_host_stack_rh_device_insertion Test...................... ERROR #7\n");
345         test_control_return(1);
346     }
347 
348     /* Register all the USB host controllers available in this system */
349     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
350 
351     /* Check for error.  */
352     if (status != UX_SUCCESS)
353     {
354 
355         printf("Running ux_host_stack_rh_device_insertion Test...................... ERROR #4\n");
356         test_control_return(1);
357     }
358 
359     /* Create the main host simulation thread.  */
360     status =  tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
361             stack_pointer, 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_rh_device_insertion Test...................... ERROR #8\n");
369         test_control_return(1);
370     }
371 
372     /* Create the main demo thread.  */
373     status =  tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
374             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
375             20, 20, 1, TX_AUTO_START);
376 
377     /* Check for error.  */
378     if (status != TX_SUCCESS)
379     {
380 
381         printf("Running ux_host_stack_rh_device_insertion Test...................... ERROR #9\n");
382         test_control_return(1);
383     }
384 }
385 
386 
tx_demo_thread_host_simulation_entry(ULONG arg)387 static void  tx_demo_thread_host_simulation_entry(ULONG arg)
388 {
389 
390 UINT            status;
391 UX_HCD          *hcd;
392 UX_HOST_CLASS   *class;
393 UX_DEVICE       *device;
394 ULONG           temp;
395 
396     /* Inform user.  */
397     printf("Running ux_host_stack_rh_device_insertion Test...................... ");
398 
399     /* Find the main data pump container.  */
400     status =  ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class);
401 
402     /* Check for error.  */
403     if (status != UX_SUCCESS)
404     {
405 
406         /* DPUMP basic test error.  */
407         printf("ERROR #10\n");
408         test_control_return(1);
409     }
410 
411     /* We get the first instance of the data pump device.  */
412     do
413     {
414 
415         status =  ux_host_stack_class_instance_get(class, 0, (VOID **) &dpump);
416         tx_thread_relinquish();
417     } while (status != UX_SUCCESS);
418 
419     /* We still need to wait for the data pump status to be live.  */
420     while (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE)
421     {
422 
423         tx_thread_relinquish();
424     }
425 
426     status = ux_host_stack_device_get(0, &device);
427     if (status != UX_SUCCESS)
428     {
429 
430         printf("ERROR #%d: fail to get device instance\n", __LINE__);
431         test_control_return(1);
432     }
433 
434     /* Wait until no enumeration in progress. */
435     tx_thread_sleep(100);
436 
437     /* Simulate _ux_host_stack_rh_device_insertion error cases. */
438 
439     /* Get HCD instance. */
440     hcd =  &_ux_system_host -> ux_system_host_hcd_array[0];
441 
442     /* Test error. */
443     test_error_cases = UX_TRUE;
444 
445     /* Simulate error: enable port. */
446     ux_test_hcd_sim_host_set_actions(enable_port_error);
447     status = _ux_host_stack_rh_device_insertion(hcd, 0);
448     if (status == UX_SUCCESS)
449     {
450 
451         printf("ERROR #%d: Expects error (enable port)\n", __LINE__);
452         error_counter ++;
453     }
454 
455     /* Simulate error: reset port. */
456     ux_test_hcd_sim_host_set_actions(reset_port_error);
457     status = _ux_host_stack_rh_device_insertion(hcd, 0);
458     if (status == UX_SUCCESS)
459     {
460 
461         printf("ERROR #%d: Expects error (reset port)\n", __LINE__);
462         error_counter ++;
463     }
464 
465     /* Simulate error: get port status. */
466     ux_test_hcd_sim_host_set_actions(get_port_status_error);
467     status = _ux_host_stack_rh_device_insertion(hcd, 0);
468     if (status == UX_SUCCESS)
469     {
470 
471         printf("ERROR #%d: Expects error (get port status)\n", __LINE__);
472         error_counter ++;
473     }
474     ux_test_hcd_sim_host_set_actions(UX_NULL);
475 
476 #if UX_MAX_DEVICES > 1
477     /* Simulate error: too many devices.  */
478     temp = _ux_system_host -> ux_system_host_max_devices;
479     _ux_system_host -> ux_system_host_max_devices = 1;
480     status = _ux_host_stack_rh_device_insertion(hcd, 0);
481     if (status != UX_DEVICE_ENUMERATION_FAILURE)
482     {
483 
484         printf("ERROR #%d: %x\n", __LINE__, status);
485         error_counter ++;
486     }
487 
488     /* Restore.  */
489     _ux_system_host -> ux_system_host_max_devices = temp;
490 #endif
491 
492     /* Stop test error. */
493     test_error_cases = UX_FALSE;
494 
495     /* Sleep for a tick to make sure everything is complete.  */
496     tx_thread_sleep(1);
497 
498     /* Check for errors from other threads.  */
499     if (error_counter)
500     {
501 
502         /* DPUMP error.  */
503         printf("ERROR #14\n");
504         test_control_return(1);
505     }
506     else
507     {
508 
509         /* Successful test.  */
510         printf("SUCCESS!\n");
511         test_control_return(0);
512     }
513 }
514 
515 
tx_demo_thread_slave_simulation_entry(ULONG arg)516 static void  tx_demo_thread_slave_simulation_entry(ULONG arg)
517 {
518 
519     while(1)
520     {
521 
522         /* Ensure the dpump class on the device is still alive.  */
523         if (dpump_slave != UX_NULL)
524         {
525 
526             /* Increment thread counter.  */
527             thread_1_counter++;
528         }
529 
530         /* Let other thread run.  */
531         tx_thread_sleep(10);
532     }
533 }
534 
tx_demo_instance_activate(VOID * dpump_instance)535 static VOID  tx_demo_instance_activate(VOID *dpump_instance)
536 {
537 
538     /* Save the DPUMP instance.  */
539     dpump_slave = (UX_SLAVE_CLASS_DPUMP *) dpump_instance;
540 }
541 
tx_demo_instance_deactivate(VOID * dpump_instance)542 static VOID  tx_demo_instance_deactivate(VOID *dpump_instance)
543 {
544 
545     /* Reset the DPUMP instance.  */
546     dpump_slave = UX_NULL;
547 }
548 
549