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