1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** USBX Component                                                        */
17 /**                                                                       */
18 /**   USBX Network Driver for NETX 5.3 and above.                         */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 #include "ux_api.h"
24 
25 #if !defined(UX_STANDALONE)
26 #ifndef UX_NETWORK_DRIVER_ENABLE
27 #define UX_NETWORK_DRIVER_ENABLE
28 #endif
29 #else
30 /* Standalone mode not supported.  */
31 #endif
32 
33 #if defined(UX_NETWORK_DRIVER_ENABLE)
34 #include "tx_api.h"
35 #include "tx_thread.h"
36 #include "nx_api.h"
37 
38 #include "ux_network_driver.h"
39 
40 static UINT usb_network_driver_initialized;
41 
42 static USB_NETWORK_DEVICE_TYPE usb_network_devices[USB_NETWORK_DEVICE_MAX_INSTANCES];
43 
44 /**************************************************************************/
45 /*                                                                        */
46 /*  FUNCTION                                               RELEASE        */
47 /*                                                                        */
48 /*    _ux_network_init                                    PORTABLE C      */
49 /*                                                           6.1.11       */
50 /*  AUTHOR                                                                */
51 /*                                                                        */
52 /*    Chaoqiong Xiao, Microsoft Corporation                               */
53 /*                                                                        */
54 /*  DESCRIPTION                                                           */
55 /*                                                                        */
56 /*    This function is called by the application to initialize the        */
57 /*    USBX portion of the network driver.                                 */
58 /*                                                                        */
59 /*  INPUT                                                                 */
60 /*                                                                        */
61 /*                                                                        */
62 /*  OUTPUT                                                                */
63 /*                                                                        */
64 /*                                                                        */
65 /*  CALLS                                                                 */
66 /*                                                                        */
67 /*    None                                                                */
68 /*                                                                        */
69 /*  CALLED BY                                                             */
70 /*                                                                        */
71 /*    Application                                                         */
72 /*                                                                        */
73 /*  RELEASE HISTORY                                                       */
74 /*                                                                        */
75 /*    DATE              NAME                      DESCRIPTION             */
76 /*                                                                        */
77 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
78 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
79 /*                                            verified memset and memcpy  */
80 /*                                            cases,                      */
81 /*                                            resulting in version 6.1    */
82 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
83 /*                                            fixed standalone compile,   */
84 /*                                            resulting in version 6.1.11 */
85 /*                                                                        */
86 /**************************************************************************/
_ux_network_driver_init(VOID)87 UINT _ux_network_driver_init(VOID)
88 {
89 
90 UINT  status = NX_SUCCESS;
91 
92     /* Check if driver is already initialized.  */
93     if (usb_network_driver_initialized == 0)
94     {
95 
96         /* Driver is not initialized yet.  */
97         usb_network_driver_initialized = 1;
98 
99         /* Reset the network device memory array.  */
100         _ux_utility_memory_set(&usb_network_devices[0], 0, sizeof(usb_network_devices)); /* Use case of memset is verified. */
101     }
102 
103     return(status);
104 }
105 
106 /**************************************************************************/
107 /*                                                                        */
108 /*  FUNCTION                                               RELEASE        */
109 /*                                                                        */
110 /*    _ux_network_driver_activate                         PORTABLE C      */
111 /*                                                           6.1.8        */
112 /*  AUTHOR                                                                */
113 /*                                                                        */
114 /*    Chaoqiong Xiao, Microsoft Corporation                               */
115 /*                                                                        */
116 /*  DESCRIPTION                                                           */
117 /*                                                                        */
118 /* The USB network driver activate function is called as the USB instance */
119 /* is created. This API takes a pointer to the instance, and returns a    */
120 /* ux_network_handle back to instance. Every time the instance receives   */
121 /* a network packet, it should call ux_network_driver_packet_received with*/
122 /* ux_network_handle.                                                     */
123 /*                                                                        */
124 /*  INPUT                                                                 */
125 /*                                                                        */
126 /*  ux_instance                      Instance of the USBX network class   */
127 /*  ux_network_device_write_function Address of the function to write a   */
128 /*                                   packet when sent by the application  */
129 /*  ux_network_handle                Address where to store the network   */
130 /*                                   handle                               */
131 /*                                                                        */
132 /*  physical_address_msw             Most significant word of network ad  */
133 /*                                                                        */
134 /*  physical_address_lsw             Least significant word of network ad */
135 /*                                                                        */
136 /*                                                                        */
137 /*                                                                        */
138 /*  OUTPUT                                                                */
139 /*                                                                        */
140 /*  Result                                                                */
141 /*                                                                        */
142 /*                                                                        */
143 /*  CALLS                                                                 */
144 /*                                                                        */
145 /*    None                                                                */
146 /*                                                                        */
147 /*  CALLED BY                                                             */
148 /*                                                                        */
149 /*    Application                                                         */
150 /*                                                                        */
151 /*  RELEASE HISTORY                                                       */
152 /*                                                                        */
153 /*    DATE              NAME                      DESCRIPTION             */
154 /*                                                                        */
155 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
156 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
157 /*                                            used UX prefix to refer to  */
158 /*                                            TX symbols instead of using */
159 /*                                            them directly,              */
160 /*                                            resulting in version 6.1    */
161 /*  08-02-2021     Wen Wang                 Modified comment(s),          */
162 /*                                            fixed spelling error,       */
163 /*                                            resulting in version 6.1.8  */
164 /*                                                                        */
165 /**************************************************************************/
166 
_ux_network_driver_activate(VOID * ux_instance,UINT (* ux_network_device_write_function)(VOID *,NX_PACKET *),VOID ** ux_network_handle,ULONG physical_address_msw,ULONG physical_address_lsw)167 UINT _ux_network_driver_activate(VOID *ux_instance, UINT(*ux_network_device_write_function)(VOID *, NX_PACKET *),
168                                 VOID **ux_network_handle, ULONG physical_address_msw, ULONG physical_address_lsw)
169 {
170 
171 UX_INTERRUPT_SAVE_AREA
172 
173 UINT    i;
174 
175     /* Critical section.  */
176     UX_DISABLE
177 
178     /* Find an available entry in the usb_network_devices table. */
179     for (i = 0; i < USB_NETWORK_DEVICE_MAX_INSTANCES; i++)
180     {
181 
182         /* If the ptr to instance is NULL, we have a free entry.  */
183         if (usb_network_devices[i].ux_network_device_usb_instance_ptr == NX_NULL)
184         {
185 
186             /* Add the instance of the USBX class driver to the network device.  */
187             usb_network_devices[i].ux_network_device_usb_instance_ptr = ux_instance;
188 
189             break;
190         }
191     }
192 
193     /* Unprotect the critical section.  */
194     UX_RESTORE
195 
196     /* Did we reach the max number of instance ? */
197     if (i == USB_NETWORK_DEVICE_MAX_INSTANCES)
198     {
199 
200         /* Report error to application.  */
201         _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT);
202 
203         /* Return error.  */
204         return(USB_NETWORK_DRIVER_FAILURE);
205     }
206 
207     /* Store the write function.  */
208     usb_network_devices[i].ux_network_device_write_function = ux_network_device_write_function;
209 
210     /* Store the physical address of the network interface.  */
211     usb_network_devices[i].ux_network_physical_address_msw = physical_address_msw;
212     usb_network_devices[i].ux_network_physical_address_lsw = physical_address_lsw;
213 
214     /* Are we not under interrupt?  */
215     if (TX_THREAD_GET_SYSTEM_STATE() == 0)
216     {
217 
218         /* Note that we were activated by a thread.  */
219         usb_network_devices[i].ux_network_device_activated_by_thread =  UX_TRUE;
220 
221         /* Create deactivation sync objects. */
222         _ux_utility_mutex_create(&usb_network_devices[i].ux_network_device_deactivate_mutex, "usb network device mutex");
223         _ux_utility_semaphore_create(&usb_network_devices[i].ux_network_device_deactivate_semaphore, "usb network device semaphore", 0);
224     }
225 
226     /* Is there an interface at the NETX level ?  */
227     if (usb_network_devices[i].ux_network_device_interface_ptr)
228     {
229 
230         /* Store the physical address at the NETX level.  */
231         usb_network_devices[i].ux_network_device_interface_ptr -> nx_interface_physical_address_msw = physical_address_msw;
232         usb_network_devices[i].ux_network_device_interface_ptr -> nx_interface_physical_address_lsw = physical_address_lsw;
233 
234         /* Is the link UP ?  */
235         if (usb_network_devices[i].ux_network_device_interface_ptr -> nx_interface_link_up == NX_TRUE)
236 
237             /* Yes, store its state.  */
238             usb_network_devices[i].ux_network_device_link_status = NX_TRUE;
239 
240     }
241     else
242 
243         /* Link not yet up.  */
244         usb_network_devices[i].ux_network_device_link_status = NX_FALSE;
245 
246 
247     /* Is there a network handle associated ?  */
248     if (ux_network_handle)
249 
250         /* Yes, the application wants to know its address.  */
251         *ux_network_handle = (VOID*)&usb_network_devices[i];
252 
253     /* The operation was successful.  */
254     return(USB_NETWORK_DRIVER_SUCCESS);
255 }
256 
257 
258 
259 /**************************************************************************/
260 /*                                                                        */
261 /*  FUNCTION                                               RELEASE        */
262 /*                                                                        */
263 /*    _ux_network_driver_deactivate                       PORTABLE C      */
264 /*                                                           6.1.8        */
265 /*  AUTHOR                                                                */
266 /*                                                                        */
267 /*    Chaoqiong Xiao, Microsoft Corporation                               */
268 /*                                                                        */
269 /*  DESCRIPTION                                                           */
270 /*                                                                        */
271 /* The USB network driver activate function is called as the USB instance */
272 /* is created. This API takes a pointer to the instance, and returns a    */
273 /* ux_network_handle back to instance. Every time the instance receives   */
274 /* a network packet, it should call ux_network_driver_packet_received with*/
275 /* ux_network_handle.                                                     */
276 /*                                                                        */
277 /*  INPUT                                                                 */
278 /*                                                                        */
279 /*  ux_instance                      Instance of the USBX network class   */
280 /*  ux_network_device_write_function Address of the function to write a   */
281 /*                                   packet when sent by the application  */
282 /*  ux_network_handle                Address where to store the network   */
283 /*                                   handle                               */
284 /*                                                                        */
285 /*  physical_address_msw             Most significant word of network ad  */
286 /*                                                                        */
287 /*  physical_address_lsw             Least significant word of network ad */
288 /*                                                                        */
289 /*                                                                        */
290 /*                                                                        */
291 /*  OUTPUT                                                                */
292 /*                                                                        */
293 /*  Result                                                                */
294 /*                                                                        */
295 /*                                                                        */
296 /*  CALLS                                                                 */
297 /*                                                                        */
298 /*    None                                                                */
299 /*                                                                        */
300 /*  CALLED BY                                                             */
301 /*                                                                        */
302 /*    Application                                                         */
303 /*                                                                        */
304 /*  RELEASE HISTORY                                                       */
305 /*                                                                        */
306 /*    DATE              NAME                      DESCRIPTION             */
307 /*                                                                        */
308 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
309 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
310 /*                                            used UX prefix to refer to  */
311 /*                                            TX symbols instead of using */
312 /*                                            them directly,              */
313 /*                                            resulting in version 6.1    */
314 /*  08-02-2021     Wen Wang                 Modified comment(s),          */
315 /*                                            fixed spelling error,       */
316 /*                                            resulting in version 6.1.8  */
317 /*                                                                        */
318 /**************************************************************************/
_ux_network_driver_deactivate(VOID * ux_instance,VOID * ux_network_handle)319 UINT _ux_network_driver_deactivate(VOID *ux_instance, VOID *ux_network_handle)
320 {
321 
322 UX_INTERRUPT_SAVE_AREA
323 
324 USB_NETWORK_DEVICE_TYPE *usb_network_device;
325 
326     UX_PARAMETER_NOT_USED(ux_instance);
327 
328     /* Check if the handle exists.  */
329     if(ux_network_handle == NX_NULL)
330         return(USB_NETWORK_DRIVER_FAILURE);
331 
332     /* Cast the network handle properly.  */
333     usb_network_device = (USB_NETWORK_DEVICE_TYPE*) ux_network_handle;
334 
335     /* Critical section.  */
336     UX_DISABLE
337 
338     /* The link is down.  */
339     _ux_network_driver_link_down(ux_network_handle);
340 
341     /* Unprotect the critical section.  */
342     UX_RESTORE
343 
344     /* Are the sync objects valid?  */
345     if (usb_network_device -> ux_network_device_activated_by_thread)
346     {
347 
348         /* Get mutex.  */
349         _ux_utility_mutex_on(&usb_network_device -> ux_network_device_deactivate_mutex);
350 
351         /* Any threads in instance?   */
352         if (usb_network_device -> ux_network_device_num_threads_inside != 0)
353         {
354 
355             /* Signal that we're waiting.  */
356             usb_network_device -> ux_network_device_deactivate_thread_waiting =  UX_TRUE;
357 
358             /* Release mutex.  */
359             _ux_utility_mutex_off(&usb_network_device -> ux_network_device_deactivate_mutex);
360 
361             /* Wait for last thread inside to resume us.  */
362             _ux_utility_semaphore_get(&usb_network_device -> ux_network_device_deactivate_semaphore, UX_WAIT_FOREVER);
363 
364             /* We're done waiting.  */
365             usb_network_device -> ux_network_device_deactivate_thread_waiting =  UX_FALSE;
366         }
367         else
368         {
369 
370             /* Release mutex.  */
371             _ux_utility_mutex_off(&usb_network_device -> ux_network_device_deactivate_mutex);
372         }
373 
374         /* Delete sync objects.  */
375         _ux_utility_mutex_delete(&usb_network_device -> ux_network_device_deactivate_mutex);
376         _ux_utility_semaphore_delete(&usb_network_device -> ux_network_device_deactivate_semaphore);
377 
378         /* Reset for next activation.  */
379         usb_network_device -> ux_network_device_activated_by_thread =  UX_FALSE;
380     }
381 
382     /* All threads are outside of the instance, and can't re-enter because the
383        link flag has been set to down. Now we can clean up.  */
384 
385     /* Reset the instance pointer.  */
386     usb_network_device -> ux_network_device_usb_instance_ptr = NX_NULL;
387 
388     /* And the write function ptr.  */
389     usb_network_device -> ux_network_device_write_function = NX_NULL;
390 
391     /* The operation was successful.  */
392     return(USB_NETWORK_DRIVER_SUCCESS);
393 
394 }
395 
396 /**************************************************************************/
397 /*                                                                        */
398 /*  FUNCTION                                               RELEASE        */
399 /*                                                                        */
400 /*    _ux_network_driver_entry                            PORTABLE C      */
401 /*                                                           6.2.1        */
402 /*  AUTHOR                                                                */
403 /*                                                                        */
404 /*    Chaoqiong Xiao, Microsoft Corporation                               */
405 /*                                                                        */
406 /*  DESCRIPTION                                                           */
407 /*                                                                        */
408 /* This function is called by NETX. This is the dispatcher to all the     */
409 /* NETX function to the driver layer.                                     */
410 /*                                                                        */
411 /*  INPUT                                                                 */
412 /*                                                                        */
413 /*  nx_ip_driver                     Pointer to the NX_IP driver instance */
414 /*                                                                        */
415 /*  OUTPUT                                                                */
416 /*                                                                        */
417 /*  Result                                                                */
418 /*                                                                        */
419 /*                                                                        */
420 /*  CALLS                                                                 */
421 /*                                                                        */
422 /*    None                                                                */
423 /*                                                                        */
424 /*  CALLED BY                                                             */
425 /*                                                                        */
426 /*    NETX                                                                */
427 /*                                                                        */
428 /*  RELEASE HISTORY                                                       */
429 /*                                                                        */
430 /*    DATE              NAME                      DESCRIPTION             */
431 /*                                                                        */
432 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
433 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
434 /*                                            used UX prefix to refer to  */
435 /*                                            TX symbols instead of using */
436 /*                                            them directly,              */
437 /*                                            resulting in version 6.1    */
438 /*  07-29-2022     Yajun Xia                Modified comment(s),          */
439 /*                                            fixed ipv6 support issue,   */
440 /*                                            resulting in version 6.1.12 */
441 /*  03-08-2023     Yajun Xia                Modified comment(s),          */
442 /*                                            fixed build issue with NETX,*/
443 /*                                            resulting in version 6.2.1  */
444 /*                                                                        */
445 /**************************************************************************/
446 
_ux_network_driver_entry(NX_IP_DRIVER * nx_ip_driver)447 VOID _ux_network_driver_entry(NX_IP_DRIVER *nx_ip_driver)
448 {
449 
450 UX_INTERRUPT_SAVE_AREA
451 NX_IP                           *nx_ip;
452 NX_PACKET                       *packet_ptr;
453 ULONG                           *ethernet_frame_ptr;
454 NX_INTERFACE                    *nx_interface_ptr;
455 USB_NETWORK_DEVICE_TYPE         *usb_network_device_ptr;
456 UINT                            i;
457 
458     /* Get the pointer to the NX_IP instance.  */
459     nx_ip = nx_ip_driver -> nx_ip_driver_ptr;
460 
461     /* Set the default status return. */
462     nx_ip_driver  -> nx_ip_driver_status =  NX_NOT_SUCCESSFUL;
463 
464     /* Get the pointer to the interface in local variable.  */
465     nx_interface_ptr = nx_ip_driver -> nx_ip_driver_interface;
466 
467     /* Is this the ATTACH command?  */
468     if (nx_ip_driver -> nx_ip_driver_command == NX_LINK_INTERFACE_ATTACH)
469     {
470 
471         /* Critical section.  */
472         UX_DISABLE
473 
474         /* Find an available entry in the usb_network_devices table. */
475         for (i = 0; i < USB_NETWORK_DEVICE_MAX_INSTANCES; i++)
476         {
477 
478             /* If the interface pointer is NULL, it is free.  */
479             if (usb_network_devices[i].ux_network_device_interface_ptr == NX_NULL)
480                 break;
481 
482         }
483 
484         /* Check if we have ran out of instances.  */
485         if (i == USB_NETWORK_DEVICE_MAX_INSTANCES)
486 
487             /* No more instances, set the error code.  */
488             nx_ip_driver -> nx_ip_driver_status = NX_NO_MORE_ENTRIES;
489 
490         else
491         {
492 
493             /* Save the IP address in the network instance.  */
494             usb_network_devices[i].ux_network_device_ip_instance = nx_ip;
495 
496             /* Save pointer to interface.  */
497             usb_network_devices[i].ux_network_device_interface_ptr = nx_interface_ptr;
498 
499             /* Set the USB class instance in the additional link. This will be used by the USB class driver.  */
500             nx_interface_ptr -> nx_interface_additional_link_info = (VOID *) &usb_network_devices[i];
501 
502             /* The operation was successful.  */
503             nx_ip_driver -> nx_ip_driver_status = NX_SUCCESS;
504         }
505 
506         /* Unprotect the critical section.  */
507         UX_RESTORE
508     }
509     else
510     {
511 
512         /* Get the usb instance.  */
513         usb_network_device_ptr = (USB_NETWORK_DEVICE_TYPE *) nx_interface_ptr -> nx_interface_additional_link_info;
514 
515         /* Identify command.  */
516         switch(nx_ip_driver  -> nx_ip_driver_command)
517         {
518 
519         case NX_LINK_INITIALIZE:
520 
521             /* INIT command, set the interface parameters.  */
522             nx_interface_ptr -> nx_interface_valid = NX_TRUE;
523             nx_interface_ptr -> nx_interface_address_mapping_needed = NX_TRUE;
524             nx_interface_ptr -> nx_interface_ip_mtu_size =  NX_ETHERNET_MTU - NX_ETHERNET_SIZE;
525 
526             /* Set the link to down for now.  */
527             nx_interface_ptr -> nx_interface_link_up = NX_FALSE;
528 
529             /* Check if instance exists.  */
530             if (usb_network_device_ptr -> ux_network_device_usb_instance_ptr)
531             {
532 
533                 /* Store the physical address in the nx interface.  */
534                 nx_interface_ptr -> nx_interface_physical_address_msw = usb_network_device_ptr -> ux_network_physical_address_msw;
535                 nx_interface_ptr -> nx_interface_physical_address_lsw = usb_network_device_ptr -> ux_network_physical_address_lsw;
536 
537             }
538             else
539             {
540 
541                 /* Reset the physical address.  */
542                 nx_interface_ptr -> nx_interface_physical_address_msw = 0;
543                 nx_interface_ptr -> nx_interface_physical_address_lsw = 0;
544             }
545 
546             /* Operation is successful.  */
547             nx_ip_driver  -> nx_ip_driver_status =  NX_SUCCESS;
548             break;
549 
550 
551 
552 
553         case NX_LINK_ENABLE:
554 
555             /* Set the link state to UP.  */
556             nx_interface_ptr -> nx_interface_link_up = NX_TRUE;
557 
558             /* Reflect link state in network device.  */
559             if (usb_network_device_ptr -> ux_network_device_usb_link_up == NX_TRUE)
560                 usb_network_device_ptr -> ux_network_device_link_status = NX_TRUE;
561             else
562                 usb_network_device_ptr -> ux_network_device_link_status = NX_FALSE;
563 
564             nx_ip_driver -> nx_ip_driver_status = NX_SUCCESS;
565             break;
566 
567 
568         case NX_LINK_DISABLE:
569 
570             /* Set the link down.  */
571             nx_interface_ptr -> nx_interface_link_up = NX_FALSE;
572             usb_network_device_ptr -> ux_network_device_link_status = NX_FALSE;
573             nx_ip_driver  -> nx_ip_driver_status =  NX_SUCCESS;
574             break;
575 
576 
577         case NX_LINK_PACKET_SEND:
578         case NX_LINK_PACKET_BROADCAST:
579         case NX_LINK_ARP_SEND:
580         case NX_LINK_ARP_RESPONSE_SEND:
581         case NX_LINK_RARP_SEND:
582 
583             /* Place the ethernet frame at the front of the packet.  */
584             packet_ptr =  nx_ip_driver -> nx_ip_driver_packet;
585 
586             /* Are the sync objects valid?  */
587             if (usb_network_device_ptr -> ux_network_device_activated_by_thread == UX_TRUE)
588 
589                 /* Get mutex for checking link state and setting our state.  */
590                 _ux_utility_mutex_on(&usb_network_device_ptr -> ux_network_device_deactivate_mutex);
591 
592             /* Do not send a packet if the link is not enabled. */
593             if (usb_network_device_ptr -> ux_network_device_link_status == NX_TRUE)
594             {
595 
596                 /* Increment number of threads inside this instance.  */
597                 usb_network_device_ptr -> ux_network_device_num_threads_inside++;
598 
599                 /* Are the sync objects valid?  */
600                 if (usb_network_device_ptr -> ux_network_device_activated_by_thread == UX_TRUE)
601 
602                     /* Release mutex.  */
603                     _ux_utility_mutex_off(&usb_network_device_ptr -> ux_network_device_deactivate_mutex);
604 
605                 /* Adjust the prepend pointer.  */
606                 packet_ptr -> nx_packet_prepend_ptr =  packet_ptr -> nx_packet_prepend_ptr - NX_ETHERNET_SIZE;
607 
608                 /* Adjust the packet length.  */
609                 packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + NX_ETHERNET_SIZE;
610 
611                 /* Setup the ethernet frame pointer to build the ethernet frame.  Back up another 2 bytes to get 32-bit word alignment. */
612                 ethernet_frame_ptr =  (ULONG*)(packet_ptr -> nx_packet_prepend_ptr - 2);
613 
614                 /* Build the ethernet frame.  */
615                 *ethernet_frame_ptr       = nx_ip_driver -> nx_ip_driver_physical_address_msw;
616                 *(ethernet_frame_ptr + 1) = nx_ip_driver -> nx_ip_driver_physical_address_lsw;
617                 *(ethernet_frame_ptr + 2) = (nx_interface_ptr -> nx_interface_physical_address_msw << 16) |
618                     (nx_interface_ptr -> nx_interface_physical_address_lsw >> 16);
619                 *(ethernet_frame_ptr + 3) = (nx_interface_ptr -> nx_interface_physical_address_lsw << 16);
620 
621                 if ((nx_ip_driver -> nx_ip_driver_command == NX_LINK_ARP_SEND)||
622                    (nx_ip_driver -> nx_ip_driver_command == NX_LINK_ARP_RESPONSE_SEND))
623                 {
624                     *(ethernet_frame_ptr+3) |= NX_ETHERNET_ARP;
625                 }
626                 else if (nx_ip_driver -> nx_ip_driver_command == NX_LINK_RARP_SEND)
627                 {
628                     *(ethernet_frame_ptr+3) |= NX_ETHERNET_RARP;
629                 }
630                 else
631                 {
632 #ifdef FEATURE_NX_IPV6
633                     if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
634 #endif /* FEATURE_NX_IPV6 */
635                         *(ethernet_frame_ptr+3) |= NX_ETHERNET_IP;
636 #ifdef FEATURE_NX_IPV6
637                     else if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
638                         *(ethernet_frame_ptr+3) |= NX_ETHERNET_IPV6;
639                     else
640                     {
641                         /* Unknown IP version */
642                         /* free the packet that we will not send */
643                         nx_packet_transmit_release(packet_ptr);
644                         nx_ip_driver  -> nx_ip_driver_status =  NX_NOT_SUCCESSFUL;
645                         break;
646                     }
647 #endif /* FEATURE_NX_IPV6 */
648                 }
649 
650                 /* Endian swapping if NX_LITTLE_ENDIAN is defined.  */
651                 NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr));
652                 NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr+1));
653                 NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr+2));
654                 NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr+3));
655 
656                 /* Write the packet or queue it.  */
657                 nx_ip_driver -> nx_ip_driver_status =
658                     usb_network_device_ptr -> ux_network_device_write_function(usb_network_device_ptr -> ux_network_device_usb_instance_ptr,
659                                                                               packet_ptr);
660 
661                 /* Are the sync objects valid?  */
662                 if (usb_network_device_ptr -> ux_network_device_activated_by_thread == UX_TRUE)
663                 {
664 
665                     /* Get mutex.  */
666                     _ux_utility_mutex_on(&usb_network_device_ptr -> ux_network_device_deactivate_mutex);
667 
668                     /* Decrement number of threads in instance.  */
669                     usb_network_device_ptr -> ux_network_device_num_threads_inside--;
670 
671                     /* No more threads in the instance?  */
672                     if (usb_network_device_ptr -> ux_network_device_num_threads_inside == 0)
673                     {
674 
675                         /* Release mutex.  */
676                         _ux_utility_mutex_off(&usb_network_device_ptr -> ux_network_device_deactivate_mutex);
677 
678                         /* Anyone waiting for us to exit?  */
679                         if (usb_network_device_ptr -> ux_network_device_deactivate_thread_waiting == UX_TRUE)
680 
681                             /* Resume deactivate thread waiting.  */
682                             _ux_utility_semaphore_put(&usb_network_device_ptr -> ux_network_device_deactivate_semaphore);
683                     }
684                     else
685                     {
686 
687                         /* Release mutex.  */
688                         _ux_utility_mutex_off(&usb_network_device_ptr -> ux_network_device_deactivate_mutex);
689                     }
690                 }
691             }
692             else
693             {
694 
695                 /* Are the sync objects valid?  */
696                 if (usb_network_device_ptr -> ux_network_device_activated_by_thread == UX_TRUE)
697 
698                     /* Release mutex.  */
699                     _ux_utility_mutex_off(&usb_network_device_ptr -> ux_network_device_deactivate_mutex);
700 
701                 /* Link down, throw away packet.  */
702                 nx_packet_transmit_release(packet_ptr);
703                 nx_ip_driver  -> nx_ip_driver_status =  NX_SUCCESS;
704 
705                 /* Report error to application.  */
706                 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_CDC_ECM_LINK_STATE_DOWN_ERROR);
707             }
708 
709             break;
710 
711         case NX_LINK_UNINITIALIZE:
712 
713             usb_network_driver_initialized =  0;
714 
715             break;
716 
717         case NX_LINK_MULTICAST_JOIN:
718         case NX_LINK_MULTICAST_LEAVE:
719         case NX_LINK_GET_STATUS:
720         case NX_LINK_GET_ERROR_COUNT:
721         case NX_LINK_GET_RX_COUNT:
722         case NX_LINK_GET_TX_COUNT:
723         case NX_LINK_GET_ALLOC_ERRORS:
724         case NX_LINK_GET_SPEED:
725         case NX_LINK_GET_DUPLEX_TYPE:
726         case NX_LINK_USER_COMMAND :
727         default:
728 
729             /* Invalid driver request.  */
730             nx_ip_driver -> nx_ip_driver_status =  NX_UNHANDLED_COMMAND;
731 
732             break;
733         }
734     }
735 
736     /* We are done here.  */
737     return;
738 }
739 
740 
741 /**************************************************************************/
742 /*                                                                        */
743 /*  FUNCTION                                               RELEASE        */
744 /*                                                                        */
745 /*    _ux_network_driver_packet_received                  PORTABLE C      */
746 /*                                                           6.1.12       */
747 /*  AUTHOR                                                                */
748 /*                                                                        */
749 /*    Chaoqiong Xiao, Microsoft Corporation                               */
750 /*                                                                        */
751 /*  DESCRIPTION                                                           */
752 /*                                                                        */
753 /* This function is called by USBX when a packet has been receiver over   */
754 /* the USB.                                                               */
755 /*                                                                        */
756 /*  INPUT                                                                 */
757 /*                                                                        */
758 /*  ux_network_handle                Handle of the USB network instance   */
759 /*  packet_ptr                       Pointer to packet received           */
760 /*                                                                        */
761 /*  OUTPUT                                                                */
762 /*                                                                        */
763 /*  Result                                                                */
764 /*                                                                        */
765 /*                                                                        */
766 /*  CALLS                                                                 */
767 /*                                                                        */
768 /*    None                                                                */
769 /*                                                                        */
770 /*  CALLED BY                                                             */
771 /*                                                                        */
772 /*    USBX                                                                */
773 /*                                                                        */
774 /*  RELEASE HISTORY                                                       */
775 /*                                                                        */
776 /*    DATE              NAME                      DESCRIPTION             */
777 /*                                                                        */
778 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
779 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
780 /*                                            resulting in version 6.1    */
781 /*  07-29-2022     Yajun Xia                Modified comment(s),          */
782 /*                                            fixed ipv6 support issue,   */
783 /*                                            resulting in version 6.1.12 */
784 /*                                                                        */
785 /**************************************************************************/
786 
_ux_network_driver_packet_received(VOID * ux_network_handle,NX_PACKET * packet_ptr)787 VOID  _ux_network_driver_packet_received(VOID *ux_network_handle, NX_PACKET *packet_ptr)
788 {
789 
790 USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr = (USB_NETWORK_DEVICE_TYPE*) ux_network_handle;
791 
792 ULONG           packet_type;
793 NX_IP           *nx_ip;
794 
795     /* Check the state of the Link.  */
796     if (usb_network_device_ptr -> ux_network_device_link_status != NX_TRUE)
797     {
798 
799         /* Link down, throw away packet.  */
800         nx_packet_release(packet_ptr);
801         return;
802 
803     }
804 
805     /* Pickup the packet header to determine where the packet needs to be
806        sent.  */
807     packet_type =  _ux_utility_short_get_big_endian(packet_ptr -> nx_packet_prepend_ptr + 12);
808 
809     /* Storing in into the packet the interface.  */
810     packet_ptr -> nx_packet_ip_interface =  usb_network_device_ptr -> ux_network_device_interface_ptr;
811 
812     /* Get the IP instance.  */
813     nx_ip = usb_network_device_ptr -> ux_network_device_ip_instance;
814 
815     /* Route the incoming packet according to its ethernet type.  */
816     switch (packet_type)
817     {
818         case NX_ETHERNET_IP     :
819 #ifdef FEATURE_NX_IPV6
820         /* fallthrough */
821         case NX_ETHERNET_IPV6   :
822 #endif /* FEATURE_NX_IPV6 */
823 
824             /* Note:  The length reported by some Ethernet hardware includes
825                bytes after the packet as well as the Ethernet header.  In some
826                cases, the actual packet length after the Ethernet header should
827                be derived from the length in the IP header (lower 16 bits of
828                the first 32-bit word).  */
829 
830             /* Clean off the Ethernet header.  */
831             packet_ptr -> nx_packet_prepend_ptr =  packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
832 
833             /* Adjust the packet length.  */
834             packet_ptr -> nx_packet_length =  packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE;
835 
836             /* Route to the ip receive function.  */
837             _nx_ip_packet_deferred_receive(nx_ip, packet_ptr);
838 
839             break;
840 
841         case NX_ETHERNET_ARP    :
842 
843             /* Clean off the Ethernet header.  */
844             packet_ptr -> nx_packet_prepend_ptr =  packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
845 
846             /* Adjust the packet length.  */
847             packet_ptr -> nx_packet_length =   packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE;
848 
849             /* Route to the ARP receive function.  */
850            _nx_arp_packet_deferred_receive(nx_ip, packet_ptr);
851 
852             break;
853 
854         case NX_ETHERNET_RARP   :
855 
856             /* Clean off the Ethernet header.  */
857             packet_ptr -> nx_packet_prepend_ptr =
858                 packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
859 
860             /* Adjust the packet length.  */
861             packet_ptr -> nx_packet_length =
862                 packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE;
863 
864             /* Route to the RARP receive function.  */
865             _nx_rarp_packet_deferred_receive(nx_ip, packet_ptr);
866 
867             break;
868 
869 
870         default :
871 
872             /* Invalid ethernet header... release the packet.  */
873             nx_packet_release(packet_ptr);
874 
875     }
876 }
877 
878 /**************************************************************************/
879 /*                                                                        */
880 /*  FUNCTION                                               RELEASE        */
881 /*                                                                        */
882 /*    _ux_network_driver_link_up                          PORTABLE C      */
883 /*                                                           6.1          */
884 /*  AUTHOR                                                                */
885 /*                                                                        */
886 /*    Chaoqiong Xiao, Microsoft Corporation                               */
887 /*                                                                        */
888 /*  DESCRIPTION                                                           */
889 /*                                                                        */
890 /* This function is called by USBX when the line link is up               */
891 /*                                                                        */
892 /*  INPUT                                                                 */
893 /*                                                                        */
894 /*  ux_network_handle                Handle of the USB network instance   */
895 /*                                                                        */
896 /*  OUTPUT                                                                */
897 /*                                                                        */
898 /*  Result                                                                */
899 /*                                                                        */
900 /*                                                                        */
901 /*  CALLS                                                                 */
902 /*                                                                        */
903 /*    None                                                                */
904 /*                                                                        */
905 /*  CALLED BY                                                             */
906 /*                                                                        */
907 /*    USBX                                                                */
908 /*                                                                        */
909 /*  RELEASE HISTORY                                                       */
910 /*                                                                        */
911 /*    DATE              NAME                      DESCRIPTION             */
912 /*                                                                        */
913 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
914 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
915 /*                                            resulting in version 6.1    */
916 /*                                                                        */
917 /**************************************************************************/
918 
_ux_network_driver_link_up(VOID * ux_network_handle)919 VOID _ux_network_driver_link_up(VOID *ux_network_handle)
920 {
921 
922 USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr = (USB_NETWORK_DEVICE_TYPE*)ux_network_handle;
923 
924     /* The USB side of the link is UP.  */
925     usb_network_device_ptr -> ux_network_device_usb_link_up = NX_TRUE;
926 
927     /* Check if there is an existing interface.  */
928     if (usb_network_device_ptr -> ux_network_device_interface_ptr)
929     {
930 
931         /* Set link status.  */
932         if (usb_network_device_ptr -> ux_network_device_interface_ptr -> nx_interface_link_up)
933             usb_network_device_ptr -> ux_network_device_link_status = NX_TRUE;
934         else
935             usb_network_device_ptr -> ux_network_device_link_status = NX_FALSE;
936     }
937 
938 }
939 
940 /**************************************************************************/
941 /*                                                                        */
942 /*  FUNCTION                                               RELEASE        */
943 /*                                                                        */
944 /*    _ux_network_driver_link_down                        PORTABLE C      */
945 /*                                                           6.1          */
946 /*  AUTHOR                                                                */
947 /*                                                                        */
948 /*    Chaoqiong Xiao, Microsoft Corporation                               */
949 /*                                                                        */
950 /*  DESCRIPTION                                                           */
951 /*                                                                        */
952 /* This function is called by USBX when the link is down.                 */
953 /*                                                                        */
954 /*  INPUT                                                                 */
955 /*                                                                        */
956 /*  ux_network_handle                Handle of the USB network instance   */
957 /*                                                                        */
958 /*  OUTPUT                                                                */
959 /*                                                                        */
960 /*  Result                                                                */
961 /*                                                                        */
962 /*                                                                        */
963 /*  CALLS                                                                 */
964 /*                                                                        */
965 /*    None                                                                */
966 /*                                                                        */
967 /*  CALLED BY                                                             */
968 /*                                                                        */
969 /*    USBX                                                                */
970 /*                                                                        */
971 /*  RELEASE HISTORY                                                       */
972 /*                                                                        */
973 /*    DATE              NAME                      DESCRIPTION             */
974 /*                                                                        */
975 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
976 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
977 /*                                            resulting in version 6.1    */
978 /*                                                                        */
979 /**************************************************************************/
_ux_network_driver_link_down(VOID * ux_network_handle)980 VOID _ux_network_driver_link_down(VOID *ux_network_handle)
981 {
982 
983 USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr = (USB_NETWORK_DEVICE_TYPE*)ux_network_handle;
984 
985     /* Set the USB link status.  */
986     usb_network_device_ptr -> ux_network_device_usb_link_up = NX_FALSE;
987 
988     /* Set the link status.  */
989     usb_network_device_ptr -> ux_network_device_link_status = NX_FALSE;
990 
991 }
992 #endif
993