GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_device_classes/src/ux_device_class_cdc_ecm_change.c Lines: 33 33 100.0 %
Date: 2026-03-06 18:57:10 Branches: 18 18 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
/** 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
/**************************************************************************/
32
/*                                                                        */
33
/*  FUNCTION                                               RELEASE        */
34
/*                                                                        */
35
/*    _ux_device_class_cdc_ecm_change                     PORTABLE C      */
36
/*                                                           6.3.0        */
37
/*  AUTHOR                                                                */
38
/*                                                                        */
39
/*    Chaoqiong Xiao, Microsoft Corporation                               */
40
/*                                                                        */
41
/*  DESCRIPTION                                                           */
42
/*                                                                        */
43
/*    This function changes the interface of the CDC_ECM device           */
44
/*                                                                        */
45
/*  INPUT                                                                 */
46
/*                                                                        */
47
/*    command                           Pointer to cdc_ecm command        */
48
/*                                                                        */
49
/*  OUTPUT                                                                */
50
/*                                                                        */
51
/*    Completion Status                                                   */
52
/*                                                                        */
53
/*  CALLS                                                                 */
54
/*                                                                        */
55
/*    _ux_network_driver_link_up            Link status up                */
56
/*    _ux_network_driver_link_down          Link status down              */
57
/*    _ux_utility_memory_set                Set memory                    */
58
/*    _ux_device_thread_resume              Resume thread                 */
59
/*    _ux_device_event_flags_set            Set event flags               */
60
/*    _ux_device_stack_transfer_all_request_abort                         */
61
/*                                          Abort transfer                */
62
/*                                                                        */
63
/*  CALLED BY                                                             */
64
/*                                                                        */
65
/*    USBX Source Code                                                    */
66
/*                                                                        */
67
/**************************************************************************/
68
101
UINT  _ux_device_class_cdc_ecm_change(UX_SLAVE_CLASS_COMMAND *command)
69
{
70
71
UX_SLAVE_INTERFACE                      *interface_ptr;
72
UX_SLAVE_CLASS                          *class_ptr;
73
UX_SLAVE_CLASS_CDC_ECM                  *cdc_ecm;
74
UX_SLAVE_ENDPOINT                       *endpoint;
75
76
    /* Get the class container.  */
77
101
    class_ptr =  command -> ux_slave_class_command_class_ptr;
78
79
    /* Get the class instance in the container.  */
80
101
    cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *) class_ptr -> ux_slave_class_instance;
81
82
    /* Get the interface that owns this instance.  */
83
101
    interface_ptr =  (UX_SLAVE_INTERFACE  *) command -> ux_slave_class_command_interface;
84
85
    /* Locate the endpoints.  Control and Bulk in/out for Data Interface.  */
86
101
    endpoint =  interface_ptr -> ux_slave_interface_first_endpoint;
87
88
    /* If the interface to mount has a non zero alternate setting, the class is really active with
89
       the endpoints active.  If the interface reverts to alternate setting 0, it needs to have
90
       the pending transactions terminated.  */
91
101
    if (interface_ptr -> ux_slave_interface_descriptor.bAlternateSetting != 0)
92
    {
93
94
        /* Parse all endpoints.  */
95
299
        while (endpoint != UX_NULL)
96
        {
97
98
            /* Check the endpoint direction, and type.  */
99
200
            if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN)
100
            {
101
102
                /* Look at type.  */
103
100
                if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)
104
105
                    /* We have found the bulk in endpoint, save it.  */
106
96
                    cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint =  endpoint;
107
#if (UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1) && !defined(UX_DEVICE_CLASS_CDC_ECM_ZERO_COPY)
108
                    endpoint -> ux_slave_endpoint_transfer_request.
109
                        ux_slave_transfer_request_data_pointer =
110
                                UX_DEVICE_CLASS_CDC_ECM_BULKIN_BUFFER(cdc_ecm);
111
#endif
112
            }
113
            else
114
            {
115
                /* Look at type for out endpoint.  */
116
100
                if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)
117
118
                    /* We have found the bulk out endpoint, save it.  */
119
96
                    cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint =  endpoint;
120
#if (UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1) && !defined(UX_DEVICE_CLASS_CDC_ECM_ZERO_COPY)
121
                    endpoint -> ux_slave_endpoint_transfer_request.
