GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_device_classes/src/ux_device_class_cdc_acm_initialize.c Lines: 56 56 100.0 %
Date: 2026-03-06 18:57:10 Branches: 28 28 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
10
 **************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** USBX Component                                                        */
17
/**                                                                       */
18
/**   Device CDC ACM Class                                                */
19
/**                                                                       */
20
/**************************************************************************/
21
/**************************************************************************/
22
23
#define UX_SOURCE_CODE
24
25
26
/* Include necessary system files.  */
27
28
#include "ux_api.h"
29
#include "ux_device_class_cdc_acm.h"
30
#include "ux_device_stack.h"
31
32
33
#if UX_OVERFLOW_CHECK_MULC_ULONG(UX_THREAD_STACK_SIZE, 2)
34
#error UX_THREAD_STACK_SIZE too large
35
#endif
36
37
/**************************************************************************/
38
/*                                                                        */
39
/*  FUNCTION                                               RELEASE        */
40
/*                                                                        */
41
/*    _ux_device_class_cdc_acm_initialize                 PORTABLE C      */
42
/*                                                           6.3.0        */
43
/*  AUTHOR                                                                */
44
/*                                                                        */
45
/*    Chaoqiong Xiao, Microsoft Corporation                               */
46
/*                                                                        */
47
/*  DESCRIPTION                                                           */
48
/*                                                                        */
49
/*    This function initializes the USB CDC device.                       */
50
/*                                                                        */
51
/*  INPUT                                                                 */
52
/*                                                                        */
53
/*    command                               Pointer to cdc acm command    */
54
/*                                                                        */
55
/*  OUTPUT                                                                */
56
/*                                                                        */
57
/*    Completion Status                                                   */
58
/*                                                                        */
59
/*  CALLS                                                                 */
60
/*                                                                        */
61
/*    _ux_utility_memory_allocate           Allocate memory               */
62
/*    _ux_utility_memory_free               Free memory                   */
63
/*    _ux_utility_mutex_create              Create mutex                  */
64
/*    _ux_device_mutex_delete               Delete mutex                  */
65
/*                                                                        */
66
/*  CALLED BY                                                             */
67
/*                                                                        */
68
/*    USBX Source Code                                                    */
69
/*                                                                        */
70
/**************************************************************************/
71
68
UINT  _ux_device_class_cdc_acm_initialize(UX_SLAVE_CLASS_COMMAND *command)
72
{
73
74
UX_SLAVE_CLASS_CDC_ACM                  *cdc_acm;
75
UX_SLAVE_CLASS_CDC_ACM_PARAMETER        *cdc_acm_parameter;
76
UX_SLAVE_CLASS                          *class_ptr;
77
#if !defined(UX_DEVICE_STANDALONE)
78
UINT                                    status;
79
#endif
80
81
    /* Get the class container.  */
82
68
    class_ptr =  command -> ux_slave_class_command_class_ptr;
83
84
    /* Create an instance of the device cdc_acm class.  */
85
68
    cdc_acm =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_CDC_ACM));
86
87
    /* Check for successful allocation.  */
88
68
    if (cdc_acm == UX_NULL)
89
1
        return(UX_MEMORY_INSUFFICIENT);
90
91
    /* Save the address of the CDC instance inside the CDC container.  */
92
67
    class_ptr -> ux_slave_class_instance = (VOID *) cdc_acm;
93
94
    /* Get the pointer to the application parameters for the cdc_acm class.  */
95
67
    cdc_acm_parameter =  command -> ux_slave_class_command_parameter;
96
97
    /* Store the start and stop signals if needed by the application.  */
98
67
    cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_instance_activate = cdc_acm_parameter -> ux_slave_class_cdc_acm_instance_activate;
99
67
    cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_instance_deactivate = cdc_acm_parameter -> ux_slave_class_cdc_acm_instance_deactivate;
100
67
    cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_parameter_change = cdc_acm_parameter -> ux_slave_class_cdc_acm_parameter_change;
