GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_device_classes/src/ux_device_class_cdc_ecm_activate.c Lines: 46 46 100.0 %
Date: 2024-12-12 17:16:36 Branches: 28 28 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 *
4
 * This program and the accompanying materials are made available under the
5
 * terms of the MIT License which is available at
6
 * https://opensource.org/licenses/MIT.
7
 *
8
 * SPDX-License-Identifier: MIT
9
 **************************************************************************/
10
11
/**************************************************************************/
12
/**                                                                       */
13
/** USBX Component                                                        */
14
/**                                                                       */
15
/**   Device CDC_ECM Class                                                */
16
/**                                                                       */
17
/**************************************************************************/
18
/**************************************************************************/
19
20
#define UX_SOURCE_CODE
21
22
23
/* Include necessary system files.  */
24
25
#include "ux_api.h"
26
#include "ux_device_class_cdc_ecm.h"
27
#include "ux_device_stack.h"
28
29
30
/**************************************************************************/
31
/*                                                                        */
32
/*  FUNCTION                                               RELEASE        */
33
/*                                                                        */
34
/*    _ux_device_class_cdc_ecm_activate                   PORTABLE C      */
35
/*                                                           6.3.0        */
36
/*  AUTHOR                                                                */
37
/*                                                                        */
38
/*    Chaoqiong Xiao, Microsoft Corporation                               */
39
/*                                                                        */
40
/*  DESCRIPTION                                                           */
41
/*                                                                        */
42
/*    This function activates the USB CDC_ECM device.                     */
43
/*                                                                        */
44
/*  INPUT                                                                 */
45
/*                                                                        */
46
/*    command                           Pointer to cdc_ecm command        */
47
/*                                                                        */
48
/*  OUTPUT                                                                */
49
/*                                                                        */
50
/*    Completion Status                                                   */
51
/*                                                                        */
52
/*  CALLS                                                                 */
53
/*                                                                        */
54
/*    None                                                                */
55
/*                                                                        */
56
/*  CALLED BY                                                             */
57
/*                                                                        */
58
/*    USBX Source Code                                                    */
59
/*                                                                        */
60
/*  RELEASE HISTORY                                                       */
61
/*                                                                        */
62
/*    DATE              NAME                      DESCRIPTION             */
63
/*                                                                        */
64
/*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
65
/*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
66
/*                                            verified memset and memcpy  */
67
/*                                            cases, used UX prefix to    */
68
/*                                            refer to TX symbols instead */
69
/*                                            of using them directly,     */
70
/*                                            resulting in version 6.1    */
71
/*  08-02-2021     Wen Wang                 Modified comment(s),          */
72
/*                                            fixed spelling error,       */
73
/*                                            resulting in version 6.1.8  */
74
/*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
75
/*                                            refined macros names,       */
76
/*                                            resulting in version 6.1.10 */
77
/*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
78
/*                                            fixed standalone compile,   */
79
/*                                            resulting in version 6.1.11 */
80
/*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
81
/*                                            fixed parameter/variable    */
82
/*                                            names conflict C++ keyword, */
83
/*                                            resulting in version 6.1.12 */
84
/*  10-31-2023     Chaoqiong Xiao           Modified comment(s),          */
85
/*                                            added zero copy support,    */
86
/*                                            added a new mode to manage  */
87
/*                                            endpoint buffer in classes, */
88
/*                                            resulting in version 6.3.0  */
89
/*                                                                        */
90
/**************************************************************************/
91
242
UINT  _ux_device_class_cdc_ecm_activate(UX_SLAVE_CLASS_COMMAND *command)
92
{
93
#if defined(UX_DEVICE_STANDALONE)
94
    UX_PARAMETER_NOT_USED(command);
95
    return(UX_FUNCTION_NOT_SUPPORTED);
96
#else
97
98
UX_SLAVE_INTERFACE          *interface_ptr;
99
UX_SLAVE_CLASS              *class_ptr;
100
UX_SLAVE_CLASS_CDC_ECM      *cdc_ecm;
101
UX_SLAVE_ENDPOINT           *endpoint;
102
ULONG                       physical_address_msw;
103
ULONG                       physical_address_lsw;
104
105
    /* Get the class container.  */
106
242
    class_ptr =  command -> ux_slave_class_command_class_ptr;
107
108
    /* Get the class instance in the container.  */
109
242
    cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *) class_ptr -> ux_slave_class_instance;
