GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: core/src/ux_device_stack_transfer_request.c Lines: 31 31 100.0 %
Date: 2026-03-06 18:57:10 Branches: 22 22 100.0 %

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
/**   Device Stack                                                        */
19
/**                                                                       */
20
/**************************************************************************/
21
/**************************************************************************/
22
23
#define UX_SOURCE_CODE
24
25
26
/* Include necessary system files.  */
27
28
#include "ux_api.h"
29
#include "ux_device_stack.h"
30
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _ux_device_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              */
45
/*    transfer request gives the endpoint pipe selected for this          */
46
/*    transaction and the parameters associated with the transfer         */
47
/*    (data payload, length of transaction).                              */
48
/*                                                                        */
49
/*  INPUT                                                                 */
50
/*                                                                        */
51
/*    transfer_request                      Pointer to transfer request   */
52
/*    slave_length                          Length returned by host       */
53
/*    host_length                           Length asked by host          */
54
/*                                                                        */
55
/*  OUTPUT                                                                */
56
/*                                                                        */
57
/*    Completion Status                                                   */
58
/*                                                                        */
59
/*  CALLS                                                                 */
60
/*                                                                        */
61
/*    (ux_slave_dcd_function)               Slave DCD dispatch function   */
62
/*    _ux_utility_delay_ms                  Delay ms                      */
63
/*                                                                        */
64
/*  CALLED BY                                                             */
65
/*                                                                        */
66
/*    Application                                                         */
67
/*    Device Stack                                                        */
68
/*                                                                        */
69
/**************************************************************************/
70
21000
UINT  _ux_device_stack_transfer_request(UX_SLAVE_TRANSFER *transfer_request,
71
                                            ULONG slave_length,
72
                                            ULONG host_length)
73
{
74
#if defined(UX_DEVICE_STANDALONE)
75
UINT            status;
76
77
    /* Start a transfer request without waiting it end.  */
78
    UX_SLAVE_TRANSFER_STATE_RESET(transfer_request);
79
    status = _ux_device_stack_transfer_run(transfer_request, slave_length, host_length);
80
    if (status == UX_STATE_LOCK)
81
        return(UX_BUSY);
82
    if (status < UX_STATE_NEXT)
83
        return(transfer_request -> ux_slave_transfer_request_completion_code);
84
85
    /* Started/done, things will be done in BG  */
86
    return(UX_SUCCESS);
87
#else
88
UX_INTERRUPT_SAVE_AREA
89
90
UX_SLAVE_DCD            *dcd;
91
UINT                    status;
92
UX_SLAVE_ENDPOINT       *endpoint;
93
ULONG                   device_state;
94
95
96
    /* Do we have to skip this transfer?  */
97
21000
    if (transfer_request -> ux_slave_transfer_request_status_phase_ignore == UX_TRUE)
98
1
        return(UX_SUCCESS);
99
100
    /* Disable interrupts to prevent the disconnection ISR from preempting us
101
       while we check the device state and set the transfer status.  */
102
20999
    UX_DISABLE
103
104
    /* Get the device state.  */
105
20999
    device_state =  _ux_system_slave -> ux_system_slave_device.ux_slave_device_state;
106
107
    /* We can only transfer when the device is ATTACHED, ADDRESSED OR CONFIGURED.  */
108

20999
    if ((device_state == UX_DEVICE_ATTACHED) || (device_state == UX_DEVICE_ADDRESSED)
109
16764
            || (device_state == UX_DEVICE_CONFIGURED))
110
111
        /* Set the transfer to pending.  */
112
20996
        transfer_request -> ux_slave_transfer_request_status =  UX_TRANSFER_STATUS_PENDING;
113
114
    else
115
    {
116
117
        /* The device is in an invalid state. Restore interrupts and return error.  */
118
3
        UX_RESTORE
119
3
        return(UX_TRANSFER_NOT_READY);
120
    }
121
122
    /* Restore interrupts.  */
123
20996
    UX_RESTORE
124
125
    /* If trace is enabled, insert this event into the trace buffer.  */
126
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_TRANSFER_REQUEST, transfer_request, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0)
127
128
    /* Get the pointer to the DCD.  */
129
20996
    dcd =  &_ux_system_slave -> ux_system_slave_dcd;
130
131
    /* Get the endpoint associated with this transaction.  */
132
20996
    endpoint =  transfer_request -> ux_slave_transfer_request_endpoint;
133
134
    /* If the endpoint is non Control, check the endpoint direction and set the data phase direction.  */
135
20996
    if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) != UX_CONTROL_ENDPOINT)
136
    {
137
138
        /* Check if the endpoint is STALLED. In this case, we must refuse the transaction until the endpoint
139
           has been reset by the host.  */
140
15099
        while (endpoint -> ux_slave_endpoint_state == UX_ENDPOINT_HALTED)
141
142
            /* Wait for 100ms for endpoint to be reset by a CLEAR_FEATURE command.  */
143
230
            _ux_utility_delay_ms(100);
144
145
        /* Isolate the direction from the endpoint address.  */
146
14869
        if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN)
147
7813
            transfer_request -> ux_slave_transfer_request_phase =  UX_TRANSFER_PHASE_DATA_OUT;
148
        else
149
7056
            transfer_request -> ux_slave_transfer_request_phase =  UX_TRANSFER_PHASE_DATA_IN;
150
    }
151
152
    /* See if we need to force a zero length packet at the end of the transfer.
153
       This happens on a DATA IN and when the host requested length is not met
154
       and the last packet is on a boundary. If slave_length is zero, then it is
155
       a explicit ZLP request, no need to force ZLP.  */
156

20995
    if ((transfer_request -> ux_slave_transfer_request_phase ==  UX_TRANSFER_PHASE_DATA_OUT) &&
157
13881
        (slave_length != 0) && (host_length != slave_length) &&
158
2310
        (slave_length % endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize) == 0)
159
    {
160
161
        /* If so force Zero Length Packet.  */
162
5
        transfer_request -> ux_slave_transfer_request_force_zlp =  UX_TRUE;
163
    }
164
    else
165
    {
166
167
        /* Condition is not met, do not force a Zero Length Packet.  */
168
20990
        transfer_request -> ux_slave_transfer_request_force_zlp =  UX_FALSE;
169
    }
170
171
    /* Reset the number of bytes sent/received.  */
172
20995
    transfer_request -> ux_slave_transfer_request_actual_length =  0;
173
174
    /* Determine how many bytes to send in this transaction.  We keep track of the original
175
        length and have a working length.  */
176
20995
    transfer_request -> ux_slave_transfer_request_requested_length =    slave_length;
177
20995
    transfer_request -> ux_slave_transfer_request_in_transfer_length =  slave_length;
178
179
    /* Save the buffer pointer.  */
180
20995
    transfer_request -> ux_slave_transfer_request_current_data_pointer =
181
20995
                            transfer_request -> ux_slave_transfer_request_data_pointer;
182
183
    /* Call the DCD driver transfer function.   */
184
20995
    status =  dcd -> ux_slave_dcd_function(dcd, UX_DCD_TRANSFER_REQUEST, transfer_request);
185
186
    /* And return the status.  */
187
20931
    return(status);
188
189
#endif
190
}
191