1 #include "ux_api.h"
2 #include "ux_system.h"
3 #include "ux_utility.h"
4 #include "ux_network_driver.h"
5 #include "ux_host_class_cdc_ecm.h"
6 #include "ux_device_class_rndis.h"
7 #include "ux_device_class_cdc_ecm.h"
8 #include "ux_test_dcd_sim_slave.h"
9 #include "ux_test_hcd_sim_host.h"
10 #include "ux_test_utility_sim.h"
11 #include "ux_test.h"
12 #include "ux_hcd_sim_host.h"
13 #include "ux_dcd_sim_slave.h"
14
15 #define DEMO_IP_THREAD_STACK_SIZE (8*1024)
16 #define HOST_IP_ADDRESS IP_ADDRESS(192,168,1,176)
17 #define HOST_SOCKET_PORT_UDP 45054
18 #define DEVICE_IP_ADDRESS IP_ADDRESS(192,168,1,175)
19 #define DEVICE_SOCKET_PORT_UDP 45055
20
21 #define PACKET_PAYLOAD 1400
22 #define PACKET_POOL_SIZE (PACKET_PAYLOAD*10000)
23 #define ARP_MEMORY_SIZE 1024
24
25 /* Define local constants. */
26
27 #define UX_DEMO_STACK_SIZE (4*1024)
28 #define UX_USBX_MEMORY_SIZE (128*1024)
29
30 /* Host */
31
32 static UX_HOST_CLASS *class_driver_host;
33 static UX_HOST_CLASS_CDC_ECM *cdc_ecm_host;
34 static UX_HOST_CLASS_CDC_ECM **cdc_ecm_host_ptr;
35 static TX_THREAD thread_host;
36 static UCHAR thread_stack_host[UX_DEMO_STACK_SIZE];
37 static NX_IP nx_ip_host;
38 static NX_PACKET_POOL packet_pool_host;
39 static NX_UDP_SOCKET udp_socket_host;
40 static CHAR *packet_pool_memory_host;
41 static CHAR ip_thread_stack_host[DEMO_IP_THREAD_STACK_SIZE];
42 static CHAR arp_memory_host[ARP_MEMORY_SIZE];
43
44 /* Device */
45
46 static TX_THREAD thread_device;
47 static UX_HOST_CLASS *class_driver_device;
48 static UX_SLAVE_CLASS_RNDIS *rndis_device;
49 static UX_SLAVE_CLASS_RNDIS_PARAMETER rndis_parameter;
50 static UCHAR thread_stack_device[UX_DEMO_STACK_SIZE];
51 static NX_IP nx_ip_device;
52 static NX_PACKET_POOL packet_pool_device;
53 static NX_UDP_SOCKET udp_socket_device;
54 static CHAR *packet_pool_memory_device;
55 static CHAR ip_thread_stack_device[DEMO_IP_THREAD_STACK_SIZE];
56 static CHAR arp_memory_device[ARP_MEMORY_SIZE];
57
58 static UCHAR global_is_device_initialized;
59
60 static ULONG global_basic_test_num_writes_host;
61 static ULONG global_basic_test_num_reads_host;
62
63 static ULONG global_basic_test_num_writes_device;
64 static ULONG global_basic_test_num_reads_device;
65
66 /* Define local prototypes and definitions. */
67 static void thread_entry_host(ULONG arg);
68 static void thread_entry_device(ULONG arg);
69
70 //#define USE_ZERO_ENDPOINT_SETTING
71
72 static unsigned char device_framework_high_speed[] = {
73
74 /* Device Descriptor */
75 0x12, /* bLength */
76 0x01, /* bDescriptorType */
77 0x10, 0x01, /* bcdUSB */
78 0xef, /* bDeviceClass - Depends on bDeviceSubClass */
79 0x02, /* bDeviceSubClass - Depends on bDeviceProtocol */
80 0x01, /* bDeviceProtocol - There's an IAD */
81 0x40, /* bMaxPacketSize0 */
82 0x70, 0x07, /* idVendor */
83 0x42, 0x10, /* idProduct */
84 0x00, 0x01, /* bcdDevice */
85 0x01, /* iManufacturer */
86 0x02, /* iProduct */
87 0x03, /* iSerialNumber */
88 0x01, /* bNumConfigurations */
89
90 /* Configuration Descriptor */
91 0x09, /* bLength */
92 0x02, /* bDescriptorType */
93
94 #ifdef USE_ZERO_ENDPOINT_SETTING
95 0x58, 0x00, /* wTotalLength */
96 #else
97 0x4f, 0x00, /* wTotalLength */
98 #endif
99 0x02, /* bNumInterfaces */
100 0x01, /* bConfigurationValue */
101 0x00, /* iConfiguration */
102 0xc0, /* bmAttributes - Self-powered */
103 0x00, /* bMaxPower */
104
105 /* Interface Association Descriptor */
106 0x08, /* bLength */
107 0x0b, /* bDescriptorType */
108 0x00, /* bFirstInterface */
109 0x02, /* bInterfaceCount */
110 0x02, /* bFunctionClass - CDC - Communication */
111 0x06, /* bFunctionSubClass - ECM */
112 0x00, /* bFunctionProtocol - No class specific protocol required */
113 0x00, /* iFunction */
114
115 /* Interface Descriptor */
116 0x09, /* bLength */
117 0x04, /* bDescriptorType */
118 0x00, /* bInterfaceNumber */
119 0x00, /* bAlternateSetting */
120 0x01, /* bNumEndpoints */
121 0x02, /* bInterfaceClass - CDC - Communication */
122 0x06, /* bInterfaceSubClass - ECM */
123 0x00, /* bInterfaceProtocol - No class specific protocol required */
124 0x00, /* iInterface */
125
126 /* CDC Header Functional Descriptor */
127 0x05, /* bLength */
128 0x24, /* bDescriptorType */
129 0x00, /* bDescriptorSubType */
130 0x10, 0x01, /* bcdCDC */
131
132 /* CDC ECM Functional Descriptor */
133 0x0d, /* bLength */
134 0x24, /* bDescriptorType */
135 0x0f, /* bDescriptorSubType */
136 0x04, /* iMACAddress */
137 0x00, 0x00, 0x00, 0x00, /* bmEthernetStatistics */
138 0xea, 0x05, /* wMaxSegmentSize */
139 0x00, 0x00, /* wNumberMCFilters */
140 0x00, /* bNumberPowerFilters */
141
142 /* CDC Union Functional Descriptor */
143 0x05, /* bLength */
144 0x24, /* bDescriptorType */
145 0x06, /* bDescriptorSubType */
146 0x00, /* bmMasterInterface */
147 0x01, /* bmSlaveInterface0 */
148
149 /* Endpoint Descriptor */
150 0x07, /* bLength */
151 0x05, /* bDescriptorType */
152 0x83, /* bEndpointAddress */
153 0x03, /* bmAttributes - Interrupt */
154 0x08, 0x00, /* wMaxPacketSize */
155 0x08, /* bInterval */
156
157 #ifdef USE_ZERO_ENDPOINT_SETTING
158 /* Interface Descriptor */
159 0x09, /* bLength */
160 0x04, /* bDescriptorType */
161 0x01, /* bInterfaceNumber */
162 0x00, /* bAlternateSetting */
163 0x00, /* bNumEndpoints */
164 0x0a, /* bInterfaceClass - CDC - Data */
165 0x00, /* bInterfaceSubClass - Should be 0x00 */
166 0x00, /* bInterfaceProtocol - No class specific protocol required */
167 0x00, /* iInterface */
168
169 /* Interface Descriptor */
170 0x09, /* bLength */
171 0x04, /* bDescriptorType */
172 0x01, /* bInterfaceNumber */
173 0x01, /* bAlternateSetting */
174 0x02, /* bNumEndpoints */
175 0x0a, /* bInterfaceClass - CDC - Data */
176 0x00, /* bInterfaceSubClass - Should be 0x00 */
177 0x00, /* bInterfaceProtocol - No class specific protocol required */
178 0x00, /* iInterface */
179 #else
180 /* Interface Descriptor */
181 0x09, /* bLength */
182 0x04, /* bDescriptorType */
183 0x01, /* bInterfaceNumber */
184 0x00, /* bAlternateSetting */
185 0x02, /* bNumEndpoints */
186 0x0a, /* bInterfaceClass - CDC - Data */
187 0x00, /* bInterfaceSubClass - Should be 0x00 */
188 0x00, /* bInterfaceProtocol - No class specific protocol required */
189 0x00, /* iInterface */
190 #endif
191
192 /* Endpoint Descriptor */
193 0x07, /* bLength */
194 0x05, /* bDescriptorType */
195 0x02, /* bEndpointAddress */
196 0x02, /* bmAttributes - Bulk */
197 0x40, 0x00, /* wMaxPacketSize */
198 0x00, /* bInterval */
199
200 /* Endpoint Descriptor */
201 0x07, /* bLength */
202 0x05, /* bDescriptorType */
203 0x81, /* bEndpointAddress */
204 0x02, /* bmAttributes - Bulk */
205 0x40, 0x00, /* wMaxPacketSize */
206 0x00, /* bInterval */
207
208 };
209
210 static unsigned char string_framework[] = {
211
212 /* Manufacturer string descriptor : Index 1 - "Express Logic" */
213 0x09, 0x04, 0x01, 0x0c,
214 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x20, 0x4c,
215 0x6f, 0x67, 0x69, 0x63,
216
217 /* Product string descriptor : Index 2 - "EL CDCECM Device" */
218 0x09, 0x04, 0x02, 0x10,
219 0x45, 0x4c, 0x20, 0x43, 0x44, 0x43, 0x45, 0x43,
220 0x4d, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
221
222 /* Serial Number string descriptor : Index 3 - "0001" */
223 0x09, 0x04, 0x03, 0x04,
224 0x30, 0x30, 0x30, 0x31,
225
226 /* MAC Address string descriptor : Index 4 - "001E5841B879" */
227 0x09, 0x04, 0x04, 0x0C,
228 0x30, 0x30, 0x31, 0x45, 0x35, 0x38,
229 0x34, 0x31, 0x42, 0x38, 0x37, 0x39,
230
231 };
232
233 static unsigned char *device_framework_full_speed = device_framework_high_speed;
234 #define FRAMEWORK_LENGTH sizeof(device_framework_high_speed)
235
236 /* Multiple languages are supported on the device, to add
237 a language besides english, the unicode language code must
238 be appended to the language_id_framework array and the length
239 adjusted accordingly. */
240 static unsigned char language_id_framework[] = {
241
242 /* English. */
243 0x09, 0x04
244 };
245
246 /* Define local variables. */
247
class_cdc_ecm_get_host(void)248 static UINT class_cdc_ecm_get_host(void)
249 {
250
251 UX_HOST_CLASS *class;
252 UINT status;
253
254 /* Find the main storage container */
255 status = ux_host_stack_class_get(_ux_system_host_class_cdc_ecm_name, &class);
256 if (status != UX_SUCCESS)
257 test_control_return(0);
258
259 /* We get the first instance of the storage device */
260 do
261 {
262 status = ux_host_stack_class_instance_get(class, 0, (void **) &cdc_ecm_host);
263 tx_thread_sleep(10);
264 } while (status != UX_SUCCESS);
265
266 /* We still need to wait for the cdc-ecm status to be live */
267 while (cdc_ecm_host -> ux_host_class_cdc_ecm_state != UX_HOST_CLASS_INSTANCE_LIVE)
268 tx_thread_sleep(10);
269
270 return(UX_SUCCESS);
271 }
272
demo_rndis_instance_activate(VOID * rndis_instance)273 static VOID demo_rndis_instance_activate(VOID *rndis_instance)
274 {
275
276 /* Save the CDC instance. */
277 rndis_device = (UX_SLAVE_CLASS_RNDIS *) rndis_instance;
278 }
279
demo_rndis_instance_deactivate(VOID * rndis_instance)280 static VOID demo_rndis_instance_deactivate(VOID *rndis_instance)
281 {
282
283 /* Reset the CDC instance. */
284 rndis_device = UX_NULL;
285 }
286
read_packet_udp(NX_UDP_SOCKET * udp_socket,ULONG num_reads,CHAR * name)287 static void read_packet_udp(NX_UDP_SOCKET *udp_socket, ULONG num_reads, CHAR *name)
288 {
289
290 NX_PACKET *rcv_packet;
291 ULONG num_writes_from_peer;
292
293 #ifndef LOCAL_MACHINE
294 if (num_reads % 100 == 0)
295 #endif
296 stepinfo("%s reading packet# %lu\n", name, num_reads);
297
298 UX_TEST_CHECK_SUCCESS(nx_udp_socket_receive(udp_socket, &rcv_packet, NX_WAIT_FOREVER));
299
300 num_writes_from_peer = *(ULONG *)rcv_packet->nx_packet_prepend_ptr;
301 if (num_writes_from_peer != num_reads)
302 test_control_return(0);
303
304 UX_TEST_CHECK_SUCCESS(nx_packet_release(rcv_packet));
305 }
306
write_packet_udp(NX_UDP_SOCKET * udp_socket,NX_PACKET_POOL * packet_pool,ULONG ip_address,ULONG port,ULONG num_writes,CHAR * name)307 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)
308 {
309
310 NX_PACKET *out_packet;
311
312 UX_TEST_CHECK_SUCCESS(nx_packet_allocate(packet_pool, &out_packet, NX_UDP_PACKET, MS_TO_TICK(1000)));
313
314 *(ULONG *)out_packet->nx_packet_prepend_ptr = num_writes;
315 out_packet->nx_packet_length = sizeof(ULONG);
316 out_packet->nx_packet_append_ptr = out_packet->nx_packet_prepend_ptr + out_packet->nx_packet_length;
317
318 #ifndef LOCAL_MACHINE
319 if (num_writes % 100 == 0)
320 #endif
321 stepinfo("%s writing packet# %lu\n", name, num_writes);
322
323 UX_TEST_CHECK_SUCCESS(nx_udp_socket_send(udp_socket, out_packet, ip_address, port));
324 }
325
326 /* Define what the initial system looks like. */
327 #ifdef CTEST
test_application_define(void * first_unused_memory)328 void test_application_define(void *first_unused_memory)
329 #else
330 void usbx_rndis_basic_test_application_define(void *first_unused_memory)
331 #endif
332 {
333
334 CHAR *memory_pointer = first_unused_memory;
335
336 /* Inform user. */
337 printf("Running RNDIS Basic Functionality Test.............................. ");
338
339 stepinfo("\n");
340
341 /* Initialize USBX Memory. */
342 UX_TEST_CHECK_SUCCESS(ux_system_initialize(memory_pointer, UX_USBX_MEMORY_SIZE, UX_NULL, 0));
343 memory_pointer += UX_USBX_MEMORY_SIZE;
344
345 /* It looks weird if this doesn't have a comment! */
346 ux_utility_error_callback_register(ux_test_error_callback);
347
348 /* Perform the initialization of the network driver. */
349 UX_TEST_CHECK_SUCCESS(ux_network_driver_init());
350
351 /* Initialize the NetX system. */
352 nx_system_initialize();
353
354 /* Now allocate memory for the packet pools. Note that using the memory passed
355 to us by ThreadX is mucho bettero than putting it in global memory because
356 we can reuse the memory for each test. So no more having to worry about
357 running out of memory! */
358 packet_pool_memory_host = memory_pointer;
359 memory_pointer += PACKET_POOL_SIZE;
360 packet_pool_memory_device = memory_pointer;
361 memory_pointer += PACKET_POOL_SIZE;
362
363 /* Create the host thread. */
364 UX_TEST_CHECK_SUCCESS(tx_thread_create(&thread_host, "host thread", thread_entry_host, 0,
365 thread_stack_host, UX_DEMO_STACK_SIZE,
366 30, 30, 1, TX_AUTO_START));
367
368 /* Create the slave thread. */
369 UX_TEST_CHECK_SUCCESS(tx_thread_create(&thread_device, "device thread", thread_entry_device, 0,
370 thread_stack_device, UX_DEMO_STACK_SIZE,
371 30, 30, 1, TX_AUTO_START));
372 }
373
374 /* Needs to be large enough to hold NetX packet data and RNDIS header. */
375 static UCHAR host_bulk_endpoint_transfer_data[16*1024];
376
my_ux_hcd_sim_host_entry(UX_HCD * hcd,UINT function,VOID * parameter)377 static UINT my_ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter)
378 {
379
380 UX_TRANSFER *transfer_request;
381 UX_ENDPOINT *endpoint;
382
383
384 if (function == UX_HCD_TRANSFER_REQUEST)
385 {
386
387 transfer_request = parameter;
388 endpoint = transfer_request->ux_transfer_request_endpoint;
389
390 /* Bulk out? */
391 if ((endpoint->ux_endpoint_descriptor.bmAttributes == 0x02) &&
392 (endpoint->ux_endpoint_descriptor.bEndpointAddress & 0x80) == 0)
393 {
394
395 UX_TEST_ASSERT(transfer_request->ux_transfer_request_requested_length + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH <= sizeof(host_bulk_endpoint_transfer_data));
396
397 /* Fix it, now! - we need to add the RNDIS header. */
398
399 /* Copy that packet payload. */
400 memcpy(host_bulk_endpoint_transfer_data + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH,
401 transfer_request->ux_transfer_request_data_pointer,
402 transfer_request->ux_transfer_request_requested_length);
403
404 /* Add the RNDIS header to this packet. */
405
406 _ux_utility_long_put(host_bulk_endpoint_transfer_data + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_TYPE, UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_MSG);
407
408 _ux_utility_long_put(host_bulk_endpoint_transfer_data + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_LENGTH,
409 transfer_request->ux_transfer_request_requested_length + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH);
410
411 _ux_utility_long_put(host_bulk_endpoint_transfer_data + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_OFFSET,
412 UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH - UX_DEVICE_CLASS_RNDIS_PACKET_DATA_OFFSET);
413
414 _ux_utility_long_put(host_bulk_endpoint_transfer_data + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_LENGTH,
415 transfer_request->ux_transfer_request_requested_length);
416
417 /* The original data pointer points to the packet, so no leak. We also
418 only allow one transfer at a time, so no worries with overriding data. */
419 transfer_request->ux_transfer_request_data_pointer = host_bulk_endpoint_transfer_data;
420 transfer_request->ux_transfer_request_requested_length += UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH;
421 }
422 }
423
424 return _ux_hcd_sim_host_entry(hcd, function, parameter);
425 }
426
my_ux_dcd_sim_slave_function(UX_SLAVE_DCD * dcd,UINT function,VOID * parameter)427 static UINT my_ux_dcd_sim_slave_function(UX_SLAVE_DCD *dcd, UINT function, VOID *parameter)
428 {
429
430 UX_SLAVE_TRANSFER *transfer_request;
431 UX_SLAVE_ENDPOINT *endpoint;
432 UINT netx_packet_length;
433 UINT i;
434
435
436 if (function == UX_HCD_TRANSFER_REQUEST)
437 {
438
439 transfer_request = parameter;
440 endpoint = transfer_request->ux_slave_transfer_request_endpoint;
441
442 /* Bulk in? */
443 if ((endpoint->ux_slave_endpoint_descriptor.bmAttributes == 0x02) &&
444 (endpoint->ux_slave_endpoint_descriptor.bEndpointAddress & 0x80) != 0)
445 {
446
447 /* Fix it, now! - we need to remove the RNDIS header. */
448
449 netx_packet_length = transfer_request->ux_slave_transfer_request_requested_length - UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH;
450
451 /* Just shift the packet over the RNDIS header. */
452 for (i = 0; i < netx_packet_length; i++)
453 {
454
455 transfer_request->ux_slave_transfer_request_data_pointer[i] = transfer_request->ux_slave_transfer_request_data_pointer[i + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH];
456 }
457
458 transfer_request->ux_slave_transfer_request_requested_length = netx_packet_length;
459 }
460 }
461
462 return _ux_dcd_sim_slave_function(dcd, function, parameter);
463 }
464
thread_entry_host(ULONG input)465 static void thread_entry_host(ULONG input)
466 {
467
468 UINT i;
469 UINT num_iters;
470
471 /* Wait for device to initialize before starting the HCD thread; also, there
472 seems to be some race condition with simultaneous NetX initialization:
473 somehow, device was calling the host CDC-ECM write. */
474 while (!global_is_device_initialized)
475 tx_thread_sleep(10);
476
477 /* Wait for device to initialize. */
478 while (!global_is_device_initialized)
479 tx_thread_sleep(10);
480
481 /* Create the IP instance. */
482
483 UX_TEST_CHECK_SUCCESS(nx_packet_pool_create(&packet_pool_host, "NetX Host Packet Pool", PACKET_PAYLOAD, packet_pool_memory_host, PACKET_POOL_SIZE));
484 UX_TEST_CHECK_SUCCESS(nx_ip_create(&nx_ip_host, "NetX Host Thread", HOST_IP_ADDRESS, 0xFF000000UL,
485 &packet_pool_host, _ux_network_driver_entry, ip_thread_stack_host, DEMO_IP_THREAD_STACK_SIZE, 1));
486
487 /* Setup ARP. */
488
489 UX_TEST_CHECK_SUCCESS(nx_arp_enable(&nx_ip_host, (void *)arp_memory_host, ARP_MEMORY_SIZE));
490 UX_TEST_CHECK_SUCCESS(nx_arp_static_entry_create(&nx_ip_host, DEVICE_IP_ADDRESS, 0x0000001E, 0x80032CD8));
491
492 /* Setup UDP. */
493
494 UX_TEST_CHECK_SUCCESS(nx_udp_enable(&nx_ip_host));
495 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));
496 UX_TEST_CHECK_SUCCESS(nx_udp_socket_bind(&udp_socket_host, HOST_SOCKET_PORT_UDP, NX_NO_WAIT));
497
498 /* The code below is required for installing the host portion of USBX. */
499 UX_TEST_CHECK_SUCCESS(ux_host_stack_initialize(UX_NULL));
500
501 /* Register cdc_ecm class. */
502 UX_TEST_CHECK_SUCCESS(ux_host_stack_class_register(_ux_system_host_class_cdc_ecm_name, ux_host_class_cdc_ecm_entry));
503
504 ux_test_ignore_all_errors();
505
506 /* Register all the USB host controllers available in this system. */
507 UX_TEST_CHECK_SUCCESS(ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize, 0, 0));
508
509 /* Change entry function. */
510 _ux_system_host->ux_system_host_hcd_array[0].ux_hcd_entry_function = my_ux_hcd_sim_host_entry;
511
512 /* Find the storage class. */
513 class_cdc_ecm_get_host();
514
515 /* Now wait for the link to be up. */
516 while (cdc_ecm_host -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP)
517 tx_thread_sleep(10);
518
519 for (num_iters = 0; num_iters < 100; num_iters++)
520 {
521
522 for (i = 0; i < 10; i++)
523 write_packet_udp(&udp_socket_host, &packet_pool_host, DEVICE_IP_ADDRESS, DEVICE_SOCKET_PORT_UDP, global_basic_test_num_writes_host++, "host");
524
525 for (i = 0; i < 10; i++)
526 read_packet_udp(&udp_socket_host, global_basic_test_num_reads_host++, "host");
527 }
528
529 /* Wait for all transfers to complete. */
530 while (global_basic_test_num_reads_host != 1000 || global_basic_test_num_reads_device != 1000)
531 tx_thread_sleep(10);
532
533 /* And finally the usbx system resources. */
534 _ux_system_uninitialize();
535
536 /* Successful test. */
537 printf("SUCCESS!\n");
538 test_control_return(0);
539 }
540
thread_entry_device(ULONG input)541 static void thread_entry_device(ULONG input)
542 {
543
544 UINT i;
545 UINT status;
546 UINT num_iters;
547 UCHAR *notification_buffer;
548 UX_SLAVE_TRANSFER *interrupt_transfer;
549
550 /* Create the IP instance. */
551
552 UX_TEST_CHECK_SUCCESS(nx_packet_pool_create(&packet_pool_device, "NetX Device Packet Pool", PACKET_PAYLOAD, packet_pool_memory_device, PACKET_POOL_SIZE));
553
554 UX_TEST_CHECK_SUCCESS(nx_ip_create(&nx_ip_device, "NetX Device Thread", DEVICE_IP_ADDRESS, 0xFF000000L, &packet_pool_device,
555 _ux_network_driver_entry, ip_thread_stack_device, DEMO_IP_THREAD_STACK_SIZE, 1));
556
557 /* Setup ARP. */
558
559 UX_TEST_CHECK_SUCCESS(nx_arp_enable(&nx_ip_device, (void *)arp_memory_device, ARP_MEMORY_SIZE));
560 UX_TEST_CHECK_SUCCESS(nx_arp_static_entry_create(&nx_ip_device, HOST_IP_ADDRESS, 0x0000001E, 0x5841B878));
561
562 /* Setup UDP. */
563
564 UX_TEST_CHECK_SUCCESS(nx_udp_enable(&nx_ip_device));
565 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));
566 UX_TEST_CHECK_SUCCESS(nx_udp_socket_bind(&udp_socket_device, DEVICE_SOCKET_PORT_UDP, NX_NO_WAIT));
567
568 /* The code below is required for installing the device portion of USBX. */
569 status = ux_device_stack_initialize(device_framework_high_speed, FRAMEWORK_LENGTH,
570 device_framework_full_speed, FRAMEWORK_LENGTH,
571 string_framework, sizeof(string_framework),
572 language_id_framework, sizeof(language_id_framework),
573 UX_NULL);
574 if (status)
575 test_control_return(0);
576
577 /* Set the parameters for callback when insertion/extraction of a CDC device. */
578 rndis_parameter.ux_slave_class_rndis_instance_activate = demo_rndis_instance_activate;
579 rndis_parameter.ux_slave_class_rndis_instance_deactivate = demo_rndis_instance_deactivate;
580
581 /* Define a local NODE ID. */
582 rndis_parameter.ux_slave_class_rndis_parameter_local_node_id[0] = 0x00;
583 rndis_parameter.ux_slave_class_rndis_parameter_local_node_id[1] = 0x1e;
584 rndis_parameter.ux_slave_class_rndis_parameter_local_node_id[2] = 0x58;
585 rndis_parameter.ux_slave_class_rndis_parameter_local_node_id[3] = 0x41;
586 rndis_parameter.ux_slave_class_rndis_parameter_local_node_id[4] = 0xb8;
587 rndis_parameter.ux_slave_class_rndis_parameter_local_node_id[5] = 0x78;
588
589 /* Define a remote NODE ID. */
590 rndis_parameter.ux_slave_class_rndis_parameter_remote_node_id[0] = 0x00;
591 rndis_parameter.ux_slave_class_rndis_parameter_remote_node_id[1] = 0x1e;
592 rndis_parameter.ux_slave_class_rndis_parameter_remote_node_id[2] = 0x58;
593 rndis_parameter.ux_slave_class_rndis_parameter_remote_node_id[3] = 0x41;
594 rndis_parameter.ux_slave_class_rndis_parameter_remote_node_id[4] = 0xb8;
595 rndis_parameter.ux_slave_class_rndis_parameter_remote_node_id[5] = 0x79;
596
597 /* Set extra parameters used by the RNDIS query command with certain OIDs. */
598 rndis_parameter.ux_slave_class_rndis_parameter_vendor_id = 0x04b4 ;
599 rndis_parameter.ux_slave_class_rndis_parameter_driver_version = 0x1127;
600 ux_utility_memory_copy(rndis_parameter.ux_slave_class_rndis_parameter_vendor_description, "ELOGIC RNDIS", 12);
601
602 /* Initialize the device rndis class. This class owns both interfaces. */
603 status = ux_device_stack_class_register(_ux_system_slave_class_rndis_name, ux_device_class_rndis_entry, 1, 0, &rndis_parameter);
604 if (status)
605 test_control_return(0);
606
607 /* Initialize the simulated device controller. */
608 status = _ux_dcd_sim_slave_initialize();
609 if (status)
610 test_control_return(0);
611
612 _ux_system_slave->ux_system_slave_dcd.ux_slave_dcd_function = my_ux_dcd_sim_slave_function;
613
614 global_is_device_initialized = UX_TRUE;
615
616 while (!rndis_device)
617 tx_thread_sleep(10);
618
619 while (rndis_device -> ux_slave_class_rndis_link_state != UX_DEVICE_CLASS_RNDIS_LINK_STATE_UP)
620 tx_thread_sleep(10);
621
622 /* Since host is CDC-ECM, it's waiting for the LINK_UP notification from the
623 interrupt endpoint. RNDIS does not send this, so we have to do it manually. */
624 {
625 interrupt_transfer = &rndis_device->ux_slave_class_rndis_interrupt_endpoint->ux_slave_endpoint_transfer_request;
626
627 /* Build the Network Notification response. */
628 notification_buffer = interrupt_transfer->ux_slave_transfer_request_data_pointer;
629
630 /* Set the request type. */
631 *(notification_buffer + UX_SETUP_REQUEST_TYPE) = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
632
633 /* Set the request itself. */
634 *(notification_buffer + UX_SETUP_REQUEST) = 0;
635
636 /* Set the value. It is the network link. */
637 _ux_utility_short_put(notification_buffer + UX_SETUP_VALUE, (USHORT)(rndis_device->ux_slave_class_rndis_link_state));
638
639 /* Set the Index. It is interface. The interface used is the DATA interface. Here we simply take the interface number of the CONTROL and add 1 to it
640 as it is assumed the classes are contiguous in number. */
641 _ux_utility_short_put(notification_buffer + UX_SETUP_INDEX, (USHORT)(rndis_device->ux_slave_class_rndis_interface->ux_slave_interface_descriptor.bInterfaceNumber + 1));
642
643 /* And the length is zero. */
644 *(notification_buffer + UX_SETUP_LENGTH) = 0;
645
646 /* Send the request to the device controller. */
647 status = _ux_device_stack_transfer_request(interrupt_transfer, UX_DEVICE_CLASS_CDC_ECM_INTERRUPT_RESPONSE_LENGTH,
648 UX_DEVICE_CLASS_CDC_ECM_INTERRUPT_RESPONSE_LENGTH);
649 /* Check error code. */
650 if (status != UX_SUCCESS)
651 test_control_return(0);
652 }
653
654 for (num_iters = 0; num_iters < 100; num_iters++)
655 {
656
657 for (i = 0; i < 10; i++)
658 write_packet_udp(&udp_socket_device, &packet_pool_device, HOST_IP_ADDRESS, HOST_SOCKET_PORT_UDP, global_basic_test_num_writes_device++, "device");
659
660 for (i = 0; i < 10; i++)
661 read_packet_udp(&udp_socket_device, global_basic_test_num_reads_device++, "device");
662 }
663 }