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