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_change PORTABLE C */
36 /* 6.1.12 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function changes the interface of the 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 /* _ux_network_driver_link_up Link status up */
56 /* _ux_network_driver_link_down Link status down */
57 /* _ux_utility_memory_set Set memory */
58 /* _ux_device_thread_resume Resume thread */
59 /* _ux_device_event_flags_set Set event flags */
60 /* _ux_device_stack_transfer_all_request_abort */
61 /* Abort transfer */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* USBX Source Code */
66 /* */
67 /* RELEASE HISTORY */
68 /* */
69 /* DATE NAME DESCRIPTION */
70 /* */
71 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
72 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
73 /* verified memset and memcpy */
74 /* cases, used UX prefix to */
75 /* refer to TX symbols instead */
76 /* of using them directly, */
77 /* resulting in version 6.1 */
78 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
79 /* refined macros names, */
80 /* resulting in version 6.1.10 */
81 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
82 /* fixed standalone compile, */
83 /* resulting in version 6.1.11 */
84 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
85 /* fixed parameter/variable */
86 /* names conflict C++ keyword, */
87 /* resulting in version 6.1.12 */
88 /* */
89 /**************************************************************************/
_ux_device_class_cdc_ecm_change(UX_SLAVE_CLASS_COMMAND * command)90 UINT _ux_device_class_cdc_ecm_change(UX_SLAVE_CLASS_COMMAND *command)
91 {
92
93 UX_SLAVE_INTERFACE *interface_ptr;
94 UX_SLAVE_CLASS *class_ptr;
95 UX_SLAVE_CLASS_CDC_ECM *cdc_ecm;
96 UX_SLAVE_ENDPOINT *endpoint;
97
98 /* Get the class container. */
99 class_ptr = command -> ux_slave_class_command_class_ptr;
100
101 /* Get the class instance in the container. */
102 cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *) class_ptr -> ux_slave_class_instance;
103
104 /* Get the interface that owns this instance. */
105 interface_ptr = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface;
106
107 /* Locate the endpoints. Control and Bulk in/out for Data Interface. */
108 endpoint = interface_ptr -> ux_slave_interface_first_endpoint;
109
110 /* If the interface to mount has a non zero alternate setting, the class is really active with
111 the endpoints active. If the interface reverts to alternate setting 0, it needs to have
112 the pending transactions terminated. */
113 if (interface_ptr -> ux_slave_interface_descriptor.bAlternateSetting != 0)
114 {
115
116 /* Parse all endpoints. */
117 while (endpoint != UX_NULL)
118 {
119
120 /* Check the endpoint direction, and type. */
121 if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN)
122 {
123
124 /* Look at type. */
125 if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)
126
127 /* We have found the bulk in endpoint, save it. */
128 cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint = endpoint;
129
130 }
131 else
132 {
133 /* Look at type for out endpoint. */
134 if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)
135
136 /* We have found the bulk out endpoint, save it. */
137 cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint = endpoint;
138 }
139
140 /* Next endpoint. */
141 endpoint = endpoint -> ux_slave_endpoint_next_endpoint;
142 }
143
144 /* Now check if all endpoints have been found. */
145 if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint == UX_NULL || cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint == UX_NULL)
146
147 /* Not all endpoints have been found. Major error, do not proceed. */
148 return(UX_ERROR);
149
150 /* Declare the link to be up. */
151 cdc_ecm -> ux_slave_class_cdc_ecm_link_state = UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP;
152
153 /* Communicate the state with the network driver. */
154 _ux_network_driver_link_up(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle);
155
156 /* Reset the endpoint buffers. */
157 _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint -> ux_slave_endpoint_transfer_request.
158 ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); /* Use case of memset is verified. */
159 _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint -> ux_slave_endpoint_transfer_request.
160 ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); /* Use case of memset is verified. */
161
162 /* Resume the endpoint threads. */
163 _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread);
164 _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread);
165
166 /* Wake up the Interrupt thread and send a network notification to the host. */
167 _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);
168
169 /* If there is an activate function call it. */
170 if (cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate != UX_NULL)
171
172 /* Invoke the application. */
173 cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate(cdc_ecm);
174 }
175 else
176 {
177
178 /* In this case, we are reverting to the Alternate Setting 0. */
179
180 /* Declare the link to be down. */
181 cdc_ecm -> ux_slave_class_cdc_ecm_link_state = UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_DOWN;
182
183 /* Communicate the state with the network driver. */
184 _ux_network_driver_link_down(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle);
185
186 /* Terminate the transactions pending on the bulk in endpoint. If there is a transfer on the
187 bulk out endpoint, we simply let it finish and let NetX throw it away. */
188 _ux_device_stack_transfer_all_request_abort(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint, UX_TRANSFER_APPLICATION_RESET);
189
190 /* Notify the thread waiting for network notification events. In this case,
191 the event is that the link state has been switched to down. */
192 _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);
193
194 /* Wake up the bulk in thread so that it can clean up the xmit queue. */
195 _ux_device_event_flags_set(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, UX_DEVICE_CLASS_CDC_ECM_NEW_DEVICE_STATE_CHANGE_EVENT, UX_OR);
196
197 /* If there is a deactivate function call it. */
198 if (cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate != UX_NULL)
199
200 /* Invoke the application. */
201 cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate(cdc_ecm);
202 }
203
204 /* Set the CDC ECM alternate setting to the new one. */
205 cdc_ecm -> ux_slave_class_cdc_ecm_current_alternate_setting = interface_ptr -> ux_slave_interface_descriptor.bAlternateSetting;
206
207 /* If trace is enabled, insert this event into the trace buffer. */
208 UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ECM_CHANGE, cdc_ecm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
209
210 /* If trace is enabled, register this object. */
211 UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, cdc_ecm, 0, 0, 0)
212
213 /* Return completion status. */
214 return(UX_SUCCESS);
215 }
216
217