GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_cdc_acm_ioctl.c Lines: 67 71 94.4 %
Date: 2026-03-06 18:57:10 Branches: 19 21 90.5 %

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_ioctl                        PORTABLE C      */
38
/*                                                           6.3.0        */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Chaoqiong Xiao, Microsoft Corporation                               */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    This function is the ioctl entry point for the application to       */
46
/*    configure the ACM device.                                           */
47
/*                                                                        */
48
/*                                                                        */
49
/*  INPUT                                                                 */
50
/*                                                                        */
51
/*    cdc_acm                               Pointer to CDC ACM class      */
52
/*    ioctl_function                        ioctl function                */
53
/*    parameter                             pointer to structure          */
54
/*                                                                        */
55
/*  OUTPUT                                                                */
56
/*                                                                        */
57
/*    Completion Status                                                   */
58
/*                                                                        */
59
/*  CALLS                                                                 */
60
/*                                                                        */
61
/*    _ux_host_stack_endpoint_transfer_abort                              */
62
/*                                          Abort transfer                */
63
/*    _ux_host_class_cdc_acm_command        Send command to acm device    */
64
/*    _ux_utility_memory_allocate           Allocate memory               */
65
/*    _ux_utility_memory_free               Free memory                   */
66
/*    _ux_utility_long_put                  Put 32-bit value              */
67
/*                                                                        */
68
/*  CALLED BY                                                             */
69
/*                                                                        */
70
/*    Application                                                         */
71
/*                                                                        */
72
/**************************************************************************/
73
239
UINT  _ux_host_class_cdc_acm_ioctl(UX_HOST_CLASS_CDC_ACM *cdc_acm, ULONG ioctl_function,
74
                                    VOID *parameter)
75
{
76
77
UINT                                    status;
78
UCHAR                                   *data_buffer;
79
UX_HOST_CLASS_CDC_ACM_LINE_CODING       *line_coding;
80
UX_HOST_CLASS_CDC_ACM_LINE_STATE        *line_state;
81
VOID                                    (*callback_function) (struct UX_HOST_CLASS_CDC_ACM_STRUCT *, ULONG, ULONG );
82
ULONG                                   value;
83
#if defined(UX_HOST_STANDALONE)
84
VOID                                    (*write_callback_function) (struct UX_HOST_CLASS_CDC_ACM_STRUCT *, UINT, ULONG );
85
UX_TRANSFER                             *transfer;
86
#endif
87
88
    /* Ensure the instance is valid.  */
89
239
    if ((cdc_acm -> ux_host_class_cdc_acm_state !=  UX_HOST_CLASS_INSTANCE_LIVE) &&
90
224
        (cdc_acm -> ux_host_class_cdc_acm_state !=  UX_HOST_CLASS_INSTANCE_MOUNTING))
91
    {
92
93
        /* If trace is enabled, insert this event into the trace buffer.  */
94
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0)
95
96
1
        return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
97
    }
98
99
    /* The command request will tell us what we need to do here.  */
100


238
    switch (ioctl_function)
101
    {
102
103
76
    case UX_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_CODING:
104
105
        /* If trace is enabled, insert this event into the trace buffer.  */
106
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_CODING, cdc_acm, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
107
108
        /* Allocate some cache safe memory for the control command.  */
109
76
        data_buffer =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_CDC_ACM_LINE_CODING_LENGTH);
110
111
        /* Check if error. Return with error if no memory could be allocated.  */
112
76
        if (data_buffer == UX_NULL)
113
114
            /* Do not proceed. Set error code.  */
115
2
            status = UX_MEMORY_INSUFFICIENT;
116
        else
117
        {
118
119
            /* Build the buffer from the calling parameter. Cast the calling parameter.  */
120
74
            line_coding = (UX_HOST_CLASS_CDC_ACM_LINE_CODING *) parameter;
121
122
            /* Put the data rate.  */
123
74
            _ux_utility_long_put(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_RATE,
124
                                line_coding -> ux_host_class_cdc_acm_line_coding_dter);
125
126
            /* Then the stop bit.  */
127
74
            *(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT) =
128
74
            (UCHAR) line_coding -> ux_host_class_cdc_acm_line_coding_stop_bit;
129
130
            /* Then the parity.  */
131
74
            *(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY) =
132
74
            (UCHAR) line_coding -> ux_host_class_cdc_acm_line_coding_parity;
133
134
            /* Finally the data bits.  */
135
74
            *(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_DATA_BIT) =
136
74
            (UCHAR) line_coding -> ux_host_class_cdc_acm_line_coding_data_bits;
137
138
            /* Send the command to the device.  */
139
74
            status = _ux_host_class_cdc_acm_command(cdc_acm, UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_CODING,
140
                                    0, data_buffer, UX_HOST_CLASS_CDC_ACM_LINE_CODING_LENGTH);
141
142
            /* We free the resources allocated no matter what.  */
143
74
            _ux_utility_memory_free(data_buffer);
144
        }
