GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: core/src/ux_device_stack_interface_set.c Lines: 75 75 100.0 %
Date: 2024-12-12 17:16:36 Branches: 33 33 100.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
/**   Device Stack                                                        */
18
/**                                                                       */
19
/**************************************************************************/
20
/**************************************************************************/
21
22
#define UX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
27
#include "ux_api.h"
28
#include "ux_device_stack.h"
29
30
31
/**************************************************************************/
32
/*                                                                        */
33
/*  FUNCTION                                               RELEASE        */
34
/*                                                                        */
35
/*    _ux_device_stack_interface_set                      PORTABLE C      */
36
/*                                                           6.1.12       */
37
/*  AUTHOR                                                                */
38
/*                                                                        */
39
/*    Chaoqiong Xiao, Microsoft Corporation                               */
40
/*                                                                        */
41
/*  DESCRIPTION                                                           */
42
/*                                                                        */
43
/*    This function sets one alternate setting of one interface and       */
44
/*    enable all endpoints associated with this alternate setting.        */
45
/*    configuration.                                                      */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    device_framework                      Address in device framework   */
50
/*                                          for selected alternate setting*/
51
/*    device_framework_length               Length of device framework    */
52
/*    alternate_setting_value               Alternate setting             */
53
/*                                                                        */
54
/*  OUTPUT                                                                */
55
/*                                                                        */
56
/*    Completion Status                                                   */
57
/*                                                                        */
58
/*  CALLS                                                                 */
59
/*                                                                        */
60
/*    (ux_slave_dcd_function)               DCD dispatch function         */
61
/*    _ux_device_stack_interface_start      Start interface               */
62
/*    _ux_utility_descriptor_parse          Parse descriptor              */
63
/*                                                                        */
64
/*  CALLED BY                                                             */
65
/*                                                                        */
66
/*    Application                                                         */
67
/*    Device Stack                                                        */
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
/*                                            optimized based on compile  */
76
/*                                            definitions,                */
77
/*                                            resulting in version 6.1    */
78
/*  10-15-2021     Chaoqiong Xiao           Modified comment(s),          */
79
/*                                            calculated payload size,    */
80
/*                                            resulting in version 6.1.9  */
81
/*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
82
/*                                            fixed parameter/variable    */
83
/*                                            names conflict C++ keyword, */
84
/*                                            resulting in version 6.1.12 */
85
/*                                                                        */
86
/**************************************************************************/
87
1543
UINT  _ux_device_stack_interface_set(UCHAR * device_framework, ULONG device_framework_length,
88
                                                    ULONG alternate_setting_value)
89
{
90
91
UX_SLAVE_DCD            *dcd;
92
UX_SLAVE_DEVICE         *device;
93
UX_SLAVE_TRANSFER       *transfer_request;
94
UX_SLAVE_INTERFACE      *interface_ptr;
95
#if !defined(UX_DEVICE_INITIALIZE_FRAMEWORK_SCAN_DISABLE) || UX_MAX_DEVICE_INTERFACES > 1
96
UX_SLAVE_INTERFACE      *interface_link;
97
ULONG                   interfaces_pool_number;
98
#endif
99
UX_SLAVE_ENDPOINT       *endpoint;
100
UX_SLAVE_ENDPOINT       *endpoint_link;
101
ULONG                   descriptor_length;
102
UCHAR                   descriptor_type;
103
ULONG                   endpoints_pool_number;
104
UINT                    status;
105
ULONG                   max_transfer_length, n_trans;
106
107
    UX_PARAMETER_NOT_USED(alternate_setting_value);
108
109
    /* If trace is enabled, insert this event into the trace buffer.  */
110
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_INTERFACE_SET, alternate_setting_value, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0)
111
112
    /* Get the pointer to the DCD.  */
113
1543
    dcd =  &_ux_system_slave -> ux_system_slave_dcd;
114
115
    /* Get the pointer to the device.  */
116
1543
    device =  &_ux_system_slave -> ux_system_slave_device;
117
118
    /* Find a free interface in the pool and hook it to the
119
       existing interface.  */
120
1543
    interface_ptr = device -> ux_slave_device_interfaces_pool;
121
122
#if !defined(UX_DEVICE_INITIALIZE_FRAMEWORK_SCAN_DISABLE) || UX_MAX_DEVICE_INTERFACES > 1
123
1543
    interfaces_pool_number = device -> ux_slave_device_interfaces_pool_number;
124
2393
    while (interfaces_pool_number != 0)
