GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_cdc_acm_endpoints_get.c Lines: 47 49 95.9 %
Date: 2024-12-12 17:16:36 Branches: 32 34 94.1 %

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_endpoints_get                PORTABLE C      */
37
/*                                                           6.3.0        */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Chaoqiong Xiao, Microsoft Corporation                               */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This function distinguishes for either the Data or Control Class.   */
45
/*    For the data class, we mount the bulk in and bulk out endpoints.    */
46
/*    For the control class, we mount the optional interrupt endpoint.    */
47
/*                                                                        */
48
/*  INPUT                                                                 */
49
/*                                                                        */
50
/*    cdc_acm                               Pointer to cdc_acm class      */
51
/*                                                                        */
52
/*  OUTPUT                                                                */
53
/*                                                                        */
54
/*    Completion Status                                                   */
55
/*                                                                        */
56
/*  CALLS                                                                 */
57
/*                                                                        */
58
/*    _ux_host_stack_interface_endpoint_get Get interface endpoint        */
59
/*                                                                        */
60
/*  CALLED BY                                                             */
61
/*                                                                        */
62
/*    _ux_host_class_cdc_acm_activate       Activate cdc_acm class        */
63
/*                                                                        */
64
/*  RELEASE HISTORY                                                       */
65
/*                                                                        */
66
/*    DATE              NAME                      DESCRIPTION             */
67
/*                                                                        */
68
/*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
69
/*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
70
/*                                            resulting in version 6.1    */
71
/*  10-15-2021     Chaoqiong Xiao           Modified comment(s),          */
72
/*                                            use pre-calculated value    */
73
/*                                            instead of wMaxPacketSize,  */
74
/*                                            resulting in version 6.1.9  */
75
/*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
76
/*                                            initialized timeout value,  */
77
/*                                            resulting in version 6.1.10 */
78
/*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
79
/*                                            internal clean up,          */
80
/*                                            resulting in version 6.1.11 */
81
/*  10-31-2023     Chaoqiong Xiao           Modified comment(s),          */
82
/*                                            checked endpoint get status,*/
83
/*                                            resulting in version 6.3.0  */
84
/*                                                                        */
85
/**************************************************************************/
86
149
UINT  _ux_host_class_cdc_acm_endpoints_get(UX_HOST_CLASS_CDC_ACM *cdc_acm)
87
{
88
89
UINT            status;
90
UINT            endpoint_index;
91
UX_ENDPOINT     *endpoint;
92
UX_TRANSFER     *transfer_request;
93
94
95
    /* Check what interface we are mounting.  */
96
149
    if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_DATA_CLASS)
97
    {
98
99
        /* Search the bulk OUT endpoint. It is attached to the interface container.  */
100
143
        for (endpoint_index = 0; endpoint_index < cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bNumEndpoints;
101
73
                            endpoint_index++)
102
        {
103
104
            /* Get interface endpoint.  */
105
134
            status = _ux_host_stack_interface_endpoint_get(cdc_acm -> ux_host_class_cdc_acm_interface, endpoint_index, &endpoint);
106
107
            /* Check status.  */
108
134
            if (status != UX_SUCCESS)
109
                continue;
110
111
            /* Check if endpoint is bulk and OUT.  */
112
134
            if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) &&
113
67
                ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT))
114
            {
115
116
                /* This transfer_request always have the OUT direction.  */
117
65
                endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type =  UX_REQUEST_OUT;
118
119
                /* Set default timeout for transfer.  */
120
65
                endpoint -> ux_endpoint_transfer_request.ux_transfer_request_timeout_value = UX_HOST_CLASS_CDC_ACM_CLASS_TRANSFER_TIMEOUT;
121
122
                /* We have found the bulk endpoint, save it.  */
123
65
                cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint =  endpoint;
124
125
                /* If found all, we break.  */
126
65
                if (cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint)
127
43
                    break;
128
            }
129
130
            /* Check if endpoint is bulk and IN.  */
131
91
            if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) &&
132
67
                ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT))
