GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_device_classes/src/ux_device_class_cdc_ecm_bulkout_thread.c Lines: 35 35 100.0 %
Date: 2026-03-06 18:57:10 Branches: 14 14 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
/** USBX Component                                                        */
16
/**                                                                       */
17
/**   Device CDC_ECM Class                                                */
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_class_cdc_ecm.h"
29
#include "ux_device_stack.h"
30
31
32
#if !defined(UX_DEVICE_STANDALONE)
33
/**************************************************************************/
34
/*                                                                        */
35
/*  FUNCTION                                               RELEASE        */
36
/*                                                                        */
37
/*    _ux_device_class_cdc_ecm_bulkout_thread             PORTABLE C      */
38
/*                                                           6.3.0        */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Chaoqiong Xiao, Microsoft Corporation                               */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    This function is the thread of the cdc_ecm bulk out endpoint. It    */
46
/*    is waiting for the host to send data on the bulk out endpoint to    */
47
/*    the device.                                                         */
48
/*                                                                        */
49
/*  INPUT                                                                 */
50
/*                                                                        */
51
/*    cdc_ecm_class                             Address of cdc_ecm class  */
52
/*                                                container               */
53
/*                                                                        */
54
/*  OUTPUT                                                                */
55
/*                                                                        */
56
/*    None                                                                */
57
/*                                                                        */
58
/*  CALLS                                                                 */
59
/*                                                                        */
60
/*    _ux_device_stack_transfer_request     Request transfer              */
61
/*    _ux_utility_memory_copy               Copy memory                   */
62
/*    nx_packet_allocate                    Allocate NetX packet          */
63
/*    nx_packet_release                     Free NetX packet              */
64
/*    _ux_device_thread_suspend             Suspend thread                */
65
/*                                                                        */
66
/*  CALLED BY                                                             */
67
/*                                                                        */
68
/*    ThreadX                                                             */
69
/*                                                                        */
70
/**************************************************************************/
71
47
VOID  _ux_device_class_cdc_ecm_bulkout_thread(ULONG cdc_ecm_class)
72
{
73
74
UX_SLAVE_CLASS                  *class_ptr;
75
UX_SLAVE_CLASS_CDC_ECM          *cdc_ecm;
76
UX_SLAVE_DEVICE                 *device;
77
UX_SLAVE_TRANSFER               *transfer_request;
78
UINT                            status;
79
NX_PACKET                       *packet;
80
USB_NETWORK_DEVICE_TYPE         *ux_nx_device;
81
82
    /* Cast properly the cdc_ecm instance.  */
83
47
    UX_THREAD_EXTENSION_PTR_GET(class_ptr, UX_SLAVE_CLASS, cdc_ecm_class)
84
85
    /* Get the cdc_ecm instance from this class container.  */
86
47
    cdc_ecm =  (UX_SLAVE_CLASS_CDC_ECM *) class_ptr -> ux_slave_class_instance;
87
88
    /* Get the pointer to the device.  */
89
47
    device =  &_ux_system_slave -> ux_system_slave_device;
90
91
    /* This thread runs forever but can be suspended or resumed.  */
92
    while (1)
93
    {
94
95
        /* As long as the device is in the CONFIGURED state.  */
96
1310
        while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED)
97
        {
98
99
            /* Check if packet pool is ready.  */
100
1224
            if (cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool == UX_NULL)
101
            {
102
103
                /* Get the network device handle.  */
104
49
                ux_nx_device = (USB_NETWORK_DEVICE_TYPE *)(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle);
105
106
                /* Get packet pool from IP instance (if available).  */
107
49
                if (ux_nx_device -> ux_network_device_ip_instance != UX_NULL)
108
                {
109
47
                    cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool = ux_nx_device -> ux_network_device_ip_instance -> nx_ip_default_packet_pool;
110
                }
111
                else
112
                {
113
114
                    /* Error trap.  */
115
2
                    _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_ETH_PACKET_POOL_ERROR);
116
117
2
                    _ux_utility_delay_ms(UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_INST_WAIT);
118
1
                    continue;
119
                }
120
            }
121
122
            /* Check if Bulk OUT endpoint is ready.  */
123
1222
            if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint == UX_NULL)
124
            {
125
1
                _ux_utility_delay_ms(UX_DEVICE_CLASS_CDC_ECM_LINK_CHECK_WAIT);
126
1
                continue;
127
            }
