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 Audio 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_audio.h"
28 #include "ux_device_stack.h"
29
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _ux_device_class_audio_interrupt_send PORTABLE C */
36 /* 6.2.0 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function queues audio interrupt data. */
44 /* */
45 /* Note the interrupt data size is predefined on initialization: */
46 /* - for Audio 1.0 interrupt status word is 2 bytes */
47 /* - for Audio 2.0 interrupt data message is 6 bytes */
48 /* */
49 /* INPUT */
50 /* */
51 /* audio Address of audio instance */
52 /* int_data Interrupt data (2 or 6 bytes) */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* None */
57 /* */
58 /* CALLS */
59 /* */
60 /* */
61 /* CALLED BY */
62 /* */
63 /* Application */
64 /* */
65 /* RELEASE HISTORY */
66 /* */
67 /* DATE NAME DESCRIPTION */
68 /* */
69 /* 07-29-2022 Chaoqiong Xiao Initial Version 6.1.12 */
70 /* 10-31-2022 Yajun Xia Modified comment(s), */
71 /* added standalone support, */
72 /* resulting in version 6.2.0 */
73 /* */
74 /**************************************************************************/
_ux_device_class_audio_interrupt_send(UX_DEVICE_CLASS_AUDIO * audio,UCHAR * int_data)75 UINT _ux_device_class_audio_interrupt_send(UX_DEVICE_CLASS_AUDIO *audio, UCHAR *int_data)
76 {
77 #if !defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT)
78 UX_PARAMETER_NOT_USED(audio);
79 UX_PARAMETER_NOT_USED(int_data);
80 return(UX_FUNCTION_NOT_SUPPORTED);
81 #else
82
83 UX_SLAVE_DEVICE *device;
84 UX_SLAVE_ENDPOINT *endpoint;
85 UCHAR *buff, *end;
86 ULONG size;
87 ULONG i;
88
89 /* Get the pointer to the device. */
90 device = &_ux_system_slave -> ux_system_slave_device;
91
92 /* As long as the device is in the CONFIGURED state. */
93 if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
94 {
95
96 /* Cannot proceed with command, the interface is down. */
97 return(UX_CONFIGURATION_HANDLE_UNKNOWN);
98 }
99
100 /* Check if endpoint is available. */
101 endpoint = audio -> ux_device_class_audio_interrupt;
102 if (endpoint == UX_NULL)
103 return(UX_FUNCTION_NOT_SUPPORTED);
104
105 /* Get interrupt data size. */
106 size = audio -> ux_device_class_audio_status_size;
107
108 /* Protect queue status. */
109 _ux_device_mutex_on(&audio -> ux_device_class_audio_status_mutex);
110
111 /* Check if data exist. */
112 buff = audio -> ux_device_class_audio_status_tail;
113 end = audio -> ux_device_class_audio_status_queue + audio -> ux_device_class_audio_status_queue_bytes;
114 for (i = 0; i < audio -> ux_device_class_audio_status_queued; i += size)
115 {
116
117 /* Check if data match. */
118 if (_ux_utility_memory_compare(buff, int_data, size) == UX_SUCCESS)
119 {
120
121 /* Already queued. */
122 _ux_device_mutex_off(&audio -> ux_device_class_audio_status_mutex);
123 return(UX_SUCCESS);
124 }
125
126 /* Next saved data. */
127 buff += size;
128 if (buff >= end)
129 buff = audio -> ux_device_class_audio_status_queue;
130 }
131
132 /* No data match before buff achieve head. */
133 UX_ASSERT(buff == audio -> ux_device_class_audio_status_head);
134
135 /* If no free space, return busy (pending). */
136 if (audio -> ux_device_class_audio_status_queued >=
137 audio -> ux_device_class_audio_status_queue_bytes)
138 {
139
140 /* No queue space, pending. */
141 _ux_device_mutex_off(&audio -> ux_device_class_audio_status_mutex);
142 return(UX_BUSY);
143 }
144
145 /* Copy data to head. */
146 _ux_utility_memory_copy(buff, int_data, size); /* Use case of memcpy is verified. */
147
148 /* Move head. */
149 buff += size;
150 if (buff >= end)
151 buff = audio -> ux_device_class_audio_status_queue;
152 audio -> ux_device_class_audio_status_head = buff;
153
154 /* Add to queued bytes. */
155 audio -> ux_device_class_audio_status_queued += size;
156
157 /* Unprotect queue status. */
158 _ux_device_mutex_off(&audio -> ux_device_class_audio_status_mutex);
159
160 /* Notify status thread to issue interrupt request. */
161 _ux_device_semaphore_put(&audio -> ux_device_class_audio_status_semaphore);
162
163 /* Resume interrupt thread. */
164 _ux_device_thread_resume(&audio -> ux_device_class_audio_class -> ux_slave_class_thread);
165
166 /* Return success. */
167 return(UX_SUCCESS);
168 #endif
169 }
170
171
172 /**************************************************************************/
173 /* */
174 /* FUNCTION RELEASE */
175 /* */
176 /* _uxe_device_class_audio_interrupt_send PORTABLE C */
177 /* 6.2.1 */
178 /* AUTHOR */
179 /* */
180 /* Chaoqiong Xiao, Microsoft Corporation */
181 /* */
182 /* DESCRIPTION */
183 /* */
184 /* This function checks errors in queuing audio interrupt data */
185 /* function call. */
186 /* */
187 /* Note the interrupt data size is predefined and not checked: */
188 /* - for Audio 1.0 interrupt status word is 2 bytes */
189 /* - for Audio 2.0 interrupt data message is 6 bytes */
190 /* */
191 /* INPUT */
192 /* */
193 /* audio Address of audio instance */
194 /* int_data Interrupt data (2 or 6 bytes) */
195 /* */
196 /* OUTPUT */
197 /* */
198 /* None */
199 /* */
200 /* CALLS */
201 /* */
202 /* _ux_device_class_audio_interrupt_send Queue interrupt data to send */
203 /* */
204 /* CALLED BY */
205 /* */
206 /* Application */
207 /* */
208 /* RELEASE HISTORY */
209 /* */
210 /* DATE NAME DESCRIPTION */
211 /* */
212 /* 03-08-2023 Chaoqiong Xiao Initial Version 6.2.1 */
213 /* */
214 /**************************************************************************/
_uxe_device_class_audio_interrupt_send(UX_DEVICE_CLASS_AUDIO * audio,UCHAR * int_data)215 UINT _uxe_device_class_audio_interrupt_send(UX_DEVICE_CLASS_AUDIO *audio, UCHAR *int_data)
216 {
217
218 /* Sanity check. */
219 if (audio == UX_NULL || int_data == UX_NULL)
220 return(UX_INVALID_PARAMETER);
221
222 /* Send interrupt data. */
223 return(_ux_device_class_audio_interrupt_send(audio, int_data));
224 }