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