GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_cdc_acm_write.c Lines: 31 36 86.1 %
Date: 2026-03-06 18:57:10 Branches: 14 22 63.6 %

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
/**   CDC ACM Class                                                       */
19
/**                                                                       */
20
/**************************************************************************/
21
/**************************************************************************/
22
23
24
/* Include necessary system files.  */
25
26
#define UX_SOURCE_CODE
27
28
#include "ux_api.h"
29
#include "ux_host_class_cdc_acm.h"
30
#include "ux_host_stack.h"
31
32
33
/**************************************************************************/
34
/*                                                                        */
35
/*  FUNCTION                                               RELEASE        */
36
/*                                                                        */
37
/*    _ux_host_class_cdc_acm_write                        PORTABLE C      */
38
/*                                                           6.1.10       */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Chaoqiong Xiao, Microsoft Corporation                               */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    This function writes to the cdc_acm interface. The call is blocking */
46
/*    and only returns when there is either an error or when the transfer */
47
/*    is complete.                                                        */
48
/*                                                                        */
49
/*  INPUT                                                                 */
50
/*                                                                        */
51
/*    cdc_acm                               Pointer to cdc_acm class      */
52
/*    data_pointer                          Pointer to data to write      */
53
/*    requested_length                      Length of data to write       */
54
/*    actual_length                         Actual length of data written */
55
/*                                                                        */
56
/*  OUTPUT                                                                */
57
/*                                                                        */
58
/*    Completion Status                                                   */
59
/*                                                                        */
60
/*  CALLS                                                                 */
61
/*                                                                        */
62
/*    _ux_host_stack_transfer_request       Process transfer request      */
63
/*    _ux_host_stack_transfer_request_abort Abort transfer request        */
64
/*    _ux_host_semaphore_get                Get protection semaphore      */
65
/*                                                                        */
66
/*  CALLED BY                                                             */
67
/*                                                                        */
68
/*    Application                                                         */
69
/*                                                                        */
70
/**************************************************************************/
71
44
UINT  _ux_host_class_cdc_acm_write(UX_HOST_CLASS_CDC_ACM *cdc_acm, UCHAR *data_pointer,
72
                                    ULONG requested_length, ULONG *actual_length)
73
{
74
75
UX_TRANSFER     *transfer_request;
76
UINT            status;
77
ULONG           transfer_request_length;
78
#if defined(UX_HOST_STANDALONE)
79
ULONG           transfer_flags;
80
#endif
81
82
    /* If trace is enabled, insert this event into the trace buffer.  */
83
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_WRITE, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
84
85
    /* Ensure the instance is valid.  */
86
44
    if (cdc_acm -> ux_host_class_cdc_acm_state !=  UX_HOST_CLASS_INSTANCE_LIVE)
87
    {
88
89
        /* Error trap. */
90
1
        _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN);
91
92
        /* If trace is enabled, insert this event into the trace buffer.  */
93
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0)
94
95
1
        return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
96
    }
97
98
    /* As further protection, we must ensure this instance of the interface is the data interface and not
99
       the control interface !  */
100
43
    if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass != UX_HOST_CLASS_CDC_DATA_CLASS)
101
    {
102
103
        /* Error trap. */
104
1
        _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN);
105
106
        /* If trace is enabled, insert this event into the trace buffer.  */
107
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0)
108
109
1
        return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
110
    }
111
112
#if defined(UX_HOST_STANDALONE)
113
    if (cdc_acm -> ux_host_class_cdc_acm_write_state == UX_STATE_WAIT)
114
        return(UX_BUSY);
115
    cdc_acm -> ux_host_class_cdc_acm_write_state = UX_STATE_WAIT;
116
#endif
117
118
    /* Start by resetting the actual length of the transfer.  */
119
42
    *actual_length =  0;
120
121
    /* Get the pointer to the bulk out endpoint transfer request.  */
122
42
    transfer_request =  &cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint -> ux_endpoint_transfer_request;
123
124
#if defined(UX_HOST_STANDALONE)
125
126
    /* Enable auto wait.  */
127
    transfer_flags = transfer_request -> ux_transfer_request_flags;
128
    transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_WAIT;
129
#endif
130
131
    /* Perform a transfer on the bulk out endpoint until either the transfer is
132
       completed or when there is an error.  */
133
    do