110
111
    /* Get the interface that owns this instance.  */
112
242
    interface_ptr =  (UX_SLAVE_INTERFACE  *) command -> ux_slave_class_command_interface;
113
114
    /* Check if this is the Control or Data interface.  */
115
242
    if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_CDC_ECM_CLASS_COMMUNICATION_CONTROL)
116
    {
117
118
        /* Store the class instance into the interface.  */
119
121
        interface_ptr -> ux_slave_interface_class_instance =  (VOID *)cdc_ecm;
120
121
        /* Now the opposite, store the interface in the class instance.  */
122
121
        cdc_ecm -> ux_slave_class_cdc_ecm_interface =  interface_ptr;
123
124
        /* Locate the interrupt endpoint. */
125
121
        endpoint =  interface_ptr -> ux_slave_interface_first_endpoint;
126
127
        /* Parse all endpoints.  */
128
243
        while (endpoint != UX_NULL)
129
        {
130
131
            /* Check the endpoint direction, and type.  */
132
122
            if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN)
133
            {
134
135
                /* Look at type.  */
136
120
                if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT)
137
                {
138
139
                    /* We have found the interrupt endpoint, save it.  */
140
118
                    cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_endpoint =  endpoint;
141
#if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
142
143
                    /* Set the endpoint buffer to the endpoint.  */
144
                    endpoint -> ux_slave_endpoint_transfer_request.
145
                        ux_slave_transfer_request_data_pointer =
146
                                UX_DEVICE_CLASS_CDC_ECM_INTERRUPTIN_BUFFER(cdc_ecm);
147
#endif
148
149
                    /* Reset the endpoint buffers.  */
150
118
                    _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_endpoint -> ux_slave_endpoint_transfer_request.
151
                                        ux_slave_transfer_request_data_pointer, 0, UX_DEVICE_CLASS_CDC_ECM_INTERRUPTIN_BUFFER_SIZE); /* Use case of memset is verified. */
152
153
                    /* Resume the interrupt endpoint threads.  */
154
118
                    _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread);
155
156
                }
157
158
            }
159
160
            /* Next endpoint.  */
161
122
            endpoint =  endpoint -> ux_slave_endpoint_next_endpoint;
162
        }
163
164
    }
165
    else
166
167
        /* This is the DATA Class, only store the cdc_ecm instance in the interface.  */
168
121
        interface_ptr -> ux_slave_interface_class_instance =  (VOID *)cdc_ecm;
169
170
    /* Reset the CDC ECM alternate setting to 0.  */
171
242
    cdc_ecm -> ux_slave_class_cdc_ecm_current_alternate_setting =  0;
172
173
    /* Check if this is the Control or Data interface.  */
174
242
    if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_CDC_ECM_CLASS_COMMUNICATION_DATA)
