GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_device_classes/src/ux_device_class_cdc_ecm_initialize.c Lines: 61 61 100.0 %
Date: 2024-12-12 17:16:36 Branches: 32 32 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_initialize                 PORTABLE C      */
35
/*                                                           6.3.0        */
36
/*  AUTHOR                                                                */
37
/*                                                                        */
38
/*    Chaoqiong Xiao, Microsoft Corporation                               */
39
/*                                                                        */
40
/*  DESCRIPTION                                                           */
41
/*                                                                        */
42
/*    This function initializes 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
/*    _ux_utility_memory_allocate           Allocate memory               */
55
/*    _ux_utility_memory_free               Free memory                   */
56
/*    _ux_utility_mutex_create              Create Mutex                  */
57
/*    _ux_device_mutex_delete               Delete Mutex                  */
58
/*    _ux_utility_event_flags_create        Create Flag group             */
59
/*    _ux_utility_event_flags_delete        Delete Flag group             */
60
/*    _ux_device_thread_create              Create Thread                 */
61
/*    _ux_device_thread_delete              Delete Thread                 */
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
/*  10-31-2022     Chaoqiong Xiao           Modified comment(s),          */
89
/*                                            removed internal NX pool,   */
90
/*                                            resulting in version 6.2.0  */
91
/*  10-31-2023     Chaoqiong Xiao           Modified comment(s),          */
92
/*                                            added a new mode to manage  */
93
/*                                            endpoint buffer in classes, */
94
/*                                            resulting in version 6.3.0  */
95
/*                                                                        */
96
/**************************************************************************/
97
65
UINT  _ux_device_class_cdc_ecm_initialize(UX_SLAVE_CLASS_COMMAND *command)
98
{
99
#if defined(UX_DEVICE_STANDALONE)
100
    UX_PARAMETER_NOT_USED(command);
101
    return(UX_FUNCTION_NOT_SUPPORTED);
102
#else
103
104
UX_SLAVE_CLASS_CDC_ECM                          *cdc_ecm;
105
UX_SLAVE_CLASS_CDC_ECM_PARAMETER                *cdc_ecm_parameter;
106
UX_SLAVE_CLASS                                  *class_ptr;
107
UINT                                            status;
108
109
110
    /* Get the class container.  */
111
65
    class_ptr =  command -> ux_slave_class_command_class_ptr;
112
113
    /* Create an instance of the device cdc_ecm class.  */
114
65
    cdc_ecm =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_CDC_ECM));
115
116
    /* Check for successful allocation.  */
117
65
    if (cdc_ecm == UX_NULL)
118
1
        return(UX_MEMORY_INSUFFICIENT);
119
120
    /* Create a mutex to protect the CDC_ECM thread and the application messing up the transmit queue.  */
121
64
    status =  _ux_utility_mutex_create(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex, "ux_slave_class_cdc_ecm_mutex");
122
64
    if (status != UX_SUCCESS)
123
    {
124
1
        _ux_utility_memory_free(cdc_ecm);
125
1
        return(UX_MUTEX_ERROR);
126
    }
127
128
    /* Assume good result.  */
129
63
    status = UX_SUCCESS;
130
131
#if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
132
133
    /* Allocate buffer for endpoints.  */
134
    UX_ASSERT(!UX_DEVICE_CLASS_CDC_ECM_ENDPOINT_BUFFER_SIZE_CALC_OVERFLOW);
135
    cdc_ecm -> ux_device_class_cdc_ecm_endpoint_buffer =
136
            _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY,
137
                                        UX_DEVICE_CLASS_CDC_ECM_ENDPOINT_BUFFER_SIZE);
138
    if (cdc_ecm -> ux_device_class_cdc_ecm_endpoint_buffer == UX_NULL)
139
        status = (UX_MEMORY_INSUFFICIENT);
140
#endif
141
142
    /* Allocate some memory for the bulk out thread stack. */
143
63
    cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack =
144
63
            _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE);
145
63
    if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack == UX_NULL)
146
1
        status = (UX_MEMORY_INSUFFICIENT);
147
148
    /* Allocate some memory for the interrupt thread stack. */
149
63
    if (status == UX_SUCCESS)
150
    {
151
62
        cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack =
152
62
                _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE);
153
154
        /* Check for successful allocation.  */
155
62
        if (cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack  == UX_NULL)
156
1
            status = (UX_MEMORY_INSUFFICIENT);
157
    }
158
159
    /* Allocate some memory for the bulk in thread stack. */
160
63
    if (status == UX_SUCCESS)
161
    {
162
61
        cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack =
163
61
                _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE);
164
165
        /* Check for successful allocation.  */
166
61
        if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack == UX_NULL)
167
1
            status = (UX_MEMORY_INSUFFICIENT);
168
    }
169
170
    /* Interrupt endpoint treatment needs to be running in a different thread. So start
171
       a new thread. We pass a pointer to the cdc_ecm instance to the new thread.  This thread
172
       does not start until we have a instance of the class. */
173
63
    if (status == UX_SUCCESS)
