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