1 #ifndef USBX_UX_TEST_CDC_ECM_H
2 #define USBX_UX_TEST_CDC_ECM_H
3 
4 #include "ux_api.h"
5 #include "ux_system.h"
6 #include "ux_utility.h"
7 #include "ux_network_driver.h"
8 #include "ux_host_class_cdc_ecm.h"
9 #include "ux_device_class_cdc_ecm.h"
10 #include "ux_test_dcd_sim_slave.h"
11 #include "ux_test_hcd_sim_host.h"
12 #include "ux_test_utility_sim.h"
13 #include "ux_test.h"
14 #include "ux_test_actions.h"
15 
16 //#define LOCAL_MACHINE
17 
18 typedef struct DEVICE_INIT_DATA
19 {
20     UCHAR *framework;
21     ULONG framework_length;
22     UCHAR *string_framework;
23     ULONG string_framework_length;
24     UCHAR dont_register_hcd;
25     UCHAR dont_connect_to_host;
26 } DEVICE_INIT_DATA;
27 
28 #define DEMO_IP_THREAD_STACK_SIZE           (8*1024)
29 #define HOST_IP_ADDRESS                     IP_ADDRESS(192,168,1,176)
30 #define HOST_SOCKET_PORT_UDP                45054
31 #define HOST_SOCKET_PORT_TCP                45056
32 #define DEVICE_IP_ADDRESS                   IP_ADDRESS(192,168,1,175)
33 #define DEVICE_SOCKET_PORT_UDP              45055
34 #define DEVICE_SOCKET_PORT_TCP              45057
35 
36 #ifndef TEST_NX_PACKET_CHAIN
37 #define TCP_WINDOW                          1600
38 #define PACKET_PAYLOAD                      1600
39 #define WRITE_APPEND_SIZE                   (0)
40 #define PACKET_POOL_SIZE                    (PACKET_PAYLOAD*10000)
41 #define HOST_IP_POOL_SIZE                   (PACKET_PAYLOAD*UX_HOST_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES)
42 #define DEVICE_IP_POOL_SIZE                 (PACKET_PAYLOAD*UX_DEVICE_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES)
43 #else
44 #define TCP_WINDOW                          1400
45 #define PACKET_PAYLOAD                      (256)
46 #define WRITE_APPEND_SIZE                   (300)
47 #define PACKET_POOL_SIZE                    (PACKET_PAYLOAD*10000)
48 #define HOST_IP_POOL_SIZE                   (PACKET_PAYLOAD*UX_HOST_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES)
49 #define DEVICE_IP_POOL_SIZE                 (PACKET_PAYLOAD*UX_DEVICE_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES)
50 #endif
51 #define ARP_MEMORY_SIZE                     1024
52 
53 /* Define local constants.  */
54 
55 #define UX_DEMO_STACK_SIZE                  (4*1024)
56 #define UX_USBX_MEMORY_SIZE                 (128*1024)
57 
58 /* Define basic test constants.  */
59 
60 #ifndef BASIC_TEST_NUM_ITERATIONS
61 #define BASIC_TEST_NUM_ITERATIONS               10
62 #endif
63 #ifndef BASIC_TEST_NUM_PACKETS_PER_ITERATION
64 #define BASIC_TEST_NUM_PACKETS_PER_ITERATION    10
65 #endif
66 #define BASIC_TEST_NUM_TOTAL_PACKETS            (BASIC_TEST_NUM_ITERATIONS*BASIC_TEST_NUM_PACKETS_PER_ITERATION)
67 #define BASIC_TEST_HOST                         0
68 #define BASIC_TEST_DEVICE                       1
69 #define BASIC_TEST_TCP                          0
70 #define BASIC_TEST_UDP                          1
71 
72 /* Host */
73 
74 static UX_HOST_CLASS                        *class_driver_host;
75 static UX_HOST_CLASS_CDC_ECM                *cdc_ecm_host;
76 static UX_HOST_CLASS_CDC_ECM                *cdc_ecm_host_from_system_change_function;
77 static TX_THREAD                            thread_host;
78 static UCHAR                                thread_stack_host[UX_DEMO_STACK_SIZE];
79 static NX_IP                                nx_ip_host;
80 static NX_PACKET_POOL                       ip_pool_host;
81 static UCHAR                                ip_pool_host_name[] = "NetX Host IP Pool";
82 static NX_PACKET_POOL                       packet_pool_host;
83 static NX_PACKET_POOL                       *packet_pool_host_ptr = &packet_pool_host;
84 static NX_UDP_SOCKET                        udp_socket_host;
85 static NX_TCP_SOCKET                        tcp_socket_host;
86 static CHAR                                 *packet_pool_memory_host;
87 static CHAR                                 ip_thread_stack_host[DEMO_IP_THREAD_STACK_SIZE];
88 static CHAR                                 arp_memory_host[ARP_MEMORY_SIZE];
89 
90 /* Device */
91 
92 static TX_THREAD                            thread_device;
93 static UX_HOST_CLASS                        *class_driver_device;
94 static UX_SLAVE_CLASS_CDC_ECM               *cdc_ecm_device;
95 static UX_SLAVE_CLASS_CDC_ECM_PARAMETER     cdc_ecm_parameter;
96 static UCHAR                                thread_stack_device[UX_DEMO_STACK_SIZE];
97 static NX_IP                                nx_ip_device;
98 static NX_PACKET_POOL                       ip_pool_device;
99 static NX_PACKET_POOL                       packet_pool_device;
100 static NX_UDP_SOCKET                        udp_socket_device;
101 static NX_TCP_SOCKET                        tcp_socket_device;
102 static CHAR                                 *packet_pool_memory_device;
103 static CHAR                                 ip_thread_stack_device[DEMO_IP_THREAD_STACK_SIZE];
104 static CHAR                                 arp_memory_device[ARP_MEMORY_SIZE];
105 
106 static UCHAR                                global_is_device_initialized;
107 static UCHAR                                global_host_ready_for_application;
108 
109 static ULONG                                global_basic_test_num_writes_host;
110 static ULONG                                global_basic_test_num_reads_host;
111 static ULONG                                global_basic_test_num_writes_device;
112 static ULONG                                global_basic_test_num_reads_device;
113 
114 /* Define local prototypes and definitions.  */
115 static void thread_entry_host(ULONG arg);
116 static void thread_entry_device(ULONG arg);
117 static void post_init_host();
118 static void post_init_device();
119 
120 #define DEFAULT_FRAMEWORK_LENGTH sizeof(default_device_framework)
121 static unsigned char default_device_framework[] = {
122 
123     /* Device Descriptor */
124     0x12, /* bLength */
125     0x01, /* bDescriptorType */
126     0x10, 0x01, /* bcdUSB */
127     0xef, /* bDeviceClass - Depends on bDeviceSubClass */
128     0x02, /* bDeviceSubClass - Depends on bDeviceProtocol */
129     0x01, /* bDeviceProtocol - There's an IAD */
130     0x40, /* bMaxPacketSize0 */
131     0x70, 0x07, /* idVendor */
132     0x42, 0x10, /* idProduct */
133     0x00, 0x01, /* bcdDevice */
134     0x01, /* iManufacturer */
135     0x02, /* iProduct */
136     0x03, /* iSerialNumber */
137     0x01, /* bNumConfigurations */
138 
139     /* Configuration Descriptor @ 18 */
140     0x09, /* bLength */
141     0x02, /* bDescriptorType */
142     0x58, 0x00, /* wTotalLength */
143     0x02, /* bNumInterfaces */
144     0x01, /* bConfigurationValue */
145     0x00, /* iConfiguration */
146     0xc0, /* bmAttributes - Self-powered */
147     0x00, /* bMaxPower */
148 
149     /* Interface Association Descriptor @ 18+9=27 */
150     0x08, /* bLength */
151     0x0b, /* bDescriptorType */
152     0x00, /* bFirstInterface */
153     0x02, /* bInterfaceCount */
154     0x02, /* bFunctionClass - CDC - Communication */
155     0x06, /* bFunctionSubClass - ECM */
156     0x00, /* bFunctionProtocol - No class specific protocol required */
157     0x00, /* iFunction */
158 
159     /* Interface Descriptor @ 27+8=35 */
160     0x09, /* bLength */
161     0x04, /* bDescriptorType */
162     0x00, /* bInterfaceNumber */
163     0x00, /* bAlternateSetting */
164     0x01, /* bNumEndpoints */
165     0x02, /* bInterfaceClass - CDC - Communication */
166     0x06, /* bInterfaceSubClass - ECM */
167     0x00, /* bInterfaceProtocol - No class specific protocol required */
168     0x00, /* iInterface */
169 
170     /* CDC Header Functional Descriptor @ 35+9=44 */
171     0x05, /* bLength */
172     0x24, /* bDescriptorType */
173     0x00, /* bDescriptorSubType */
174     0x10, 0x01, /* bcdCDC */
175 
176     /* CDC ECM Functional Descriptor @ 44+5=49 */
177     0x0d, /* bLength */
178     0x24, /* bDescriptorType */
179     0x0f, /* bDescriptorSubType */
180     0x04, /* iMACAddress */
181     0x00, 0x00, 0x00, 0x00, /* bmEthernetStatistics */
182     0xea, 0x05, /* wMaxSegmentSize */
183     0x00, 0x00, /* wNumberMCFilters */
184     0x00, /* bNumberPowerFilters */
185 
186     /* CDC Union Functional Descriptor @ 49+13=62 */
187     0x05, /* bLength */
188     0x24, /* bDescriptorType */
189     0x06, /* bDescriptorSubType */
190     0x00, /* bmMasterInterface */
191     0x01, /* bmSlaveInterface0 */
192 
193     /* Endpoint Descriptor */
194     0x07, /* bLength */
195     0x05, /* bDescriptorType */
196     0x83, /* bEndpointAddress */
197     0x03, /* bmAttributes - Interrupt */
198     0x08, 0x00, /* wMaxPacketSize */
199     0x08, /* bInterval */
200 
201     /* Interface Descriptor */
202     0x09, /* bLength */
203     0x04, /* bDescriptorType */
204     0x01, /* bInterfaceNumber */
205     0x00, /* bAlternateSetting */
206     0x00, /* bNumEndpoints */
207     0x0a, /* bInterfaceClass - CDC - Data */
208     0x00, /* bInterfaceSubClass - Should be 0x00 */
209     0x00, /* bInterfaceProtocol - No class specific protocol required */
210     0x00, /* iInterface */
211 
212     /* Interface Descriptor */
213     0x09, /* bLength */
214     0x04, /* bDescriptorType */
215     0x01, /* bInterfaceNumber */
216     0x01, /* bAlternateSetting */
217     0x02, /* bNumEndpoints */
218     0x0a, /* bInterfaceClass - CDC - Data */
219     0x00, /* bInterfaceSubClass - Should be 0x00 */
220     0x00, /* bInterfaceProtocol - No class specific protocol required */
221     0x00, /* iInterface */
222 
223     /* Endpoint Descriptor */
224     0x07, /* bLength */
225     0x05, /* bDescriptorType */
226     0x02, /* bEndpointAddress */
227     0x02, /* bmAttributes - Bulk */
228     0x40, 0x00, /* wMaxPacketSize */
229     0x00, /* bInterval */
230 
231     /* Endpoint Descriptor */
232     0x07, /* bLength */
233     0x05, /* bDescriptorType */
234     0x81, /* bEndpointAddress */
235     0x02, /* bmAttributes - Bulk */
236     0x40, 0x00, /* wMaxPacketSize */
237     0x00, /* bInterval */
238 
239 };
240 
241 static unsigned char default_string_framework[] = {
242 
243     /* Manufacturer string descriptor : Index 1 - "Express Logic" */
244         0x09, 0x04, 0x01, 0x0c,
245         0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x20, 0x4c,
246         0x6f, 0x67, 0x69, 0x63,
247 
248     /* Product string descriptor : Index 2 - "EL CDCECM Device" */
249         0x09, 0x04, 0x02, 0x10,
250         0x45, 0x4c, 0x20, 0x43, 0x44, 0x43, 0x45, 0x43,
251         0x4d, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
252 
253     /* Serial Number string descriptor : Index 3 - "0001" */
254         0x09, 0x04, 0x03, 0x04,
255         0x30, 0x30, 0x30, 0x31,
256 
257     /* MAC Address string descriptor : Index 4 - "001E5841B879" */
258         0x09, 0x04, 0x04, 0x0C,
259         0x30, 0x30, 0x31, 0x45, 0x35, 0x38,
260         0x34, 0x31, 0x42, 0x38, 0x37, 0x39,
261 
262 };
263 
264     /* Multiple languages are supported on the device, to add
265        a language besides english, the unicode language code must
266        be appended to the language_id_framework array and the length
267        adjusted accordingly. */
268 static unsigned char language_id_framework[] = {
269 
270     /* English. */
271         0x09, 0x04
272     };
273 
274 static DEVICE_INIT_DATA default_device_init_data = {
275     .framework = default_device_framework,
276     .framework_length = sizeof(default_device_framework),
277     .string_framework = default_string_framework,
278     .string_framework_length = sizeof(default_string_framework)
279 };
280 
ux_test_cdc_ecm_initialize_use_framework(void * first_unused_memory,DEVICE_INIT_DATA * device_init_data)281 static void ux_test_cdc_ecm_initialize_use_framework(void *first_unused_memory, DEVICE_INIT_DATA *device_init_data)
282 {
283 
284 CHAR *memory_pointer = first_unused_memory;
285 
286     /* Initialize possible uninitialized device init values. */
287 
288     if (device_init_data->framework == NULL)
289     {
290         device_init_data->framework = default_device_framework;
291         device_init_data->framework_length = sizeof(default_device_framework);
292     }
293 
294     if (device_init_data->string_framework == NULL)
295     {
296         device_init_data->string_framework = default_string_framework;
297         device_init_data->string_framework_length = sizeof(default_string_framework);
298     }
299 
300     /* Initialize USBX Memory. */
301     ux_system_initialize(memory_pointer, UX_USBX_MEMORY_SIZE, UX_NULL, 0);
302     memory_pointer += UX_USBX_MEMORY_SIZE;
303 
304     /* It looks weird if this doesn't have a comment! */
305     ux_utility_error_callback_register(ux_test_error_callback);
306 
307     /* Perform the initialization of the network driver. */
308     UX_TEST_CHECK_SUCCESS(ux_network_driver_init());
309 
310     /* Initialize the NetX system. */
311     nx_system_initialize();
312 
313     /* Now allocate memory for the packet pools. Note that using the memory passed
314        to us by ThreadX is mucho bettero than putting it in global memory because
315        we can reuse the memory for each test. So no more having to worry about
316        running out of memory! */
317     packet_pool_memory_host = memory_pointer;
318     memory_pointer += PACKET_POOL_SIZE + HOST_IP_POOL_SIZE;
319     packet_pool_memory_device = memory_pointer;
320     memory_pointer += PACKET_POOL_SIZE + DEVICE_IP_POOL_SIZE;
321 
322     /* Create the host thread. */
323     UX_TEST_CHECK_SUCCESS(tx_thread_create(&thread_host, "host thread", thread_entry_host, (ULONG)(ALIGN_TYPE)device_init_data,
324                                            thread_stack_host, UX_DEMO_STACK_SIZE,
325                                            30, 30, 1, TX_DONT_START));
326     UX_THREAD_EXTENSION_PTR_SET(&thread_host, device_init_data)
327     tx_thread_resume(&thread_host);
328 
329     /* Create the slave thread. */
330     UX_TEST_CHECK_SUCCESS(tx_thread_create(&thread_device, "device thread", thread_entry_device, (ULONG)(ALIGN_TYPE)device_init_data,
331                                            thread_stack_device, UX_DEMO_STACK_SIZE,
332                                            30, 30, 1, TX_DONT_START));
333     UX_THREAD_EXTENSION_PTR_SET(&thread_device, device_init_data)
334     tx_thread_resume(&thread_device);
335 }
336 
ux_test_cdc_ecm_initialize(void * first_unused_memory)337 static void ux_test_cdc_ecm_initialize(void *first_unused_memory)
338 {
339 
340     ux_test_cdc_ecm_initialize_use_framework(first_unused_memory, &default_device_init_data);
341 }
342 
system_change_function(ULONG event,UX_HOST_CLASS * class,VOID * instance)343 static UINT system_change_function(ULONG event, UX_HOST_CLASS *class, VOID *instance)
344 {
345     if (event == UX_DEVICE_INSERTION)
346     {printf("hINS\n");
347         cdc_ecm_host_from_system_change_function = instance;
348     }
349     else if (event == UX_DEVICE_REMOVAL)
350     {printf("hRM\n");
351         cdc_ecm_host_from_system_change_function = UX_NULL;
352     }
353     return(UX_SUCCESS);
354 }
355 
class_cdc_ecm_get_host(void)356 static void class_cdc_ecm_get_host(void)
357 {
358 
359 UX_HOST_CLASS   *class;
360 
361     /* Find the main storage container */
362     UX_TEST_CHECK_SUCCESS(ux_host_stack_class_get(_ux_system_host_class_cdc_ecm_name, &class));
363 
364     /* We get the first instance of the storage device */
365     UX_TEST_CHECK_SUCCESS(ux_test_host_stack_class_instance_get(class, 0, (void **) &cdc_ecm_host));
366 
367     /* We still need to wait for the cdc-ecm status to be live */
368     UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uint(&cdc_ecm_host -> ux_host_class_cdc_ecm_state, UX_HOST_CLASS_INSTANCE_LIVE));
369 
370 	/* Now wait for the link to be up.  */
371     UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_host->ux_host_class_cdc_ecm_link_state, UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP));
372 }
373 
demo_cdc_ecm_instance_activate(VOID * cdc_ecm_instance)374 static VOID demo_cdc_ecm_instance_activate(VOID *cdc_ecm_instance)
375 {
376 
377     /* Save the CDC instance.  */
378     cdc_ecm_device = (UX_SLAVE_CLASS_CDC_ECM *) cdc_ecm_instance;
379 }
380 
demo_cdc_ecm_instance_deactivate(VOID * cdc_ecm_instance)381 static VOID demo_cdc_ecm_instance_deactivate(VOID *cdc_ecm_instance)
382 {
383 
384     /* Reset the CDC instance.  */
385     cdc_ecm_device = UX_NULL;
386 }
387 
388 /* Copied and pasted from ux_device_class_cdc_ecm_change.c. */
ux_test_device_class_cdc_ecm_set_link_state(UX_SLAVE_CLASS_CDC_ECM * cdc_ecm,UCHAR new_link_state)389 static void ux_test_device_class_cdc_ecm_set_link_state(UX_SLAVE_CLASS_CDC_ECM *cdc_ecm, UCHAR new_link_state)
390 {
391 
392     /* Declare the link to be down. */
393     cdc_ecm_device -> ux_slave_class_cdc_ecm_link_state =  new_link_state;
394 
395     /* We have a thread waiting for an event, we wake it up with a NETWORK NOTIFICATION CHANGE event.
396        In turn they will release the NetX resources used and suspend.  */
397     UX_TEST_CHECK_SUCCESS(_ux_utility_event_flags_set(&cdc_ecm_device -> ux_slave_class_cdc_ecm_event_flags_group, UX_DEVICE_CLASS_CDC_ECM_NETWORK_NOTIFICATION_EVENT, TX_OR));
398 }
399 
read_packet_tcp(NX_TCP_SOCKET * tcp_socket,ULONG num_reads,CHAR * name)400 static void read_packet_tcp(NX_TCP_SOCKET *tcp_socket, ULONG num_reads, CHAR *name)
401 {
402 
403 NX_PACKET 	*rcv_packet;
404 ULONG       num_writes_from_peer;
405 
406 #ifndef LOCAL_MACHINE
407     if (num_reads % 100 == 0)
408 #endif
409         stepinfo("%s reading tcp packet# %lu\n", name, num_reads);
410 
411     UX_TEST_CHECK_SUCCESS(nx_tcp_socket_receive(tcp_socket, &rcv_packet, NX_WAIT_FOREVER));
412 
413     num_writes_from_peer = *(ULONG *)rcv_packet->nx_packet_prepend_ptr;
414     UX_TEST_ASSERT(num_writes_from_peer == num_reads);
415 
416     UX_TEST_CHECK_SUCCESS(nx_packet_release(rcv_packet));
417 }
418 
write_packet_tcp(NX_TCP_SOCKET * tcp_socket,NX_PACKET_POOL * packet_pool,ULONG num_writes,CHAR * name)419 static void write_packet_tcp(NX_TCP_SOCKET *tcp_socket, NX_PACKET_POOL *packet_pool, ULONG num_writes, CHAR *name)
420 {
421 
422 NX_PACKET 	*out_packet;
423 
424     UX_TEST_CHECK_SUCCESS(nx_packet_allocate(packet_pool, &out_packet, NX_TCP_PACKET, NX_WAIT_FOREVER));
425 
426     *(ULONG *)out_packet->nx_packet_prepend_ptr = num_writes;
427     out_packet->nx_packet_length = sizeof(ULONG);
428     out_packet->nx_packet_append_ptr = out_packet->nx_packet_prepend_ptr + out_packet->nx_packet_length;
429 #if WRITE_APPEND_SIZE > 0
430     /* Append data until packet chain created.  */
431     for (int i = 0, remain = WRITE_APPEND_SIZE; i < WRITE_APPEND_SIZE; i += 10)
432     {
433         remain = WRITE_APPEND_SIZE - i;
434         if (remain < 10)
435         {
436             nx_packet_data_append(out_packet, "0123456789", remain, packet_pool, NX_WAIT_FOREVER);
437             break;
438         }
439         else
440         {
441             nx_packet_data_append(out_packet, "0123456789", 10, packet_pool, NX_WAIT_FOREVER);
442         }
443     }
444 #endif
445 
446 #ifndef LOCAL_MACHINE
447     if (num_writes % 100 == 0)
448 #endif
449         stepinfo("%s writing tcp packet# %lu\n", name, num_writes);
450 
451     UX_TEST_CHECK_SUCCESS(nx_tcp_socket_send(tcp_socket, out_packet, NX_WAIT_FOREVER));
452 }
453 
read_packet_udp(NX_UDP_SOCKET * udp_socket,ULONG num_reads,CHAR * name)454 static void read_packet_udp(NX_UDP_SOCKET *udp_socket, ULONG num_reads, CHAR *name)
455 {
456 
457 NX_PACKET 	*rcv_packet;
458 ULONG       num_writes_from_peer;
459 
460 #ifndef LOCAL_MACHINE
461     if (num_reads % 100 == 0)
462 #endif
463         stepinfo("%s reading udp packet# %lu\n", name, num_reads);
464 
465     UX_TEST_CHECK_SUCCESS(nx_udp_socket_receive(udp_socket, &rcv_packet, NX_WAIT_FOREVER));
466 
467     num_writes_from_peer = *(ULONG *)rcv_packet->nx_packet_prepend_ptr;
468     UX_TEST_ASSERT(num_writes_from_peer == num_reads);
469 
470     UX_TEST_CHECK_SUCCESS(nx_packet_release(rcv_packet));
471 }
472 
write_udp(NX_UDP_SOCKET * udp_socket,NX_PACKET_POOL * packet_pool,ULONG ip_address,ULONG port,ULONG num_writes,CHAR * name,ULONG len)473 static void write_udp(NX_UDP_SOCKET *udp_socket, NX_PACKET_POOL *packet_pool, ULONG ip_address, ULONG port, ULONG num_writes, CHAR *name, ULONG len)
474 {
475 
476 NX_PACKET 	*out_packet;
477 ULONG       i, remain;
478 
479     UX_TEST_CHECK_SUCCESS(nx_packet_allocate(packet_pool, &out_packet, NX_UDP_PACKET, NX_WAIT_FOREVER));
480 
481     *(ULONG *)out_packet->nx_packet_prepend_ptr = num_writes;
482     out_packet->nx_packet_length = sizeof(ULONG);
483     out_packet->nx_packet_append_ptr = out_packet->nx_packet_prepend_ptr + out_packet->nx_packet_length;
484     if (len > 4)
485     {
486 
487         /* Append packet data.  */
488         for (i = 0, remain = len - 4; i < len - 4; i += 10)
489         {
490             remain = len - 4 - i;
491             if (remain < 10)
492             {
493                 nx_packet_data_append(out_packet, "0123456789", remain, packet_pool, NX_WAIT_FOREVER);
494                 break;
495             }
496             else
497             {
498                 nx_packet_data_append(out_packet, "0123456789", 10, packet_pool, NX_WAIT_FOREVER);
499             }
500         }
501     }
502 
503 #ifndef LOCAL_MACHINE
504     if (num_writes % 100 == 0)
505 #endif
506         stepinfo("%s writing udp packet# %lu, %ld\n", name, num_writes, out_packet->nx_packet_length);
507 
508     UX_TEST_CHECK_SUCCESS(nx_udp_socket_send(udp_socket, out_packet, ip_address, port));
509 }
510 
write_packet_udp(NX_UDP_SOCKET * udp_socket,NX_PACKET_POOL * packet_pool,ULONG ip_address,ULONG port,ULONG num_writes,CHAR * name)511 static void write_packet_udp(NX_UDP_SOCKET *udp_socket, NX_PACKET_POOL *packet_pool, ULONG ip_address, ULONG port, ULONG num_writes, CHAR *name)
512 {
513     write_udp(udp_socket, packet_pool, ip_address, port, num_writes, name, 4 + WRITE_APPEND_SIZE);
514 }
515 
cdc_ecm_basic_test(UCHAR host_or_device,UCHAR socket_type)516 static void cdc_ecm_basic_test(UCHAR host_or_device, UCHAR socket_type)
517 {
518 
519 UINT i;
520 UINT num_iters;
521 
522     if (host_or_device == BASIC_TEST_HOST)
523     {
524 
525         if (socket_type == BASIC_TEST_TCP)
526         {
527 
528             for (num_iters = 0; num_iters < BASIC_TEST_NUM_ITERATIONS; num_iters++)
529             {
530 
531                 for (i = 0; i < BASIC_TEST_NUM_PACKETS_PER_ITERATION; i++)
532                     write_packet_tcp(&tcp_socket_host, &packet_pool_host, global_basic_test_num_writes_host++, "host");
533 
534                 for (i = 0; i < BASIC_TEST_NUM_PACKETS_PER_ITERATION; i++)
535                     read_packet_tcp(&tcp_socket_host, global_basic_test_num_reads_host++, "host");
536             }
537         }
538         else
539         {
540 
541             for (num_iters = 0; num_iters < BASIC_TEST_NUM_ITERATIONS; num_iters++)
542             {
543 
544                 for (i = 0; i < BASIC_TEST_NUM_PACKETS_PER_ITERATION; i++)
545                     write_packet_udp(&udp_socket_host, &packet_pool_host, DEVICE_IP_ADDRESS, DEVICE_SOCKET_PORT_UDP, global_basic_test_num_writes_host++, "host");
546 
547                 for (i = 0; i < BASIC_TEST_NUM_PACKETS_PER_ITERATION; i++)
548                     read_packet_udp(&udp_socket_host, global_basic_test_num_reads_host++, "host");
549             }
550         }
551 
552         /* Wait for all transfers to complete. */
553         UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&global_basic_test_num_writes_host, BASIC_TEST_NUM_TOTAL_PACKETS));
554         UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&global_basic_test_num_reads_host, BASIC_TEST_NUM_TOTAL_PACKETS));
555 
556         if (socket_type == BASIC_TEST_TCP)
557 
558             /* Wait for all ACKs to complete. */
559             /* TODO: find better way. */
560             tx_thread_sleep(MS_TO_TICK(1000));
561 
562         /* Reset for next test. */
563         global_basic_test_num_reads_host = 0;
564         global_basic_test_num_writes_host = 0;
565     }
566     else
567     {
568 
569         if (socket_type == BASIC_TEST_TCP)
570         {
571 
572             for (num_iters = 0; num_iters < BASIC_TEST_NUM_ITERATIONS; num_iters++)
573             {
574 
575                 for (i = 0; i < BASIC_TEST_NUM_PACKETS_PER_ITERATION; i++)
576                     write_packet_tcp(&tcp_socket_device, &packet_pool_device, global_basic_test_num_writes_device++, "device");
577 
578                 for (i = 0; i < BASIC_TEST_NUM_PACKETS_PER_ITERATION; i++)
579                     read_packet_tcp(&tcp_socket_device, global_basic_test_num_reads_device++, "device");
580             }
581         }
582         else
583         {
584 
585             for (num_iters = 0; num_iters < BASIC_TEST_NUM_ITERATIONS; num_iters++)
586             {
587 
588                 for (i = 0; i < BASIC_TEST_NUM_PACKETS_PER_ITERATION; i++)
589                     write_packet_udp(&udp_socket_device, &packet_pool_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_UDP, global_basic_test_num_writes_device++, "device");
590 
591                 for (i = 0; i < BASIC_TEST_NUM_PACKETS_PER_ITERATION; i++)
592                     read_packet_udp(&udp_socket_device, global_basic_test_num_reads_device++, "device");
593             }
594         }
595 
596         /* Wait for all transfers to complete. */
597         UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&global_basic_test_num_writes_device, BASIC_TEST_NUM_TOTAL_PACKETS));
598         UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&global_basic_test_num_reads_device, BASIC_TEST_NUM_TOTAL_PACKETS));
599 
600         /* Reset for next test. */
601         global_basic_test_num_reads_device = 0;
602         global_basic_test_num_writes_device = 0;
603     }
604 }
605 
thread_entry_host(ULONG device_init_data_ptr)606 static void thread_entry_host(ULONG device_init_data_ptr)
607 {
608 
609 DEVICE_INIT_DATA *device_init_data;
610 
611     UX_THREAD_EXTENSION_PTR_GET(device_init_data, DEVICE_INIT_DATA, device_init_data_ptr);
612 
613     /* Wait for device to initialize. */
614     UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&global_is_device_initialized, 1));
615 
616     /* Create the IP instance. */
617 
618     UX_TEST_CHECK_SUCCESS(nx_packet_pool_create(&packet_pool_host, "NetX Host Packet Pool", PACKET_PAYLOAD, packet_pool_memory_host, PACKET_POOL_SIZE));
619     UX_TEST_CHECK_SUCCESS(nx_packet_pool_create(&ip_pool_host, ip_pool_host_name, PACKET_PAYLOAD, packet_pool_memory_host+PACKET_POOL_SIZE, HOST_IP_POOL_SIZE));
620     UX_TEST_CHECK_SUCCESS(nx_ip_create(&nx_ip_host, "NetX Host Thread", HOST_IP_ADDRESS, 0xFF000000UL,
621                           &ip_pool_host, _ux_network_driver_entry, ip_thread_stack_host, DEMO_IP_THREAD_STACK_SIZE, 1));
622 
623     /* Setup ARP. */
624 
625     UX_TEST_CHECK_SUCCESS(nx_arp_enable(&nx_ip_host, (void *)arp_memory_host, ARP_MEMORY_SIZE));
626     UX_TEST_CHECK_SUCCESS(nx_arp_static_entry_create(&nx_ip_host, DEVICE_IP_ADDRESS, 0x0000001E, 0x80032CD8));
627 
628     /* Setup UDP. */
629 
630     UX_TEST_CHECK_SUCCESS(nx_udp_enable(&nx_ip_host));
631     UX_TEST_CHECK_SUCCESS(nx_udp_socket_create(&nx_ip_host, &udp_socket_host, "USB HOST UDP SOCKET", NX_IP_NORMAL, NX_DONT_FRAGMENT, 20, 20));
632     UX_TEST_CHECK_SUCCESS(nx_udp_socket_bind(&udp_socket_host, HOST_SOCKET_PORT_UDP, NX_NO_WAIT));
633 
634     /* Setup TCP. */
635 
636     UX_TEST_CHECK_SUCCESS(nx_tcp_enable(&nx_ip_host));
637     UX_TEST_CHECK_SUCCESS(nx_tcp_socket_create(&nx_ip_host, &tcp_socket_host, "USB HOST TCP SOCKET", NX_IP_NORMAL, NX_DONT_FRAGMENT, NX_IP_TIME_TO_LIVE, TCP_WINDOW, NX_NULL, NX_NULL));
638     UX_TEST_CHECK_SUCCESS(nx_tcp_server_socket_listen(&nx_ip_host, HOST_SOCKET_PORT_TCP, &tcp_socket_host, 5, NX_NULL));
639 
640     /* The code below is required for installing the host portion of USBX. */
641     UX_TEST_CHECK_SUCCESS(ux_host_stack_initialize(system_change_function));
642 
643     /* Register cdc_ecm class.  */
644     UX_TEST_CHECK_SUCCESS(ux_host_stack_class_register(_ux_system_host_class_cdc_ecm_name, ux_host_class_cdc_ecm_entry));
645 
646     if (!device_init_data->dont_register_hcd)
647     {
648 
649         /* Register all the USB host controllers available in this system. */
650         UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
651 
652         /* Find the storage class. */
653         class_cdc_ecm_get_host();
654 
655         if (!device_init_data->dont_connect_to_host)
656         {
657 
658             /* Connect to device TCP socket. */
659             UX_TEST_CHECK_SUCCESS(nx_tcp_server_socket_accept(&tcp_socket_host, NX_WAIT_FOREVER));
660         }
661     }
662     global_host_ready_for_application = 1;
663 
664     /* Call test code. */
665     post_init_host();
666 
667     /* We need to disconnect the host and device. This is because the NetX cleaning
668        process (in usbxtestcontrol.c) includes disconnect the device, which tries
669        to send a RST packet to the peer (or something). By disconnecting here,
670        we ensure the deactivate routines notify the network driver so that the
671        packet tranmissiong is stopped there. */
672     ux_test_disconnect_slave();
673     ux_test_disconnect_host_wait_for_enum_completion();
674 
675     /* And finally the usbx system resources.  */
676     _ux_system_uninitialize();
677 
678     /* Successful test.  */
679     printf("SUCCESS!\n");
680     test_control_return(0);
681 }
682 
thread_entry_device(ULONG device_init_data_ptr)683 static void thread_entry_device(ULONG device_init_data_ptr)
684 {
685 
686 DEVICE_INIT_DATA *device_init_data;
687 
688     UX_THREAD_EXTENSION_PTR_GET(device_init_data, DEVICE_INIT_DATA, device_init_data_ptr)
689 
690     /* Create the IP instance.  */
691 
692     UX_TEST_CHECK_SUCCESS(nx_packet_pool_create(&packet_pool_device, "NetX Device Packet Pool", PACKET_PAYLOAD, packet_pool_memory_device, PACKET_POOL_SIZE));
693     UX_TEST_CHECK_SUCCESS(nx_packet_pool_create(&ip_pool_device, "NetX Device IP Pool", PACKET_PAYLOAD, packet_pool_memory_device+PACKET_POOL_SIZE, DEVICE_IP_POOL_SIZE));
694 
695     UX_TEST_CHECK_SUCCESS(nx_ip_create(&nx_ip_device, "NetX Device Thread", DEVICE_IP_ADDRESS, 0xFF000000L, &ip_pool_device,
696                                        _ux_network_driver_entry, ip_thread_stack_device, DEMO_IP_THREAD_STACK_SIZE, 1));
697 
698     /* Setup ARP.  */
699 
700     UX_TEST_CHECK_SUCCESS(nx_arp_enable(&nx_ip_device, (void *)arp_memory_device, ARP_MEMORY_SIZE));
701     UX_TEST_CHECK_SUCCESS(nx_arp_static_entry_create(&nx_ip_device, HOST_IP_ADDRESS, 0x0000001E, 0x5841B878));
702 
703     /* Setup UDP.  */
704 
705     UX_TEST_CHECK_SUCCESS(nx_udp_enable(&nx_ip_device));
706     UX_TEST_CHECK_SUCCESS(nx_udp_socket_create(&nx_ip_device, &udp_socket_device, "USB DEVICE UDP SOCKET", NX_IP_NORMAL, NX_DONT_FRAGMENT, 20, 20));
707     UX_TEST_CHECK_SUCCESS(nx_udp_socket_bind(&udp_socket_device, DEVICE_SOCKET_PORT_UDP, NX_NO_WAIT));
708 
709     /* Setup TCP. */
710 
711     UX_TEST_CHECK_SUCCESS(nx_tcp_enable(&nx_ip_device));
712     UX_TEST_CHECK_SUCCESS(nx_tcp_socket_create(&nx_ip_device, &tcp_socket_device, "USB DEVICE TCP SOCKET", NX_IP_NORMAL, NX_DONT_FRAGMENT, NX_IP_TIME_TO_LIVE, 100, NX_NULL, NX_NULL));
713     UX_TEST_CHECK_SUCCESS(nx_tcp_client_socket_bind(&tcp_socket_device, DEVICE_SOCKET_PORT_TCP, NX_WAIT_FOREVER));
714 
715     /* The code below is required for installing the device portion of USBX.
716        In this demo, DFU is possible and we have a call back for state change. */
717     UX_TEST_CHECK_SUCCESS(ux_device_stack_initialize(device_init_data->framework, device_init_data->framework_length,
718                                                       device_init_data->framework, device_init_data->framework_length,
719                                                       device_init_data->string_framework, device_init_data->string_framework_length,
720                                                       language_id_framework, sizeof(language_id_framework),
721                                                       UX_NULL));
722 
723     /* Set the parameters for callback when insertion/extraction of a CDC device.  Set to NULL.*/
724     cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate   =  demo_cdc_ecm_instance_activate;
725     cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate =  demo_cdc_ecm_instance_deactivate;
726 
727     /* Define a NODE ID.  */
728     cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[0] = 0x00;
729     cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[1] = 0x1e;
730     cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[2] = 0x58;
731     cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[3] = 0x41;
732     cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[4] = 0xb8;
733     cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[5] = 0x78;
734 
735     /* Define a remote NODE ID.  */
736     cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[0] = 0x00;
737     cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[1] = 0x1e;
738     cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[2] = 0x58;
739     cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[3] = 0x41;
740     cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[4] = 0xb8;
741     cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[5] = 0x79;
742 
743     /* Initialize the device cdc_ecm class. */
744     UX_TEST_CHECK_SUCCESS(ux_device_stack_class_register(_ux_system_slave_class_cdc_ecm_name, ux_device_class_cdc_ecm_entry, 1, 0, &cdc_ecm_parameter));
745 
746     /* Initialize the simulated device controller.  */
747     UX_TEST_CHECK_SUCCESS(_ux_test_dcd_sim_slave_initialize());
748 
749     global_is_device_initialized = UX_TRUE;
750 
751     if (!device_init_data->dont_connect_to_host)
752     {
753 
754         if (!device_init_data->dont_register_hcd)
755         {
756 
757             UX_TEST_CHECK_SUCCESS(ux_test_wait_for_non_null((VOID **)&cdc_ecm_device));
758             UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_ulong(&cdc_ecm_device->ux_slave_class_cdc_ecm_link_state, UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP));
759 
760             /* Connect to host TCP socket. */
761             UX_TEST_CHECK_SUCCESS(nx_tcp_client_socket_connect(&tcp_socket_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_TCP, NX_WAIT_FOREVER));
762         }
763 
764         /* Wait for host - believe this is so that we know host is always first... gives us some 'determinism'. */
765         UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uchar(&global_host_ready_for_application, 1));
766     }
767 
768     /* Call test code. */
769     post_init_device();
770 }
771 
772 #endif