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