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: 2024-12-12 17:16:36 Branches: 14 22 63.6 %

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