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 "fx_api.h"
10 
11 #include "ux_device_class_cdc_acm.h"
12 #include "ux_device_stack.h"
13 #include "ux_host_class_cdc_acm.h"
14 
15 #include "ux_test.h"
16 #include "ux_test_dcd_sim_slave.h"
17 #include "ux_test_hcd_sim_host.h"
18 #include "ux_test_utility_sim.h"
19 
20 /* Define constants.  */
21 #define                             UX_DEMO_DEBUG_SIZE  (4096*8)
22 #define                             UX_DEMO_STACK_SIZE  1024
23 #define                             UX_DEMO_BUFFER_SIZE (UX_SLAVE_REQUEST_DATA_MAX_LENGTH + 1)
24 #define                             UX_DEMO_XMIT_BUFFER_SIZE 512
25 #define                             UX_DEMO_RECEPTION_BUFFER_SIZE 512
26 #define                             UX_DEMO_FILE_BUFFER_SIZE 512
27 #define                             UX_DEMO_RECEPTION_BLOCK_SIZE 64
28 #define                             UX_DEMO_MEMORY_SIZE     (64*1024)
29 #define                             UX_DEMO_FILE_SIZE       (128 * 1024)
30 #define                             UX_RAM_DISK_MEMORY      (256 * 1024)
31 
32 /* Define local/extern function prototypes.  */
33 static VOID                                test_thread_entry(ULONG);
34 static TX_THREAD                           tx_test_thread_host_simulation;
35 static TX_THREAD                           tx_test_thread_slave_simulation;
36 static VOID                                tx_test_thread_host_simulation_entry(ULONG);
37 static VOID                                tx_test_thread_slave_simulation_entry(ULONG);
38 static VOID                                test_cdc_instance_activate(VOID  *cdc_instance);
39 static VOID                                test_cdc_instance_deactivate(VOID *cdc_instance);
40 static VOID                                test_cdc_instance_parameter_change(VOID *cdc_instance);
41 
42 static VOID                                ux_test_hcd_entry_should_not_be_called(UX_TEST_ACTION *action, VOID *params);
43 static VOID                                ux_test_hcd_entry_disconnect(UX_TEST_ACTION *action, VOID *params);
44 static VOID                                ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *params);
45 
46 /* Define global data structures.  */
47 static UCHAR                               usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
48 static UX_HOST_CLASS                       *class_driver;
49 static UX_HOST_CLASS_CDC_ACM               *cdc_acm_host_control;
50 static UX_HOST_CLASS_CDC_ACM               *cdc_acm_host_data;
51 
52 static UX_SLAVE_CLASS_CDC_ACM              *cdc_acm_slave;
53 static UCHAR                               cdc_acm_slave_change;
54 static UX_SLAVE_CLASS_CDC_ACM_PARAMETER    parameter;
55 
56 static ULONG                               error_counter;
57 
58 static ULONG                               set_cfg_counter;
59 
60 static ULONG                               rsc_mem_alloc_cnt_on_set_cfg;
61 static ULONG                               rsc_sem_on_set_cfg;
62 static ULONG                               rsc_sem_get_on_set_cfg;
63 static ULONG                               rsc_mutex_on_set_cfg;
64 
65 static ULONG                               rsc_enum_mem_alloc_count;
66 static ULONG                               rsc_enum_sem_usage;
67 static ULONG                               rsc_enum_sem_get_count;
68 static ULONG                               rsc_enum_mutex_usage;
69 
70 /* Define device framework.  */
71 
72 #define             DEVICE_FRAMEWORK_LENGTH_FULL_SPEED      93
73 #define             DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED      103
74 #define             STRING_FRAMEWORK_LENGTH                 47
75 #define             LANGUAGE_ID_FRAMEWORK_LENGTH            2
76 
77 static unsigned char device_framework_full_speed[] = {
78 
79     /* Device descriptor     18 bytes
80        0x02 bDeviceClass:    CDC class code
81        0x00 bDeviceSubclass: CDC class sub code
82        0x00 bDeviceProtocol: CDC Device protocol
83 
84        idVendor & idProduct - http://www.linux-usb.org/usb.ids
85     */
86     0x12, 0x01, 0x10, 0x01,
87     0xEF, 0x02, 0x01,
88     0x08,
89     0x84, 0x84, 0x00, 0x00,
90     0x00, 0x01,
91     0x01, 0x02, 03,
92     0x01,
93 
94     /* Configuration 1 descriptor 9 bytes */
95     0x09, 0x02, 0x4b, 0x00,
96     0x02, 0x01, 0x00,
97     0x40, 0x00,
98 
99     /* Interface association descriptor. 8 bytes.  */
100     0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
101 
102     /* Communication Class Interface Descriptor Requirement. 9 bytes.   */
103     0x09, 0x04, 0x00,
104     0x00,
105     0x01,
106     0x02, 0x02, 0x01,
107     0x00,
108 
109     /* Header Functional Descriptor 5 bytes */
110     0x05, 0x24, 0x00,
111     0x10, 0x01,
112 
113     /* ACM Functional Descriptor 4 bytes */
114     0x04, 0x24, 0x02,
115     0x0f,
116 
117     /* Union Functional Descriptor 5 bytes */
118     0x05, 0x24, 0x06,
119     0x00,                          /* Master interface */
120     0x01,                          /* Slave interface  */
121 
122     /* Call Management Functional Descriptor 5 bytes */
123     0x05, 0x24, 0x01,
124     0x03,
125     0x01,                          /* Data interface   */
126 
127     /* Endpoint 0x83 descriptor 7 bytes */
128     0x07, 0x05, 0x83,
129     0x03,
130     0x08, 0x00,
131     0xFF,
132 
133     /* Data Class Interface Descriptor Requirement 9 bytes */
134     0x09, 0x04, 0x01,
135     0x00,
136     0x02,
137     0x0A, 0x00, 0x00,
138     0x00,
139 
140     /* Endpoint 0x81 descriptor 7 bytes */
141     0x07, 0x05, 0x81, /* @ 93 - 14 + 2 = 81 */
142     0x02,
143     0x40, 0x00,
144     0x00,
145 
146     /* Endpoint 0x02 descriptor 7 bytes */
147     0x07, 0x05, 0x02, /* @ 93 - 7 + 2 = 88 */
148     0x02,
149     0x40, 0x00,
150     0x00,
151 
152 };
153 
154 #define DEVICE_FRAMEWORK_EPA_POS_1_FS (DEVICE_FRAMEWORK_LENGTH_FULL_SPEED - 14 + 2)
155 #define DEVICE_FRAMEWORK_EPA_POS_2_FS (DEVICE_FRAMEWORK_LENGTH_FULL_SPEED - 7 + 2)
156 
157 static unsigned char device_framework_high_speed[] = {
158 
159     /* Device descriptor
160        0x02 bDeviceClass:    CDC class code
161        0x00 bDeviceSubclass: CDC class sub code
162        0x00 bDeviceProtocol: CDC Device protocol
163 
164        idVendor & idProduct - http://www.linux-usb.org/usb.ids
165     */
166     0x12, 0x01, 0x00, 0x02,
167     0xEF, 0x02, 0x01,
168     0x40,
169     0x84, 0x84, 0x00, 0x00,
170     0x00, 0x01,
171     0x01, 0x02, 03,
172     0x01,
173 
174     /* Device qualifier descriptor */
175     0x0a, 0x06, 0x00, 0x02,
176     0x02, 0x00, 0x00,
177     0x40,
178     0x01,
179     0x00,
180 
181     /* Configuration 1 descriptor */
182     0x09, 0x02, 0x4b, 0x00,
183     0x02, 0x01, 0x00,
184     0x40, 0x00,
185 
186     /* Interface association descriptor. */
187     0x08, 0x0b, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,
188 
189     /* Communication Class Interface Descriptor Requirement */
190     0x09, 0x04, 0x00,
191     0x00,
192     0x01,
193     0x02, 0x02, 0x01,
194     0x00,
195 
196     /* Header Functional Descriptor */
197     0x05, 0x24, 0x00,
198     0x10, 0x01,
199 
200     /* ACM Functional Descriptor */
201     0x04, 0x24, 0x02,
202     0x0f,
203 
204     /* Union Functional Descriptor */
205     0x05, 0x24, 0x06,
206     0x00,
207     0x01,
208 
209     /* Call Management Functional Descriptor */
210     0x05, 0x24, 0x01,
211     0x00,
212     0x01,
213 
214     /* Endpoint 0x83 descriptor */
215     0x07, 0x05, 0x83,
216     0x03,
217     0x08, 0x00,
218     0xFF,
219 
220     /* Data Class Interface Descriptor Requirement */
221     0x09, 0x04, 0x01,
222     0x00,
223     0x02,
224     0x0A, 0x00, 0x00,
225     0x00,
226 
227     /* Endpoint 0x81 descriptor */
228     0x07, 0x05, 0x81, /* @ 103 - 14 + 2 = 91 */
229     0x02,
230     0x40, 0x00,
231     0x00,
232 
233     /* Endpoint 0x02 descriptor */
234     0x07, 0x05, 0x02, /* @ 103 - 7 + 2 = 98 */
235     0x02,
236     0x40, 0x00,
237     0x00,
238 
239 };
240 
241 #define DEVICE_FRAMEWORK_EPA_POS_1_HS (DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED - 14 + 2)
242 #define DEVICE_FRAMEWORK_EPA_POS_2_HS (DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED - 7 + 2)
243 
244 static unsigned char string_framework[] = {
245 
246     /* Manufacturer string descriptor : Index 1 - "Express Logic" */
247         0x09, 0x04, 0x01, 0x0c,
248         0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
249         0x6f, 0x67, 0x69, 0x63,
250 
251     /* Product string descriptor : Index 2 - "EL Composite device" */
252         0x09, 0x04, 0x02, 0x13,
253         0x45, 0x4c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x6f,
254         0x73, 0x69, 0x74, 0x65, 0x20, 0x64, 0x65, 0x76,
255         0x69, 0x63, 0x65,
256 
257     /* Serial Number string descriptor : Index 3 - "0001" */
258         0x09, 0x04, 0x03, 0x04,
259         0x30, 0x30, 0x30, 0x31
260     };
261 
262 
263     /* Multiple languages are supported on the device, to add
264        a language besides english, the unicode language code must
265        be appended to the language_id_framework array and the length
266        adjusted accordingly. */
267 static unsigned char language_id_framework[] = {
268 
269     /* English. */
270         0x09, 0x04
271     };
272 
273 static UX_TEST_SETUP _SetAddress = UX_TEST_SETUP_SetAddress;
274 static UX_TEST_SETUP _GetDeviceDescriptor = UX_TEST_SETUP_GetDevDescr;
275 static UX_TEST_SETUP _GetConfigDescriptor = UX_TEST_SETUP_GetCfgDescr;
276 static UX_TEST_SETUP _SetConfigure = UX_TEST_SETUP_SetConfigure;
277 
278 /* Test interactions */
279 
280 /* Disconnect on RESET:
281  * Host still create the EP0 and expects first SETUP request failure.
282  */
283 
284 static UX_TEST_HCD_SIM_ACTION disconnect_on_reset[] = {
285 /* function, request to match,
286    port action, port status,
287    request action, request EP, request data, request actual length, request status,
288    status, additional callback,
289    no_return */
290 {   UX_HCD_RESET_PORT, NULL,
291         UX_TRUE , UX_TEST_PORT_STATUS_DISC,
292         0         , 0, UX_NULL, 0, 0,
293         UX_SUCCESS, ux_test_hcd_entry_disconnect},
294 #if 0
295 {   UX_HCD_CREATE_ENDPOINT, NULL,
296         UX_FALSE, 0,
297         0         , 0, UX_NULL, 0, 0,
298         UX_ERROR , ux_test_hcd_entry_should_not_be_called},
299 #endif
300 {   UX_HCD_TRANSFER_REQUEST, NULL,
301         UX_FALSE, 0,
302         0         , 0, UX_NULL, 0, 0,
303         UX_ERROR , UX_NULL}, /* Request just fail on disconnect */
304 {   UX_HCD_TRANSFER_REQUEST, NULL,
305         UX_FALSE, 0,
306         0         , 0, UX_NULL, 0, 0,
307         UX_ERROR , UX_NULL},
308 {   UX_HCD_TRANSFER_REQUEST, NULL,
309         UX_FALSE, 0,
310         0         , 0, UX_NULL, 0, 0,
311         UX_ERROR , UX_NULL},
312 {   0   }
313 };
314 
315 static UX_TEST_HCD_SIM_ACTION endpoint0_create_fail[] = {
316 /* function, request to match,
317    port action, port status,
318    request action, request EP, request data, request actual length, request status,
319    status, additional callback,
320    no_return */
321 {   UX_HCD_CREATE_ENDPOINT, NULL,
322         UX_FALSE, 0,
323         0         , 0, UX_NULL, 0, 0,
324         UX_ERROR},
325 {   UX_HCD_CREATE_ENDPOINT, NULL,
326         UX_FALSE, 0,
327         0         , 0, UX_NULL, 0, 0,
328         UX_ERROR},
329 {   UX_HCD_CREATE_ENDPOINT, NULL,
330         UX_FALSE, 0,
331         0         , 0, UX_NULL, 0, 0,
332         UX_ERROR},
333 {   UX_HCD_TRANSFER_REQUEST, NULL,
334         UX_FALSE, 0,
335         0         , 0, UX_NULL, 0, 0,
336         UX_ERROR , ux_test_hcd_entry_should_not_be_called},
337 {   0   }
338 };
339 
340 static UX_TEST_HCD_SIM_ACTION disconnect_on_SetAddress[] = {
341 /* function, request to match,
342    port action, port status,
343    request action, request EP, request data, request actual length, request status,
344    status, additional callback,
345    no_return */
346 {   UX_HCD_TRANSFER_REQUEST, &_SetAddress,
347         UX_TRUE, UX_TEST_PORT_STATUS_DISC,
348         UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, 0,
349         UX_ERROR},
350 {   UX_HCD_TRANSFER_REQUEST, &_SetAddress,
351         UX_TRUE, UX_TEST_PORT_STATUS_DISC,
352         UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, 0,
353         UX_ERROR},
354 {   UX_HCD_TRANSFER_REQUEST, &_SetAddress,
355         UX_TRUE, UX_TEST_PORT_STATUS_DISC,
356         UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, 0,
357         UX_ERROR},
358 {   0   }
359 };
360 
361 static UX_TEST_HCD_SIM_ACTION disconnect_on_GetDevDescr[] = {
362 /* function, request to match,
363    port action, port status,
364    request action, request EP, request data, request actual length, request status,
365    status, additional callback,
366    no_return */
367 {   UX_HCD_TRANSFER_REQUEST, &_GetDeviceDescriptor,
368         UX_TRUE, UX_TEST_PORT_STATUS_DISC,
369         UX_TEST_SETUP_MATCH_REQ_V, 0, UX_NULL, 0, 0,
370         UX_ERROR},
371 {   UX_HCD_TRANSFER_REQUEST, &_GetDeviceDescriptor,
372         UX_TRUE, UX_TEST_PORT_STATUS_DISC,
373         UX_TEST_SETUP_MATCH_REQ_V, 0, UX_NULL, 0, 0,
374         UX_ERROR},
375 {   UX_HCD_TRANSFER_REQUEST, &_GetDeviceDescriptor,
376         UX_FALSE, UX_TEST_PORT_STATUS_DISC,
377         UX_TEST_SETUP_MATCH_REQ_V, 0, UX_NULL, 0, 0,
378         0, UX_NULL,
379         UX_TRUE},
380 {   UX_HCD_TRANSFER_REQUEST, &_GetDeviceDescriptor,
381         UX_TRUE, UX_TEST_PORT_STATUS_DISC,
382         UX_TEST_SETUP_MATCH_REQ_V, 0, UX_NULL, 0, 0,
383         UX_ERROR},
384 {   0   }
385 };
386 
387 static UX_TEST_HCD_SIM_ACTION disconnect_on_GetCfgDescr[] = {
388 /* function, request to match,
389    port action, port status,
390    request action, request EP, request data, request actual length, request status,
391    status, additional callback,
392    no_return */
393 {   UX_HCD_TRANSFER_REQUEST, &_GetConfigDescriptor,
394         UX_TRUE, UX_TEST_PORT_STATUS_DISC,
395         UX_TEST_SETUP_MATCH_REQ_V, 0, UX_NULL, 0, 0,
396         UX_ERROR}, /* First try */
397 {   UX_HCD_TRANSFER_REQUEST, &_GetConfigDescriptor,
398         UX_TRUE, UX_TEST_PORT_STATUS_DISC,
399         UX_TEST_SETUP_MATCH_REQ_V, 0, UX_NULL, 0, 0,
400         UX_ERROR}, /* Second try */
401 {   UX_HCD_TRANSFER_REQUEST, &_GetConfigDescriptor,
402         UX_FALSE, UX_TEST_PORT_STATUS_DISC,
403         UX_TEST_SETUP_MATCH_REQ_V, 0, UX_NULL, 0, 0,
404         UX_SUCCESS, UX_NULL,
405         UX_TRUE}, /* Last try first run */
406 {   UX_HCD_TRANSFER_REQUEST, &_GetConfigDescriptor,
407         UX_TRUE, UX_TEST_PORT_STATUS_DISC,
408         UX_TEST_SETUP_MATCH_REQ_V, 0, UX_NULL, 0, 0,
409         UX_ERROR},
410 {   0   }
411 };
412 
413 static UX_TEST_HCD_SIM_ACTION disconnect_on_SetCfg[] = {
414 /* function, request to match,
415    port action, port status,
416    request action, request EP, request data, request actual length, request status,
417    status, additional callback,
418    no_return */
419 {   UX_HCD_TRANSFER_REQUEST, &_SetConfigure,
420         UX_TRUE, UX_TEST_PORT_STATUS_DISC,
421         UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, 0,
422         UX_ERROR}, /* First try */
423 {   UX_HCD_TRANSFER_REQUEST, &_SetConfigure,
424         UX_TRUE, UX_TEST_PORT_STATUS_DISC,
425         UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, 0,
426         UX_ERROR}, /* Second try */
427 {   UX_HCD_TRANSFER_REQUEST, &_SetConfigure,
428         UX_TRUE, UX_TEST_PORT_STATUS_DISC,
429         UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, 0,
430         UX_ERROR}, /* Last try */
431 {   0   }
432 };
433 
434 static UX_TEST_HCD_SIM_ACTION log_on_SetCfg[] = {
435 /* function, request to match,
436    port action, port status,
437    request action, request EP, request data, request actual length, request status,
438    status, additional callback,
439    no_return */
440 {   UX_HCD_TRANSFER_REQUEST, &_SetConfigure,
441         UX_FALSE, UX_TEST_PORT_STATUS_DISC,
442         UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, 0,
443         UX_SUCCESS, ux_test_hcd_entry_set_cfg,
444         UX_TRUE}, /* Invoke callback & continue */
445 {   0   }
446 };
447 
448 static UX_TEST_HCD_SIM_ACTION normal_enum_replace[] = {
449 /* function, request to match,
450    port action, port status,
451    request action, request EP, request data, request actual length, request status,
452    status, additional callback,
453    no_return */
454 {   UX_HCD_TRANSFER_REQUEST, &_GetDeviceDescriptor,
455         UX_FALSE, 0,
456         UX_TEST_SIM_REQ_ANSWER | UX_TEST_SETUP_MATCH_REQ_V, 0, device_framework_full_speed + 0, 8, 0,
457         UX_SUCCESS, UX_NULL},
458 {   UX_HCD_TRANSFER_REQUEST, &_GetDeviceDescriptor,
459         UX_FALSE, 0,
460         UX_TEST_SIM_REQ_ANSWER | UX_TEST_SETUP_MATCH_REQ_V, 0, device_framework_full_speed + 0, 18, 0,
461         UX_SUCCESS, UX_NULL},
462 {   UX_HCD_TRANSFER_REQUEST, &_GetConfigDescriptor,
463         UX_FALSE, 0,
464         UX_TEST_SIM_REQ_ANSWER | UX_TEST_SETUP_MATCH_REQ_V, 0, device_framework_full_speed + 18, UX_CONFIGURATION_DESCRIPTOR_LENGTH, 0,
465         UX_SUCCESS, UX_NULL},
466 {   UX_HCD_TRANSFER_REQUEST, &_GetConfigDescriptor,
467         UX_FALSE, 0,
468         UX_TEST_SIM_REQ_ANSWER | UX_TEST_SETUP_MATCH_REQ_V, 0, device_framework_full_speed + 18, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED - 18, 0,
469         UX_SUCCESS, UX_NULL},
470 {   0   }
471 }
472 ;
473 
474 /* Define the ISR dispatch.  */
475 
476 extern VOID    (*test_isr_dispatch)(void);
477 
478 
479 /* Prototype for test control return.  */
480 
481 void  test_control_return(UINT status);
482 
483 
484 /* Define the ISR dispatch routine.  */
485 
test_isr(void)486 static void test_isr(void)
487 {
488 
489     /* For further expansion of interrupt-level testing.  */
490 }
491 
492 
test_class_cdc_acm_get(void)493 static UINT test_class_cdc_acm_get(void)
494 {
495 
496 UINT                                status;
497 UX_HOST_CLASS                       *class;
498 UX_HOST_CLASS_CDC_ACM               *cdc_acm_host;
499 
500 
501     /* Find the main cdc_acm container */
502     status =  ux_host_stack_class_get(_ux_system_host_class_cdc_acm_name, &class);
503     if (status != UX_SUCCESS)
504         return(status);
505 
506     /* We get the first instance of the cdc_acm device */
507     do
508     {
509 
510         status =  ux_host_stack_class_instance_get(class, 0, (void **) &cdc_acm_host);
511         tx_thread_sleep(10);
512     } while (status != UX_SUCCESS);
513 
514     /* We still need to wait for the cdc_acm status to be live */
515     while (cdc_acm_host -> ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE)
516         tx_thread_sleep(10);
517 
518     /* Isolate both the control and data interfaces.  */
519     if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_DATA_CLASS)
520     {
521         /* This is the data interface.  */
522         cdc_acm_host_data = cdc_acm_host;
523 
524         /* In that case, the second one should be the control interface.  */
525         status =  ux_host_stack_class_instance_get(class, 1, (void **) &cdc_acm_host);
526 
527         /* Check error.  */
528         if (status != UX_SUCCESS)
529             return(status);
530 
531         /* Check for the control interfaces.  */
532         if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
533         {
534 
535             /* This is the control interface.  */
536             cdc_acm_host_control = cdc_acm_host;
537 
538             return(UX_SUCCESS);
539 
540         }
541     }
542     else
543     {
544         /* Check for the control interfaces.  */
545         if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
546         {
547 
548             /* This is the control interface.  */
549             cdc_acm_host_control = cdc_acm_host;
550 
551             /* In that case, the second one should be the data interface.  */
552             status =  ux_host_stack_class_instance_get(class, 1, (void **) &cdc_acm_host);
553 
554             /* Check error.  */
555             if (status != UX_SUCCESS)
556                 return(status);
557 
558             /* Check for the data interface.  */
559             if (cdc_acm_host -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_DATA_CLASS)
560             {
561 
562                 /* This is the data interface.  */
563                 cdc_acm_host_data = cdc_acm_host;
564 
565                 return(UX_SUCCESS);
566 
567             }
568         }
569     }
570 
571     /* Return ERROR.  */
572     return(UX_ERROR);
573 }
574 
test_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)575 static UINT test_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
576 {
577 
578 UX_HOST_CLASS_CDC_ACM *cdc_acm = (UX_HOST_CLASS_CDC_ACM *) inst;
579 
580     switch(event)
581     {
582 
583         case UX_DEVICE_INSERTION:
584 
585             if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
586                 cdc_acm_host_control = cdc_acm;
587             else
588                 cdc_acm_host_data = cdc_acm;
589             break;
590 
591         case UX_DEVICE_REMOVAL:
592 
593             if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
594                 cdc_acm_host_control = UX_NULL;
595             else
596                 cdc_acm_host_data = UX_NULL;
597             break;
598 
599         default:
600             break;
601     }
602     return 0;
603 }
604 
test_cdc_instance_activate(VOID * cdc_instance)605 static VOID test_cdc_instance_activate(VOID *cdc_instance)
606 {
607 
608     /* Save the CDC instance.  */
609     cdc_acm_slave = (UX_SLAVE_CLASS_CDC_ACM *) cdc_instance;
610 }
test_cdc_instance_deactivate(VOID * cdc_instance)611 static VOID test_cdc_instance_deactivate(VOID *cdc_instance)
612 {
613 
614     /* Reset the CDC instance.  */
615     cdc_acm_slave = UX_NULL;
616 }
617 
test_cdc_instance_parameter_change(VOID * cdc_instance)618 static VOID test_cdc_instance_parameter_change(VOID *cdc_instance)
619 {
620 
621     /* Set CDC parameter change flag. */
622     cdc_acm_slave_change = UX_TRUE;
623 }
624 
test_swap_framework_bulk_ep_descriptors(VOID)625 static VOID test_swap_framework_bulk_ep_descriptors(VOID)
626 {
627 UCHAR tmp;
628 
629     tmp = device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_1_FS];
630     device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_1_FS] = device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_2_FS];
631     device_framework_full_speed[DEVICE_FRAMEWORK_EPA_POS_2_FS] = tmp;
632 
633     tmp = device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_1_HS];
634     device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_1_HS] = device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_2_HS];
635     device_framework_high_speed[DEVICE_FRAMEWORK_EPA_POS_2_HS] = tmp;
636 }
637 
638 
test_ux_error_callback(UINT system_level,UINT system_context,UINT error_code)639 static VOID test_ux_error_callback(UINT system_level, UINT system_context, UINT error_code)
640 {
641 }
642 
ux_test_hcd_entry_should_not_be_called(UX_TEST_ACTION * action,VOID * params)643 static VOID ux_test_hcd_entry_should_not_be_called(UX_TEST_ACTION *action, VOID *params)
644 {
645 
646     error_counter ++;
647 }
648 
ux_test_hcd_entry_disconnect(UX_TEST_ACTION * action,VOID * params)649 static VOID ux_test_hcd_entry_disconnect(UX_TEST_ACTION *action, VOID *params)
650 {
651 
652     ux_test_dcd_sim_slave_disconnect();
653 }
654 
ux_test_hcd_entry_set_cfg(UX_TEST_ACTION * action,VOID * params)655 static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *params)
656 {
657 
658     set_cfg_counter ++;
659 
660     rsc_mem_alloc_cnt_on_set_cfg = ux_test_utility_sim_mem_alloc_count();
661 
662     rsc_sem_on_set_cfg = ux_test_utility_sim_sem_create_count();
663     rsc_enum_sem_get_count = ux_test_utility_sim_sem_get_count();
664     rsc_mutex_on_set_cfg = ux_test_utility_sim_mutex_create_count();
665 }
666 
667 /* Define what the initial system looks like.  */
668 
669 #ifdef CTEST
test_application_define(void * first_unused_memory)670 void test_application_define(void *first_unused_memory)
671 #else
672 void    usbx_host_device_basic_memory_test_application_define(void *first_unused_memory)
673 #endif
674 {
675 
676 UINT                    status;
677 CHAR *                  stack_pointer;
678 CHAR *                  memory_pointer;
679 
680     printf("Running Host & Device Basic Memory Test............................. ");
681 
682     stepinfo("\n");
683 
684     /* Reset testing counts. */
685     ux_test_utility_sim_mem_alloc_log_enable(UX_TRUE);
686     ux_test_utility_sim_mem_alloc_count_reset();
687     ux_test_utility_sim_mutex_create_count_reset();
688     ux_test_utility_sim_sem_create_count_reset();
689     ux_test_utility_sim_sem_get_count_reset();
690     /* Reset error generations */
691     ux_test_utility_sim_mem_alloc_error_generation_stop();
692     ux_test_utility_sim_sem_error_generation_stop();
693     ux_test_utility_sim_mutex_error_generation_stop();
694     ux_test_utility_sim_sem_get_error_generation_stop();
695 
696     /* Initialize the free memory pointer */
697     stack_pointer = (CHAR *) usbx_memory;
698     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
699 
700     /* Initialize USBX Memory */
701     status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
702 
703     /* Check for error.  */
704     if (status != UX_SUCCESS)
705     {
706 
707         printf(" ERROR #1\n");
708         test_control_return(1);
709     }
710 
711     /* Register the error callback. */
712     _ux_utility_error_callback_register(test_ux_error_callback);
713 
714     stepinfo(">>>>>>>>>>>>>>>> ux_host_stack_initialize\n");
715 
716     /* The code below is required for installing the host portion of USBX */
717     status =  ux_host_stack_initialize(test_host_change_function);
718     if (status != UX_SUCCESS)
719     {
720 
721         printf(" ERROR #2\n");
722         test_control_return(1);
723     }
724 
725     stepinfo(">>>>>>>>>>>>>>>> ux_host_stack_class_register(cdc_acm)\n");
726 
727     /* Register CDC-ACM class.  */
728     status =  ux_host_stack_class_register(_ux_system_host_class_cdc_acm_name, ux_host_class_cdc_acm_entry);
729     if (status != UX_SUCCESS)
730     {
731 
732         printf(" ERROR #3\n");
733         test_control_return(1);
734     }
735 
736     stepinfo(">>>>>>>>>>>>>>>> ux_device_stack_initialize\n");
737 
738     /* The code below is required for installing the device portion of USBX. No call back for
739        device status change in this example. */
740     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
741                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
742                                        string_framework, STRING_FRAMEWORK_LENGTH,
743                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
744     if(status!=UX_SUCCESS)
745     {
746 
747         printf(" ERROR #5\n");
748         test_control_return(1);
749     }
750 
751     stepinfo(">>>>>>>>>>>>>>>> ux_device_stack_class_register(cdc_acm)\n");
752 
753     /* Set the parameters for callback when insertion/extraction of a CDC device.  */
754     parameter.ux_slave_class_cdc_acm_instance_activate   =  test_cdc_instance_activate;
755     parameter.ux_slave_class_cdc_acm_instance_deactivate =  test_cdc_instance_deactivate;
756     parameter.ux_slave_class_cdc_acm_parameter_change    =  test_cdc_instance_parameter_change;
757 
758     /* Initialize the device cdc class. This class owns both interfaces starting with 0. */
759     status =  ux_device_stack_class_register(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry,
760                                              1,0,  &parameter);
761 
762     if(status!=UX_SUCCESS)
763     {
764 
765         printf(" ERROR #7\n");
766         test_control_return(1);
767     }
768 
769     stepinfo(">>>>>>>>>>>>>>>> _ux_dcd_sim_slave_initialize\n");
770 
771     /* Initialize the simulated device controller.  */
772     status =  _ux_dcd_sim_slave_initialize();
773 
774     /* Check for error.  */
775     if (status != TX_SUCCESS)
776     {
777 
778         printf(" ERROR #8\n");
779         test_control_return(1);
780     }
781 
782     stepinfo(">>>>>>>>>>>>>>>> ux_host_stack_hcd_register(sim)\n");
783 
784     /* Register all the USB host controllers available in this system */
785     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
786     if (status != UX_SUCCESS)
787     {
788 
789         printf(" ERROR #4\n");
790         test_control_return(1);
791     }
792 
793     stepinfo(">>>>>>>>>>>>>>>> tx_thread_create(tx_test_thread_host_simulation)\n");
794 
795     /* Create the main host simulation thread.  */
796     status =  tx_thread_create(&tx_test_thread_host_simulation, "tx test host simulation", tx_test_thread_host_simulation_entry, 0,
797             stack_pointer, UX_DEMO_STACK_SIZE,
798             20, 20, 1, TX_AUTO_START);
799 
800     /* Check for error.  */
801     if (status != TX_SUCCESS)
802     {
803 
804         printf(" ERROR #9\n");
805         test_control_return(1);
806     }
807 
808     stepinfo(">>>>>>>>>>>>>>>> tx_thread_create(tx_test_thread_slave_simulation)\n");
809 
810     /* Create the main slave simulation  thread.  */
811     status =  tx_thread_create(&tx_test_thread_slave_simulation, "tx test slave simulation", tx_test_thread_slave_simulation_entry, 0,
812             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
813             20, 20, 1, TX_AUTO_START);
814 
815     /* Check for error.  */
816     if (status != TX_SUCCESS)
817     {
818 
819         printf(" ERROR #10\n");
820         test_control_return(1);
821     }
822 }
823 
tx_test_thread_host_simulation_entry(ULONG arg)824 void  tx_test_thread_host_simulation_entry(ULONG arg)
825 {
826 UINT                                                status;
827 ULONG                                               test_n;
828 ULONG                                               mem_free;
829 ULONG                                               retry;
830 UX_HCD                                              *hcd;
831 
832 
833     hcd = &_ux_system_host->ux_system_host_hcd_array[0];
834 
835     /* Find the cdc_acm class and wait for the link to be up.  */
836     status =  test_class_cdc_acm_get();
837     if (status != UX_SUCCESS)
838     {
839 
840         /* DPUMP basic test error.  */
841         printf("ERROR #11: class not found\n");
842         test_control_return(1);
843     }
844     if (!cdc_acm_host_control && !cdc_acm_host_data)
845     {
846 
847         printf("ERROR #12: instance not detected\n");
848         test_control_return(1);
849     }
850     stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
851 
852     /* Test disconnect. */
853     stepinfo(">>>>>>>>>>>>>>>> Test disconnect\n");
854     ux_test_dcd_sim_slave_disconnect();
855     ux_test_hcd_sim_host_disconnect();
856     if (cdc_acm_host_control || cdc_acm_host_data)
857     {
858 
859         printf("ERROR #13: instance not removed when disconnect");
860         test_control_return(1);
861     }
862     stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
863 
864     /* Reset testing counts. */
865     stepinfo(">>>>>>>>>>>>>>>> Test connect & connection resource\n");
866 
867     ux_test_utility_sim_mem_alloc_count_reset();
868     ux_test_utility_sim_mutex_create_count_reset();
869     ux_test_utility_sim_sem_create_count_reset();
870     ux_test_utility_sim_sem_get_count_reset();
871 
872     ux_test_hcd_sim_host_set_actions(log_on_SetCfg);
873 
874     ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
875     ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
876     test_n = 10;
877     while((!cdc_acm_host_control || !cdc_acm_host_data) && test_n --)
878         tx_thread_sleep(10);
879     /* Log create counts when SetConfigure for further tests. */
880     rsc_enum_mutex_usage = rsc_mutex_on_set_cfg;
881     rsc_enum_sem_usage = rsc_sem_on_set_cfg;
882     rsc_enum_sem_get_count = rsc_sem_get_on_set_cfg;
883     rsc_enum_mem_alloc_count = rsc_mem_alloc_cnt_on_set_cfg;
884 
885     /* Lock memory allocate logs for tests. */
886     ux_test_utility_sim_mem_alloc_log_lock();
887 
888     stepinfo("enum mem alloc count: %ld\n", rsc_enum_mem_alloc_count);
889     stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
890 
891     /* Simulate detach and attach for FS enumeration,
892        and check if there is memory error in normal enumeration.
893      */
894     stepinfo(">>>>>>>>>>>>>>>> Enumeration test\n");
895     mem_free = (~0);
896     for (test_n = 0; test_n < 3; test_n++)
897     {
898         stepinfo("%4ld / 2\n", test_n);
899 
900         /* Disconnect. */
901         ux_test_dcd_sim_slave_disconnect();
902         ux_test_hcd_sim_host_disconnect();
903 
904         /* Check number of devices.  */
905         if (hcd->ux_hcd_nb_devices != 0)
906         {
907             printf("ERROR #%d.%ld: number of devices (%d) must be 0\n", __LINE__, test_n, hcd->ux_hcd_nb_devices);
908             error_counter ++;
909         }
910 
911         /* Update memory free level (disconnect) */
912         if (mem_free == (~0))
913             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
914         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
915         {
916 
917             printf("ERROR #14.%ld: Memory level different after re-enumerations %ld <> %ld\n", test_n, mem_free, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
918             test_control_return(1);
919         }
920 
921         /* Connect. */
922         ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
923         ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
924 
925         /* Wait */
926         for (retry = 0; (retry < 10) && (cdc_acm_host_control == UX_NULL || cdc_acm_host_data == UX_NULL); retry ++)
927             tx_thread_sleep(10);
928 
929         /* Check */
930         if (!cdc_acm_host_control || !cdc_acm_host_data)
931         {
932 
933             printf("ERROR #15.%ld: Enumeration fail\n", test_n);
934             test_control_return(1);
935         }
936     }
937 
938     /* Simulate detach and attach for FS enumeration,
939        and test possible memory allocation error handlings.
940      */
941     if (rsc_enum_mem_alloc_count) stepinfo(">>>>>>>>>>>>>>>> Memory errors enumeration test\n");
942     mem_free = (~0);
943     for (test_n = 0; test_n < rsc_enum_mem_alloc_count; test_n ++)
944     {
945 
946         stepinfo("%4ld / %4ld\n", test_n, rsc_enum_mem_alloc_count - 1);
947 
948         /* Disconnect. */
949         ux_test_dcd_sim_slave_disconnect();
950         ux_test_hcd_sim_host_disconnect();
951 
952         /* Check number of devices.  */
953         if (hcd->ux_hcd_nb_devices != 0)
954         {
955             printf("ERROR #%d.%ld: number of devices (%d) must be 0\n", __LINE__, test_n, hcd->ux_hcd_nb_devices);
956             error_counter ++;
957         }
958 
959         /* Update memory free level (disconnect) */
960         if (mem_free == (~0))
961             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
962         /* Check memory level */
963         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
964         {
965 
966             printf("ERROR #16.%ld: Memory level different after re-enumerations\n", test_n);
967             test_control_return(1);
968         }
969 
970         /* Set memory error generation */
971         ux_test_utility_sim_mem_alloc_error_generation_start(test_n);
972 
973         /* Count SetConfigure */
974         set_cfg_counter = 0;
975         ux_test_hcd_sim_host_set_actions(log_on_SetCfg);
976 
977         /* Connect. */
978         ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
979         ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
980 
981         /* Check error */
982         if (set_cfg_counter)
983         {
984 
985             printf("ERROR #17.%ld: device detected when there is memory error\n", test_n);
986             test_control_return(1);
987         }
988         stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
989     }
990     ux_test_utility_sim_mem_alloc_error_generation_stop();
991     if (rsc_enum_mem_alloc_count) stepinfo("\n");
992 
993     /* Finally disconnect the device. */
994     ux_device_stack_disconnect();
995 
996     /* And deinitialize the class.  */
997     status =  ux_device_stack_class_unregister(_ux_system_slave_class_cdc_acm_name, ux_device_class_cdc_acm_entry);
998 
999     /* Deinitialize the device side of usbx.  */
1000     _ux_device_stack_uninitialize();
1001 
1002     /* And finally the usbx system resources.  */
1003     _ux_system_uninitialize();
1004 
1005     /* Successful test.  */
1006     printf("SUCCESS!\n");
1007     test_control_return(0);
1008 
1009 }
1010 
tx_test_thread_slave_simulation_entry(ULONG arg)1011 void  tx_test_thread_slave_simulation_entry(ULONG arg)
1012 {
1013 
1014     while(1)
1015     {
1016 
1017         /* Sleep so ThreadX on Win32 will delete this thread. */
1018         tx_thread_sleep(10);
1019     }
1020 }
1021