101
102
#if defined(UX_DEVICE_CLASS_CDC_ACM_OWN_ENDPOINT_BUFFER)
103
104
    /* Allocate the buffer for the CDC ACM endpoints.  */
105
    UX_ASSERT(!UX_DEVICE_CLASS_CDC_ACM_ENDPOINT_BUFFER_SIZE_CALC_OVERFLOW);
106
    cdc_acm -> ux_device_class_cdc_acm_endpoint_buffer = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY,
107
                                    UX_DEVICE_CLASS_CDC_ACM_ENDPOINT_BUFFER_SIZE);
108
    if (cdc_acm -> ux_device_class_cdc_acm_endpoint_buffer == UX_NULL)
109
    {
110
111
        /* Free the resources.  */
112
        _ux_utility_memory_free(cdc_acm);
113
114
        /* Return fatal error.  */
115
        return(UX_MEMORY_INSUFFICIENT);
116
    }
117
#endif
118
119
#if !defined(UX_DEVICE_STANDALONE)
120
121
    /* Create the Mutex for each endpoint as multiple threads cannot access each pipe at the same time.  */
122
67
    status =  _ux_utility_mutex_create(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex, "ux_slave_class_cdc_acm_in_mutex");
123
124
    /* Check Mutex creation error.  */
125
67
    if(status != UX_SUCCESS)
126
    {
127
128
        /* Free the resources.  */
129
#if defined(UX_DEVICE_CLASS_CDC_ACM_OWN_ENDPOINT_BUFFER)
130
        _ux_utility_memory_free(cdc_acm -> ux_device_class_cdc_acm_endpoint_buffer);
131
#endif
132
1
        _ux_utility_memory_free(cdc_acm);
133
134
        /* Return fatal error.  */
135
1
        return(UX_MUTEX_ERROR);
136
    }
137
138
    /* Out Mutex. */
139
66
    status =  _ux_utility_mutex_create(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex, "ux_slave_class_cdc_acm_out_mutex");
140
141
    /* Check Mutex creation error.  */
142
66
    if(status != UX_SUCCESS)
143
    {
144
145
        /* Delete the endpoint IN mutex.  */
146
1
        _ux_device_mutex_delete(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex);
147
148
        /* Free the resources.  */
149
#if defined(UX_DEVICE_CLASS_CDC_ACM_OWN_ENDPOINT_BUFFER)
150
        _ux_utility_memory_free(cdc_acm -> ux_device_class_cdc_acm_endpoint_buffer);
151
#endif
152
1
        _ux_utility_memory_free(cdc_acm);
153
154
        /* Return fatal error.  */
155
1
        return(UX_MUTEX_ERROR);
156
    }
157
158
#endif
159
160
    /* Update the line coding fields with default values.  */
161
65
    cdc_acm -> ux_slave_class_cdc_acm_baudrate  =  UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_BAUDRATE;
162
65
    cdc_acm -> ux_slave_class_cdc_acm_stop_bit  =  UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_STOP_BIT;
163
65
    cdc_acm -> ux_slave_class_cdc_acm_parity    =  UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARITY;
164
65
    cdc_acm -> ux_slave_class_cdc_acm_data_bit  =  UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_DATA_BIT;
165
166
    /* Initialize break duration.  */
167
65
    cdc_acm -> ux_slave_class_cdc_acm_break_duration = 0;
168
169
#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE
170
171
#if defined(UX_DEVICE_STANDALONE)
172
173
    /* Set task function.  */
174
    class_ptr -> ux_slave_class_task_function = _ux_device_class_cdc_acm_tasks_run;
175
#else
176
177
    /* We need to prepare the 2 threads for sending and receiving.  */
178
    /* Allocate some memory for the bulk out and in thread stack. */
179
65
    cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack =
180
65
            _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE * 2);
181
182
    /* Check for successful allocation.  */
183
65
    if (cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack == UX_NULL)
184
185
        /* Return the status to the caller.  */
