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, 0x00, /* wTotalLength */
56 0x01, 0x01, /* bNumInterfaces, bConfigurationValue */
57 0x00,
58 0xc0, 0x32, /* bmAttributes, bMaxPower */
59
60 /* Interface descriptor */
61 0x09, 0x04,
62 0x00, 0x00, 0x02, /* bInterfaceNumber, bAlternateSetting, bNumEndpoints */
63 0x99, 0x99, 0x99, /* bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol */
64 0x00,
65
66 /* Endpoint descriptor (Bulk Out) */
67 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00,
68
69 /* Endpoint descriptor (Bulk In) */
70 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00
71 };
72 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
73
74
75 static UCHAR device_framework_high_speed[] = {
76
77 /* Device descriptor */
78 0x12, 0x01, 0x00, 0x02,
79 0x00, 0x00, 0x00, /* bDeviceClass, bDeviceSubClass, bDeviceProtocol */
80 0x40, /* bMaxPacketSize0 */
81 0x0a, 0x07, /* idVendor */
82 0x25, 0x40, /* idProduct */
83 0x01, 0x00,
84 0x01, 0x02, 0x03,
85 0x01, /* bNumConfigurations */
86
87 /* Device qualifier descriptor */
88 0x0a, 0x06, 0x00, 0x02,
89 0x00, 0x00, 0x00, /* bDeviceClass, bDeviceSubClass, bDeviceProtocol */
90 0x40, /* bMaxPacketSize0 */
91 0x01, /* bNumConfigurations */
92 0x00,
93
94 /* Configuration descriptor */
95 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
96 0x32,
97
98 /* Interface descriptor */
99 0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99,
100 0x00,
101
102 /* Endpoint descriptor (Bulk Out) */
103 0x07, 0x05, 0x01, 0x02, 0x00, 0x02, 0x00,
104
105 /* Endpoint descriptor (Bulk In) */
106 0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00
107 };
108 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
109
110 /* String Device Framework :
111 Byte 0 and 1 : Word containing the language ID : 0x0904 for US
112 Byte 2 : Byte containing the index of the descriptor
113 Byte 3 : Byte containing the length of the descriptor string
114 */
115 static UCHAR string_framework[] = {
116
117 /* Manufacturer string descriptor : Index 1 */
118 0x09, 0x04, 0x01, 0x0c,
119 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
120 0x6f, 0x67, 0x69, 0x63,
121
122 /* Product string descriptor : Index 2 */
123 0x09, 0x04, 0x02, 0x0c,
124 0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
125 0x44, 0x65, 0x6d, 0x6f,
126
127 /* Serial Number string descriptor : Index 3 */
128 0x09, 0x04, 0x03, 0x04,
129 0x30, 0x30, 0x30, 0x31
130 };
131 #define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
132
133 /* Multiple languages are supported on the device, to add
134 a language besides English, the unicode language code must
135 be appended to the language_id_framework array and the length
136 adjusted accordingly. */
137 static UCHAR language_id_framework[] = {
138
139 /* English. */
140 0x09, 0x04
141 };
142 #define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
143
144 static UCHAR iso_ep_desc[] =
145 {
146 /* Endpoint descriptor (ISO) */
147 0x07, 0x05, 0x01, 0x01, 0x00, 0x01, 0x00,
148 };
149
150
151 /* Define prototypes for external Host Controller's (HCDs), classes and clients. */
152
153 static VOID tx_test_instance_activate(VOID *dpump_instance);
154 static VOID tx_test_instance_deactivate(VOID *dpump_instance);
155
156 UINT _ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command);
157 UINT ux_hcd_sim_initialize(UX_HCD *hcd);
158 UINT _ux_host_class_dpump_write(UX_HOST_CLASS_DPUMP *dpump, UCHAR * data_pointer,
159 ULONG requested_length, ULONG *actual_length);
160 UINT _ux_host_class_dpump_read (UX_HOST_CLASS_DPUMP *dpump, UCHAR *data_pointer,
161 ULONG requested_length, ULONG *actual_length);
162
163 static TX_THREAD tx_test_thread_host_simulation;
164 static TX_THREAD tx_test_thread_slave_simulation;
165 static void tx_test_thread_host_simulation_entry(ULONG);
166 static void tx_test_thread_slave_simulation_entry(ULONG);
167
168 static VOID ux_test_hcd_entry_invoked(UX_TEST_ACTION *action, VOID *params);
169
170 /* Define the ISR dispatch. */
171
172 extern VOID (*test_isr_dispatch)(void);
173
174
175 /* Prototype for test control return. */
176
177 void test_control_return(UINT status);
178
179 /* Simulation */
180
181 static UX_TEST_HCD_SIM_ACTION endpoint_create_fail[] = {
182 /* function, request to match,
183 port action, port status,
184 request action, request EP, request data, request actual length, request status,
185 status, additional callback,
186 no_return */
187 { UX_HCD_CREATE_ENDPOINT, NULL,
188 UX_FALSE, 0,
189 0 , 0, UX_NULL, 0, 0,
190 UX_ERROR, ux_test_hcd_entry_invoked},
191 { 0 }
192 };
193
194 /* Define the ISR dispatch routine. */
195
test_isr(void)196 static void test_isr(void)
197 {
198
199 /* For further expansion of interrupt-level testing. */
200 }
201
202
error_callback(UINT system_level,UINT system_context,UINT error_code)203 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
204 {
205
206 test_error_counter ++;
207
208 /* Failed test. */
209 if (!test_error_cases)
210 {
211
212 printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
213 test_control_return(1);
214 }
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_endpoint_instance_create_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_endpoint_instance_create 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_endpoint_instance_create 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, _ux_host_class_dpump_entry);
263
264 /* Check for error. */
265 if (status != UX_SUCCESS)
266 {
267
268 printf("Running ux_host_stack_endpoint_instance_create 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_endpoint_instance_create 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_test_instance_activate;
288 parameter.ux_slave_class_dpump_instance_deactivate = tx_test_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_endpoint_instance_create Test................. ERROR #6\n");
299 test_control_return(1);
300 }
301
302 /* Initialize the simulated device controller. */
303 status = _ux_test_dcd_sim_slave_initialize();
304
305 /* Check for error. */
306 if (status != UX_SUCCESS)
307 {
308
309 printf("Running ux_host_stack_endpoint_instance_create 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_test_hcd_sim_host_initialize,0,0);
315
316 /* Check for error. */
317 if (status != UX_SUCCESS)
318 {
319
320 printf("Running ux_host_stack_endpoint_instance_create Test................. ERROR #4\n");
321 test_control_return(1);
322 }
323
324 /* Create the main host simulation thread. */
325 status = tx_thread_create(&tx_test_thread_host_simulation, "tx demo host simulation", tx_test_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_endpoint_instance_create Test................. ERROR #8\n");
334 test_control_return(1);
335 }
336
337 /* Create the main demo thread. */
338 status = tx_thread_create(&tx_test_thread_slave_simulation, "tx demo slave simulation", tx_test_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_endpoint_instance_create Test................. ERROR #9\n");
347 test_control_return(1);
348 }
349 }
350
351
tx_test_thread_host_simulation_entry(ULONG arg)352 static void tx_test_thread_host_simulation_entry(ULONG arg)
353 {
354
355 UINT status;
356 UX_HOST_CLASS *class;
357 UX_DEVICE *device;
358 UX_ENDPOINT endpoint;
359 UX_HCD *hcd;
360
361 /* Inform user. */
362 printf("Running ux_host_stack_endpoint_instance_create Test................. ");
363
364 /* Find the main data pump container. */
365 status = ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class);
366
367 /* Check for error. */
368 if (status != UX_SUCCESS)
369 {
370
371 /* DPUMP basic test error. */
372 printf("ERROR #10\n");
373 test_control_return(1);
374 }
375
376 /* We get the first instance of the data pump device. */
377 do
378 {
379
380 status = ux_host_stack_class_instance_get(class, 0, (VOID **) &dpump);
381 tx_thread_relinquish();
382 } while (status != UX_SUCCESS);
383
384 /* We still need to wait for the data pump status to be live. */
385 while (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE)
386 {
387
388 tx_thread_relinquish();
389 }
390
391 status = ux_host_stack_device_get(0, &device);
392 if (status != UX_SUCCESS)
393 {
394
395 printf("ERROR #%d: fail to get device instance\n", __LINE__);
396 test_control_return(1);
397 }
398
399 /* Simulate _ux_host_stack_endpoint_instance_create error cases. */
400 hcd = &_ux_system_host -> ux_system_host_hcd_array[0];
401 endpoint.ux_endpoint_device = device;
402
403 _ux_utility_descriptor_parse(iso_ep_desc, _ux_system_endpoint_descriptor_structure,
404 UX_ENDPOINT_DESCRIPTOR_ENTRIES, (UCHAR *) &endpoint.ux_endpoint_descriptor);
405
406 test_error_cases = UX_TRUE;
407
408 /* Simulate endpoint creation error. */
409 ux_test_hcd_sim_host_set_actions(endpoint_create_fail);
410 status = _ux_host_stack_endpoint_instance_create(&endpoint);
411 if (status == UX_SUCCESS)
412 {
413
414 printf("ERROR #%d: expect error\n", __LINE__);
415 error_counter ++;
416 }
417 #if UX_MAX_DEVICES > 1
418 /* Simulate bandwidth error: available bandwidth is 0. */
419 hcd -> ux_hcd_available_bandwidth = 0;
420
421 status = _ux_host_stack_endpoint_instance_create(&endpoint);
422 if (status != UX_NO_BANDWIDTH_AVAILABLE)
423 {
424
425 printf("ERROR #%d: expect UX_NO_BANDWIDTH_AVAILABLE but got %x\n", __LINE__, status);
426 error_counter ++;
427 }
428 #endif
429 test_error_cases = UX_FALSE;
430
431 /* Sleep for a tick to make sure everything is complete. */
432 tx_thread_sleep(1);
433
434 /* Check for errors from other threads. */
435 if (error_counter)
436 {
437
438 /* DPUMP error. */
439 printf("ERROR #14\n");
440 test_control_return(1);
441 }
442 else
443 {
444
445 /* Successful test. */
446 printf("SUCCESS!\n");
447 test_control_return(0);
448 }
449 }
450
451
tx_test_thread_slave_simulation_entry(ULONG arg)452 static void tx_test_thread_slave_simulation_entry(ULONG arg)
453 {
454
455 while(1)
456 {
457
458 /* Ensure the dpump class on the device is still alive. */
459 if (dpump_slave != UX_NULL)
460 {
461
462 /* Increment thread counter. */
463 thread_1_counter++;
464 }
465
466 /* Let other thread run. */
467 tx_thread_sleep(10);
468 }
469 }
470
tx_test_instance_activate(VOID * dpump_instance)471 static VOID tx_test_instance_activate(VOID *dpump_instance)
472 {
473
474 /* Save the DPUMP instance. */
475 dpump_slave = (UX_SLAVE_CLASS_DPUMP *) dpump_instance;
476 }
477
tx_test_instance_deactivate(VOID * dpump_instance)478 static VOID tx_test_instance_deactivate(VOID *dpump_instance)
479 {
480
481 /* Reset the DPUMP instance. */
482 dpump_slave = UX_NULL;
483 }
484
ux_test_hcd_entry_invoked(UX_TEST_ACTION * action,VOID * params)485 static VOID ux_test_hcd_entry_invoked(UX_TEST_ACTION *action, VOID *params)
486 {
487
488 test_error_counter ++;
489 }