134
    {
135
136
        /* Program the maximum authorized length for this transfer_request.  */
137
43
        if (requested_length > transfer_request -> ux_transfer_request_maximum_length)
138
2
            transfer_request_length =  transfer_request -> ux_transfer_request_maximum_length;
139
        else
140
41
            transfer_request_length =  requested_length;
141
142
        /* Initialize the transfer_request.  */
143
43
        transfer_request -> ux_transfer_request_data_pointer =  data_pointer;
144
43
        transfer_request -> ux_transfer_request_requested_length =  transfer_request_length;
145
146
        /* Perform the transfer.  */
147
43
        status =  _ux_host_stack_transfer_request(transfer_request);
148
149
        /* If the transfer is successful, we need to wait for the transfer request to be completed.  */
150
43
        if (status == UX_SUCCESS)
151
        {
152
153
#if !defined(UX_HOST_STANDALONE)
154
            /* Wait for the completion of the transfer request.  */
155
41
            status =  _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore,
156
                                             transfer_request -> ux_transfer_request_timeout_value);
157
158
            /* If the semaphore did not succeed we probably have a time out.  */
159
41
            if (status != UX_SUCCESS)
160
            {
161
162
                /* All transfers pending need to abort. There may have been a partial transfer.  */
163
1
                _ux_host_stack_transfer_request_abort(transfer_request);
164
165
                /* Update the length of the actual data transferred. We do this after the
166
                   abort of the transfer_request in case some data actually went out.  */
167
1
                *actual_length +=  transfer_request -> ux_transfer_request_actual_length;
168
169
                /* Set the completion code.  */
170
1
                transfer_request -> ux_transfer_request_completion_code =  UX_TRANSFER_TIMEOUT;
171
172
                /* Error trap. */
173
1
                _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT);
174
175
                /* If trace is enabled, insert this event into the trace buffer.  */
176
                UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0)
177
178
                /* There was an error, return to the caller.  */
179
1
                return(UX_TRANSFER_TIMEOUT);
180
            }
181
#endif
182
        }
183
        else
184
        {
185
186
#if defined(UX_HOST_STANDALONE)
187
188
            /* Update the length of the actual data transferred. We do this after the
189
                abort of the transfer request in case some data was actually received.  */
190
            *actual_length +=  transfer_request -> ux_transfer_request_actual_length;
191
192
            /* Restore previous setting.  */
193
            transfer_request -> ux_transfer_request_flags = transfer_flags;
194
195
            /* Not busy any more.  */
196
            cdc_acm -> ux_host_class_cdc_acm_write_state = UX_STATE_RESET;
197
#endif
198
199
            /* There was a non transfer error, no partial transfer to be checked */
200
2
            return(status);
201
        }
202
203
        /* Update the length of the transfer. Normally all the data has to be sent.  */
204
40
        *actual_length +=  transfer_request -> ux_transfer_request_actual_length;
205
206
        /* Check for completion of transfer. If the transfer is partial, return to caller.
207
           The transfer is marked as successful but the caller will need to check the length
208
           actually sent and determine if a partial transfer is OK. */
209
40
        if (transfer_request_length !=  transfer_request -> ux_transfer_request_actual_length)
210
        {
211
212
            /* Return success.  */
213
1
            return(UX_SUCCESS);
214
        }
215
216
        /* Update the data pointer for next transfer.  */
217
39
        data_pointer +=  transfer_request_length;
218
219
        /* Update what is left to send out.  */
220
39
        requested_length -=  transfer_request_length;
221
222
39
    } while (requested_length);
223
224
#if defined(UX_HOST_STANDALONE)
225
226
    /* Restore previous setting.  */
227
    transfer_request -> ux_transfer_request_flags = transfer_flags;
228
229
    /* Not busy any more.  */
230
    cdc_acm -> ux_host_class_cdc_acm_write_state = UX_STATE_RESET;
231
#endif
232
233
    /* We get here when all the transfers went through without errors.  */
234
38
    return(UX_SUCCESS);
235
}
236
237
238
/**************************************************************************/
239
/*                                                                        */
240
/*  FUNCTION                                               RELEASE        */
241
/*                                                                        */
242
/*    _uxe_host_class_cdc_acm_write                       PORTABLE C      */
243
/*                                                           6.3.0        */
244
/*  AUTHOR                                                                */
245
/*                                                                        */
246
/*    Chaoqiong Xiao, Microsoft Corporation                               */
247
/*                                                                        */
248
/*  DESCRIPTION                                                           */
249
/*                                                                        */
250
/*    This function checks errors in CDC ACM write function call.         */
251
/*                                                                        */
252
/*  INPUT                                                                 */
253
/*                                                                        */
254
/*    cdc_acm                               Pointer to CDC ACM class      */
255
/*    data_pointer                          Pointer to data to write      */
256
/*    requested_length                      Length of data to write       */
257
/*    actual_length                         Actual length of data written */
258
/*                                                                        */
259
/*  OUTPUT                                                                */
260
/*                                                                        */
261
/*    Status                                                              */
262
/*                                                                        */
263
/*  CALLS                                                                 */
264
/*                                                                        */
265
/*    _ux_host_class_cdc_acm_write          CDC ACM write                 */
266
/*                                                                        */
267
/*  CALLED BY                                                             */
268
/*                                                                        */
269
/*    Application                                                         */
270
/*                                                                        */
271
/**************************************************************************/
272
UINT  _uxe_host_class_cdc_acm_write(UX_HOST_CLASS_CDC_ACM *cdc_acm, UCHAR *data_pointer,
273
                                    ULONG requested_length, ULONG *actual_length)
274
{
275
276
    /* Sanity checks.  */
277
    if ((cdc_acm == UX_NULL) ||
278
        ((data_pointer == UX_NULL) && (requested_length != 0)) ||
279
        (actual_length == UX_NULL))
280
    {
281
        return(UX_INVALID_PARAMETER);
282
    }
283
284
    /* Invoke CDC ACM write function.  */
285
    return(_ux_host_class_cdc_acm_write(cdc_acm, data_pointer, requested_length, actual_length));
286
}