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 thread_0_counter;
25 static ULONG thread_1_counter;
26 static ULONG error_counter;
27
28 static UCHAR test_sim_entry;
29 static ULONG test_sim_query_usage;
30 static ULONG test_sim_query_count;
31 static ULONG test_sim_activate_count;
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
test_ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND * command)164 static UINT test_ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command)
165 {
166 if (test_sim_entry)
167 {
168
169 switch (command -> ux_host_class_command_request)
170 {
171 case UX_HOST_CLASS_COMMAND_QUERY:
172 test_sim_query_count ++;
173 if (command -> ux_host_class_command_usage != test_sim_query_usage)
174 return UX_NO_CLASS_MATCH;
175 break;
176
177 case UX_HOST_CLASS_COMMAND_ACTIVATE:
178 test_sim_activate_count ++;
179 break;
180
181 default:
182 break;
183 }
184 return UX_SUCCESS;
185 }
186 return ux_host_class_dpump_entry(command);
187 }
188
189
190 /* Define the ISR dispatch. */
191
192 extern VOID (*test_isr_dispatch)(void);
193
194
195 /* Prototype for test control return. */
196
197 void test_control_return(UINT status);
198
199
200 /* Define the ISR dispatch routine. */
201
test_isr(void)202 static void test_isr(void)
203 {
204
205 /* For further expansion of interrupt-level testing. */
206 }
207
208
error_callback(UINT system_level,UINT system_context,UINT error_code)209 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
210 {
211
212 /* Failed test. */
213 printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
214 test_control_return(1);
215 }
216
217 /* Define what the initial system looks like. */
218
219 #ifdef CTEST
test_application_define(void * first_unused_memory)220 void test_application_define(void *first_unused_memory)
221 #else
222 void usbx_ux_host_stack_class_device_scan_test_application_define(void *first_unused_memory)
223 #endif
224 {
225
226 UINT status;
227 CHAR *stack_pointer;
228 CHAR *memory_pointer;
229 UX_SLAVE_CLASS_DPUMP_PARAMETER parameter;
230
231
232 /* Initialize the free memory pointer. */
233 stack_pointer = (CHAR *) first_unused_memory;
234 memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
235
236 /* Initialize USBX Memory. */
237 status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
238
239 /* Check for error. */
240 if (status != UX_SUCCESS)
241 {
242
243 printf("Running ux_host_stack_class_device_scan Test........................ ERROR #1\n");
244 test_control_return(1);
245 }
246
247 /* Register the error callback. */
248 _ux_utility_error_callback_register(error_callback);
249
250 /* The code below is required for installing the host portion of USBX. */
251 status = ux_host_stack_initialize(UX_NULL);
252
253 /* Check for error. */
254 if (status != UX_SUCCESS)
255 {
256
257 printf("Running ux_host_stack_class_device_scan Test........................ ERROR #2\n");
258 test_control_return(1);
259 }
260
261 /* Register all the host class drivers for this USBX implementation. */
262 status = ux_host_stack_class_register(_ux_system_host_class_dpump_name, test_ux_host_class_dpump_entry);
263
264 /* Check for error. */
265 if (status != UX_SUCCESS)
266 {
267
268 printf("Running ux_host_stack_class_device_scan Test........................ ERROR #3\n");
269 test_control_return(1);
270 }
271
272 /* The code below is required for installing the device portion of USBX */
273 status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
274 device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
275 string_framework, STRING_FRAMEWORK_LENGTH,
276 language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
277
278 /* Check for error. */
279 if (status != UX_SUCCESS)
280 {
281
282 printf("Running ux_host_stack_class_device_scan Test........................ ERROR #5\n");
283 test_control_return(1);
284 }
285
286 /* Set the parameters for callback when insertion/extraction of a Data Pump device. */
287 parameter.ux_slave_class_dpump_instance_activate = tx_demo_instance_activate;
288 parameter.ux_slave_class_dpump_instance_deactivate = tx_demo_instance_deactivate;
289
290 /* Initialize the device dpump class. The class is connected with interface 0 */
291 status = ux_device_stack_class_register(_ux_system_slave_class_dpump_name, _ux_device_class_dpump_entry,
292 1, 0, ¶meter);
293
294 /* Check for error. */
295 if (status != UX_SUCCESS)
296 {
297
298 printf("Running ux_host_stack_class_device_scan Test........................ ERROR #6\n");
299 test_control_return(1);
300 }
301
302 /* Initialize the simulated device controller. */
303 status = _ux_dcd_sim_slave_initialize();
304
305 /* Check for error. */
306 if (status != UX_SUCCESS)
307 {
308
309 printf("Running ux_host_stack_class_device_scan Test........................ ERROR #7\n");
310 test_control_return(1);
311 }
312
313 /* Register all the USB host controllers available in this system */
314 status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, ux_hcd_sim_host_initialize,0,0);
315
316 /* Check for error. */
317 if (status != UX_SUCCESS)
318 {
319
320 printf("Running ux_host_stack_class_device_scan Test........................ ERROR #4\n");
321 test_control_return(1);
322 }
323
324 /* Create the main host simulation thread. */
325 status = tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
326 stack_pointer, UX_DEMO_STACK_SIZE,
327 20, 20, 1, TX_AUTO_START);
328
329 /* Check for error. */
330 if (status != TX_SUCCESS)
331 {
332
333 printf("Running ux_host_stack_class_device_scan Test........................ ERROR #8\n");
334 test_control_return(1);
335 }
336
337 /* Create the main demo thread. */
338 status = tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
339 stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
340 20, 20, 1, TX_AUTO_START);
341
342 /* Check for error. */
343 if (status != TX_SUCCESS)
344 {
345
346 printf("Running ux_host_stack_class_device_scan Test........................ ERROR #9\n");
347 test_control_return(1);
348 }
349 }
350
351
tx_demo_thread_host_simulation_entry(ULONG arg)352 static void tx_demo_thread_host_simulation_entry(ULONG arg)
353 {
354
355 UINT status;
356 UX_HOST_CLASS *class;
357 UX_DEVICE *device;
358
359
360 /* Inform user. */
361 printf("Running ux_host_stack_class_device_scan Test........................ ");
362
363 /* Find the main data pump container. */
364 status = ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class);
365
366 /* Check for error. */
367 if (status != UX_SUCCESS)
368 {
369
370 /* DPUMP basic test error. */
371 printf("ERROR #10\n");
372 test_control_return(1);
373 }
374
375 /* We get the first instance of the data pump device. */
376 do
377 {
378
379 status = ux_host_stack_class_instance_get(class, 0, (VOID **) &dpump);
380 tx_thread_relinquish();
381 } while (status != UX_SUCCESS);
382
383 /* We still need to wait for the data pump status to be live. */
384 while (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE)
385 {
386
387 tx_thread_relinquish();
388 }
389
390 status = ux_host_stack_device_get(0, &device);
391 if (status != UX_SUCCESS)
392 {
393
394 printf("ERROR #%d: fail to get device instance\n", __LINE__);
395 test_control_return(1);
396 }
397
398 #if !defined(UX_HOST_STACK_DEVICE_DRIVER_SCAN_DISABLE)
399 /* Simulate class device scan, query and activate should happen. */
400 test_sim_entry = UX_TRUE;
401
402 /* Query fail case */
403 test_sim_query_usage = 0xFF; /* UX_HOST_CLASS_COMMAND_USAGE_PIDVID, UX_HOST_CLASS_COMMAND_USAGE_CSP */
404 test_sim_activate_count = 0;
405 test_sim_query_count = 0;
406 status = _ux_host_stack_class_device_scan(device);
407 if (status == UX_SUCCESS)
408 {
409
410 printf("ERROR #%d: Queries should fail\n", __LINE__);
411 error_counter ++;
412 }
413 if (test_sim_query_count != 2)
414 {
415
416 printf("ERROR #%d: Queries tried must be 2\n", __LINE__);
417 error_counter ++;
418 }
419 if (test_sim_activate_count > 0)
420 {
421
422 printf("ERROR #%d: No activate should be done\n", __LINE__);
423 error_counter ++;
424 }
425
426 #if !defined(UX_HOST_STACK_DEVICE_DRIVER_SCAN_VIDPID_DISABLE)
427 /* VIDPID success case */
428 test_sim_query_usage = UX_HOST_CLASS_COMMAND_USAGE_PIDVID; /* UX_HOST_CLASS_COMMAND_USAGE_PIDVID, UX_HOST_CLASS_COMMAND_USAGE_DCSP */
429 test_sim_activate_count = 0;
430 test_sim_query_count = 0;
431 status = _ux_host_stack_class_device_scan(device);
432 if (status != UX_SUCCESS)
433 {
434
435 printf("ERROR #%d: Queries should pass\n", __LINE__);
436 error_counter ++;
437 }
438 if (test_sim_query_count == 0)
439 {
440
441 printf("ERROR #%d: There should be at least 1 query\n", __LINE__);
442 error_counter ++;
443 }
444 if (test_sim_activate_count != 1)
445 {
446
447 printf("ERROR #%d: There must be 1 activate\n", __LINE__);
448 error_counter ++;
449 }
450 #endif /* !defined(UX_HOST_STACK_DEVICE_DRIVER_SCAN_DCSP_DISABLE) */
451
452 #if !defined(UX_HOST_STACK_DEVICE_DRIVER_SCAN_DCSP_DISABLE)
453 /* Class/SubClass/Protocol success case */
454 test_sim_query_usage = UX_HOST_CLASS_COMMAND_USAGE_DCSP; /* UX_HOST_CLASS_COMMAND_USAGE_PIDVID, UX_HOST_CLASS_COMMAND_USAGE_DCSP */
455 test_sim_activate_count = 0;
456 test_sim_query_count = 0;
457 status = _ux_host_stack_class_device_scan(device);
458 if (status != UX_SUCCESS)
459 {
460
461 printf("ERROR #%d: Queries should pass\n", __LINE__);
462 error_counter ++;
463 }
464 if (test_sim_query_count == 0)
465 {
466
467 printf("ERROR #%d: There should be at least 1 query\n", __LINE__);
468 error_counter ++;
469 }
470 if (test_sim_activate_count != 1)
471 {
472
473 printf("ERROR #%d: There must be 1 activate\n", __LINE__);
474 error_counter ++;
475 }
476 #endif /* !defined(UX_HOST_STACK_DEVICE_DRIVER_SCAN_DCSP_DISABLE) */
477
478 #endif /* !defined(UX_HOST_STACK_DEVICE_DRIVER_SCAN_DISABLE) */
479
480 /* Sleep for a tick to make sure everything is complete. */
481 tx_thread_sleep(1);
482
483 /* Check for errors from other threads. */
484 if (error_counter)
485 {
486
487 /* DPUMP error. */
488 printf("ERROR #14\n");
489 test_control_return(1);
490 }
491 else
492 {
493
494 /* Successful test. */
495 printf("SUCCESS!\n");
496 test_control_return(0);
497 }
498 }
499
500
tx_demo_thread_slave_simulation_entry(ULONG arg)501 static void tx_demo_thread_slave_simulation_entry(ULONG arg)
502 {
503
504 while(1)
505 {
506
507 /* Ensure the dpump class on the device is still alive. */
508 if (dpump_slave != UX_NULL)
509 {
510
511 /* Increment thread counter. */
512 thread_1_counter++;
513 }
514
515 /* Let other thread run. */
516 tx_thread_sleep(10);
517 }
518 }
519
tx_demo_instance_activate(VOID * dpump_instance)520 static VOID tx_demo_instance_activate(VOID *dpump_instance)
521 {
522
523 /* Save the DPUMP instance. */
524 dpump_slave = (UX_SLAVE_CLASS_DPUMP *) dpump_instance;
525 }
526
tx_demo_instance_deactivate(VOID * dpump_instance)527 static VOID tx_demo_instance_deactivate(VOID *dpump_instance)
528 {
529
530 /* Reset the DPUMP instance. */
531 dpump_slave = UX_NULL;
532 }
533
534