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 /**   CDC ECM Class                                                       */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 /* Include necessary system files.  */
24 
25 #define UX_SOURCE_CODE
26 
27 #include "ux_api.h"
28 #include "ux_host_class_cdc_ecm.h"
29 #include "ux_host_stack.h"
30 
31 
32 #if !defined(UX_HOST_STANDALONE)
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _ux_host_class_cdc_ecm_deactivate                   PORTABLE C      */
38 /*                                                           6.2.0        */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function is called when this instance of the cdc_ecm has been  */
46 /*    removed from the bus either directly or indirectly. The bulk in\out */
47 /*    and interrupt pipes will be destroyed and the instance              */
48 /*    removed.                                                            */
49 /*                                                                        */
50 /*  INPUT                                                                 */
51 /*                                                                        */
52 /*    command                           CDC ECM class command pointer     */
53 /*                                                                        */
54 /*  OUTPUT                                                                */
55 /*                                                                        */
56 /*    Completion Status                                                   */
57 /*                                                                        */
58 /*  CALLS                                                                 */
59 /*                                                                        */
60 /*    _ux_host_stack_class_instance_destroy Destroy the class instance    */
61 /*    _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer      */
62 /*    _ux_utility_memory_free               Free memory block             */
63 /*    _ux_host_semaphore_get                Get protection semaphore      */
64 /*    _ux_host_semaphore_delete             Delete protection semaphore   */
65 /*                                                                        */
66 /*  CALLED BY                                                             */
67 /*                                                                        */
68 /*    _ux_host_class_cdc_ecm_entry       Entry of cdc_ecm class           */
69 /*                                                                        */
70 /*  RELEASE HISTORY                                                       */
71 /*                                                                        */
72 /*    DATE              NAME                      DESCRIPTION             */
73 /*                                                                        */
74 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
75 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
76 /*                                            used UX prefix to refer to  */
77 /*                                            TX symbols instead of using */
78 /*                                            them directly,              */
79 /*                                            resulting in version 6.1    */
80 /*  02-02-2021     Xiuwen Cai               Modified comment(s), added    */
81 /*                                            compile option for using    */
82 /*                                            packet pool from NetX,      */
83 /*                                            resulting in version 6.1.4  */
84 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
85 /*                                            refined macros names,       */
86 /*                                            resulting in version 6.1.10 */
87 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
88 /*                                            internal clean up,          */
89 /*                                            fixed standalone compile,   */
90 /*                                            resulting in version 6.1.11 */
91 /*  10-31-2022     Chaoqiong Xiao           Modified comment(s),          */
92 /*                                            deprecated ECM pool option, */
93 /*                                            supported NX packet chain,  */
94 /*                                            resulting in version 6.2.0  */
95 /*                                                                        */
96 /**************************************************************************/
_ux_host_class_cdc_ecm_deactivate(UX_HOST_CLASS_COMMAND * command)97 UINT  _ux_host_class_cdc_ecm_deactivate(UX_HOST_CLASS_COMMAND *command)
98 {
99 
100 UX_INTERRUPT_SAVE_AREA
101 
102 UX_HOST_CLASS_CDC_ECM       *cdc_ecm;
103 UX_TRANSFER                 *transfer_request;
104 
105     /* This must be the data interface, since the control interface doesn't have
106        a class instance.  */
107 
108     /* Get the control instance for this class.  */
109     cdc_ecm =  (UX_HOST_CLASS_CDC_ECM *) command -> ux_host_class_command_instance;
110 
111     /* The cdc_ecm is being shut down.  */
112     cdc_ecm -> ux_host_class_cdc_ecm_state =  UX_HOST_CLASS_INSTANCE_SHUTDOWN;
113 
114     /* If the interrupt endpoint is defined, abort transfers so the link state
115        doesn't change.  */
116     if (cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint != UX_NULL)
117     {
118 
119         /* Get the transfer request.  */
120         transfer_request =  &cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint -> ux_endpoint_transfer_request;
121 
122         /* Abort any transfers.  */
123         _ux_host_stack_transfer_request_abort(transfer_request);
124     }
125 
126     /* Check if link was up to see if we should clean the transmit queue. If
127        the link is pending down, that means the CDC-ECM thread is in the process
128        of cleaning the transmit queue.  */
129     if (cdc_ecm -> ux_host_class_cdc_ecm_link_state == UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP)
130 
131         _ux_host_class_cdc_ecm_transmit_queue_clean(cdc_ecm);
132 
133     /* Get the bulk in transfer request.  */
134     transfer_request =  &cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_endpoint -> ux_endpoint_transfer_request;
135 
136     /* Now abort all transfers. It's possible we're executing right before the transfer
137        is armed. If this is the case, then the transfer will not be aborted if we do the abort right now; instead,
138        we should wait until after the transfer is armed. We must look at the CDC-ECM thread's state.  */
139 
140     /* Disable interrupts while we check the link state and possibly set our state.  */
141     UX_DISABLE
142 
143     /* Is it in the process of checking the link state and arming the transfer?  */
144     if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_check_and_arm_in_process == UX_TRUE)
145     {
146 
147         /* Yes. We must wait for it to finish arming the transfer.  */
148 
149         /* Let the CDC-ECM thread know we're waiting so it can wake us up.  */
150         cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish =  UX_TRUE;
151 
152         /* Restore interrupts.  */
153         UX_RESTORE
154 
155         /* Wait for the transfer to be armed, or possibly an error. The CDC-ECM thread will wake us up.  */
156         _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);
157 
158         /* We're no longer waiting.  */
159         cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish =  UX_FALSE;
160     }
161     else
162     {
163 
164         /* Restore interrupts.  */
165         UX_RESTORE
166     }
167 
168     /* Now we can abort the transfer.  */
169     _ux_host_stack_transfer_request_abort(transfer_request);
170 
171     /* De-register this interface to the NetX USB interface broker.  */
172     _ux_network_driver_deactivate((VOID *) cdc_ecm, cdc_ecm -> ux_host_class_cdc_ecm_network_handle);
173 
174     /* Destroy the control instance.  */
175     _ux_host_stack_class_instance_destroy(cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm);
176 
177     /* Now wait for all threads to leave the instance before freeing the resources.  */
178     _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM);
179 
180     /* Free the memory used by the interrupt endpoint.  */
181     if (cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint != UX_NULL)
182         _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer);
183 
184     /* Destroy the link monitoring thread. We should do this before destroying
185        the notification semaphore so that it does not run due to semaphore deletion.  */
186     _ux_utility_thread_delete(&cdc_ecm -> ux_host_class_cdc_ecm_thread);
187 
188     /* Free the CDC-ECM thread's stack memory.  */
189     _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_thread_stack);
190 
191     /* Destroy the bulk semaphores.  */
192     _ux_host_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore);
193     _ux_host_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore);
194 
195     /* Destroy the notification semaphore.  */
196     _ux_host_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore);
197 
198 #ifdef UX_HOST_CLASS_CDC_ECM_PACKET_CHAIN_SUPPORT
199 
200     /* Free packet transmission memories.  */
201     if (cdc_ecm -> ux_host_class_cdc_ecm_receive_buffer)
202         _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_receive_buffer);
203     if (cdc_ecm -> ux_host_class_cdc_ecm_xmit_buffer)
204         _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_xmit_buffer);
205 #endif
206 
207     /* Before we free the device resources, we need to inform the application
208         that the device is removed.  */
209     if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
210 
211         /* Inform the application the device is removed.  */
212         _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm);
213 
214     /* If trace is enabled, insert this event into the trace buffer.  */
215     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ECM_DEACTIVATE, cdc_ecm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
216 
217     /* If trace is enabled, unregister this object.  */
218     UX_TRACE_OBJECT_UNREGISTER(cdc_ecm);
219 
220     /* Free the cdc_ecm control instance memory.  */
221     _ux_utility_memory_free(cdc_ecm);
222 
223     /* Return successful status.  */
224     return(UX_SUCCESS);
225 }
226 #endif
227