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 /** USBX Component */
15 /** */
16 /** Device CDC_ECM Class */
17 /** */
18 /**************************************************************************/
19 /**************************************************************************/
20
21 #define UX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "ux_api.h"
27 #include "ux_device_class_cdc_ecm.h"
28 #include "ux_device_stack.h"
29
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _ux_device_class_cdc_ecm_activate PORTABLE C */
36 /* 6.1.12 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function activates the USB CDC_ECM device. */
44 /* */
45 /* INPUT */
46 /* */
47 /* command Pointer to cdc_ecm command */
48 /* */
49 /* OUTPUT */
50 /* */
51 /* Completion Status */
52 /* */
53 /* CALLS */
54 /* */
55 /* None */
56 /* */
57 /* CALLED BY */
58 /* */
59 /* USBX Source Code */
60 /* */
61 /* RELEASE HISTORY */
62 /* */
63 /* DATE NAME DESCRIPTION */
64 /* */
65 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
66 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
67 /* verified memset and memcpy */
68 /* cases, used UX prefix to */
69 /* refer to TX symbols instead */
70 /* of using them directly, */
71 /* resulting in version 6.1 */
72 /* 08-02-2021 Wen Wang Modified comment(s), */
73 /* fixed spelling error, */
74 /* resulting in version 6.1.8 */
75 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
76 /* refined macros names, */
77 /* resulting in version 6.1.10 */
78 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
79 /* fixed standalone compile, */
80 /* resulting in version 6.1.11 */
81 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
82 /* fixed parameter/variable */
83 /* names conflict C++ keyword, */
84 /* resulting in version 6.1.12 */
85 /* */
86 /**************************************************************************/
_ux_device_class_cdc_ecm_activate(UX_SLAVE_CLASS_COMMAND * command)87 UINT _ux_device_class_cdc_ecm_activate(UX_SLAVE_CLASS_COMMAND *command)
88 {
89 #if defined(UX_DEVICE_STANDALONE)
90 UX_PARAMETER_NOT_USED(command);
91 return(UX_FUNCTION_NOT_SUPPORTED);
92 #else
93
94 UX_SLAVE_INTERFACE *interface_ptr;
95 UX_SLAVE_CLASS *class_ptr;
96 UX_SLAVE_CLASS_CDC_ECM *cdc_ecm;
97 UX_SLAVE_ENDPOINT *endpoint;
98 ULONG physical_address_msw;
99 ULONG physical_address_lsw;
100
101 /* Get the class container. */
102 class_ptr = command -> ux_slave_class_command_class_ptr;
103
104 /* Get the class instance in the container. */
105 cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *) class_ptr -> ux_slave_class_instance;
106
107 /* Get the interface that owns this instance. */
108 interface_ptr = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface;
109
110 /* Check if this is the Control or Data interface. */
111 if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_CDC_ECM_CLASS_COMMUNICATION_CONTROL)
112 {
113
114 /* Store the class instance into the interface. */
115 interface_ptr -> ux_slave_interface_class_instance = (VOID *)cdc_ecm;
116
117 /* Now the opposite, store the interface in the class instance. */
118 cdc_ecm -> ux_slave_class_cdc_ecm_interface = interface_ptr;
119
120 /* Locate the interrupt endpoint. */
121 endpoint = interface_ptr -> ux_slave_interface_first_endpoint;
122
123 /* Parse all endpoints. */
124 while (endpoint != UX_NULL)
125 {
126
127 /* Check the endpoint direction, and type. */
128 if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN)
129 {
130
131 /* Look at type. */
132 if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT)
133 {
134
135 /* We have found the interrupt endpoint, save it. */
136 cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_endpoint = endpoint;
137
138 /* Reset the endpoint buffers. */
139 _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_endpoint -> ux_slave_endpoint_transfer_request.
140 ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); /* Use case of memset is verified. */
141
142 /* Resume the interrupt endpoint threads. */
143 _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread);
144
145 }
146
147 }
148
149 /* Next endpoint. */
150 endpoint = endpoint -> ux_slave_endpoint_next_endpoint;
151 }
152
153 }
154 else
155
156 /* This is the DATA Class, only store the cdc_ecm instance in the interface. */
157 interface_ptr -> ux_slave_interface_class_instance = (VOID *)cdc_ecm;
158
159 /* Reset the CDC ECM alternate setting to 0. */
160 cdc_ecm -> ux_slave_class_cdc_ecm_current_alternate_setting = 0;
161
162 /* Check if this is the Control or Data interface. */
163 if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_CDC_ECM_CLASS_COMMUNICATION_DATA)
164 {
165
166 /* Reset endpoint instance pointers. */
167 cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint = UX_NULL;
168 cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint = UX_NULL;
169
170 /* Does the data class have bulk endpoint declared ? If yes we need to start link.
171 If not, the host will change the alternate setting at a later stage. */
172 if (interface_ptr -> ux_slave_interface_descriptor.bNumEndpoints != 0)
173 {
174
175 /* Locate the endpoints. Control and Bulk in/out for Data Interface. */
176 endpoint = interface_ptr -> ux_slave_interface_first_endpoint;
177
178 /* Parse all endpoints. */
179 while (endpoint != UX_NULL)
180 {
181
182 /* Check the endpoint direction, and type. */
183 if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN)
184 {
185
186 /* Look at type. */
187 if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)
188
189 /* We have found the bulk in endpoint, save it. */
190 cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint = endpoint;
191
192 }
193 else
194 {
195 /* Look at type for out endpoint. */
196 if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)
197
198 /* We have found the bulk out endpoint, save it. */
199 cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint = endpoint;
200 }
201
202 /* Next endpoint. */
203 endpoint = endpoint -> ux_slave_endpoint_next_endpoint;
204 }
205
206
207 /* Now check if all endpoints have been found. */
208 if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint == UX_NULL || cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint == UX_NULL)
209
210 /* Not all endpoints have been found. Major error, do not proceed. */
211 return(UX_ERROR);
212
213 /* Declare the link to be up. That may need to change later to make it dependent on the
214 WAN/Wireless modem. */
215 cdc_ecm -> ux_slave_class_cdc_ecm_link_state = UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP;
216
217 /* Wake up the Interrupt thread and send a network notification to the host. */
218 _ux_device_event_flags_set(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, UX_DEVICE_CLASS_CDC_ECM_NETWORK_NOTIFICATION_EVENT, UX_OR);
219
220 /* Reset the endpoint buffers. */
221 _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint -> ux_slave_endpoint_transfer_request.
222 ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); /* Use case of memset is verified. */
223 _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint -> ux_slave_endpoint_transfer_request.
224 ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); /* Use case of memset is verified. */
225
226 /* Resume the endpoint threads. */
227 _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread);
228 _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread);
229
230 }
231
232 /* Setup the physical address of this IP instance. */
233 physical_address_msw = (ULONG)((cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id[0] << 8) | (cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id[1]));
234 physical_address_lsw = (ULONG)((cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id[2] << 24) | (cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id[3] << 16) |
235 (cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id[4] << 8) | (cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id[5]));
236
237 /* Register this interface to the NetX USB interface broker. */
238 _ux_network_driver_activate((VOID *) cdc_ecm, _ux_device_class_cdc_ecm_write,
239 &cdc_ecm -> ux_slave_class_cdc_ecm_network_handle,
240 physical_address_msw,
241 physical_address_lsw);
242
243 /* Check Link. */
244 if (cdc_ecm -> ux_slave_class_cdc_ecm_link_state == UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP)
245 {
246
247 /* Communicate the state with the network driver. */
248 _ux_network_driver_link_up(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle);
249
250 /* If there is an activate function call it. */
251 if (cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate != UX_NULL)
252
253 /* Invoke the application. */
254 cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate(cdc_ecm);
255 }
256 }
257
258 /* If trace is enabled, insert this event into the trace buffer. */
259 UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ECM_ACTIVATE, cdc_ecm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
260
261 /* If trace is enabled, register this object. */
262 UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, cdc_ecm, 0, 0, 0)
263
264 /* Return completion status. */
265 return(UX_SUCCESS);
266 #endif
267 }
268