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 /** Audio 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_audio.h"
29 #include "ux_host_stack.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _ux_host_class_audio_deactivate PORTABLE C */
37 /* 6.3.0 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function is called when this instance of the audio has been */
45 /* removed from the bus either directly or indirectly. The iso pipes */
46 /* will be destroyed and the instanced removed. */
47 /* */
48 /* INPUT */
49 /* */
50 /* command Pointer to command */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* Completion Status */
55 /* */
56 /* CALLS */
57 /* */
58 /* _ux_host_stack_class_instance_destroy Destroy class instance */
59 /* _ux_host_stack_endpoint_transfer_abort Abort outstanding transfer */
60 /* _ux_host_mutex_on Get mutex */
61 /* _ux_host_mutex_delete Delete mutex */
62 /* _ux_utility_memory_free Release memory block */
63 /* */
64 /* CALLED BY */
65 /* */
66 /* Audio Class */
67 /* */
68 /* RELEASE HISTORY */
69 /* */
70 /* DATE NAME DESCRIPTION */
71 /* */
72 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
73 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
74 /* resulting in version 6.1 */
75 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
76 /* refined macros names, */
77 /* resulting in version 6.1.10 */
78 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
79 /* added interrupt support, */
80 /* protect reentry with mutex, */
81 /* added feedback support, */
82 /* resulting in version 6.1.12 */
83 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), */
84 /* improved AC AS management, */
85 /* resulting in version 6.3.0 */
86 /* */
87 /**************************************************************************/
_ux_host_class_audio_deactivate(UX_HOST_CLASS_COMMAND * command)88 UINT _ux_host_class_audio_deactivate(UX_HOST_CLASS_COMMAND *command)
89 {
90
91 UX_HOST_CLASS_AUDIO *audio;
92 #if defined(UX_HOST_CLASS_AUDIO_INTERRUPT_SUPPORT)
93 UX_HOST_CLASS_AUDIO_AC *ac;
94 UINT i;
95 #endif
96
97 /* Get the instance for this class. */
98 audio = (UX_HOST_CLASS_AUDIO *) command -> ux_host_class_command_instance;
99
100 #if defined(UX_HOST_CLASS_AUDIO_INTERRUPT_SUPPORT)
101 if (_ux_host_class_audio_subclass_get(audio) == UX_HOST_CLASS_AUDIO_SUBCLASS_CONTROL)
102 {
103 ac = (UX_HOST_CLASS_AUDIO_AC *)audio;
104
105 /* Stop interrupt and free allocated buffer for it. */
106 if (ac -> ux_host_class_audio_interrupt_endpoint)
107 {
108 _ux_host_stack_endpoint_transfer_abort(ac -> ux_host_class_audio_interrupt_endpoint);
109 _ux_utility_memory_free(ac -> ux_host_class_audio_interrupt_endpoint ->
110 ux_endpoint_transfer_request.ux_transfer_request_data_pointer);
111 }
112
113 /* The enumeration thread needs to sleep a while to allow the application or the class that may be using
114 endpoints to exit properly. */
115 _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM);
116
117 /* Clear the links in AS interfaces. */
118 for (i = 0; i < ac -> ux_host_class_audio_as_count; i++)
119 {
120 if (ac -> ux_host_class_audio_as[i])
121 ac -> ux_host_class_audio_as[i] -> ux_host_class_audio_ac = UX_NULL;
122 }
123
124 /* Destroy the instance. */
125 _ux_host_stack_class_instance_destroy(audio -> ux_host_class_audio_class, (VOID *) audio);
126 }
127 else
128 #endif
129 {
130
131 /* The audio is being shut down. */
132 audio -> ux_host_class_audio_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN;
133
134 /* Protect thread reentry to this instance. */
135 _ux_host_mutex_on(&audio -> ux_host_class_audio_mutex);
136
137 /* We need to abort transactions on the iso pipe. */
138 if (audio -> ux_host_class_audio_isochronous_endpoint)
139 _ux_host_stack_endpoint_transfer_abort(audio -> ux_host_class_audio_isochronous_endpoint);
140 #if defined(UX_HOST_CLASS_AUDIO_FEEDBACK_SUPPORT)
141 if (audio -> ux_host_class_audio_feedback_endpoint)
142 {
143 _ux_host_stack_endpoint_transfer_abort(audio -> ux_host_class_audio_feedback_endpoint);
144 _ux_utility_memory_free(audio -> ux_host_class_audio_feedback_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer);
145 }
146 #endif
147
148 /* The enumeration thread needs to sleep a while to allow the application or the class that may be using
149 endpoints to exit properly. */
150 _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM);
151
152 #if defined(UX_HOST_CLASS_AUDIO_INTERRUPT_SUPPORT)
153
154 /* Clear the links in AC interface. */
155 ac = audio -> ux_host_class_audio_ac;
156 if (ac)
157 ac -> ux_host_class_audio_as[audio -> ux_host_class_audio_ac_as] = UX_NULL;
158 #endif
159
160 /* Destroy the instance. */
161 _ux_host_stack_class_instance_destroy(audio -> ux_host_class_audio_class, (VOID *) audio);
162
163 /* Destroy the semaphore. */
164 _ux_host_mutex_delete(&audio -> ux_host_class_audio_mutex);
165 }
166
167 /* Before we free the device resources, we need to inform the application
168 that the device is removed. */
169 if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
170 {
171
172 /* Inform the application the device is removed. */
173 _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, audio -> ux_host_class_audio_class, (VOID *) audio);
174 }
175
176 /* If trace is enabled, insert this event into the trace buffer. */
177 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_AUDIO_DEACTIVATE, audio, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
178
179 /* If trace is enabled, register this object. */
180 UX_TRACE_OBJECT_UNREGISTER(audio);
181
182 /* Free the audio instance memory. */
183 _ux_utility_memory_free(audio);
184
185 /* Return successful completion. */
186 return(UX_SUCCESS);
187 }
188
189