175
    {
176
177
        /* Reset endpoint instance pointers.  */
178
121
        cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint = UX_NULL;
179
121
        cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint = UX_NULL;
180
181
        /* Does the data class have bulk endpoint declared ? If yes we need to start link.
182
           If not, the host will change the alternate setting at a later stage.  */
183
121
        if (interface_ptr -> ux_slave_interface_descriptor.bNumEndpoints != 0)
184
        {
185
186
            /* Locate the endpoints.  Control and Bulk in/out for Data Interface.  */
187
9
            endpoint =  interface_ptr -> ux_slave_interface_first_endpoint;
188
189
            /* Parse all endpoints.  */
190
27
            while (endpoint != UX_NULL)
191
            {
192
193
                /* Check the endpoint direction, and type.  */
194
18
                if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN)
195
                {
196
197
                    /* Look at type.  */
198
9
                    if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)
199
                    {
200
201
                        /* We have found the bulk in endpoint, save it.  */
202
6
                        cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint =  endpoint;
203
#if (UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1) && !defined(UX_DEVICE_CLASS_CDC_ECM_ZERO_COPY)
204
                        endpoint -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer =
205
                                UX_DEVICE_CLASS_CDC_ECM_BULKIN_BUFFER(cdc_ecm);
206
#endif
207
                    }
208
209
                }
210
                else
211
                {
212
                    /* Look at type for out endpoint.  */
213
9
                    if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)
214
                    {
215
216
                        /* We have found the bulk out endpoint, save it.  */
217
6
                        cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint =  endpoint;
218
#if (UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1) && !defined(UX_DEVICE_CLASS_CDC_ECM_ZERO_COPY)
219
                        endpoint -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer =
220
                                UX_DEVICE_CLASS_CDC_ECM_BULKOUT_BUFFER(cdc_ecm);
221
#endif
222
                    }
223
                }
224
225
                /* Next endpoint.  */
226
18
                endpoint =  endpoint -> ux_slave_endpoint_next_endpoint;
227
            }
228
229
230
            /* Now check if all endpoints have been found.  */
231

9
            if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint == UX_NULL || cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint == UX_NULL)
232
233
                /* Not all endpoints have been found. Major error, do not proceed.  */
234
6
                return(UX_ERROR);
235
236
            /* Declare the link to be up. That may need to change later to make it dependent on the
237
               WAN/Wireless modem.  */
238
3
            cdc_ecm -> ux_slave_class_cdc_ecm_link_state = UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP;
239
240
            /* Wake up the Interrupt thread and send a network notification to the host.  */
241
3
            _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);
242
243
#if (UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1) && defined(UX_DEVICE_CLASS_CDC_ECM_ZERO_COPY)
244
245
            /* There is no endpoint buffer.  */
246
#else
247
248
            /* Reset the endpoint buffers.  */
249
3
            _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint -> ux_slave_endpoint_transfer_request.
250
                                            ux_slave_transfer_request_data_pointer, 0, UX_DEVICE_CLASS_CDC_ECM_BULKOUT_BUFFER_SIZE); /* Use case of memset is verified. */
251
3
            _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint -> ux_slave_endpoint_transfer_request.
252
                                            ux_slave_transfer_request_data_pointer, 0, UX_DEVICE_CLASS_CDC_ECM_BULKIN_BUFFER_SIZE); /* Use case of memset is verified. */
253
#endif
254
255
            /* Resume the endpoint threads.  */
256
3
            _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread);
257
3
            _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread);
258
259
        }
260
261
        /* Setup the physical address of this IP instance.  */
262
115
        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]));
263
115
        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) |
264
115
                                                       (cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id[4] << 8) | (cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id[5]));
265
266
        /* Register this interface to the NetX USB interface broker.  */
267
115
        _ux_network_driver_activate((VOID *) cdc_ecm, _ux_device_class_cdc_ecm_write,
268
                                        &cdc_ecm -> ux_slave_class_cdc_ecm_network_handle,
269
                                        physical_address_msw,
270
                                        physical_address_lsw);
271
272
        /* Check Link.  */
273
115
        if (cdc_ecm -> ux_slave_class_cdc_ecm_link_state == UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP)
274
        {
275
276
            /* Communicate the state with the network driver.  */
277
3
            _ux_network_driver_link_up(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle);
278
279
            /* If there is an activate function call it.  */
280
3
            if (cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate != UX_NULL)
281
282
                /* Invoke the application.  */
283
1
                cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate(cdc_ecm);
284
        }
285
    }
286
287
    /* If trace is enabled, insert this event into the trace buffer.  */
288
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ECM_ACTIVATE, cdc_ecm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
289
290
    /* If trace is enabled, register this object.  */
291
    UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, cdc_ecm, 0, 0, 0)
292
293
    /* Return completion status.  */
294
236
    return(UX_SUCCESS);
295
#endif
296
}