133
            {
134
135
                /* This transfer_request always have the IN direction.  */
136
66
                endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type =  UX_REQUEST_IN;
137
138
                /* Set default timeout for transfer.  */
139
66
                endpoint -> ux_endpoint_transfer_request.ux_transfer_request_timeout_value = UX_HOST_CLASS_CDC_ACM_CLASS_TRANSFER_TIMEOUT;
140
141
                /* We have found the bulk endpoint, save it.  */
142
66
                cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint =  endpoint;
143
144
                /* If found all, we break.  */
145
66
                if (cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint)
146
18
                    break;
147
            }
148
        }
149
150
        /* The both bulk endpoints are mandatory.  */
151
70
        if (cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint == UX_NULL ||
152
65
            cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint == UX_NULL)
153
        {
154
155
            /* Error trap. */
156
9
            _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN);
157
158
            /* If trace is enabled, insert this event into the trace buffer.  */
159
            UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0)
160
161
9
            return(UX_ENDPOINT_HANDLE_UNKNOWN);
162
        }
163
    }
164
    else
165
    {
166
        /* Search the Interrupt endpoint. It is attached to the interface container of the control interface. It is not mandatory.  */
167
98
        for (endpoint_index = 0; endpoint_index < cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bNumEndpoints;
168
19
                            endpoint_index++)
169
        {
170
171
            /* Get the endpoint handle.  */
172
89
            status = _ux_host_stack_interface_endpoint_get(cdc_acm -> ux_host_class_cdc_acm_interface, endpoint_index, &endpoint);
173
174
            /* Check status.  */
175
89
            if (status != UX_SUCCESS)
176
                continue;
177
178
            /* Check if endpoint is Interrupt and IN.  */
179
89
            if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) &&
180
75
                ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT))
181
            {
182
183
                /* This transfer_request always have the IN direction.  */
184
70
                endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type =  UX_REQUEST_IN;
185
186
                /* We have found the interrupt endpoint, save it.  */
187
70
                cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint =  endpoint;
188
189
                /* The endpoint is correct, Fill in the transfer request with the length requested for this endpoint.  */
190
70
                transfer_request =  &cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint -> ux_endpoint_transfer_request;
191
70
                transfer_request -> ux_transfer_request_requested_length =  transfer_request -> ux_transfer_request_packet_length;
192
70
                transfer_request -> ux_transfer_request_actual_length =     0;
193
194
                /* The direction is always IN for the CDC interrupt endpoint.  */
195
70
                transfer_request -> ux_transfer_request_type =  UX_REQUEST_IN;
196
197
                /* There is a callback function associated with the transfer request, so we need the class instance.  */
198
70
                transfer_request -> ux_transfer_request_class_instance =  (VOID *) cdc_acm;
199
200
                /* Interrupt transactions have a completion routine. */
201
70
                transfer_request -> ux_transfer_request_completion_function =  _ux_host_class_cdc_acm_transfer_request_completed;
202
203
                /* Obtain a buffer for this transaction. The buffer will always be reused.  */
204
70
                transfer_request -> ux_transfer_request_data_pointer =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY,
205
                                                                transfer_request -> ux_transfer_request_requested_length);
206
207
                /* If the endpoint is available and we have memory, we start the interrupt endpoint.  */
208
70
                if (transfer_request -> ux_transfer_request_data_pointer != UX_NULL)
209
                {
210
211
                    /* The transfer on the interrupt endpoint can be started.  */
212
69
                    status =  _ux_host_stack_transfer_request(transfer_request);
213
214
                    /* Check error, if endpoint interrupt IN transfer not successful, do not proceed. */
215
69
                    if (status != UX_SUCCESS)
216
217
                        /* Error, do not proceed.  */
218
1
                        return(status);
219
                }
220
                else
221
                {
222
223
                    /* Error trap. */
224
1
                    _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT);
225
226
                    /* If trace is enabled, insert this event into the trace buffer.  */
227
                    UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0)
228
229
                    /* We must return an error.  */
230
1
                    return(UX_ENDPOINT_HANDLE_UNKNOWN);
231
                }
232
68
                break;
233
            }
234
        }
235
    }
236
237
    /* All endpoints have been mounted.  */
238
138
    return(UX_SUCCESS);
239
}
240