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