122
                        ux_slave_transfer_request_data_pointer =
123
                                UX_DEVICE_CLASS_CDC_ECM_BULKOUT_BUFFER(cdc_ecm);
124
#endif
125
            }
126
127
            /* Next endpoint.  */
128
200
            endpoint =  endpoint -> ux_slave_endpoint_next_endpoint;
129
        }
130
131
        /* Now check if all endpoints have been found.  */
132

99
        if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint == UX_NULL || cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint == UX_NULL)
133
134
            /* Not all endpoints have been found. Major error, do not proceed.  */
135
6
            return(UX_ERROR);
136
137
        /* Declare the link to be up. */
138
93
        cdc_ecm -> ux_slave_class_cdc_ecm_link_state = UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP;
139
140
        /* Communicate the state with the network driver.  */
141
93
        _ux_network_driver_link_up(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle);
142
143
#if (UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1) && defined(UX_DEVICE_CLASS_CDC_ECM_ZERO_COPY)
144
145
        /* There is no endpoint buffer.  */
146
#else
147
148
        /* Reset the endpoint buffers.  */
149
93
        _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint -> ux_slave_endpoint_transfer_request.
150
                                        ux_slave_transfer_request_data_pointer, 0, UX_DEVICE_CLASS_CDC_ECM_BULKOUT_BUFFER_SIZE); /* Use case of memset is verified. */
151
93
        _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint -> ux_slave_endpoint_transfer_request.
152
                                        ux_slave_transfer_request_data_pointer, 0, UX_DEVICE_CLASS_CDC_ECM_BULKIN_BUFFER_SIZE); /* Use case of memset is verified. */
153
#endif
154
155
        /* Resume the endpoint threads.  */
156
93
        _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread);
157
93
        _ux_device_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread);
158
159
        /* Wake up the Interrupt thread and send a network notification to the host.  */
160
93
        _ux_device_event_flags_set(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, UX_DEVICE_CLASS_CDC_ECM_NETWORK_NOTIFICATION_EVENT, UX_OR);
161
162
        /* If there is an activate function call it.  */
163
93
        if (cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate != UX_NULL)
164
165
            /* Invoke the application.  */
166
89
            cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate(cdc_ecm);
167
    }
168
    else
169
    {
170
171
        /* In this case, we are reverting to the Alternate Setting 0.  */
172
173
        /* Declare the link to be down.  */
174
2
        cdc_ecm -> ux_slave_class_cdc_ecm_link_state = UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_DOWN;
175
176
        /* Communicate the state with the network driver.  */
177
2
        _ux_network_driver_link_down(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle);
178
179
        /* Terminate the transactions pending on the bulk in endpoint.  If there is a transfer on the
180
           bulk out endpoint, we simply let it finish and let NetX throw it away.  */
181
2
        _ux_device_stack_transfer_all_request_abort(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint, UX_TRANSFER_APPLICATION_RESET);
182
183
        /* Notify the thread waiting for network notification events. In this case,
184
           the event is that the link state has been switched to down.  */
185
2
        _ux_device_event_flags_set(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, UX_DEVICE_CLASS_CDC_ECM_NETWORK_NOTIFICATION_EVENT, UX_OR);
186
187
        /* Wake up the bulk in thread so that it can clean up the xmit queue.  */
188
2
        _ux_device_event_flags_set(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, UX_DEVICE_CLASS_CDC_ECM_NEW_DEVICE_STATE_CHANGE_EVENT, UX_OR);
189
190
        /* If there is a deactivate function call it.  */
191
2
        if (cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate != UX_NULL)
192
193
            /* Invoke the application.  */
194
1
            cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate(cdc_ecm);
195
    }
196
197
    /* Set the CDC ECM alternate setting to the new one.  */
198
95
    cdc_ecm -> ux_slave_class_cdc_ecm_current_alternate_setting = interface_ptr -> ux_slave_interface_descriptor.bAlternateSetting;
199
200
    /* If trace is enabled, insert this event into the trace buffer.  */
201
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ECM_CHANGE, cdc_ecm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
202
203
    /* If trace is enabled, register this object.  */
204
    UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, cdc_ecm, 0, 0, 0)
205
206
    /* Return completion status.  */
207
95
    return(UX_SUCCESS);
208
}
209