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