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