GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_device_classes/src/ux_device_class_cdc_acm_read.c Lines: 35 39 89.7 %
Date: 2026-03-06 18:57:10 Branches: 18 26 69.2 %

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
/** USBX Component                                                        */
16
/**                                                                       */
17
/**   Device CDC Class                                                    */
18
/**                                                                       */
19
/**************************************************************************/
20
/**************************************************************************/
21
22
#define UX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
27
#include "ux_api.h"
28
#include "ux_device_class_cdc_acm.h"
29
#include "ux_device_stack.h"
30
31
32
#if !defined(UX_DEVICE_STANDALONE)
33
/**************************************************************************/
34
/*                                                                        */
35
/*  FUNCTION                                               RELEASE        */
36
/*                                                                        */
37
/*    _ux_device_class_cdc_acm_read                       PORTABLE C      */
38
/*                                                           6.3.0        */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Chaoqiong Xiao, Microsoft Corporation                               */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    This function reads from the CDC class.                             */
46
/*                                                                        */
47
/*    It's for RTOS mode.                                                 */
48
/*                                                                        */
49
/*  INPUT                                                                 */
50
/*                                                                        */
51
/*    cdc_acm                                   Address of cdc_acm class  */
52
/*                                              instance                  */
53
/*    buffer                                    Pointer to buffer to save */
54
/*                                              received data             */
55
/*    requested_length                          Length of bytes to read   */
56
/*    actual_length                             Pointer to save number of */
57
/*                                              bytes read                */
58
/*                                                                        */
59
/*  OUTPUT                                                                */
60
/*                                                                        */
61
/*    None                                                                */
62
/*                                                                        */
63
/*  CALLS                                                                 */
64
/*                                                                        */
65
/*    _ux_device_stack_transfer_request     Transfer request              */
66
/*    _ux_utility_memory_copy               Copy memory                   */
67
/*    _ux_device_mutex_off                  Release mutex                 */
68
/*                                                                        */
69
/*  CALLED BY                                                             */
70
/*                                                                        */
71
/*    Application                                                         */
72
/*                                                                        */
73
/**************************************************************************/
74
65
UINT _ux_device_class_cdc_acm_read(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer,
75
                                ULONG requested_length, ULONG *actual_length)
76
{
77
78
UX_SLAVE_ENDPOINT           *endpoint;
79
UX_SLAVE_DEVICE             *device;
80
UX_SLAVE_INTERFACE          *interface_ptr;
81
UX_SLAVE_TRANSFER           *transfer_request;
82
65
UINT                        status= UX_SUCCESS;
83
ULONG                       local_requested_length;
84
85
    /* If trace is enabled, insert this event into the trace buffer.  */
86
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ACM_READ, cdc_acm, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
87
88
#ifndef UX_DEVICE_CLASS_CDC_ACM_TRANSMISSION_DISABLE
89
90
    /* Check if current cdc-acm is using callback or not. We cannot use direct reads with callback on.  */
91
65
    if (cdc_acm -> ux_slave_class_cdc_acm_transmission_status == UX_TRUE)
92
93
        /* Not allowed. */
94
1
        return(UX_ERROR);
95
#endif
96
97
    /* Get the pointer to the device.  */
98
64
    device =  &_ux_system_slave -> ux_system_slave_device;
99
100
    /* As long as the device is in the CONFIGURED state.  */
101
64
    if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
102
    {
103
104
        /* Error trap. */
105
10
        _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN);
106
107
108
        /* If trace is enabled, insert this event into the trace buffer.  */
109
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0)
110
111
        /* Cannot proceed with command, the interface is down.  */
112
10
        return(UX_CONFIGURATION_HANDLE_UNKNOWN);
113
    }
114
115
    /* This is the first time we are activated. We need the interface to the class.  */
116
54
    interface_ptr =  cdc_acm -> ux_slave_class_cdc_acm_interface;
117
118
    /* Locate the endpoints.  */
119
54
    endpoint =  interface_ptr -> ux_slave_interface_first_endpoint;
120
121
    /* Check the endpoint direction, if OUT we have the correct endpoint.  */
122
54
    if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT)
123
    {
124
125
        /* So the next endpoint has to be the OUT endpoint.  */
126
39
        endpoint =  endpoint -> ux_slave_endpoint_next_endpoint;
127
    }
128
129
    /* Protect this thread.  */
130
54
    _ux_device_mutex_on(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex);
131
132
    /* All CDC readings are on the endpoint OUT, from the host.  */
133
54
    transfer_request =  &endpoint -> ux_slave_endpoint_transfer_request;
134
135
#if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
136
#if !defined(UX_DEVICE_CLASS_CDC_ACM_ZERO_COPY)
137
    transfer_request -> ux_slave_transfer_request_data_pointer =
138
                                UX_DEVICE_CLASS_CDC_ACM_READ_BUFFER(cdc_acm);
139
#else
140
    transfer_request -> ux_slave_transfer_request_data_pointer = buffer;
141
#endif
142
#endif
143
144
#if (UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1) && defined(UX_DEVICE_CLASS_CDC_ACM_ZERO_COPY)
145
146
    /* Check if device is configured.  */
