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: 2024-12-12 17:16:36 Branches: 19 21 90.5 %

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_ioctl                        PORTABLE C      */
37
/*                                                           6.3.0        */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Chaoqiong Xiao, Microsoft Corporation                               */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This function is the ioctl entry point for the application to       */
45
/*    configure the ACM device.                                           */
46
/*                                                                        */
47
/*                                                                        */
48
/*  INPUT                                                                 */
49
/*                                                                        */
50
/*    cdc_acm                               Pointer to CDC ACM class      */
51
/*    ioctl_function                        ioctl function                */
52
/*    parameter                             pointer to structure          */
53
/*                                                                        */
54
/*  OUTPUT                                                                */
55
/*                                                                        */
56
/*    Completion Status                                                   */
57
/*                                                                        */
58
/*  CALLS                                                                 */
59
/*                                                                        */
60
/*    _ux_host_stack_endpoint_transfer_abort                              */
61
/*                                          Abort transfer                */
62
/*    _ux_host_class_cdc_acm_command        Send command to acm device    */
63
/*    _ux_utility_memory_allocate           Allocate memory               */
64
/*    _ux_utility_memory_free               Free memory                   */
65
/*    _ux_utility_long_put                  Put 32-bit value              */
66
/*                                                                        */
67
/*  CALLED BY                                                             */
68
/*                                                                        */
69
/*    Application                                                         */
70
/*                                                                        */
71
/*  RELEASE HISTORY                                                       */
72
/*                                                                        */
73
/*    DATE              NAME                      DESCRIPTION             */
74
/*                                                                        */
75
/*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
76
/*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
77
/*                                            resulting in version 6.1    */
78
/*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
79
/*                                            added standalone support,   */
80
/*                                            resulting in version 6.1.10 */
81
/*  10-31-2023     Chaoqiong Xiao           Modified comment(s),          */
82
/*                                            resulting in version 6.3.0  */
83
/*                                                                        */
84
/**************************************************************************/
85
237
UINT  _ux_host_class_cdc_acm_ioctl(UX_HOST_CLASS_CDC_ACM *cdc_acm, ULONG ioctl_function,
86
                                    VOID *parameter)
87
{
88
89
UINT                                    status;
90
UCHAR                                   *data_buffer;
91
UX_HOST_CLASS_CDC_ACM_LINE_CODING       *line_coding;
92
UX_HOST_CLASS_CDC_ACM_LINE_STATE        *line_state;
93
VOID                                    (*callback_function) (struct UX_HOST_CLASS_CDC_ACM_STRUCT *, ULONG, ULONG );
94
ULONG                                   value;
95
#if defined(UX_HOST_STANDALONE)
96
VOID                                    (*write_callback_function) (struct UX_HOST_CLASS_CDC_ACM_STRUCT *, UINT, ULONG );
97
UX_TRANSFER                             *transfer;
98
#endif
99
100
    /* Ensure the instance is valid.  */
101
237
    if ((cdc_acm -> ux_host_class_cdc_acm_state !=  UX_HOST_CLASS_INSTANCE_LIVE) &&
102
224
        (cdc_acm -> ux_host_class_cdc_acm_state !=  UX_HOST_CLASS_INSTANCE_MOUNTING))
103
    {
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
    /* The command request will tell us what we need to do here.  */
112


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