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.3.0        */
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 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s),          */
785 /*                                            checked packet data length  */
786 /*                                            before process the packet,  */
787 /*                                            resulting in version 6.3.0  */
788 /*                                                                        */
789 /**************************************************************************/
790 
_ux_network_driver_packet_received(VOID * ux_network_handle,NX_PACKET * packet_ptr)791 VOID  _ux_network_driver_packet_received(VOID *ux_network_handle, NX_PACKET *packet_ptr)
792 {
793 
794 USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr = (USB_NETWORK_DEVICE_TYPE*) ux_network_handle;
795 
796 ULONG           packet_type;
797 NX_IP           *nx_ip;
798 
799     /* Check the state of the Link.  */
800     if (usb_network_device_ptr -> ux_network_device_link_status != NX_TRUE)
801     {
802 
803         /* Link down, throw away packet.  */
804         nx_packet_release(packet_ptr);
805         return;
806 
807     }
808 
809     /* Check if the packet is valid for ethernet header process.  */
810     if (packet_ptr -> nx_packet_length < NX_ETHERNET_SIZE)
811     {
812 
813         /* We received a malformed packet. Report to application.  */
814         _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR);
815 
816         /* Invalid ethernet header... release the packet.  */
817         nx_packet_release(packet_ptr);
818         return;
819     }
820 
821     /* Pickup the packet header to determine where the packet needs to be
822        sent.  */
823     packet_type =  _ux_utility_short_get_big_endian(packet_ptr -> nx_packet_prepend_ptr + 12);
824 
825     /* Storing in into the packet the interface.  */
826     packet_ptr -> nx_packet_ip_interface =  usb_network_device_ptr -> ux_network_device_interface_ptr;
827 
828     /* Get the IP instance.  */
829     nx_ip = usb_network_device_ptr -> ux_network_device_ip_instance;
830 
831     /* Route the incoming packet according to its ethernet type.  */
832     switch (packet_type)
833     {
834         case NX_ETHERNET_IP     :
835 #ifdef FEATURE_NX_IPV6
836         /* fallthrough */
837         case NX_ETHERNET_IPV6   :
838 #endif /* FEATURE_NX_IPV6 */
839 
840             /* Note:  The length reported by some Ethernet hardware includes
841                bytes after the packet as well as the Ethernet header.  In some
842                cases, the actual packet length after the Ethernet header should
843                be derived from the length in the IP header (lower 16 bits of
844                the first 32-bit word).  */
845 
846             /* Clean off the Ethernet header.  */
847             packet_ptr -> nx_packet_prepend_ptr =  packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
848 
849             /* Adjust the packet length.  */
850             packet_ptr -> nx_packet_length =  packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE;
851 
852             /* Route to the ip receive function.  */
853             _nx_ip_packet_deferred_receive(nx_ip, packet_ptr);
854 
855             break;
856 
857         case NX_ETHERNET_ARP    :
858 
859             /* Clean off the Ethernet header.  */
860             packet_ptr -> nx_packet_prepend_ptr =  packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
861 
862             /* Adjust the packet length.  */
863             packet_ptr -> nx_packet_length =   packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE;
864 
865             /* Route to the ARP receive function.  */
866            _nx_arp_packet_deferred_receive(nx_ip, packet_ptr);
867 
868             break;
869 
870         case NX_ETHERNET_RARP   :
871 
872             /* Clean off the Ethernet header.  */
873             packet_ptr -> nx_packet_prepend_ptr =
874                 packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE;
875 
876             /* Adjust the packet length.  */
877             packet_ptr -> nx_packet_length =
878                 packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE;
879 
880             /* Route to the RARP receive function.  */
881             _nx_rarp_packet_deferred_receive(nx_ip, packet_ptr);
882 
883             break;
884 
885 
886         default :
887 
888             /* Invalid ethernet header... release the packet.  */
889             nx_packet_release(packet_ptr);
890 
891     }
892 }
893 
894 /**************************************************************************/
895 /*                                                                        */
896 /*  FUNCTION                                               RELEASE        */
897 /*                                                                        */
898 /*    _ux_network_driver_link_up                          PORTABLE C      */
899 /*                                                           6.1          */
900 /*  AUTHOR                                                                */
901 /*                                                                        */
902 /*    Chaoqiong Xiao, Microsoft Corporation                               */
903 /*                                                                        */
904 /*  DESCRIPTION                                                           */
905 /*                                                                        */
906 /* This function is called by USBX when the line link is up               */
907 /*                                                                        */
908 /*  INPUT                                                                 */
909 /*                                                                        */
910 /*  ux_network_handle                Handle of the USB network instance   */
911 /*                                                                        */
912 /*  OUTPUT                                                                */
913 /*                                                                        */
914 /*  Result                                                                */
915 /*                                                                        */
916 /*                                                                        */
917 /*  CALLS                                                                 */
918 /*                                                                        */
919 /*    None                                                                */
920 /*                                                                        */
921 /*  CALLED BY                                                             */
922 /*                                                                        */
923 /*    USBX                                                                */
924 /*                                                                        */
925 /*  RELEASE HISTORY                                                       */
926 /*                                                                        */
927 /*    DATE              NAME                      DESCRIPTION             */
928 /*                                                                        */
929 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
930 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
931 /*                                            resulting in version 6.1    */
932 /*                                                                        */
933 /**************************************************************************/
934 
_ux_network_driver_link_up(VOID * ux_network_handle)935 VOID _ux_network_driver_link_up(VOID *ux_network_handle)
936 {
937 
938 USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr = (USB_NETWORK_DEVICE_TYPE*)ux_network_handle;
939 
940     /* The USB side of the link is UP.  */
941     usb_network_device_ptr -> ux_network_device_usb_link_up = NX_TRUE;
942 
943     /* Check if there is an existing interface.  */
944     if (usb_network_device_ptr -> ux_network_device_interface_ptr)
945     {
946 
947         /* Set link status.  */
948         if (usb_network_device_ptr -> ux_network_device_interface_ptr -> nx_interface_link_up)
949             usb_network_device_ptr -> ux_network_device_link_status = NX_TRUE;
950         else
951             usb_network_device_ptr -> ux_network_device_link_status = NX_FALSE;
952     }
953 
954 }
955 
956 /**************************************************************************/
957 /*                                                                        */
958 /*  FUNCTION                                               RELEASE        */
959 /*                                                                        */
960 /*    _ux_network_driver_link_down                        PORTABLE C      */
961 /*                                                           6.1          */
962 /*  AUTHOR                                                                */
963 /*                                                                        */
964 /*    Chaoqiong Xiao, Microsoft Corporation                               */
965 /*                                                                        */
966 /*  DESCRIPTION                                                           */
967 /*                                                                        */
968 /* This function is called by USBX when the link is down.                 */
969 /*                                                                        */
970 /*  INPUT                                                                 */
971 /*                                                                        */
972 /*  ux_network_handle                Handle of the USB network instance   */
973 /*                                                                        */
974 /*  OUTPUT                                                                */
975 /*                                                                        */
976 /*  Result                                                                */
977 /*                                                                        */
978 /*                                                                        */
979 /*  CALLS                                                                 */
980 /*                                                                        */
981 /*    None                                                                */
982 /*                                                                        */
983 /*  CALLED BY                                                             */
984 /*                                                                        */
985 /*    USBX                                                                */
986 /*                                                                        */
987 /*  RELEASE HISTORY                                                       */
988 /*                                                                        */
989 /*    DATE              NAME                      DESCRIPTION             */
990 /*                                                                        */
991 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
992 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
993 /*                                            resulting in version 6.1    */
994 /*                                                                        */
995 /**************************************************************************/
_ux_network_driver_link_down(VOID * ux_network_handle)996 VOID _ux_network_driver_link_down(VOID *ux_network_handle)
997 {
998 
999 USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr = (USB_NETWORK_DEVICE_TYPE*)ux_network_handle;
1000 
1001     /* Set the USB link status.  */
1002     usb_network_device_ptr -> ux_network_device_usb_link_up = NX_FALSE;
1003 
1004     /* Set the link status.  */
1005     usb_network_device_ptr -> ux_network_device_link_status = NX_FALSE;
1006 
1007 }
1008 #endif
1009