147
    if (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED)
148
    {
149
150
        /* Issue the transfer request.  */
151
        local_requested_length = requested_length;
152
        status = _ux_device_stack_transfer_request(transfer_request, requested_length, local_requested_length);
153
        *actual_length = transfer_request -> ux_slave_transfer_request_actual_length;
154
    }
155
156
#else
157
158
    /* Reset the actual length.  */
159
54
    *actual_length =  0;
160
161
    /* Check if we need more transactions.  */
162

196
    while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED && requested_length != 0)
163
    {
164
165
        /* Check if we have enough in the local buffer.  */
166
192
        if (requested_length > endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize)
167
168
            /* We have too much to transfer.  */
169
179
            local_requested_length = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize;
170
171
        else
172
173
            /* We can proceed with the demanded length.  */
174
13
            local_requested_length = requested_length;
175
176
        /* Send the request to the device controller.  */
177
192
        status =  _ux_device_stack_transfer_request(transfer_request, local_requested_length, local_requested_length);
178
179
        /* Check the status */
180
192
        if (status == UX_SUCCESS)
181
        {
182
183
            /* We need to copy the buffer locally.  */
184
174
            _ux_utility_memory_copy(buffer, transfer_request -> ux_slave_transfer_request_data_pointer,
185
                            transfer_request -> ux_slave_transfer_request_actual_length); /* Use case of memcpy is verified. */
186
187
            /* Next buffer address.  */
188
174
            buffer += transfer_request -> ux_slave_transfer_request_actual_length;
189
190
            /* Set the length actually received. */
191
174
            *actual_length += transfer_request -> ux_slave_transfer_request_actual_length;
192
193
            /* Decrement what left has to be done.  */
194
174
            requested_length -= transfer_request -> ux_slave_transfer_request_actual_length;
195
196
197
            /* Is this a short packet or a ZLP indicating we are done with this transfer ?  */
198
174
            if (transfer_request -> ux_slave_transfer_request_actual_length < endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize)
199
            {
200
201
                /* We are done.  */
202
                /* Free Mutex resource.  */
203
32
                _ux_device_mutex_off(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex);
204
205
                /* Return with success.  */
206
32
                return(UX_SUCCESS);
207
208
            }
209
        }
210
        else
211
        {
212
213
            /* Free Mutex resource.  */
214
18
            _ux_device_mutex_off(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex);
215
216
            /* We got an error.  */
217
18
            return(status);
218
        }
219
    }
220
221
#endif
222
223
    /* Free Mutex resource.  */
224
4
    _ux_device_mutex_off(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex);
225
226
    /* Check why we got here, either completion or device was extracted.  */
227
4
    if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
228
    {
229
230
        /* Error trap. */
231
1
        _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NO_ANSWER);
232
233
        /* If trace is enabled, insert this event into the trace buffer.  */
234
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0)
235
236
        /* Device must have been extracted.  */
237
1
        return (UX_TRANSFER_NO_ANSWER);
238
    }
239
    else
240
241
        /* Simply return the last transaction result.  */
242
3
        return(status);
243
}
244
245
/**************************************************************************/
246
/*                                                                        */
247
/*  FUNCTION                                               RELEASE        */
248
/*                                                                        */
249
/*    _uxe_device_class_cdc_acm_read                      PORTABLE C      */
250
/*                                                           6.3.0        */
251
/*  AUTHOR                                                                */
252
/*                                                                        */
253
/*    Yajun Xia, Microsoft Corporation                                    */
254
/*                                                                        */
255
/*  DESCRIPTION                                                           */
256
/*                                                                        */
257
/*    This function checks errors in CDC ACM class read function.         */
258
/*                                                                        */
259
/*  INPUT                                                                 */
260
/*                                                                        */
261
/*    cdc_acm                                   Address of cdc_acm class  */
262
/*                                              instance                  */
263
/*    buffer                                    Pointer to buffer to save */
264
/*                                              received data             */
265
/*    requested_length                          Length of bytes to read   */
266
/*    actual_length                             Pointer to save number of */
267
/*                                              bytes read                */
268
/*                                                                        */
269
/*  OUTPUT                                                                */
270
/*                                                                        */
271
/*    None                                                                */
272
/*                                                                        */
273
/*  CALLS                                                                 */
274
/*                                                                        */
275
/*    _ux_device_class_cdc_acm_read         CDC ACM class read function   */
276
/*                                                                        */
277
/*  CALLED BY                                                             */
278
/*                                                                        */
279
/*    Application                                                         */
280
/*                                                                        */
281
/**************************************************************************/
282
UINT _uxe_device_class_cdc_acm_read(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer,
283
                                    ULONG requested_length, ULONG *actual_length)
284
{
285
286
    /* Sanity checks.  */
287
    if ((cdc_acm == UX_NULL) || ((buffer == UX_NULL) && (requested_length > 0)) || (actual_length == UX_NULL))
288
    {
289
        return (UX_INVALID_PARAMETER);
290
    }
291
292
    return (_ux_device_class_cdc_acm_read(cdc_acm, buffer, requested_length, actual_length));
293
}
294
295
#endif