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 /**   CDC ECM Class                                                       */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 /* Include necessary system files.  */
25 
26 #define UX_SOURCE_CODE
27 
28 #include "ux_api.h"
29 #include "ux_host_class_cdc_ecm.h"
30 #include "ux_host_stack.h"
31 
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _ux_host_class_cdc_ecm_interrupt_notification       PORTABLE C      */
38 /*                                                           6.1.11       */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function is called by the stack when an interrupt packet as    */
46 /*    been received.                                                      */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    transfer_request                      Pointer to transfer request   */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    None                                                                */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    None                                                                */
59 /*                                                                        */
60 /*  CALLED BY                                                             */
61 /*                                                                        */
62 /*    USBX stack                                                          */
63 /*                                                                        */
64 /*  RELEASE HISTORY                                                       */
65 /*                                                                        */
66 /*    DATE              NAME                      DESCRIPTION             */
67 /*                                                                        */
68 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
69 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
70 /*                                            resulting in version 6.1    */
71 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
72 /*                                            refined macros names,       */
73 /*                                            resulting in version 6.1.10 */
74 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
75 /*                                            fixed standalone compile,   */
76 /*                                            resulting in version 6.1.11 */
77 /*                                                                        */
78 /**************************************************************************/
_ux_host_class_cdc_ecm_interrupt_notification(UX_TRANSFER * transfer_request)79 VOID  _ux_host_class_cdc_ecm_interrupt_notification(UX_TRANSFER *transfer_request)
80 {
81 
82 UX_HOST_CLASS_CDC_ECM                       *cdc_ecm;
83 ULONG                                       notification_type;
84 ULONG                                       notification_value;
85 
86 
87     /* Get the control class instance for this transfer request.  */
88     cdc_ecm =  (UX_HOST_CLASS_CDC_ECM *) transfer_request -> ux_transfer_request_class_instance;
89 
90     /* Check the state of the transfer.  If there is an error, we do not proceed with this notification.  */
91     if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
92 
93         /* We do not proceed.  */
94         return;
95 
96     /* Check if the class is in shutdown.  */
97     if (cdc_ecm -> ux_host_class_cdc_ecm_state ==  UX_HOST_CLASS_INSTANCE_SHUTDOWN)
98 
99         /* We do not proceed.  */
100         return;
101 
102     /* Increment the notification count.   */
103     cdc_ecm -> ux_host_class_cdc_ecm_notification_count++;
104 
105     /* Get the notification.  */
106     notification_type = (ULONG) *(transfer_request -> ux_transfer_request_data_pointer + UX_HOST_CLASS_CDC_ECM_NPF_NOTIFICATION_TYPE);
107 
108     /* And the value.  */
109     notification_value = (ULONG) *(transfer_request -> ux_transfer_request_data_pointer + UX_HOST_CLASS_CDC_ECM_NPF_VALUE);
110 
111     /* Check if the notification is a Network notification.  */
112     if (notification_type == UX_HOST_CLASS_CDC_ECM_NOTIFICATION_NETWORK_CONNECTION)
113     {
114 
115         /* Check the state of the link.  */
116         if (notification_value == UX_HOST_CLASS_CDC_ECM_NOTIFICATION_NETWORK_LINK_UP)
117         {
118 
119             /* Link is up. See if we know about that.  */
120             if (cdc_ecm -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP &&
121                 cdc_ecm -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_UP)
122             {
123 
124                 /* Memorize the new link state.  */
125                 cdc_ecm -> ux_host_class_cdc_ecm_link_state =  UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_UP;
126 
127                 /* We need to inform the cdc_ecm thread of this change.  */
128                 _ux_host_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore);
129             }
130         }
131         else
132         {
133 
134             /* Link is down. See if we know about that.  */
135             if (cdc_ecm -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN &&
136                 cdc_ecm -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_DOWN)
137             {
138 
139                 /* We need to abort any transfers on the bulk in endpoint.  */
140 
141                 /* Make sure no one does any more transfers.  */
142                 cdc_ecm -> ux_host_class_cdc_ecm_link_state =  UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_DOWN;
143 
144                 /* Now abort all transfers. It's possible we're executing right before the transfer
145                    is armed. If this is the case, then the transfer will not be aborted if we do the abort right now; instead,
146                    we should wait until after the transfer is armed. We must look at the CDC-ECM thread's state.  */
147 
148                 /* Is it in the process of checking the link state and arming the transfer?  */
149                 if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_check_and_arm_in_process == UX_TRUE)
150                 {
151 
152                     /* Yes. We must wait for it to finish arming the transfer.  */
153 
154                     /* Let the CDC-ECM thread know we're waiting so it can wake us up.  */
155                     cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish =  UX_TRUE;
156 
157                     /* Wait for the transfer to be armed, or possibly an error. The CDC-ECM thread will wake us up.  */
158                     _ux_host_semaphore_get_norc(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore, UX_WAIT_FOREVER);
159 
160                     /* We're no longer waiting.  */
161                     cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish =  UX_FALSE;
162                 }
163 
164                 /* Now we can abort the transfer.  */
165                 _ux_host_stack_transfer_request_abort(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_endpoint -> ux_endpoint_transfer_request);
166 
167                 /* We need to inform the CDC-ECM thread of this change.  */
168                 _ux_host_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore);
169             }
170         }
171     }
172 
173     /* Reactivate the CDC_ECM interrupt pipe.  */
174     _ux_host_stack_transfer_request(transfer_request);
175 
176     /* If trace is enabled, insert this event into the trace buffer.  */
177     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ECM_INTERRUPT_NOTIFICATION, cdc_ecm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
178 
179     /* Return to caller.  */
180     return;
181 }
182 
183