1 /* Include necessary system files. */
2
3 #include "ux_api.h"
4 #include "ux_system.h"
5 #include "ux_utility.h"
6 #include "ux_network_driver.h"
7 #include "ux_host_class_cdc_ecm.h"
8 #include "ux_device_class_cdc_ecm.h"
9 #include "ux_test_dcd_sim_slave.h"
10 #include "ux_test_hcd_sim_host.h"
11 #include "ux_test_utility_sim.h"
12 #include "ux_test.h"
13
14 #define DEMO_IP_THREAD_STACK_SIZE (8*1024)
15 #define HOST_IP_ADDRESS IP_ADDRESS(192,168,1,176)
16 #define HOST_SOCKET_PORT_UDP 45054
17 #define DEVICE_IP_ADDRESS IP_ADDRESS(192,168,1,175)
18 #define DEVICE_SOCKET_PORT_UDP 45055
19
20 #define PACKET_PAYLOAD 1400
21 #define PACKET_POOL_SIZE (PACKET_PAYLOAD*20)
22 #define ARP_MEMORY_SIZE 1024
23
24 /* Define local constants. */
25
26 #define UX_DEMO_STACK_SIZE (4*1024)
27 #define UX_USBX_MEMORY_SIZE (128*1024)
28
29 /* Host */
30
31 static CHAR global_buffer_write_host[128];
32 static CHAR global_buffer_read_host[128];
33 static ULONG global_basic_test_num_writes_host;
34 static ULONG global_basic_test_num_reads_host;
35 static UX_HOST_CLASS *class_driver_host;
36 static UX_HOST_CLASS_CDC_ECM *cdc_ecm_host;
37 static TX_THREAD thread_host;
38 static UCHAR thread_stack_host[UX_DEMO_STACK_SIZE];
39 static NX_IP nx_ip_host;
40
41 /* Device */
42
43 static CHAR global_buffer_write_device[128];
44 static CHAR global_buffer_read_device[128];
45 static ULONG global_basic_test_num_writes_device;
46 static ULONG global_basic_test_num_reads_device;
47 static TX_THREAD thread_device;
48 static UX_HOST_CLASS *class_driver_device;
49 static UX_SLAVE_CLASS_CDC_ECM *cdc_ecm_device;
50 static UX_SLAVE_CLASS_CDC_ECM_PARAMETER cdc_ecm_parameter;
51 static UCHAR thread_stack_device[UX_DEMO_STACK_SIZE];
52 static NX_IP nx_ip_device;
53
54 /* Define local prototypes and definitions. */
55 static void thread_entry_host(ULONG arg);
56 static void thread_entry_device(ULONG arg);
57
58 static UCHAR usbx_memory[UX_USBX_MEMORY_SIZE];
59
60 static unsigned char device_framework_high_speed[] = {
61
62 /* Device Descriptor */
63 0x12, /* bLength */
64 0x01, /* bDescriptorType */
65 0x10, 0x01, /* bcdUSB */
66 0xef, /* bDeviceClass - Depends on bDeviceSubClass */
67 0x02, /* bDeviceSubClass - Depends on bDeviceProtocol */
68 0x01, /* bDeviceProtocol - There's an IAD */
69 0x40, /* bMaxPacketSize0 */
70 0x70, 0x07, /* idVendor */
71 0x42, 0x10, /* idProduct */
72 0x00, 0x01, /* bcdDevice */
73 0x01, /* iManufacturer */
74 0x02, /* iProduct */
75 0x03, /* iSerialNumber */
76 0x01, /* bNumConfigurations */
77
78 /* Configuration Descriptor */
79 0x09, /* bLength */
80 0x02, /* bDescriptorType */
81
82 0x58, 0x00, /* wTotalLength */
83 0x02, /* bNumInterfaces */
84 0x01, /* bConfigurationValue */
85 0x00, /* iConfiguration */
86 0xc0, /* bmAttributes - Self-powered */
87 0x00, /* bMaxPower */
88
89 /* Interface Association Descriptor */
90 0x08, /* bLength */
91 0x0b, /* bDescriptorType */
92 0x00, /* bFirstInterface */
93 0x02, /* bInterfaceCount */
94 0x02, /* bFunctionClass - CDC - Communication */
95 0x06, /* bFunctionSubClass - ECM */
96 0x00, /* bFunctionProtocol - No class specific protocol required */
97 0x00, /* iFunction */
98
99 /* Interface Descriptor */
100 0x09, /* bLength */
101 0x04, /* bDescriptorType */
102 0x00, /* bInterfaceNumber */
103 0x00, /* bAlternateSetting */
104 0x01, /* bNumEndpoints */
105 0x02, /* bInterfaceClass - CDC - Communication */
106 0x06, /* bInterfaceSubClass - ECM */
107 0x00, /* bInterfaceProtocol - No class specific protocol required */
108 0x00, /* iInterface */
109
110 /* CDC Header Functional Descriptor */
111 0x05, /* bLength */
112 0x24, /* bDescriptorType */
113 0x00, /* bDescriptorSubType */
114 0x10, 0x01, /* bcdCDC */
115
116 /* CDC ECM Functional Descriptor */
117 0x0d, /* bLength */
118 0x24, /* bDescriptorType */
119 0x0f, /* bDescriptorSubType */
120 0x04, /* iMACAddress */
121 0x00, 0x00, 0x00, 0x00, /* bmEthernetStatistics */
122 0xea, 0x05, /* wMaxSegmentSize */
123 0x00, 0x00, /* wNumberMCFilters */
124 0x00, /* bNumberPowerFilters */
125
126 /* CDC Union Functional Descriptor */
127 0x05, /* bLength */
128 0x24, /* bDescriptorType */
129 0x06, /* bDescriptorSubType */
130 0x00, /* bmMasterInterface */
131 0x01, /* bmSlaveInterface0 */
132
133 /* Endpoint Descriptor */
134 0x07, /* bLength */
135 0x05, /* bDescriptorType */
136 0x83, /* bEndpointAddress */
137 0x03, /* bmAttributes - Interrupt */
138 0x08, 0x00, /* wMaxPacketSize */
139 0x08, /* bInterval */
140
141 /* Interface Descriptor */
142 0x09, /* bLength */
143 0x04, /* bDescriptorType */
144 0x01, /* bInterfaceNumber */
145 0x00, /* bAlternateSetting */
146 0x00, /* bNumEndpoints */
147 0x0a, /* bInterfaceClass - CDC - Data */
148 0x00, /* bInterfaceSubClass - Should be 0x00 */
149 0x00, /* bInterfaceProtocol - No class specific protocol required */
150 0x00, /* iInterface */
151
152 /* Interface Descriptor */
153 0x09, /* bLength */
154 0x04, /* bDescriptorType */
155 0x01, /* bInterfaceNumber */
156 0x01, /* bAlternateSetting */
157 0x02, /* bNumEndpoints */
158 0x0a, /* bInterfaceClass - CDC - Data */
159 0x00, /* bInterfaceSubClass - Should be 0x00 */
160 0x00, /* bInterfaceProtocol - No class specific protocol required */
161 0x00, /* iInterface */
162
163 /* Endpoint Descriptor */
164 0x07, /* bLength */
165 0x05, /* bDescriptorType */
166 0x02, /* bEndpointAddress */
167 0x02, /* bmAttributes - Bulk */
168 0x40, 0x00, /* wMaxPacketSize */
169 0x00, /* bInterval */
170
171 /* Endpoint Descriptor */
172 0x07, /* bLength */
173 0x05, /* bDescriptorType */
174 0x81, /* bEndpointAddress */
175 0x02, /* bmAttributes - Bulk */
176 0x40, 0x00, /* wMaxPacketSize */
177 0x00, /* bInterval */
178
179 };
180
181 static unsigned char string_framework[] = {
182
183 /* Manufacturer string descriptor : Index 1 - "Express Logic" */
184 0x09, 0x04, 0x01, 0x0c,
185 0x45, 0x78, 0x70, 0x72, 0x65, 0x73, 0x20, 0x4c,
186 0x6f, 0x67, 0x69, 0x63,
187
188 /* Product string descriptor : Index 2 - "EL CDCECM Device" */
189 0x09, 0x04, 0x02, 0x10,
190 0x45, 0x4c, 0x20, 0x43, 0x44, 0x43, 0x45, 0x43,
191 0x4d, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
192
193 /* Serial Number string descriptor : Index 3 - "0001" */
194 0x09, 0x04, 0x03, 0x04,
195 0x30, 0x30, 0x30, 0x31,
196
197 /* MAC Address string descriptor : Index 4 - "001E5841B879" */
198 0x09, 0x04, 0x04, 0x0C,
199 0x30, 0x30, 0x31, 0x45, 0x35, 0x38,
200 0x34, 0x31, 0x42, 0x38, 0x37, 0x39,
201
202 };
203
204 static unsigned char *device_framework_full_speed = device_framework_high_speed;
205 #define FRAMEWORK_LENGTH sizeof(device_framework_high_speed)
206
207 /* Multiple languages are supported on the device, to add
208 a language besides english, the unicode language code must
209 be appended to the language_id_framework array and the length
210 adjusted accordingly. */
211 static unsigned char language_id_framework[] = {
212
213 /* English. */
214 0x09, 0x04
215 };
216
217 /* Define local variables. */
218
class_cdc_ecm_get_host(void)219 static void class_cdc_ecm_get_host(void)
220 {
221
222 UX_HOST_CLASS *class;
223
224 /* Find the main storage container */
225 UX_TEST_CHECK_SUCCESS(ux_host_stack_class_get(_ux_system_host_class_cdc_ecm_name, &class));
226
227 /* We get the first instance of the storage device */
228 UX_TEST_CHECK_SUCCESS(ux_test_host_stack_class_instance_get(class, 0, (void **) &cdc_ecm_host));
229
230 /* We still need to wait for the cdc-ecm status to be live */
231 UX_TEST_CHECK_SUCCESS(ux_test_wait_for_value_uint(&cdc_ecm_host -> ux_host_class_cdc_ecm_state, UX_HOST_CLASS_INSTANCE_LIVE));
232 }
233
demo_cdc_ecm_instance_activate(VOID * cdc_ecm_instance)234 static VOID demo_cdc_ecm_instance_activate(VOID *cdc_ecm_instance)
235 {
236
237 /* Save the CDC instance. */
238 cdc_ecm_device = (UX_SLAVE_CLASS_CDC_ECM *) cdc_ecm_instance;
239 }
240
demo_cdc_ecm_instance_deactivate(VOID * cdc_ecm_instance)241 static VOID demo_cdc_ecm_instance_deactivate(VOID *cdc_ecm_instance)
242 {
243
244 /* Reset the CDC instance. */
245 cdc_ecm_device = UX_NULL;
246 }
247
248 /* Define what the initial system looks like. */
249
250 #ifdef CTEST
test_application_define(void * first_unused_memory)251 void test_application_define(void *first_unused_memory)
252 #else
253 void usbx_ux_device_class_cdc_ecm_uninitialize_test_application_define(void *first_unused_memory)
254 #endif
255 {
256
257 /* Inform user. */
258 printf("Running ux_device_class_cdc_ecm_uninitialize Test................... ");
259
260 stepinfo("\n");
261
262 /* Initialize USBX Memory. */
263 ux_system_initialize((CHAR *)usbx_memory, UX_USBX_MEMORY_SIZE, UX_NULL, 0);
264
265 /* It looks weird if this doesn't have a comment! */
266 ux_utility_error_callback_register(ux_test_error_callback);
267
268 /* Perform the initialization of the network driver. */
269 UX_TEST_CHECK_SUCCESS(ux_network_driver_init());
270
271 nx_system_initialize();
272
273 /* Create the slave thread. */
274 UX_TEST_CHECK_SUCCESS(tx_thread_create(&thread_device, "device thread", thread_entry_device, 0,
275 thread_stack_device, UX_DEMO_STACK_SIZE,
276 30, 30, 1, TX_AUTO_START));
277 }
278
thread_entry_device(ULONG input)279 static void thread_entry_device(ULONG input)
280 {
281
282 ULONG free_memory_pre_init;
283 ULONG free_memory_post_uninit;
284 UX_SLAVE_CLASS *class;
285 UX_SLAVE_CLASS_CDC_ECM *cdc_ecm;
286 UX_SLAVE_CLASS_COMMAND command;
287
288 /* The code below is required for installing the device portion of USBX.
289 In this demo, DFU is possible and we have a call back for state change. */
290 UX_TEST_CHECK_SUCCESS(ux_device_stack_initialize(device_framework_high_speed, FRAMEWORK_LENGTH,
291 device_framework_full_speed, FRAMEWORK_LENGTH,
292 string_framework, sizeof(string_framework),
293 language_id_framework, sizeof(language_id_framework),
294 UX_NULL));
295
296 /* Set the parameters for callback when insertion/extraction of a CDC device. Set to NULL.*/
297 cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate = demo_cdc_ecm_instance_activate;
298 cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate = demo_cdc_ecm_instance_deactivate;
299
300 /* Define a NODE ID. */
301 cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[0] = 0x00;
302 cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[1] = 0x1e;
303 cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[2] = 0x58;
304 cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[3] = 0x41;
305 cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[4] = 0xb8;
306 cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_local_node_id[5] = 0x78;
307
308 /* Define a remote NODE ID. */
309 cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[0] = 0x00;
310 cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[1] = 0x1e;
311 cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[2] = 0x58;
312 cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[3] = 0x41;
313 cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[4] = 0xb8;
314 cdc_ecm_parameter.ux_slave_class_cdc_ecm_parameter_remote_node_id[5] = 0x79;
315
316 /* Test. */
317 {
318 /* Save the amount of free memory before initing. */
319 free_memory_pre_init = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
320
321 /* Initialize the device cdc_ecm class. */
322 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));
323
324 /* And deinitialize the class. */
325 UX_TEST_CHECK_SUCCESS(ux_device_stack_class_unregister(_ux_system_slave_class_cdc_ecm_name, ux_device_class_cdc_ecm_entry));
326
327 /* Save the amount of free memory after uniniting. */
328 free_memory_post_uninit = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
329
330 /* Make sure they're the same. */
331 UX_TEST_ASSERT(free_memory_pre_init == free_memory_post_uninit);
332
333 }
334
335 /* Test: class instance freed before invoking uninitialize. */
336 {
337 /* Save the amount of free memory before initing. */
338 free_memory_pre_init = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
339
340 /* Initialize the device cdc_ecm class. */
341 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));
342
343 /* Obtain class driver. */
344 class = &_ux_system_slave -> ux_system_slave_class_array[0];
345
346 /* Confirm class registered. */
347 UX_TEST_ASSERT(class -> ux_slave_class_status == UX_USED);
348 UX_TEST_ASSERT(class -> ux_slave_class_instance != UX_NULL);
349
350 /* Modify class instance for test. */
351 cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *)class -> ux_slave_class_instance;
352 class -> ux_slave_class_instance = UX_NULL;
353
354 /* And deinitialize the class, unregister is not used since it may change class state. */
355 command.ux_slave_class_command_request = UX_SLAVE_CLASS_COMMAND_UNINITIALIZE;
356 command.ux_slave_class_command_class_ptr = class;
357 UX_TEST_CHECK_SUCCESS(ux_device_class_cdc_ecm_entry(&command));
358
359 /* Memory still valid. */
360 // UX_TEST_ASSERT(cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory != UX_NULL);
361
362 /* Restore normal data. */
363 class -> ux_slave_class_instance = (VOID*)cdc_ecm;
364
365 /* And deinitialize the class. */
366 UX_TEST_CHECK_SUCCESS(ux_device_stack_class_unregister(_ux_system_slave_class_cdc_ecm_name, ux_device_class_cdc_ecm_entry));
367
368 /* Save the amount of free memory after uniniting. */
369 free_memory_post_uninit = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
370
371 /* Make sure they're the same. */
372 UX_TEST_ASSERT(free_memory_pre_init == free_memory_post_uninit);
373 }
374
375 /* Deinitialize the device side of usbx. */
376 UX_TEST_CHECK_SUCCESS(_ux_device_stack_uninitialize());
377
378 /* And finally the usbx system resources. */
379 _ux_system_uninitialize();
380
381 /* Successful test. */
382 printf("SUCCESS!\n");
383 test_control_return(0);
384 }
385