174
    {
175
60
        status =  _ux_device_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread , "ux_slave_class_cdc_ecm_interrupt_thread",
176
                    _ux_device_class_cdc_ecm_interrupt_thread,
177
60
                    (ULONG) (ALIGN_TYPE) class_ptr, (VOID *) cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack ,
178
                    UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
179
                    UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
180
60
        if (status != UX_SUCCESS)
181
1
            status = (UX_THREAD_ERROR);
182
    }
183
184
    UX_THREAD_EXTENSION_PTR_SET(&(cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread), class_ptr)
185
186
    /* Check the creation of this thread.  */
187
63
    if (status == UX_SUCCESS)
188
    {
189
190
        /* Bulk endpoint treatment needs to be running in a different thread. So start
191
        a new thread. We pass a pointer to the cdc_ecm instance to the new thread.  This thread
192
        does not start until we have a instance of the class. */
193
59
        status =  _ux_device_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread , "ux_slave_class_cdc_ecm_bulkout_thread",
194
                    _ux_device_class_cdc_ecm_bulkout_thread,
195
59
                    (ULONG) (ALIGN_TYPE) class_ptr, (VOID *) cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack ,
196
                    UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
197
                    UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
198
59
        if (status != UX_SUCCESS)
199
1
            status = (UX_THREAD_ERROR);
200
        else
201
        {
202
203
            UX_THREAD_EXTENSION_PTR_SET(&(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread), class_ptr)
204
205
            /* Bulk endpoint treatment needs to be running in a different thread. So start
206
            a new thread. We pass a pointer to the cdc_ecm instance to the new thread.  This thread
207
            does not start until we have a instance of the class. */
208
58
            status =  _ux_device_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread , "ux_slave_class_cdc_ecm_bulkin_thread",
209
                        _ux_device_class_cdc_ecm_bulkin_thread,
210
58
                        (ULONG) (ALIGN_TYPE) class_ptr, (VOID *) cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack ,
211
                        UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
212
                        UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
213
58
            if (status != UX_SUCCESS)
214
1
                status = (UX_THREAD_ERROR);
215
            else
216
            {
217
218
                UX_THREAD_EXTENSION_PTR_SET(&(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread), class_ptr)
219
220
                /* Create a event flag group for the cdc_ecm class to synchronize with the event interrupt thread.  */
221
57
                status =  _ux_utility_event_flags_create(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, "ux_device_class_cdc_ecm_event_flag");
222
57
                if (status != UX_SUCCESS)
223
1
                    status = (UX_EVENT_ERROR);
224
                else
225
                {
226
227
                    /* Save the address of the CDC_ECM instance inside the CDC_ECM container.  */
228
56
                    class_ptr -> ux_slave_class_instance = (VOID *) cdc_ecm;
229
230
                    /* Get the pointer to the application parameters for the cdc_ecm class.  */
231
56
                    cdc_ecm_parameter =  command -> ux_slave_class_command_parameter;
232
233
                    /* Store the start and stop signals if needed by the application.  */
234
56
                    cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate = cdc_ecm_parameter -> ux_slave_class_cdc_ecm_instance_activate;
235
56
                    cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate = cdc_ecm_parameter -> ux_slave_class_cdc_ecm_instance_deactivate;
236
237
                    /* Copy the local node ID.  */
238
56
                    _ux_utility_memory_copy(cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id, cdc_ecm_parameter -> ux_slave_class_cdc_ecm_parameter_local_node_id,
239
                                            UX_DEVICE_CLASS_CDC_ECM_NODE_ID_LENGTH); /* Use case of memcpy is verified. */
240
241
                    /* Copy the remote node ID.  */
242
56
                    _ux_utility_memory_copy(cdc_ecm -> ux_slave_class_cdc_ecm_remote_node_id, cdc_ecm_parameter -> ux_slave_class_cdc_ecm_parameter_remote_node_id,
243
                                            UX_DEVICE_CLASS_CDC_ECM_NODE_ID_LENGTH); /* Use case of memcpy is verified. */
244
245
                    /* Store the rest of the parameters as they are in the local instance.  */
246
56
                    _ux_utility_memory_copy(&cdc_ecm -> ux_slave_class_cdc_ecm_parameter, cdc_ecm_parameter, sizeof (UX_SLAVE_CLASS_CDC_ECM_PARAMETER)); /* Use case of memcpy is verified. */
247
248
56
                    return(UX_SUCCESS);
249
                }
250
251
1
                _ux_device_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread);
252
            }
253
254
2
            _ux_device_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread);
255
        }
256
257
3
        _ux_device_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread);
258
    }
259
260
    /* Free allocated resources.  */
261
262
7
    if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack)
263
4
        _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack);
264
7
    if (cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack)
265
5
        _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack);
266
7
    if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack)
267
6
        _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack);
268
#if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
269
    if (cdc_ecm -> ux_device_class_cdc_ecm_endpoint_buffer)
270
        _ux_utility_memory_free(cdc_ecm -> ux_device_class_cdc_ecm_endpoint_buffer);
271
#endif
272
7
    _ux_device_mutex_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex);
273
7
    _ux_utility_memory_free(cdc_ecm);
274
275
    /* Return completion status.  */
276
7
    return(status);
277
#endif
278
}