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