GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_cdc_acm_read.c Lines: 31 35 88.6 %
Date: 2026-03-06 18:57:10 Branches: 14 20 70.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
/**   ACM CDC 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_read                         PORTABLE C      */
38
/*                                                           6.1.10       */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Chaoqiong Xiao, Microsoft Corporation                               */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    This function reads from the cdc_acm interface. The call is         */
46
/*    blocking and only returns when there is either an error or when     */
47
/*    the transfer is complete.                                           */
48
/*                                                                        */
49
/*  INPUT                                                                 */
50
/*                                                                        */
51
/*    cdc_acm                               Pointer to cdc_acm class      */
52
/*    data_pointer                          Pointer to buffer             */
53
/*    requested_length                      Requested data read           */
54
/*    actual_length                         Actual data read              */
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
15
UINT  _ux_host_class_cdc_acm_read (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_READ, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
84
85
    /* Ensure the instance is valid.  */
86
15
    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
14
    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
    /* Start by resetting the actual length of the transfer to zero.  */
113
13
    *actual_length =  0;
114
115
    /* Get the pointer to the bulk in endpoint in the transfer_request.  */
116
13
    transfer_request =  &cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint -> ux_endpoint_transfer_request;
117
118
#if defined(UX_HOST_STANDALONE)
119
120
    /* Enable auto wait.  */
121
    transfer_flags = transfer_request -> ux_transfer_request_flags;
122
    transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_WAIT;
123
#endif
124
125
    /* Perform a transfer on the bulk in endpoint until either the transfer is
126
       completed or until there is an error.  */
127
20
    while (requested_length)
128
    {
129
130
        /* Program the maximum authorized length for this transfer request.  */
131
15
        if (requested_length > transfer_request -> ux_transfer_request_maximum_length)
132
4
            transfer_request_length =  transfer_request -> ux_transfer_request_maximum_length;
133
        else
134
11
            transfer_request_length =  requested_length;
135
136
        /* Initialize the transfer request.  */
137
15
        transfer_request -> ux_transfer_request_data_pointer =      data_pointer;
138
15
        transfer_request -> ux_transfer_request_requested_length =  transfer_request_length;
139
140
        /* Perform the transfer.  */
141
15
        status =  _ux_host_stack_transfer_request(transfer_request);
142
143
        /* If the transfer is successful, we need to wait for the transfer request to be completed.  */
144
15
        if (status == UX_SUCCESS)
145
        {
146
#if !defined(UX_HOST_STANDALONE)
147
148
            /* Wait for the completion of the transfer_request.  */
149
13
            status =  _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore,
150
                                             transfer_request -> ux_transfer_request_timeout_value);
151
152
            /* If the semaphore did not succeed we probably have a time out.  */
153
13
            if (status != UX_SUCCESS)
154
            {
155
156
                /* All transfers pending need to abort. There may have been a partial transfer.  */
157
2
                _ux_host_stack_transfer_request_abort(transfer_request);
158
159
                /* Update the length of the actual data transferred. We do this after the
160
                   abort of the transfer request in case some data was actually received.  */
161
2
                *actual_length +=  transfer_request -> ux_transfer_request_actual_length;
162
163
                /* Set the completion code.  */
164
2
                transfer_request -> ux_transfer_request_completion_code =  UX_TRANSFER_TIMEOUT;
165
166
                /* Error trap. */
167
2
                _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT);
168
169
                /* If trace is enabled, insert this event into the trace buffer.  */
170
                UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0)
171
172
                /* There was an error, return to the caller */
173
2
                return(UX_TRANSFER_TIMEOUT);
174
            }
175
#endif
176
        }
177
        else
178
        {
179
180
#if defined(UX_HOST_STANDALONE)
181
182
            /* Update the length of the actual data transferred. We do this after the
183
                abort of the transfer request in case some data was actually received.  */
184
            *actual_length +=  transfer_request -> ux_transfer_request_actual_length;
185
186
            /* Restore previous setting.  */
187
            transfer_request -> ux_transfer_request_flags = transfer_flags;
188
#endif
189
190
            /* There was a non transfer error, no partial transfer to be checked.  */
191
2
            return(status);
192
        }
193
194
        /* Update the length of the transfer. Normally all the data has to be received.  */
195
11
        *actual_length +=  transfer_request -> ux_transfer_request_actual_length;
196
197
        /* Check for completion of transfer. If the transfer is partial, return to caller.
198
           The transfer is marked as successful but the caller will need to check the length
199
           actually received and determine if a partial transfer is OK.  */
200
11
        if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length)
201
        {
202
203
            /* Return success to caller.  */
204
4
            return(UX_SUCCESS);
205
        }
206
207
        /* Update the data pointer for next transfer. */
208
7
        data_pointer +=  transfer_request_length;
209
210
        /* Update what is left to receive.  */
211
7
        requested_length -=  transfer_request_length;
212
    }
213
214
#if defined(UX_HOST_STANDALONE)
215
216
    /* Restore previous setting.  */
217
    transfer_request -> ux_transfer_request_flags = transfer_flags;
218
#endif
219
220
    /* We get here when all the transfers went through without errors.  */
221
5
    return(UX_SUCCESS);
222
}
223
224
225
/**************************************************************************/
226
/*                                                                        */
227
/*  FUNCTION                                               RELEASE        */
228
/*                                                                        */
229
/*    _uxe_host_class_cdc_acm_read                        PORTABLE C      */
230
/*                                                           6.3.0        */
231
/*  AUTHOR                                                                */
232
/*                                                                        */
233
/*    Chaoqiong Xiao, Microsoft Corporation                               */
234
/*                                                                        */
235
/*  DESCRIPTION                                                           */
236
/*                                                                        */
237
/*    This function checks errors in CDC ACM read function call.          */
238
/*                                                                        */
239
/*  INPUT                                                                 */
240
/*                                                                        */
241
/*    cdc_acm                               Pointer to CDC ACM class      */
242
/*    data_pointer                          Pointer to buffer             */
243
/*    requested_length                      Requested data read           */
244
/*    actual_length                         Actual data read              */
245
/*                                                                        */
246
/*  OUTPUT                                                                */
247
/*                                                                        */
248
/*    Status                                                              */
249
/*                                                                        */
250
/*  CALLS                                                                 */
251
/*                                                                        */
252
/*    _ux_host_class_cdc_acm_read           CDC ACM read                  */
253
/*                                                                        */
254
/*  CALLED BY                                                             */
255
/*                                                                        */
256
/*    Application                                                         */
257
/*                                                                        */
258
/**************************************************************************/
259
UINT  _uxe_host_class_cdc_acm_read (UX_HOST_CLASS_CDC_ACM *cdc_acm, UCHAR *data_pointer,
260
                                    ULONG requested_length, ULONG *actual_length)
261
{
262
263
    /* Sanity checks.  */
264
    if ((cdc_acm == UX_NULL) || (data_pointer == UX_NULL) || (actual_length == UX_NULL))
265
        return(UX_INVALID_PARAMETER);
266
267
    /* Invoke CDC ACM read function.  */
268
    return(_ux_host_class_cdc_acm_read(cdc_acm, data_pointer, requested_length, actual_length));
269
}