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