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