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