128
129
            /* We can accept new reception. Get a NX Packet */
130
1221
            status =  nx_packet_allocate(cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool, &packet,
131
                                         NX_RECEIVE_PACKET, UX_MS_TO_TICK(UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_WAIT));
132
133
1221
            if (status == NX_SUCCESS)
134
            {
135
136
                /* Select the transfer request associated with BULK OUT endpoint.   */
137
1220
                transfer_request =  &cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint -> ux_slave_endpoint_transfer_request;
138
139
                /* And length.  */
140
1220
                transfer_request -> ux_slave_transfer_request_requested_length =  UX_DEVICE_CLASS_CDC_ECM_BULKOUT_BUFFER_SIZE;
141
1220
                transfer_request -> ux_slave_transfer_request_actual_length =     0;
142
143
                /* Memorize this packet at the beginning of the queue.  */
144
1220
                cdc_ecm -> ux_slave_class_cdc_ecm_receive_queue = packet;
145
146
                /* Reset the queue pointer of this packet.  */
147
1220
                packet -> nx_packet_queue_next = UX_NULL;
148
149
#if (UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1) && defined(UX_DEVICE_CLASS_CDC_ECM_ZERO_COPY)
150
151
                /* Send the request to the device controller.  */
152
                transfer_request -> ux_slave_transfer_request_data_pointer = packet -> nx_packet_prepend_ptr + sizeof(USHORT);
153
                status =  _ux_device_stack_transfer_request(transfer_request,
154
                        packet -> nx_packet_pool_owner -> nx_packet_pool_payload_size - sizeof(USHORT),
155
                        packet -> nx_packet_pool_owner -> nx_packet_pool_payload_size - sizeof(USHORT));
156
#else
157
158
                /* Send the request to the device controller.  */
159
1220
                status =  _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_CDC_ECM_BULKOUT_BUFFER_SIZE,
160
                                                                    UX_DEVICE_CLASS_CDC_ECM_BULKOUT_BUFFER_SIZE);
161
#endif
162
163
                /* Check the completion code. */
164
1212
                if (status == UX_SUCCESS)
165
                {
166
167
                    /* We only proceed with packets that are received OK, if error, ignore the packet. */
168
                    /* If trace is enabled, insert this event into the trace buffer.  */
169
                    UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ECM_PACKET_RECEIVE, cdc_ecm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
170
171
                    /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header.  */
172
1124
                    packet -> nx_packet_prepend_ptr += sizeof(USHORT);
173
1124
                    packet -> nx_packet_append_ptr += sizeof(USHORT);
174
175
#if (UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1) && defined(UX_DEVICE_CLASS_CDC_ECM_ZERO_COPY)
176
177
                    /* Data already in packet.  */
178
                    packet -> nx_packet_length = transfer_request -> ux_slave_transfer_request_actual_length;
179
180
                    /* Send that packet to the NetX USB broker.  */
181
                    _ux_network_driver_packet_received(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle, packet);
182
#else
183
184
                    /* Copy the received packet in the IP packet data area.  */
185
1124
                    status = nx_packet_data_append(packet,
186
1124
                            transfer_request -> ux_slave_transfer_request_data_pointer,
187
                            transfer_request -> ux_slave_transfer_request_actual_length,
188
                            cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool,
189
                            UX_MS_TO_TICK(UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_WAIT));
190
1124
                    if (status == NX_SUCCESS)
191
                    {
192
193
                        /* Send that packet to the NetX USB broker.  */
194
1123
                        _ux_network_driver_packet_received(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle, packet);
195
                    }
196
                    else
197
                    {
198
199
                        /* We received a malformed packet. Report to application.  */
200
1
                        _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR);
201
1
                        nx_packet_release(packet);
202
                    }
203
#endif
204
                }
205
                else
206
207
                    /* Free the packet that was not successfully received.  */
208
88
                    nx_packet_release(packet);
209
            }
210
            else
211
            {
212
213
                /* Packet allocation timed out. Note that the timeout value is
214
                   configurable.  */
215
216
                /* Error trap. No need for trace, since NetX does it.  */
217
1
                _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT);
218
            }
219
        }
220
221
        /* We need to suspend ourselves. We will be resumed by the device enumeration module.  */
222
86
        _ux_device_thread_suspend(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread);
223
    }
224
}
225
#endif