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 test_error_cases = UX_FALSE;
25
26 static ULONG thread_0_counter;
27 static ULONG thread_1_counter;
28 static ULONG error_counter;
29
30 /* Define USBX demo global variables. */
31
32 static unsigned char host_out_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
33 static unsigned char host_in_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
34 static unsigned char slave_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
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 /* Failed test. */
184 if (!test_error_cases)
185 {
186
187 printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
188 test_control_return(1);
189 }
190 }
191
192 /* Define what the initial system looks like. */
193
194 #ifdef CTEST
test_application_define(void * first_unused_memory)195 void test_application_define(void *first_unused_memory)
196 #else
197 void usbx_ux_host_stack_class_instance_destroy_test_application_define(void *first_unused_memory)
198 #endif
199 {
200
201 UINT status;
202 CHAR *stack_pointer;
203 CHAR *memory_pointer;
204 UX_SLAVE_CLASS_DPUMP_PARAMETER parameter;
205
206
207 /* Initialize the free memory pointer. */
208 stack_pointer = (CHAR *) first_unused_memory;
209 memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
210
211 /* Initialize USBX Memory. */
212 status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
213
214 /* Check for error. */
215 if (status != UX_SUCCESS)
216 {
217
218 printf("Running ux_host_stack_class_instance_destroy Test................... ERROR #1\n");
219 test_control_return(1);
220 }
221
222 /* Register the error callback. */
223 _ux_utility_error_callback_register(error_callback);
224
225 /* The code below is required for installing the host portion of USBX. */
226 status = ux_host_stack_initialize(UX_NULL);
227
228 /* Check for error. */
229 if (status != UX_SUCCESS)
230 {
231
232 printf("Running ux_host_stack_class_instance_destroy Test................... ERROR #2\n");
233 test_control_return(1);
234 }
235
236 /* Register all the host class drivers for this USBX implementation. */
237 status = ux_host_stack_class_register(_ux_system_host_class_dpump_name, _ux_host_class_dpump_entry);
238
239 /* Check for error. */
240 if (status != UX_SUCCESS)
241 {
242
243 printf("Running ux_host_stack_class_instance_destroy Test................... ERROR #3\n");
244 test_control_return(1);
245 }
246
247 /* The code below is required for installing the device portion of USBX */
248 status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
249 device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
250 string_framework, STRING_FRAMEWORK_LENGTH,
251 language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
252
253 /* Check for error. */
254 if (status != UX_SUCCESS)
255 {
256
257 printf("Running ux_host_stack_class_instance_destroy Test................... ERROR #5\n");
258 test_control_return(1);
259 }
260
261 /* Set the parameters for callback when insertion/extraction of a Data Pump device. */
262 parameter.ux_slave_class_dpump_instance_activate = tx_demo_instance_activate;
263 parameter.ux_slave_class_dpump_instance_deactivate = tx_demo_instance_deactivate;
264
265 /* Initialize the device dpump class. The class is connected with interface 0 */
266 status = ux_device_stack_class_register(_ux_system_slave_class_dpump_name, _ux_device_class_dpump_entry,
267 1, 0, ¶meter);
268
269 /* Check for error. */
270 if (status != UX_SUCCESS)
271 {
272
273 printf("Running ux_host_stack_class_instance_destroy Test................... ERROR #6\n");
274 test_control_return(1);
275 }
276
277 /* Initialize the simulated device controller. */
278 status = _ux_dcd_sim_slave_initialize();
279
280 /* Check for error. */
281 if (status != UX_SUCCESS)
282 {
283
284 printf("Running ux_host_stack_class_instance_destroy Test................... ERROR #7\n");
285 test_control_return(1);
286 }
287
288 /* Register all the USB host controllers available in this system */
289 status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, ux_hcd_sim_host_initialize,0,0);
290
291 /* Check for error. */
292 if (status != UX_SUCCESS)
293 {
294
295 printf("Running ux_host_stack_class_instance_destroy Test................... ERROR #4\n");
296 test_control_return(1);
297 }
298
299 /* Create the main host simulation thread. */
300 status = tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
301 stack_pointer, UX_DEMO_STACK_SIZE,
302 20, 20, 1, TX_AUTO_START);
303
304 /* Check for error. */
305 if (status != TX_SUCCESS)
306 {
307
308 printf("Running ux_host_stack_class_instance_destroy Test................... ERROR #8\n");
309 test_control_return(1);
310 }
311
312 /* Create the main demo thread. */
313 status = tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
314 stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
315 20, 20, 1, TX_AUTO_START);
316
317 /* Check for error. */
318 if (status != TX_SUCCESS)
319 {
320
321 printf("Running ux_host_stack_class_instance_destroy Test................... ERROR #9\n");
322 test_control_return(1);
323 }
324 }
325
326
tx_demo_thread_host_simulation_entry(ULONG arg)327 static void tx_demo_thread_host_simulation_entry(ULONG arg)
328 {
329
330 UINT status;
331 ULONG actual_length;
332 UX_HOST_CLASS *class;
333 UX_DEVICE *device;
334 UX_HOST_CLASS class_backup;
335
336 /* Inform user. */
337 printf("Running ux_host_stack_class_instance_destroy Test................... ");
338
339 /* Find the main data pump container. */
340 status = ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class);
341
342 /* Check for error. */
343 if (status != UX_SUCCESS)
344 {
345
346 /* DPUMP basic test error. */
347 printf("ERROR #10\n");
348 test_control_return(1);
349 }
350
351 /* We get the first instance of the data pump device. */
352 do
353 {
354
355 status = ux_host_stack_class_instance_get(class, 0, (VOID **) &dpump);
356 tx_thread_relinquish();
357 } while (status != UX_SUCCESS);
358
359 /* We still need to wait for the data pump status to be live. */
360 while (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE)
361 {
362
363 tx_thread_relinquish();
364 }
365
366 status = ux_host_stack_device_get(0, &device);
367 if (status != UX_SUCCESS)
368 {
369
370 printf("ERROR #%d: fail to get device instance\n", __LINE__);
371 test_control_return(1);
372 }
373
374 /* Simulate _ux_host_stack_class_instance_destroy error cases. */
375
376 /* Backup class */
377 ux_utility_memory_copy(&class_backup, class, sizeof(UX_HOST_CLASS));
378
379 /* We are testing error cases. */
380 test_error_cases = UX_TRUE;
381
382 /* Simulate error: no class instance attached. */
383 class->ux_host_class_first_instance = UX_NULL;
384 status = _ux_host_stack_class_instance_destroy(class, class_backup.ux_host_class_first_instance);
385 if (status == UX_SUCCESS)
386 {
387
388 printf("ERROR #%d: Expects fail since no class instance in class\n", __LINE__);
389 error_counter ++;
390 }
391
392 /* Restore class */
393 ux_utility_memory_copy(class, &class_backup, sizeof(UX_HOST_CLASS));
394
395 /* Simulate error: class instance not found. */
396 status = _ux_host_stack_class_instance_destroy(class, &actual_length);
397 if (status == UX_SUCCESS)
398 {
399
400 printf("ERROR #%d: Expects fail since no class instance match\n", __LINE__);
401 error_counter ++;
402 }
403
404 /* We finish testing error cases. */
405 test_error_cases = UX_FALSE;
406
407 /* Restore class */
408 ux_utility_memory_copy(class, &class_backup, sizeof(UX_HOST_CLASS));
409
410 /* Sleep for a tick to make sure everything is complete. */
411 tx_thread_sleep(1);
412
413 /* Check for errors from other threads. */
414 if (error_counter)
415 {
416
417 /* DPUMP error. */
418 printf("ERROR #14\n");
419 test_control_return(1);
420 }
421 else
422 {
423
424 /* Successful test. */
425 printf("SUCCESS!\n");
426 test_control_return(0);
427 }
428 }
429
430
tx_demo_thread_slave_simulation_entry(ULONG arg)431 static void tx_demo_thread_slave_simulation_entry(ULONG arg)
432 {
433
434 while(1)
435 {
436
437 /* Ensure the dpump class on the device is still alive. */
438 if (dpump_slave != UX_NULL)
439 {
440
441 /* Increment thread counter. */
442 thread_1_counter++;
443 }
444
445 /* Let other thread run. */
446 tx_thread_sleep(10);
447 }
448 }
449
tx_demo_instance_activate(VOID * dpump_instance)450 static VOID tx_demo_instance_activate(VOID *dpump_instance)
451 {
452
453 /* Save the DPUMP instance. */
454 dpump_slave = (UX_SLAVE_CLASS_DPUMP *) dpump_instance;
455 }
456
tx_demo_instance_deactivate(VOID * dpump_instance)457 static VOID tx_demo_instance_deactivate(VOID *dpump_instance)
458 {
459
460 /* Reset the DPUMP instance. */
461 dpump_slave = UX_NULL;
462 }
463
464