145
76
        break;
146
147
78
    case UX_HOST_CLASS_CDC_ACM_IOCTL_GET_LINE_CODING:
148
149
        /* If trace is enabled, insert this event into the trace buffer.  */
150
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_GET_LINE_CODING, cdc_acm, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
151
152
        /* Allocate some cache safe memory for the control command.  */
153
78
        data_buffer =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_CDC_ACM_LINE_CODING_LENGTH);
154
155
        /* Check if error. Return with error if no memory could be allocated.  */
156
78
        if (data_buffer == UX_NULL)
157
158
            /* Do not proceed. Set error code.  */
159
2
            status = UX_MEMORY_INSUFFICIENT;
160
        else
161
        {
162
163
            /* Send the command to the device.  */
164
76
            status = _ux_host_class_cdc_acm_command(cdc_acm, UX_HOST_CLASS_CDC_ACM_REQ_GET_LINE_CODING,
165
                                    0, data_buffer, UX_HOST_CLASS_CDC_ACM_LINE_CODING_LENGTH);
166
167
            /* Fill in the calling buffer if the result is successful. */
168
75
            if (status == UX_SUCCESS)
169
            {
170
171
                /* Build the buffer from the calling parameter. Cast the calling parameter.  */
172
74
                line_coding = (UX_HOST_CLASS_CDC_ACM_LINE_CODING *) parameter;
173
174
                /* Get the data rate.  */
175
74
                line_coding -> ux_host_class_cdc_acm_line_coding_dter = _ux_utility_long_get(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_RATE);
176
177
                /* Then the stop bit.  */
178
74
                line_coding -> ux_host_class_cdc_acm_line_coding_stop_bit =
179
74
                (ULONG) *(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT);
180
181
                /* Then the parity.  */
182
74
                line_coding -> ux_host_class_cdc_acm_line_coding_parity =
183
74
                (ULONG) *(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY);
184
185
                /* Finally the data bits.  */
186
74
                line_coding -> ux_host_class_cdc_acm_line_coding_data_bits =
187
74
                (ULONG) *(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_DATA_BIT);
188
            }
189
190
            /* We free the resources allocated no matter what.  */
191
75
            _ux_utility_memory_free(data_buffer);
192
        }
193
77
        break;
194
195
75
    case UX_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_STATE:
196
197
        /* If trace is enabled, insert this event into the trace buffer.  */
198
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_STATE, cdc_acm, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
199
200
        /* Cast the calling parameter.  */
201
75
        line_state = (UX_HOST_CLASS_CDC_ACM_LINE_STATE *) parameter;
202
203
        /* Build the value field.  */
204
75
        value = (line_state -> ux_host_class_cdc_acm_line_state_dtr |
205
75
                (line_state -> ux_host_class_cdc_acm_line_state_rts << 1));
206
207
        /* Send the command to the device.  */
208
75
        status = _ux_host_class_cdc_acm_command(cdc_acm, UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_STATE,
209
                                    value, UX_NULL,0);
210
75
        break;
211
212
3
    case UX_HOST_CLASS_CDC_ACM_IOCTL_SEND_BREAK :
213
214
        /* If trace is enabled, insert this event into the trace buffer.  */
215
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_SEND_BREAK, cdc_acm, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
216
217
        /* Build the value field.  */
218
3
        value = *((ULONG *) parameter);
219
220
        /* Send the command to the device.  */
221
3
        status = _ux_host_class_cdc_acm_command(cdc_acm, UX_HOST_CLASS_CDC_ACM_REQ_SEND_BREAK,
222
                                    value, UX_NULL,0);
223
3
        break;
224
225
226
227
1
    case UX_HOST_CLASS_CDC_ACM_IOCTL_ABORT_IN_PIPE :
228
229
        /* If trace is enabled, insert this event into the trace buffer.  */
230
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_ABORT_IN_PIPE, cdc_acm, cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
231
232
        /* We need to abort transactions on the bulk In pipe.  */
233
1
        _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint);
234
235
        /* Status is successful.  */
236
1
        status = UX_SUCCESS;
237
1
        break;
238
239
1
    case UX_HOST_CLASS_CDC_ACM_IOCTL_ABORT_OUT_PIPE :
240
241
        /* If trace is enabled, insert this event into the trace buffer.  */
242
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_ABORT_OUT_PIPE, cdc_acm, cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
243
244
        /* We need to abort transactions on the bulk Out pipe.  */
245
1
        _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint);
246
247
#if defined(UX_HOST_STANDALONE)
248
249
        /* Reset write state.  */
250
        cdc_acm -> ux_host_class_cdc_acm_write_state = UX_STATE_RESET;
251
#endif
252
253
        /* Status is successful.  */
254
1
        status = UX_SUCCESS;
255
1
        break;
256
257
2
    case UX_HOST_CLASS_CDC_ACM_IOCTL_NOTIFICATION_CALLBACK :
