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