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 static ULONG                           test_error_counter = 0;
29 
30 static ULONG                           thread_0_counter;
31 static ULONG                           thread_1_counter;
32 static ULONG                           error_counter;
33 
34 /* Define USBX demo global variables.  */
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     test_error_counter ++;
184 
185     /* Failed test.  */
186     if (!test_error_cases)
187     {
188 
189         printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
190         test_control_return(1);
191     }
192 }
193 
194 /* Define what the initial system looks like.  */
195 
196 #ifdef CTEST
test_application_define(void * first_unused_memory)197 void test_application_define(void *first_unused_memory)
198 #else
199 void    usbx_ux_host_stack_interface_endpoint_get_test_application_define(void *first_unused_memory)
200 #endif
201 {
202 
203 UINT status;
204 CHAR                            *stack_pointer;
205 CHAR                            *memory_pointer;
206 UX_SLAVE_CLASS_DPUMP_PARAMETER  parameter;
207 
208 
209     /* Initialize the free memory pointer.  */
210     stack_pointer = (CHAR *) first_unused_memory;
211     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
212 
213     /* Initialize USBX Memory.  */
214     status =  ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
215 
216     /* Check for error.  */
217     if (status != UX_SUCCESS)
218     {
219 
220         printf("Running ux_host_stack_interface_endpoint_get Test................... ERROR #1\n");
221         test_control_return(1);
222     }
223 
224     /* Register the error callback. */
225     _ux_utility_error_callback_register(error_callback);
226 
227     /* The code below is required for installing the host portion of USBX.  */
228     status =  ux_host_stack_initialize(UX_NULL);
229 
230     /* Check for error.  */
231     if (status != UX_SUCCESS)
232     {
233 
234         printf("Running ux_host_stack_interface_endpoint_get Test................... ERROR #2\n");
235         test_control_return(1);
236     }
237 
238     /* Register all the host class drivers for this USBX implementation.  */
239     status =  ux_host_stack_class_register(_ux_system_host_class_dpump_name, _ux_host_class_dpump_entry);
240 
241     /* Check for error.  */
242     if (status != UX_SUCCESS)
243     {
244 
245         printf("Running ux_host_stack_interface_endpoint_get Test................... ERROR #3\n");
246         test_control_return(1);
247     }
248 
249     /* The code below is required for installing the device portion of USBX */
250     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
251                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
252                                        string_framework, STRING_FRAMEWORK_LENGTH,
253                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
254 
255     /* Check for error.  */
256     if (status != UX_SUCCESS)
257     {
258 
259         printf("Running ux_host_stack_interface_endpoint_get Test................... ERROR #5\n");
260         test_control_return(1);
261     }
262 
263     /* Set the parameters for callback when insertion/extraction of a Data Pump device.  */
264     parameter.ux_slave_class_dpump_instance_activate   =  tx_demo_instance_activate;
265     parameter.ux_slave_class_dpump_instance_deactivate =  tx_demo_instance_deactivate;
266 
267     /* Initialize the device dpump class. The class is connected with interface 0 */
268     status  = ux_device_stack_class_register(_ux_system_slave_class_dpump_name, _ux_device_class_dpump_entry,
269                                               1, 0, &parameter);
270 
271     /* Check for error.  */
272     if (status != UX_SUCCESS)
273     {
274 
275         printf("Running ux_host_stack_interface_endpoint_get Test................... ERROR #6\n");
276         test_control_return(1);
277     }
278 
279     /* Initialize the simulated device controller.  */
280     status =  _ux_dcd_sim_slave_initialize();
281 
282     /* Check for error.  */
283     if (status != UX_SUCCESS)
284     {
285 
286         printf("Running ux_host_stack_interface_endpoint_get Test................... ERROR #7\n");
287         test_control_return(1);
288     }
289 
290     /* Register all the USB host controllers available in this system */
291     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
292 
293     /* Check for error.  */
294     if (status != UX_SUCCESS)
295     {
296 
297         printf("Running ux_host_stack_interface_endpoint_get Test................... ERROR #4\n");
298         test_control_return(1);
299     }
300 
301     /* Create the main host simulation thread.  */
302     status =  tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
303             stack_pointer, UX_DEMO_STACK_SIZE,
304             20, 20, 1, TX_AUTO_START);
305 
306     /* Check for error.  */
307     if (status != TX_SUCCESS)
308     {
309 
310         printf("Running ux_host_stack_interface_endpoint_get Test................... ERROR #8\n");
311         test_control_return(1);
312     }
313 
314     /* Create the main demo thread.  */
315     status =  tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
316             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
317             20, 20, 1, TX_AUTO_START);
318 
319     /* Check for error.  */
320     if (status != TX_SUCCESS)
321     {
322 
323         printf("Running ux_host_stack_interface_endpoint_get Test................... ERROR #9\n");
324         test_control_return(1);
325     }
326 }
327 
328 
tx_demo_thread_host_simulation_entry(ULONG arg)329 static void  tx_demo_thread_host_simulation_entry(ULONG arg)
330 {
331 
332 UINT              status;
333 UX_HOST_CLASS    *class;
334 UX_DEVICE        *device;
335 UX_CONFIGURATION *configuration;
336 UX_INTERFACE     *interface;
337 UX_ENDPOINT      *endpoint;
338 ULONG             interface_handler;
339 
340     /* Inform user.  */
341     printf("Running ux_host_stack_interface_endpoint_get Test................... ");
342 
343     /* Find the main data pump container.  */
344     status =  ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class);
345 
346     /* Check for error.  */
347     if (status != UX_SUCCESS)
348     {
349 
350         /* DPUMP basic test error.  */
351         printf("ERROR #10\n");
352         test_control_return(1);
353     }
354 
355     /* We get the first instance of the data pump device.  */
356     do
357     {
358 
359         status =  ux_host_stack_class_instance_get(class, 0, (VOID **) &dpump);
360         tx_thread_relinquish();
361     } while (status != UX_SUCCESS);
362 
363     /* We still need to wait for the data pump status to be live.  */
364     while (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE)
365     {
366 
367         tx_thread_relinquish();
368     }
369 
370     status = ux_host_stack_device_get(0, &device);
371     if (status != UX_SUCCESS)
372     {
373 
374         printf("ERROR #%d: fail to get device instance\n", __LINE__);
375         test_control_return(1);
376     }
377 
378     status = ux_host_stack_device_configuration_get(device, 0, &configuration);
379     if (status != UX_SUCCESS)
380     {
381 
382         printf("ERROR #%d: fail to get configuration instance\n", __LINE__);
383         test_control_return(1);
384     }
385 
386     status = ux_host_stack_configuration_interface_get(configuration, 0, 0, &interface);
387     if (status != UX_SUCCESS)
388     {
389 
390         printf("ERROR #%d: fail to get interface instance\n", __LINE__);
391         test_control_return(1);
392     }
393 
394     /* Simulate _ux_host_stack_interface_endpoint_get error cases. */
395 
396     /* Expecting errors. */
397     test_error_cases = UX_TRUE;
398 
399     /* Simulate invalid interface. */
400     interface_handler = interface->ux_interface_handle;
401     interface->ux_interface_handle = 0;
402     status = _ux_host_stack_interface_endpoint_get(interface, 0, &endpoint);
403     if (status != UX_INTERFACE_HANDLE_UNKNOWN)
404     {
405 
406         printf("ERROR #%d: expect interface error but got %x\n", __LINE__, status);
407         error_counter ++;
408     }
409     interface->ux_interface_handle = interface_handler;
410 
411     /* Simulate invalid endpoint index. */
412     status = _ux_host_stack_interface_endpoint_get(interface, 10, &endpoint);
413     if (status != UX_ENDPOINT_HANDLE_UNKNOWN)
414     {
415 
416         printf("ERROR #%d: expect endpoint error but got %x\n", __LINE__, status);
417         error_counter ++;
418     }
419 
420     /* Break on errors. */
421     test_error_cases = UX_FALSE;
422 
423     /* Sleep for a tick to make sure everything is complete.  */
424     tx_thread_sleep(1);
425 
426     /* Check for errors from other threads.  */
427     if (error_counter)
428     {
429 
430         /* DPUMP error.  */
431         printf("ERROR #14\n");
432         test_control_return(1);
433     }
434     else
435     {
436 
437         /* Successful test.  */
438         printf("SUCCESS!\n");
439         test_control_return(0);
440     }
441 }
442 
443 
tx_demo_thread_slave_simulation_entry(ULONG arg)444 static void  tx_demo_thread_slave_simulation_entry(ULONG arg)
445 {
446 
447     while(1)
448     {
449 
450         /* Ensure the dpump class on the device is still alive.  */
451         if (dpump_slave != UX_NULL)
452         {
453 
454             /* Increment thread counter.  */
455             thread_1_counter++;
456         }
457 
458         /* Let other thread run.  */
459         tx_thread_sleep(10);
460     }
461 }
462 
tx_demo_instance_activate(VOID * dpump_instance)463 static VOID  tx_demo_instance_activate(VOID *dpump_instance)
464 {
465 
466     /* Save the DPUMP instance.  */
467     dpump_slave = (UX_SLAVE_CLASS_DPUMP *) dpump_instance;
468 }
469 
tx_demo_instance_deactivate(VOID * dpump_instance)470 static VOID  tx_demo_instance_deactivate(VOID *dpump_instance)
471 {
472 
473     /* Reset the DPUMP instance.  */
474     dpump_slave = UX_NULL;
475 }
476 
477