258
259
        /* If trace is enabled, insert this event into the trace buffer.  */
260
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_NOTIFICATION_CALLBACK, cdc_acm, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
261
262
        /* Register a callback when the line state has changed. */
263
2
        callback_function = ((VOID (*) (struct UX_HOST_CLASS_CDC_ACM_STRUCT *, ULONG, ULONG )) (ALIGN_TYPE)parameter);
264
2
        cdc_acm -> ux_host_class_cdc_acm_device_status_change_callback = callback_function;
265
266
        /* Status is successful.  */
267
2
        status = UX_SUCCESS;
268
2
        break;
269
270
1
    case UX_HOST_CLASS_CDC_ACM_IOCTL_GET_DEVICE_STATUS :
271
272
        /* If trace is enabled, insert this event into the trace buffer.  */
273
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_GET_DEVICE_STATUS, cdc_acm, cdc_acm -> ux_host_class_cdc_acm_device_state, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
274
275
        /* Return the device status.  */
276
1
        *((ULONG *) parameter) = cdc_acm -> ux_host_class_cdc_acm_device_state;
277
278
        /* Status is successful.  */
279
1
        status = UX_SUCCESS;
280
1
        break;
281
282
#if defined(UX_HOST_STANDALONE)
283
    case UX_HOST_CLASS_CDC_ACM_IOCTL_WRITE_CALLBACK:
284
285
        /* Register a callback when write is done. */
286
        write_callback_function = ((VOID (*) (struct UX_HOST_CLASS_CDC_ACM_STRUCT *, UINT, ULONG )) (ALIGN_TYPE)parameter);
287
        cdc_acm -> ux_host_class_cdc_acm_write_callback = write_callback_function;
288
289
        /* Status is successful.  */
290
        status = UX_SUCCESS;
291
        break;
292
293
    case UX_HOST_CLASS_CDC_ACM_IOCTL_GET_WRITE_STATUS:
294
295
        /* Check write state.  */
296
        if (cdc_acm -> ux_host_class_cdc_acm_write_state == UX_STATE_WAIT)
297
        {
298
            status = UX_BUSY;
299
        }
300
        else
301
        {
302
303
            /* Get transfer for write.  */
304
            transfer = &cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint ->
305
                                                ux_endpoint_transfer_request;
306
307
            /* Status is from transfer completion code.  */
308
            status = transfer -> ux_transfer_request_completion_code;
309
310
            /* Actual length is from latest write count.  */
311
            *(ULONG *)parameter = cdc_acm -> ux_host_class_cdc_acm_write_count;
312
        }
313
        break;
314
#endif
315
316
1
    default:
317
318
        /* Error trap. */
319
1
        _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED);
320
321
        /* If trace is enabled, insert this event into the trace buffer.  */
322
        UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
323
324
        /* Function not supported. Return an error.  */
325
1
        status =  UX_FUNCTION_NOT_SUPPORTED;
326
    }
327
328
    /* Return status to caller.  */
329
237
    return(status);
330
}
331
332
333
/**************************************************************************/
334
/*                                                                        */
335
/*  FUNCTION                                               RELEASE        */
336
/*                                                                        */
337
/*    _uxe_host_class_cdc_acm_ioctl                       PORTABLE C      */
338
/*                                                           6.3.0        */
339
/*  AUTHOR                                                                */
340
/*                                                                        */
341
/*    Chaoqiong Xiao, Microsoft Corporation                               */
342
/*                                                                        */
343
/*  DESCRIPTION                                                           */
344
/*                                                                        */
345
/*    This function checks errors in CDC ACM ioctl function call.         */
346
/*                                                                        */
347
/*  INPUT                                                                 */
348
/*                                                                        */
349
/*    cdc_acm                               Pointer to CDC ACM class      */
350
/*    ioctl_function                        ioctl function                */
351
/*    parameter                             pointer to structure          */
352
/*                                                                        */
353
/*  OUTPUT                                                                */
354
/*                                                                        */
355
/*    Status                                                              */
356
/*                                                                        */
357
/*  CALLS                                                                 */
358
/*                                                                        */
359
/*    _ux_host_class_cdc_acm_ioctl          CDC ACM ioctl                 */
360
/*                                                                        */
361
/*  CALLED BY                                                             */
362
/*                                                                        */
363
/*    Application                                                         */
364
/*                                                                        */
365
/**************************************************************************/
366
UINT  _uxe_host_class_cdc_acm_ioctl(UX_HOST_CLASS_CDC_ACM *cdc_acm, ULONG ioctl_function,
367
                                    VOID *parameter)
368
{
369
370
    /* Sanity checks.  */
371
    if (cdc_acm == UX_NULL)
372
        return(UX_INVALID_PARAMETER);
373
374
    /* Invoke CDC ACM ioctl function.  */
375
    return(_ux_host_class_cdc_acm_ioctl(cdc_acm, ioctl_function, parameter));
376
377
}