GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: core/src/ux_host_stack_transfer_request.c Lines: 24 34 70.6 %
Date: 2026-03-06 18:57:10 Branches: 18 26 69.2 %

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
/**   Host Stack                                                          */
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_stack.h"
30
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _ux_host_stack_transfer_request                     PORTABLE C      */
37
/*                                                           6.1.10       */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Chaoqiong Xiao, Microsoft Corporation                               */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This function performs a USB transaction. On entry the transfer     */
45
/*    request gives the endpoint pipe selected for this transaction and   */
46
/*    the parameters associated with the transfer (data payload, length   */
47
/*    of transaction)                                                     */
48
/*                                                                        */
49
/*    For Control pipe, the transaction is blocking and will only return  */
50
/*    when the 3 phases of the control transfer have been completed or if */
51
/*    there is a previous error. For other pipes, the USB stack will      */
52
/*    schedule the transaction on the USB but will not wait for its       */
53
/*    completion. Each request for non blocking pipes has to specify a    */
54
/*    completion routine.                                                 */
55
/*                                                                        */
56
/*  INPUT                                                                 */
57
/*                                                                        */
58
/*    transfer_request                      Transfer request structure    */
59
/*                                                                        */
60
/*  OUTPUT                                                                */
61
/*                                                                        */
62
/*    Completion Status                     If UX_SUCCESS, transfer was   */
63
/*                                            successfully started        */
64
/*                                                                        */
65
/*  CALLS                                                                 */
66
/*                                                                        */
67
/*    HCD Entry Function                                                  */
68
/*    _ux_utility_semaphore_put             Put semaphore                 */
69
/*    _ux_utility_semaphore_get             Get semaphore                 */
70
/*                                                                        */
71
/*  CALLED BY                                                             */
72
/*                                                                        */
73
/*    Application                                                         */
74
/*    USBX Components                                                     */
75
/*                                                                        */
76
/**************************************************************************/
77
26647
UINT  _ux_host_stack_transfer_request(UX_TRANSFER *transfer_request)
78
{
79
#if defined(UX_HOST_STANDALONE)
80
UINT        status;
81
82
    UX_TRANSFER_STATE_RESET(transfer_request);
83
    _ux_host_stack_transfer_run(transfer_request);
84
    if ((transfer_request -> ux_transfer_request_flags & UX_TRANSFER_FLAG_AUTO_WAIT))
85
    {
86
        while(1)
87
        {
88
89
            /* Allow tasks running during waiting.  */
90
            _ux_system_host_tasks_run();
91
92
            if (transfer_request -> ux_transfer_request_state <= UX_STATE_NEXT)
93
                break;
94
        }
95
        status = transfer_request -> ux_transfer_request_completion_code;
96
    }
97
    else
98
    {
99
100
        /* In this mode, transfer pending is a success started case.  */
101
        if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING)
102
            status = UX_SUCCESS;
103
        else
104
            status = transfer_request -> ux_transfer_request_completion_code;
105
    }
106
107
    /* Return transfer completion status.  */
108
    return(status);
109
#else
110
UX_INTERRUPT_SAVE_AREA
111
112
UX_ENDPOINT     *endpoint;
113
UX_DEVICE       *device;
114
UX_HCD          *hcd;
115
UINT            status;
116
117
118
    /* Get the endpoint container from the transfer_request */
119
26647
    endpoint =  transfer_request -> ux_transfer_request_endpoint;
120
121
    /* Get the device container from the endpoint.  */
122
26647
    device =  endpoint -> ux_endpoint_device;
123
124
    /* Ensure we are not preempted by the enum thread while we check the device
125
       state and set the transfer status.  */
126
26647
    UX_DISABLE
127
128
    /* We can only transfer when the device is ATTACHED, ADDRESSED OR CONFIGURED.  */
129

26647
    if ((device -> ux_device_state == UX_DEVICE_ATTACHED) || (device -> ux_device_state == UX_DEVICE_ADDRESSED)
130
19835
            || (device -> ux_device_state == UX_DEVICE_CONFIGURED))
131
    {
132
133
        /* Set the transfer to pending.  */
134
26592
        transfer_request -> ux_transfer_request_completion_code =  UX_TRANSFER_STATUS_PENDING;
135
#if !defined(UX_HOST_STANDALONE)
136
        /* Save the thread making this transfer. If we're under interrupt, this
137
           will be null.  */
138
26592
        transfer_request -> ux_transfer_request_thread_pending =  _ux_utility_thread_identify();
139
#endif
140
    }
141
    else
