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, ¶meter);
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