1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** USBX Component                                                        */
17 /**                                                                       */
18 /**   Audio 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_audio.h"
30 #include "ux_host_stack.h"
31 
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _ux_host_class_audio_entity_control_get             PORTABLE C      */
38 /*                                                           6.1.12       */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function obtains the static values for a single audio control  */
46 /*    control on either the master channel or a specific channel.         */
47 /*                                                                        */
48 /*    Note only control value of BYTE, WORD and DWORD (<4) is supported.  */
49 /*    E.g., Graphic Equalizer Control is not supported.                   */
50 /*                                                                        */
51 /*  INPUT                                                                 */
52 /*                                                                        */
53 /*    audio                                 Pointer to audio class        */
54 /*    audio_control                         Pointer to audio control      */
55 /*                                                                        */
56 /*  OUTPUT                                                                */
57 /*                                                                        */
58 /*    Completion Status                                                   */
59 /*                                                                        */
60 /*  CALLS                                                                 */
61 /*                                                                        */
62 /*    _ux_host_stack_class_instance_verify  Verify instance is valid      */
63 /*    _ux_host_stack_transfer_request       Process transfer request      */
64 /*    _ux_host_semaphore_get                Get semaphore                 */
65 /*    _ux_host_semaphore_put                Release semaphore             */
66 /*    _ux_host_mutex_on                     Get mutex                     */
67 /*    _ux_host_mutex_off                    Release mutex                 */
68 /*    _ux_utility_memory_allocate           Allocate memory block         */
69 /*    _ux_utility_memory_free               Release memory block          */
70 /*    _ux_utility_short_get                 Read 16-bit value             */
71 /*                                                                        */
72 /*  CALLED BY                                                             */
73 /*                                                                        */
74 /*    Application                                                         */
75 /*    Audio Class                                                         */
76 /*                                                                        */
77 /*  RELEASE HISTORY                                                       */
78 /*                                                                        */
79 /*    DATE              NAME                      DESCRIPTION             */
80 /*                                                                        */
81 /*  07-29-2022     Chaoqiong Xiao           Initial Version 6.1.12        */
82 /*                                                                        */
83 /**************************************************************************/
_ux_host_class_audio_entity_control_get(UX_HOST_CLASS_AUDIO * audio,UX_HOST_CLASS_AUDIO_CONTROL * audio_control)84 UINT  _ux_host_class_audio_entity_control_get(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_CONTROL *audio_control)
85 {
86 
87 UINT            status;
88 UCHAR *         control_buffer;
89 ULONG           actual_size;
90 #if defined(UX_HOST_CLASS_AUDIO_2_SUPPORT)
91 ULONG           n_subs, sub, pos, min, max, res, size;
92 #endif
93 
94 
95     /* Validate control size.  */
96     if (audio_control -> ux_host_class_audio_control_size > 4)
97         return(UX_INVALID_PARAMETER);
98 
99     /* Ensure the instance is valid.  */
100     if (_ux_host_stack_class_instance_verify(_ux_system_host_class_audio_name, (VOID *) audio) != UX_SUCCESS)
101     {
102 
103         /* Error trap. */
104         _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN);
105 
106         /* If trace is enabled, insert this event into the trace buffer.  */
107         UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, audio, 0, 0, UX_TRACE_ERRORS, 0, 0)
108 
109         return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
110     }
111 
112     /* Protect thread reentry to this instance.  */
113     _ux_host_mutex_on(&audio -> ux_host_class_audio_mutex);
114 
115 #if defined(UX_HOST_CLASS_AUDIO_2_SUPPORT)
116     if (_ux_host_class_audio_protocol_get(audio) == UX_HOST_CLASS_AUDIO_PROTOCOL_IP_VERSION_02_00)
117     {
118 
119         /* Need to allocate enough memory for the control buffer.  */
120         /* Max RANGE size (single item): 2+4*3=14.  */
121         control_buffer =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 16);
122         if (control_buffer == UX_NULL)
123         {
124 
125             /* Return an error.  */
126             _ux_host_mutex_off(&audio -> ux_host_class_audio_mutex);
127             return(UX_MEMORY_INSUFFICIENT);
128         }
129 
130         /* Issue GET RANGE request.  */
131         status = _ux_host_class_audio_control_request(audio, 0,
132             UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE,
133             UX_CLASS_AUDIO20_RANGE,
134             audio_control -> ux_host_class_audio_control_channel |
135                 (audio_control -> ux_host_class_audio_control << 8),
136             audio_control -> ux_host_class_audio_control_entity,
137             control_buffer, 16, &actual_size);
138 
139         /* Check request status code.  */
140         if (status == UX_SUCCESS)
141         {
142 
143             /* Check returned size.  */
144             if (actual_size < 2)
145             {
146 
147                 /* Return an error.  */
148                 _ux_host_mutex_off(&audio -> ux_host_class_audio_mutex);
149                 _ux_utility_memory_free(control_buffer);
150                 return(UX_TRANSFER_ERROR);
151             }
152 
153             /* Check wNumSubRanges.  */
154             n_subs = _ux_utility_short_get(control_buffer);
155             if (n_subs > 1)
156             {
157 
158                 /* wNumSubRanges is short, control size max 4, no overflow.  */
159                 size = 2 + n_subs * audio_control -> ux_host_class_audio_control_size;
160                 if (size > 16)
161                 {
162 
163                     /* Issue GET RANGE again with larger buffer.  */
164                     _ux_utility_memory_free(control_buffer);
165                     control_buffer = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, size);
166                     if (control_buffer == UX_NULL)
167                     {
168 
169                         /* Return an error.  */
170                         _ux_host_mutex_off(&audio -> ux_host_class_audio_mutex);
171                         return(UX_MEMORY_INSUFFICIENT);
172                     }
173 
174                     /* Issue GET RANGE request.  */
175                     status = _ux_host_class_audio_control_request(audio, 0,
176                         UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE,
177                         UX_CLASS_AUDIO20_RANGE,
178                         audio_control -> ux_host_class_audio_control_channel |
179                             (audio_control -> ux_host_class_audio_control << 8),
180                         audio_control -> ux_host_class_audio_control_entity,
181                         control_buffer, size, &actual_size);
182 
183                     if ((status != UX_SUCCESS) || (actual_size != size))
184                     {
185 
186                         /* Return an error.  */
187                         _ux_utility_memory_free(control_buffer);
188                         _ux_host_mutex_off(&audio -> ux_host_class_audio_mutex);
189                         return(UX_TRANSFER_ERROR);
190                     }
191                 }
192             }
193 
194             /* Parse returned values.  */
195             audio_control -> ux_host_class_audio_control_max = 0;
196             audio_control -> ux_host_class_audio_control_min = 0xFFFFFFFF;
197             audio_control -> ux_host_class_audio_control_res = 0;
198             pos = 2;
199             for (sub = 0; sub < n_subs; sub ++)
200             {
201 
202                 /* Get MIN, MAX and POS.  */
203                 switch(audio_control -> ux_host_class_audio_control_size)
204                 {
205                 case 1:
206                     min = *(control_buffer + pos);
207                     pos ++;
208                     max = *(control_buffer + pos);
209                     pos ++;
210                     res = *(control_buffer + pos);
211                     pos ++;
212                     break;
213 
214                 case 2:
215                     min = _ux_utility_short_get(control_buffer + pos);
216                     pos += 2;
217                     max = _ux_utility_short_get(control_buffer + pos);
218                     pos += 2;
219                     res = _ux_utility_short_get(control_buffer + pos);
220                     pos += 2;
221                     break;
222 
223                 default:
224                     min = _ux_utility_long_get(control_buffer + pos);
225                     pos += 4;
226                     max = _ux_utility_long_get(control_buffer + pos);
227                     pos += 4;
228                     res = _ux_utility_long_get(control_buffer + pos);
229                     pos += 4;
230                     break;
231                 }
232 
233                 /* Keep MAX.  */
234                 if (audio_control -> ux_host_class_audio_control_max < max)
235                     audio_control -> ux_host_class_audio_control_max = max;
236 
237                 /* Keep MIN.  */
238                 if (audio_control -> ux_host_class_audio_control_min > min)
239                     audio_control -> ux_host_class_audio_control_min = min;
240 
241                 /* If there is RES, keep the min of RES.  */
242                 if (audio_control -> ux_host_class_audio_control_res == 0)
243                     audio_control -> ux_host_class_audio_control_res = res;
244                 else if (res < audio_control -> ux_host_class_audio_control_res)
245                     audio_control -> ux_host_class_audio_control_res = res;
246             }
247 
248             /* If there is list of RANGEs and no RES, guess it (average of max-min).  */
249             if (n_subs > 1 && audio_control -> ux_host_class_audio_control_res == 0)
250             {
251                 audio_control -> ux_host_class_audio_control_res =
252                     (audio_control -> ux_host_class_audio_control_max -
253                     audio_control -> ux_host_class_audio_control_min) / n_subs;
254             }
255         }
256     }
257     else
258 #endif
259     {
260 
261         /* Need to allocate memory for the control buffer, max DWORD (4).  */
262         control_buffer =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 4);
263         if (control_buffer == UX_NULL)
264         {
265 
266             /* Return an error.  */
267             _ux_host_mutex_off(&audio -> ux_host_class_audio_mutex);
268             return(UX_MEMORY_INSUFFICIENT);
269         }
270 
271         /* Issue GET_MIN request.  */
272         * (ULONG *)control_buffer = 0;
273         status = _ux_host_class_audio_control_request(audio, 0,
274             UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE,
275             UX_HOST_CLASS_AUDIO_GET_MIN,
276             audio_control -> ux_host_class_audio_control_channel |
277                 (audio_control -> ux_host_class_audio_control << 8),
278             audio_control -> ux_host_class_audio_control_entity,
279             control_buffer, 4, &actual_size);
280 
281         /* Check for correct transfer and entire control buffer returned.
282          * Start GET_MAX request.  */
283         if (status == UX_SUCCESS)
284         {
285 
286             /* Update the MIN static value for the caller.  */
287             audio_control -> ux_host_class_audio_control_min = _ux_utility_long_get(control_buffer);
288 
289             /* Issue GET_MAX request.  */
290             * (ULONG *)control_buffer = 0;
291             status = _ux_host_class_audio_control_request(audio, 0,
292                 UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE,
293                 UX_HOST_CLASS_AUDIO_GET_MAX,
294                 audio_control -> ux_host_class_audio_control_channel |
295                     (audio_control -> ux_host_class_audio_control << 8),
296                 audio_control -> ux_host_class_audio_control_entity,
297                 control_buffer, 4, &actual_size);
298         }
299 
300         /* Check for correct transfer and entire control buffer returned.
301          * Start GET_RES request.  */
302         if (status == UX_SUCCESS)
303         {
304 
305             /* Update the MAX static value for the caller.  */
306             audio_control -> ux_host_class_audio_control_max = _ux_utility_long_get(control_buffer);
307 
308             /* Issue GET_RES request.  */
309             * (ULONG *)control_buffer = 0;
310             status = _ux_host_class_audio_control_request(audio, 0,
311                 UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE,
312                 UX_HOST_CLASS_AUDIO_GET_RES,
313                 audio_control -> ux_host_class_audio_control_channel |
314                     (audio_control -> ux_host_class_audio_control << 8),
315                 audio_control -> ux_host_class_audio_control_entity,
316                 control_buffer, 4, &actual_size);
317         }
318 
319         /* Check for correct transfer and entire control buffer returned.  */
320         if (status == UX_SUCCESS)
321         {
322 
323             /* Update the RES static value for the caller.  */
324             audio_control -> ux_host_class_audio_control_res = _ux_utility_long_get(control_buffer);
325         }
326     }
327 
328     /* Free all used resources.  */
329     _ux_utility_memory_free(control_buffer);
330 
331     /* Unprotect thread reentry to this instance.  */
332     _ux_host_mutex_off(&audio -> ux_host_class_audio_mutex);
333 
334     /* Return completion status.  */
335     return(status);
336 }
337