142
    {
143
144
        /* The device is in an invalid state. Restore interrupts and return error.  */
145
55
        UX_RESTORE
146
147
        /* Check if this is endpoint 0.  */
148
55
        if ((endpoint -> ux_endpoint_descriptor.bEndpointAddress & (UINT)~UX_ENDPOINT_DIRECTION) == 0)
149
        {
150
151
            /* Check if the class has already protected it.  */
152
45
            if (!_ux_host_semaphore_waiting(&device -> ux_device_protection_semaphore))
153
            {
154
155
                /* Class is using endpoint 0. Unprotect semaphore.  */
156
13
                _ux_host_semaphore_put(&device -> ux_device_protection_semaphore);
157
            }
158
        }
159
160
55
        return(UX_TRANSFER_NOT_READY);
161
    }
162
163
    /* Restore interrupts.  */
164
26592
    UX_RESTORE
165
166
    /* If trace is enabled, insert this event into the trace buffer.  */
167
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_TRANSFER_REQUEST, device, endpoint, transfer_request, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0)
168
169
    /* With the device we have the pointer to the HCD.  */
170
26592
    hcd = UX_DEVICE_HCD_GET(device);
171
172
    /* If this is endpoint 0, we protect the endpoint from a possible re-entry.  */
173
26592
    if ((endpoint -> ux_endpoint_descriptor.bEndpointAddress & (UINT)~UX_ENDPOINT_DIRECTION) == 0)
174
    {
175
176
        /* Check if the class has already protected it.  */
177
11448
        if (_ux_host_semaphore_waiting(&device -> ux_device_protection_semaphore))
178
        {
179
180
            /* We are using endpoint 0. Protect with semaphore.  */
181
10101
            status =  _ux_host_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER);
182
183
            /* Check for status.  */
184
10101
            if (status != UX_SUCCESS)
185
186
                /* Something went wrong. */
187
1
                return(status);
188
        }
189
    }
190
191
    /* Send the command to the controller.  */
192
26591
    status =  hcd -> ux_hcd_entry_function(hcd, UX_HCD_TRANSFER_REQUEST, transfer_request);
193
194
    /* If this is endpoint 0, we unprotect the endpoint. */
195
26589
    if ((endpoint -> ux_endpoint_descriptor.bEndpointAddress & (UINT)~UX_ENDPOINT_DIRECTION) == 0)
196
197
        /* We are using endpoint 0. Unprotect with semaphore.  */
198
11445
        _ux_host_semaphore_put(&device -> ux_device_protection_semaphore);
199
200
    /* And return the status.  */
201
26589
    return(status);
202
#endif
203
}
204
205
206
/**************************************************************************/
207
/*                                                                        */
208
/*  FUNCTION                                               RELEASE        */
209
/*                                                                        */
210
/*    _uxe_host_stack_transfer_request                    PORTABLE C      */
211
/*                                                           6.3.0        */
212
/*  AUTHOR                                                                */
213
/*                                                                        */
214
/*    Chaoqiong Xiao, Microsoft Corporation                               */
215
/*                                                                        */
216
/*  DESCRIPTION                                                           */
217
/*                                                                        */
218
/*    This function checks errors in host stack transfer function call.   */
219
/*                                                                        */
220
/*  INPUT                                                                 */
221
/*                                                                        */
222
/*    transfer_request                      Pointer to transfer           */
223
/*                                                                        */
224
/*  OUTPUT                                                                */
225
/*                                                                        */
226
/*    None                                                                */
227
/*                                                                        */
228
/*  CALLS                                                                 */
229
/*                                                                        */
230
/*    _ux_host_stack_transfer_request       Issue a transfer request      */
231
/*                                                                        */
232
/*  CALLED BY                                                             */
233
/*                                                                        */
234
/*    Application                                                         */
235
/*                                                                        */
236
/**************************************************************************/
237
UINT  _uxe_host_stack_transfer_request(UX_TRANSFER *transfer_request)
238
{
239
240
    /* Sanity checks.  */
241
    if (transfer_request == UX_NULL)
242
        return(UX_INVALID_PARAMETER);
243
    if (transfer_request -> ux_transfer_request_endpoint == UX_NULL)
244
        return(UX_ENDPOINT_HANDLE_UNKNOWN);
245
    if (transfer_request -> ux_transfer_request_endpoint -> ux_endpoint_device == UX_NULL)
246
        return(UX_DEVICE_HANDLE_UNKNOWN);
247
    if (UX_DEVICE_HCD_GET(transfer_request -> ux_transfer_request_endpoint -> ux_endpoint_device) == UX_NULL)
248
        return(UX_INVALID_PARAMETER);
249
250
    /* Invoke transfer request function.  */
251
    return(_ux_host_stack_transfer_request(transfer_request));
252
}