186
1
        status = (UX_MEMORY_INSUFFICIENT);
187
188
    /* If success, go on to create event flags.  */
189
65
    if (status == UX_SUCCESS)
190
    {
191
192
        /* Allocate some memory for the bulk in thread stack. */
193
64
        cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack =
194
64
            cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack + UX_THREAD_STACK_SIZE;
195
196
        /* Create a event flag group for the cdc_acm class to synchronize with the application writing event .  */
197
64
        status =  _ux_utility_event_flags_create(
198
                        &cdc_acm -> ux_slave_class_cdc_acm_event_flags_group,
199
                        "ux_device_class_cdc_acm_event_flag");
200
201
        /* Check status.  */
202
64
        if (status != UX_SUCCESS)
203
        {
204
1
            status = (UX_EVENT_ERROR);
205
        }
206
    }
207
208
    /* If success, go on to create bulkin thread.  */
209
65
    if (status == UX_SUCCESS)
210
    {
211
212
        /* Bulk endpoint treatment needs to be running in a different thread. So start
213
            a new thread. We pass a pointer to the cdc_acm instance to the new thread.  This thread
214
            does not start until we have a instance of the class. */
215
63
        status =  _ux_utility_thread_create(
216
                    &cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread,
217
                    "ux_slave_class_cdc_acm_bulkin_thread",
218
                    _ux_device_class_cdc_acm_bulkin_thread,
219
                    (ULONG) (ALIGN_TYPE) cdc_acm,
220
63
                    (VOID *) cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack,
221
                    UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
222
                    UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
223
224
        /* Check the creation of this thread.  */
225
63
        if (status != UX_SUCCESS)
226
        {
227
1
            status = (UX_THREAD_ERROR);
228
        }
229
        else
230
        {
231
            UX_THREAD_EXTENSION_PTR_SET(
232
                &(cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread), cdc_acm)
233
        }
234
    }
235
236
    /* If success, go on to create bulkout thread.  */
237
65
    if (status == UX_SUCCESS)
238
    {
239
240
        /* Bulk endpoint treatment needs to be running in a different thread. So start
241
            a new thread. We pass a pointer to the cdc_acm instance to the new thread.  This thread
242
            does not start until we have a instance of the class. */
243
62
        status =  _ux_utility_thread_create(
244
                    &cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread,
245
                    "ux_slave_class_cdc_acm_bulkout_thread",
246
                    _ux_device_class_cdc_acm_bulkout_thread,
247
                    (ULONG) (ALIGN_TYPE) cdc_acm,
248
62
                    (VOID *) cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack,
249
                    UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
250
                    UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
251
252
        /* Check the creation of this thread.  */
253
62
        if (status != UX_SUCCESS)
254
        {
255
1
            status = (UX_THREAD_ERROR);
256
        }
257
        else
258
        {
259
            UX_THREAD_EXTENSION_PTR_SET(
260
                &(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread), cdc_acm)
261
        }
262
    }
263
264
    /* Check error.  */
265
65
    if (status != UX_SUCCESS)
266
    {
267
268
        /* Free resources and return error.  */
269
4
        if (_ux_device_thread_created(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread))
270
1
            _ux_utility_thread_delete(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread);
271
4
        if (_ux_device_event_flags_created(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group))
272
2
            _ux_utility_event_flags_delete(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group);
273
4
        if (cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack)
274
3
            _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack);
275
4
        _ux_device_mutex_delete(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex);
276
4
        _ux_device_mutex_delete(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex);
277
#if defined(UX_DEVICE_CLASS_CDC_ACM_OWN_ENDPOINT_BUFFER)
278
        _ux_utility_memory_free(cdc_acm -> ux_device_class_cdc_acm_endpoint_buffer);
279
#endif
280
4
        _ux_utility_memory_free(cdc_acm);
281
4
        return(status);
282
    }
283
284
#endif
285
#endif
286
287
    /* Return completion status.  */
288
61
    return(UX_SUCCESS);
289
}