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