GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_cdc_acm_deactivate.c Lines: 24 24 100.0 %
Date: 2026-03-06 18:57:10 Branches: 12 12 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
/**   CDC ACM Class                                                       */
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_class_cdc_acm.h"
30
#include "ux_host_stack.h"
31
32
33
/**************************************************************************/
34
/*                                                                        */
35
/*  FUNCTION                                               RELEASE        */
36
/*                                                                        */
37
/*    _ux_host_class_cdc_acm_deactivate                   PORTABLE C      */
38
/*                                                           6.1.10       */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Chaoqiong Xiao, Microsoft Corporation                               */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    This function is called when this instance of the cdc_acm has been  */
46
/*    removed from the bus either directly or indirectly. The bulk in\out */
47
/*    and optional interrupt pipes will be destroyed and the instance     */
48
/*    removed.                                                            */
49
/*                                                                        */
50
/*  INPUT                                                                 */
51
/*                                                                        */
52
/*    command                               CDC ACM class command pointer */
53
/*                                                                        */
54
/*  OUTPUT                                                                */
55
/*                                                                        */
56
/*    Completion Status                                                   */
57
/*                                                                        */
58
/*  CALLS                                                                 */
59
/*                                                                        */
60
/*    _ux_host_stack_class_instance_destroy Destroy the class instance    */
61
/*    _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer      */
62
/*    _ux_utility_memory_free               Free memory block             */
63
/*    _ux_host_semaphore_get                Get protection semaphore      */
64
/*    _ux_host_semaphore_delete             Delete protection semaphore   */
65
/*    _ux_utility_thread_schedule_other     Schedule other threads        */
66
/*                                                                        */
67
/*  CALLED BY                                                             */
68
/*                                                                        */
69
/*    _ux_host_class_cdc_acm_entry          Entry of cdc_acm class        */
70
/*                                                                        */
71
/**************************************************************************/
72
97
UINT  _ux_host_class_cdc_acm_deactivate(UX_HOST_CLASS_COMMAND *command)
73
{
74
75
UX_HOST_CLASS_CDC_ACM       *cdc_acm;
76
UX_TRANSFER                 *transfer_request;
77
#if !defined(UX_HOST_STANDALONE)
78
UINT                        status;
79
#else
80
UX_HOST_CLASS_CDC_ACM       *cdc_acm_inst;
81
#endif
82
83
    /* Get the instance for this class.  */
84
97
    cdc_acm =  (UX_HOST_CLASS_CDC_ACM *) command -> ux_host_class_command_instance;
85
86
    /* The cdc_acm is being shut down.  */
87
97
    cdc_acm -> ux_host_class_cdc_acm_state =  UX_HOST_CLASS_INSTANCE_SHUTDOWN;
88
89
#if !defined(UX_HOST_STANDALONE)
90
91
    /* Protect thread reentry to this instance.  */
92
97
    status =  _ux_host_semaphore_get(&cdc_acm -> ux_host_class_cdc_acm_semaphore, UX_WAIT_FOREVER);
93
97
    if (status != UX_SUCCESS)
94
95
        /* Return error.  */
96
1
        return(status);
97
#endif
98
99
    /* If we have the Control Class, we only unmount the interrupt endpoint if it is active.  */
100
96
    if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS)
101
    {
102
103
        /* If the interrupt endpoint is defined, clean any pending transfer.  */
104
51
        if (cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint != UX_NULL)
105
        {
106
48
            transfer_request =  &cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint -> ux_endpoint_transfer_request;
107
108
            /* And abort any transfer.  */
109
48
            _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint);
110
111
            /* Free data buffer for the interrupt transfer.  */
112
47
            _ux_utility_memory_free(transfer_request -> ux_transfer_request_data_pointer);
113
        }
114
115
#if defined(UX_HOST_STANDALONE)
116
117
        /* Linked from data instance must be removed then.  */
118
        /* We scan CDC ACM instances to find the master instance.  */
119
        /* Get first instance linked to the class.  */
120
        cdc_acm_inst = (UX_HOST_CLASS_CDC_ACM *) cdc_acm ->
121
                    ux_host_class_cdc_acm_class -> ux_host_class_first_instance;
122
123
        /* Scan all instances.  */
124
        while(cdc_acm_inst)
125
        {
126
127
            /* If this data interface is linking to the control instance, unlink it.  */
128
            if (cdc_acm_inst -> ux_host_class_cdc_acm_control == cdc_acm)
129
                cdc_acm_inst -> ux_host_class_cdc_acm_control = UX_NULL;
130
131
            /* Next instance.  */
132
            cdc_acm_inst = cdc_acm_inst -> ux_host_class_cdc_acm_next_instance;
133
        }
134
#endif
135
    }
136
    else
137
    {
138
139
        /* We come to this point when the device has been extracted and this is the data class.
140
           So there may have been a transaction being scheduled.
141
           We make sure the transaction has been completed by the controller driver.
142
           When the device is extracted, the controller tries multiple times the transaction and retires it
143
           with a DEVICE_NOT_RESPONDING error code.
144
145
           First we take care of endpoint IN.  */
146
45
        transfer_request =  &cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint -> ux_endpoint_transfer_request;
147
45
        if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING)
148
149
            /* We need to abort transactions on the bulk In pipe.  */
150
4
            _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint);
151
152
        /* Then endpoint OUT.  */
153
45
        transfer_request =  &cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint -> ux_endpoint_transfer_request;
154
45
        if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING)
155
156
            /* We need to abort transactions on the bulk Out pipe. */
157
1
            _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint);
158
159
    }
160
161
#if !defined(UX_HOST_STANDALONE)
162
163
    /* The enumeration thread needs to sleep a while to allow the application or the class that may be using
164
       endpoints to exit properly.  */
165
95
    _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM);
166
#else
167
168
    /* If there is allocated resource, free it.  */
169
    if (cdc_acm -> ux_host_class_cdc_acm_allocated)
170
    {
171
        _ux_utility_memory_free(cdc_acm -> ux_host_class_cdc_acm_allocated);
172
    }
173
#endif
174
175
    /* Destroy the instance.  */
176
95
    _ux_host_stack_class_instance_destroy(cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm);
177
178
#if !defined(UX_HOST_STANDALONE)
179
180
    /* Destroy the semaphore.  */
181
95
    _ux_host_semaphore_delete(&cdc_acm -> ux_host_class_cdc_acm_semaphore);
182
#endif
183
184
    /* Before we free the device resources, we need to inform the application
185
        that the device is removed.  */
186
95
    if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
187
    {
188
189
        /* Inform the application the device is removed.  */
190
76
        _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm);
191
    }
192
193
    /* Free the cdc_acm instance memory.  */
194
95
    _ux_utility_memory_free(cdc_acm);
195
196
    /* If trace is enabled, insert this event into the trace buffer.  */
197
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_DEACTIVATE, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
198
199
    /* If trace is enabled, register this object.  */
200
    UX_TRACE_OBJECT_UNREGISTER(cdc_acm);
201
202
    /* Return successful status.  */
203
95
    return(UX_SUCCESS);
204
}
205