125
    {
126
        /* Check if this interface is free.  */
127
2392
        if (interface_ptr -> ux_slave_interface_status == UX_UNUSED)
128
1542
            break;
129
130
        /* Try the next interface.  */
131
850
        interface_ptr++;
132
133
        /* Decrement the number of interfaces left to scan in the pool.  */
134
850
        interfaces_pool_number--;
135
    }
136
137
    /* Did we find a free interface ?  */
138
1543
    if (interfaces_pool_number == 0)
139
1
        return(UX_MEMORY_INSUFFICIENT);
140
#else
141
142
    /* Check if this interface is free.  */
143
    if (interface_ptr -> ux_slave_interface_status != UX_UNUSED)
144
        return(UX_MEMORY_INSUFFICIENT);
145
146
#endif
147
148
    /* Mark this interface as used now.  */
149
1542
    interface_ptr -> ux_slave_interface_status = UX_USED;
150
151
    /* If trace is enabled, register this object.  */
152
    UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, interface_ptr, 0, 0, 0)
153
154
    /* Parse the descriptor in something more readable.  */
155
1542
    _ux_utility_descriptor_parse(device_framework,
156
                _ux_system_interface_descriptor_structure,
157
                UX_INTERFACE_DESCRIPTOR_ENTRIES,
158
1542
                (UCHAR *) &interface_ptr -> ux_slave_interface_descriptor);
159
160
#if !defined(UX_DEVICE_INITIALIZE_FRAMEWORK_SCAN_DISABLE) || UX_MAX_DEVICE_INTERFACES > 1
161
162
    /* Attach this interface to the end of the interface chain.  */
163
1542
    if (device -> ux_slave_device_first_interface == UX_NULL)
164
    {
165
166
906
        device -> ux_slave_device_first_interface =  interface_ptr;
167
    }
168
    else
169
    {
170
        /* Multiple interfaces exist, so find the end of the chain.  */
171
636
        interface_link =  device -> ux_slave_device_first_interface;
172
849
        while (interface_link -> ux_slave_interface_next_interface != UX_NULL)
173
213
            interface_link =  interface_link -> ux_slave_interface_next_interface;
174
636
        interface_link -> ux_slave_interface_next_interface =  interface_ptr;
175
    }
176
#else
177
178
    /* It must be very first one.  */
179
    device -> ux_slave_device_first_interface = interface_ptr;
180
#endif
181
182
    /* Point beyond the interface descriptor.  */
183
1542
    device_framework_length -=  (ULONG) *device_framework;
184
1542
    device_framework +=  (ULONG) *device_framework;
185
186
    /* Parse the device framework and locate endpoint descriptor(s).  */
187
5028
    while (device_framework_length != 0)
