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