188
    {
189
190
        /* Get the length of the current descriptor.  */
191
4349
        descriptor_length =  (ULONG) *device_framework;
192
193
        /* And its type.  */
194
4349
        descriptor_type =  *(device_framework + 1);
195
196
        /* Check if this is an endpoint descriptor.  */
197
4349
        switch(descriptor_type)
198
        {
199
200
1859
        case UX_ENDPOINT_DESCRIPTOR_ITEM:
201
202
            /* Find a free endpoint in the pool and hook it to the
203
               existing interface after it's created by DCD.  */
204
1859
            endpoint = device -> ux_slave_device_endpoints_pool;
205
1859
            endpoints_pool_number = device -> ux_slave_device_endpoints_pool_number;
206
3424
            while (endpoints_pool_number != 0)
207
            {
208
                /* Check if this endpoint is free.  */
209
3423
                if (endpoint ->    ux_slave_endpoint_status == UX_UNUSED)
210
                {
211
                    /* Mark this endpoint as used now.  */
212
1858
                    endpoint ->    ux_slave_endpoint_status = UX_USED;
213
1858
                    break;
214
                }
215
216
                /* Try the next endpoint.  */
217
1565
                endpoint++;
218
219
                /* Decrement the number of endpoints to scan from the pool.  */
220
1565
               endpoints_pool_number--;
221
            }
222
223
            /* Did we find a free endpoint ?  */
224
1859
            if (endpoints_pool_number == 0)
225
1
                return(UX_MEMORY_INSUFFICIENT);
226
227
            /* Parse the descriptor in something more readable.  */
228
1858
            _ux_utility_descriptor_parse(device_framework,
229
                            _ux_system_endpoint_descriptor_structure,
230
                            UX_ENDPOINT_DESCRIPTOR_ENTRIES,
231
1858
                            (UCHAR *) &endpoint -> ux_slave_endpoint_descriptor);
232
233
            /* Now we create a transfer request to accept transfer on this endpoint.  */
234
1858
            transfer_request =  &endpoint -> ux_slave_endpoint_transfer_request;
235
236
            /* Validate endpoint descriptor wMaxPacketSize.  */
237
            UX_ASSERT(endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize != 0);
238
239
            /* Calculate endpoint transfer payload max size.  */
240
1858
            max_transfer_length =
241
1858
                    endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize &
242
                                                        UX_MAX_PACKET_SIZE_MASK;
243
1858
            if ((_ux_system_slave -> ux_system_slave_speed == UX_HIGH_SPEED_DEVICE) &&
244
163
                (endpoint -> ux_slave_endpoint_descriptor.bmAttributes & 0x1u))
245
            {
246
57
                n_trans = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize &
247
                                            UX_MAX_NUMBER_OF_TRANSACTIONS_MASK;
248
57
                if (n_trans)
249
                {
250
5
                    n_trans >>= UX_MAX_NUMBER_OF_TRANSACTIONS_SHIFT;
251
5
                    n_trans ++;
252
5
                    max_transfer_length *= n_trans;
253
                }
254
            }
255
256
            /* Validate max transfer size and save it.  */
257
            UX_ASSERT(max_transfer_length <= UX_SLAVE_REQUEST_DATA_MAX_LENGTH);
258
1858
            transfer_request -> ux_slave_transfer_request_transfer_length = max_transfer_length;
259
260
            /* We store the endpoint in the transfer request as well.  */
261
1858
            transfer_request -> ux_slave_transfer_request_endpoint =  endpoint;
262
263
            /* By default the timeout is infinite on request.  */
264
1858
            transfer_request -> ux_slave_transfer_request_timeout = UX_WAIT_FOREVER;
265
266
            /* Attach the interface to the endpoint.  */
267
1858
            endpoint -> ux_slave_endpoint_interface =  interface_ptr;
268
269
            /* Attach the device to the endpoint.  */
270
1858
            endpoint -> ux_slave_endpoint_device =  device;
271
272
            /* Create the endpoint at the DCD level.  */
273
1858
            status =  dcd -> ux_slave_dcd_function(dcd, UX_DCD_CREATE_ENDPOINT, (VOID *) endpoint);
274
275
            /* Do a sanity check on endpoint creation.  */
276
1858
            if (status != UX_SUCCESS)
277
            {
278
279
                /* Error was returned, endpoint cannot be created.  */
280
1
                endpoint -> ux_slave_endpoint_status = UX_UNUSED;
281
1
                return(status);
282
            }
283
284
            /* Attach this endpoint to the end of the endpoint chain.  */
285
1857
            if (interface_ptr -> ux_slave_interface_first_endpoint == UX_NULL)
286
            {
287
288
1345
                interface_ptr -> ux_slave_interface_first_endpoint =  endpoint;
289
            }
290
            else
291
            {
292
                /* Multiple endpoints exist, so find the end of the chain.  */
293
512
                endpoint_link =  interface_ptr -> ux_slave_interface_first_endpoint;
294
633
                while (endpoint_link -> ux_slave_endpoint_next_endpoint != UX_NULL)
295
121
                    endpoint_link =  endpoint_link -> ux_slave_endpoint_next_endpoint;
296
512
                endpoint_link -> ux_slave_endpoint_next_endpoint =  endpoint;
297
            }
298
1857
            break;
299
300
861
        case UX_CONFIGURATION_DESCRIPTOR_ITEM:
301
        case UX_INTERFACE_DESCRIPTOR_ITEM:
302
303
            /* If the descriptor is a configuration or interface,
304
               we have parsed and mounted all endpoints.
305
               The interface attached to this configuration must be started at the class level.  */
306
861
            status =  _ux_device_stack_interface_start(interface_ptr);
307
308
            /* Return the status to the caller.  */
309
861
            return(status);
310
311
1629
        default:
312
1629
            break;
313
        }
314
315
        /* Adjust what is left of the device framework.  */
316
3486
        device_framework_length -=  descriptor_length;
317
318
        /* Point to the next descriptor.  */
319
3486
        device_framework +=  descriptor_length;
320
    }
321
322
    /* The interface attached to this configuration must be started at the class
323
       level.  */
324
679
    status =  _ux_device_stack_interface_start(interface_ptr);
325
326
    /* Return the status to the caller.  */
327
679
    return(status);
328
}
329