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 /** USBX Component                                                        */
14 /**                                                                       */
15 /**   Device Audio Class                                                  */
16 /**                                                                       */
17 /**************************************************************************/
18 /**************************************************************************/
19 
20 #define UX_SOURCE_CODE
21 
22 
23 /* Include necessary system files.  */
24 
25 #include "ux_api.h"
26 #include "ux_device_class_audio.h"
27 #include "ux_device_stack.h"
28 
29 
30 /**************************************************************************/
31 /*                                                                        */
32 /*  FUNCTION                                               RELEASE        */
33 /*                                                                        */
34 /*    _ux_device_class_audio_initialize                   PORTABLE C      */
35 /*                                                           6.3.0        */
36 /*  AUTHOR                                                                */
37 /*                                                                        */
38 /*    Chaoqiong Xiao, Microsoft Corporation                               */
39 /*                                                                        */
40 /*  DESCRIPTION                                                           */
41 /*                                                                        */
42 /*    This function initializes the USB Audio device.                     */
43 /*                                                                        */
44 /*  INPUT                                                                 */
45 /*                                                                        */
46 /*    command                               Pointer to audio command      */
47 /*                                                                        */
48 /*  OUTPUT                                                                */
49 /*                                                                        */
50 /*    Completion Status                                                   */
51 /*                                                                        */
52 /*  CALLS                                                                 */
53 /*                                                                        */
54 /*    _ux_utility_memory_allocate           Allocate memory               */
55 /*    _ux_utility_memory_copy               Copy memory                   */
56 /*    _ux_utility_memory_free               Free memory                   */
57 /*    _ux_device_thread_create              Create thread to use          */
58 /*    _ux_device_thread_delete              Delete thread                 */
59 /*                                                                        */
60 /*  CALLED BY                                                             */
61 /*                                                                        */
62 /*    Device Audio Class                                                  */
63 /*                                                                        */
64 /*  RELEASE HISTORY                                                       */
65 /*                                                                        */
66 /*    DATE              NAME                      DESCRIPTION             */
67 /*                                                                        */
68 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
69 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
70 /*                                            verified memset and memcpy  */
71 /*                                            cases, used UX prefix to    */
72 /*                                            refer to TX symbols instead */
73 /*                                            of using them directly,     */
74 /*                                            resulting in version 6.1    */
75 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
76 /*                                            refined macros names,       */
77 /*                                            added feedback support,     */
78 /*                                            resulting in version 6.1.10 */
79 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
80 /*                                            fixed standalone compile,   */
81 /*                                            resulting in version 6.1.11 */
82 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
83 /*                                            added interrupt support,    */
84 /*                                            refined internal logic,     */
85 /*                                            resulting in version 6.1.12 */
86 /*  10-31-2022     Yajun Xia                Modified comment(s),          */
87 /*                                            added standalone support,   */
88 /*                                            resulting in version 6.2.0  */
89 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s),          */
90 /*                                            added a new mode to manage  */
91 /*                                            endpoint buffer in classes  */
92 /*                                            with zero copy enabled,     */
93 /*                                            resulting in version 6.3.0  */
94 /*                                                                        */
95 /**************************************************************************/
_ux_device_class_audio_initialize(UX_SLAVE_CLASS_COMMAND * command)96 UINT  _ux_device_class_audio_initialize(UX_SLAVE_CLASS_COMMAND *command)
97 {
98 
99 UINT                                    status = UX_SUCCESS;
100 UX_DEVICE_CLASS_AUDIO                   *audio;
101 UX_DEVICE_CLASS_AUDIO_PARAMETER         *audio_parameter;
102 UX_DEVICE_CLASS_AUDIO_STREAM            *stream;
103 UX_DEVICE_CLASS_AUDIO_STREAM_PARAMETER  *stream_parameter;
104 UX_SLAVE_CLASS                          *audio_class;
105 ULONG                                   memory_size;
106 ULONG                                   streams_size;
107 ULONG                                   i;
108 
109 
110     /* Get the class container.  */
111     audio_class =  command -> ux_slave_class_command_class_ptr;
112 
113     /* Get the pointer to the application parameters for the audio class.  */
114     audio_parameter = (UX_DEVICE_CLASS_AUDIO_PARAMETER *)command -> ux_slave_class_command_parameter;
115 
116     /* Create an instance of the device audio class, with additional streams and controls instances.  */
117     memory_size  = sizeof(UX_DEVICE_CLASS_AUDIO);
118 
119     /* Put 0 to default result.  */
120     streams_size = 0;
121 
122     /* Confirm there is no overflow on multiply.  */
123     UX_UTILITY_MULC_SAFE(audio_parameter -> ux_device_class_audio_parameter_streams_nb, (ULONG)sizeof(UX_DEVICE_CLASS_AUDIO_STREAM), streams_size, status);
124     if (status != UX_SUCCESS)
125         return(status);
126 
127     /* Confirm there is no overflow on add.  */
128     UX_UTILITY_ADD_SAFE(memory_size, streams_size, memory_size, status);
129     if (status != UX_SUCCESS)
130         return(status);
131 
132     /* Create buffer for audio and controls.  */
133     audio = (UX_DEVICE_CLASS_AUDIO *)_ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, memory_size);
134 
135     /* Check for successful allocation.  */
136     if (audio == UX_NULL)
137         return(UX_MEMORY_INSUFFICIENT);
138 
139 #if defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT)
140 
141     /* Create resources for interrupt endpoint support.  */
142 
143     /* Get status data size.  */
144     audio -> ux_device_class_audio_status_size =
145                 audio_parameter -> ux_device_class_audio_parameter_status_size;
146 
147     /* Calculate queue size in bytes.  */
148     if (UX_OVERFLOW_CHECK_MULV_ULONG(
149         audio_parameter -> ux_device_class_audio_parameter_status_queue_size,
150         audio_parameter -> ux_device_class_audio_parameter_status_size))
151     {
152         _ux_utility_memory_free(audio);
153         return(UX_MATH_OVERFLOW);
154     }
155     memory_size = audio_parameter -> ux_device_class_audio_parameter_status_queue_size *
156                 audio_parameter -> ux_device_class_audio_parameter_status_size;
157     audio -> ux_device_class_audio_status_queue_bytes = memory_size;
158 
159 #if !defined(UX_DEVICE_STANDALONE)
160     if (UX_OVERFLOW_CHECK_ADD_ULONG(memory_size, UX_DEVICE_CLASS_AUDIO_INTERRUPT_THREAD_STACK_SIZE))
161     {
162         _ux_utility_memory_free(audio);
163         return(UX_MATH_OVERFLOW);
164     }
165     memory_size += UX_DEVICE_CLASS_AUDIO_INTERRUPT_THREAD_STACK_SIZE;
166 
167     audio_class -> ux_slave_class_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, memory_size);
168     if (audio_class -> ux_slave_class_thread_stack == UX_NULL)
169         status = UX_MEMORY_INSUFFICIENT;
170 
171     if (status == UX_SUCCESS)
172     {
173         status = _ux_device_thread_create(&audio_class -> ux_slave_class_thread,
174                         "ux_device_class_audio_status_thread",
175                         _ux_device_class_audio_interrupt_thread_entry, (ULONG)(ALIGN_TYPE)audio,
176                         audio_class -> ux_slave_class_thread_stack,
177                         UX_DEVICE_CLASS_AUDIO_INTERRUPT_THREAD_STACK_SIZE,
178                         UX_THREAD_PRIORITY_CLASS, UX_THREAD_PRIORITY_CLASS,
179                         UX_NO_TIME_SLICE, UX_DONT_START);
180         if (status == UX_SUCCESS)
181         {
182             UX_THREAD_EXTENSION_PTR_SET(&(audio_class -> ux_slave_class_thread), audio)
183 
184             status = _ux_device_semaphore_create(&audio -> ux_device_class_audio_status_semaphore,
185                                 "ux_device_class_audio_status_semaphore", 0);
186             if (status == UX_SUCCESS)
187             {
188                 status = _ux_device_mutex_create(&audio -> ux_device_class_audio_status_mutex,
189                                 "ux_device_class_audio_status_mutex");
190                 if (status != UX_SUCCESS)
191                     status = UX_MUTEX_ERROR;
192 
193                 if (status != UX_SUCCESS)
194                     _ux_device_semaphore_delete(&audio -> ux_device_class_audio_status_semaphore);
195             }
196             else
197                 status = UX_SEMAPHORE_ERROR;
198 
199             if (status != UX_SUCCESS)
200                 _ux_device_thread_delete(&audio_class -> ux_slave_class_thread);
201         }
202         else
203             status = UX_THREAD_ERROR;
204 
205         if (status != UX_SUCCESS)
206         {
207             _ux_utility_memory_free(audio_class -> ux_slave_class_thread_stack);
208             audio_class -> ux_slave_class_thread_stack = UX_NULL;
209         }
210     }
211 
212     if (status != UX_SUCCESS)
213     {
214         _ux_utility_memory_free(audio);
215         return(status);
216     }
217 
218     /* Status queue locates right after status stack.  */
219     audio -> ux_device_class_audio_status_queue =
220                         (UCHAR *)audio_class -> ux_slave_class_thread_stack +
221                         UX_DEVICE_CLASS_AUDIO_INTERRUPT_THREAD_STACK_SIZE;
222 #else
223     audio -> ux_device_class_audio_status_queue = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, memory_size);
224 
225     /* Check for successful allocation.  */
226     if (audio -> ux_device_class_audio_status_queue == UX_NULL)
227     {
228         _ux_utility_memory_free(audio);
229         return(UX_MEMORY_INSUFFICIENT);
230     }
231 #endif
232 
233 #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
234 
235     /* Allocate memory for interrupt endpoint buffer.  */
236     audio -> ux_device_class_audio_interrupt_buffer = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY,
237                     audio_parameter -> ux_device_class_audio_parameter_status_size);
238     if (audio -> ux_device_class_audio_interrupt_buffer == UX_NULL)
239     {
240         _ux_utility_memory_free(audio -> ux_device_class_audio_status_queue);
241         _ux_utility_memory_free(audio);
242         return(UX_MEMORY_INSUFFICIENT);
243     }
244 #endif
245 
246 #endif
247 
248     /* Save streams.  */
249     if (streams_size)
250     {
251         audio -> ux_device_class_audio_streams = (UX_DEVICE_CLASS_AUDIO_STREAM *)((UCHAR *)audio + sizeof(UX_DEVICE_CLASS_AUDIO));
252         audio -> ux_device_class_audio_streams_nb = audio_parameter -> ux_device_class_audio_parameter_streams_nb;
253     }
254 
255     /* Allocate resources for streams.  */
256     stream = audio -> ux_device_class_audio_streams;
257     stream_parameter = audio_parameter -> ux_device_class_audio_parameter_streams;
258     for (i = 0; i < audio -> ux_device_class_audio_streams_nb; i ++)
259     {
260 
261 #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
262 #if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT)
263 
264         /* Allocate memory for feedback endpoint buffer.  */
265         stream -> ux_device_class_audio_stream_feedback_buffer = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY,
266                         UX_DEVICE_CLASS_AUDIO_FEEDBACK_BUFFER_SIZE);
267         if (stream -> ux_device_class_audio_stream_feedback_buffer == UX_NULL)
268         {
269             status = UX_MEMORY_INSUFFICIENT;
270             break;
271         }
272 #endif
273 #endif
274 
275         /* Create memory block based on max frame buffer size and max number of frames buffered.
276            Each frame require some additional header memory (8 bytes).  */
277         stream -> ux_device_class_audio_stream_frame_buffer_size = stream_parameter -> ux_device_class_audio_stream_parameter_max_frame_buffer_size;
278 
279         if (UX_OVERFLOW_CHECK_ADD_USHORT(stream -> ux_device_class_audio_stream_frame_buffer_size, 8))
280         {
281             status = UX_ERROR;
282             break;
283         }
284         stream -> ux_device_class_audio_stream_frame_buffer_size += 8;
285 
286         if (UX_OVERFLOW_CHECK_MULV_ULONG(stream -> ux_device_class_audio_stream_frame_buffer_size,
287             stream_parameter -> ux_device_class_audio_stream_parameter_max_frame_buffer_nb))
288         {
289             status = UX_ERROR;
290             break;
291         }
292         memory_size = stream -> ux_device_class_audio_stream_frame_buffer_size *
293                             stream_parameter -> ux_device_class_audio_stream_parameter_max_frame_buffer_nb;
294 
295         /* Create block of buffer buffer is cache safe for USB transfer.  */
296 #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
297         stream -> ux_device_class_audio_stream_buffer = (UCHAR *)_ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, memory_size);
298 #else
299         stream -> ux_device_class_audio_stream_buffer = (UCHAR *)_ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, memory_size);
300 #endif
301 
302         /* Check for successful allocation.  */
303         if (stream -> ux_device_class_audio_stream_buffer == UX_NULL)
304         {
305             status = UX_MEMORY_INSUFFICIENT;
306             break;
307         }
308 
309         stream -> ux_device_class_audio_stream_buffer_size = memory_size;
310         stream -> ux_device_class_audio_stream_transfer_pos = (UX_DEVICE_CLASS_AUDIO_FRAME *)stream -> ux_device_class_audio_stream_buffer;
311         stream -> ux_device_class_audio_stream_access_pos = stream -> ux_device_class_audio_stream_transfer_pos;
312 
313 #if !defined(UX_DEVICE_STANDALONE)
314 
315         /* Create memory block for streaming thread stack in addition.  */
316         if (stream_parameter -> ux_device_class_audio_stream_parameter_thread_stack_size == 0)
317             memory_size = UX_DEVICE_CLASS_AUDIO_FEEDBACK_THREAD_STACK_SIZE;
318         else
319             memory_size = stream_parameter -> ux_device_class_audio_stream_parameter_thread_stack_size;
320         stream -> ux_device_class_audio_stream_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, memory_size);
321 
322         /* Check for successful allocation.  */
323         if (stream -> ux_device_class_audio_stream_thread_stack == UX_NULL)
324         {
325             status = UX_MEMORY_INSUFFICIENT;
326             break;
327         }
328 
329         /* Create streaming thread.  */
330         status =  _ux_device_thread_create(&stream -> ux_device_class_audio_stream_thread , "ux_device_class_audio_stream_thread",
331                     stream_parameter -> ux_device_class_audio_stream_parameter_thread_entry,
332                     (ULONG)(ALIGN_TYPE)stream, (VOID *) stream -> ux_device_class_audio_stream_thread_stack,
333                     memory_size, UX_THREAD_PRIORITY_CLASS,
334                     UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
335 
336         /* Check for successful allocation.  */
337         if (status != UX_SUCCESS)
338         {
339             _ux_utility_memory_free(stream -> ux_device_class_audio_stream_thread_stack);
340             stream -> ux_device_class_audio_stream_thread_stack = UX_NULL;
341             break;
342         }
343 
344         UX_THREAD_EXTENSION_PTR_SET(&(stream -> ux_device_class_audio_stream_thread), stream)
345 #else
346 
347         /* Save task function for streaming.  */
348         stream -> ux_device_class_audio_stream_task_function = stream_parameter -> ux_device_class_audio_stream_parameter_task_function;
349 #endif
350 
351 #if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT)
352 
353 #if !defined(UX_DEVICE_STANDALONE)
354 
355         /* Check entry to confirm feedback is supported.  */
356         if (stream_parameter -> ux_device_class_audio_stream_parameter_feedback_thread_entry)
357         {
358             /* Create memory block for streaming thread stack in addition.  */
359             if (stream_parameter -> ux_device_class_audio_stream_parameter_feedback_thread_stack_size == 0)
360                 memory_size = UX_THREAD_STACK_SIZE;
361             else
362                 memory_size = stream_parameter -> ux_device_class_audio_stream_parameter_feedback_thread_stack_size;
363             stream -> ux_device_class_audio_stream_feedback_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, memory_size);
364 
365             /* Check for successful allocation.  */
366             if (stream -> ux_device_class_audio_stream_feedback_thread_stack == UX_NULL)
367             {
368                 status = UX_MEMORY_INSUFFICIENT;
369                 break;
370             }
371 
372             /* Create streaming thread.  */
373             status =  _ux_utility_thread_create(&stream -> ux_device_class_audio_stream_feedback_thread , "ux_device_class_audio_stream_feedback_thread",
374                         stream_parameter -> ux_device_class_audio_stream_parameter_feedback_thread_entry,
375                         (ULONG)(ALIGN_TYPE)stream, (VOID *) stream -> ux_device_class_audio_stream_feedback_thread_stack,
376                         memory_size, UX_THREAD_PRIORITY_CLASS,
377                         UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
378 
379             /* Check for successful allocation.  */
380             if (status != UX_SUCCESS)
381             {
382                 _ux_utility_memory_free(stream -> ux_device_class_audio_stream_feedback_thread_stack);
383                 stream -> ux_device_class_audio_stream_feedback_thread_stack = UX_NULL;
384                 break;
385             }
386 
387             UX_THREAD_EXTENSION_PTR_SET(&(stream -> ux_device_class_audio_stream_feedback_thread), stream)
388         }
389 #else
390         if (stream_parameter -> ux_device_class_audio_stream_parameter_feedback_task_function)
391         {
392 
393             /* Save task function for streaming.  */
394             stream -> ux_device_class_audio_stream_feedback_task_function = stream_parameter -> ux_device_class_audio_stream_parameter_feedback_task_function;
395         }
396 #endif
397 #endif
398 
399         /* Save callbacks.  */
400         _ux_utility_memory_copy(&stream -> ux_device_class_audio_stream_callbacks,
401                                 &stream_parameter -> ux_device_class_audio_stream_parameter_callbacks,
402                                 sizeof(UX_DEVICE_CLASS_AUDIO_STREAM_CALLBACKS)); /* Use case of memcpy is verified. */
403 
404         /* Save audio instance.  */
405         stream -> ux_device_class_audio_stream_audio = audio;
406 
407         stream ++;
408         stream_parameter ++;
409     }
410 
411     /* Check for successful creation.  */
412     if (status == UX_SUCCESS)
413     {
414 
415         /* Save the address of the Audio instance inside the Audio container.  */
416         audio_class -> ux_slave_class_instance = (VOID *) audio;
417 
418         /* Link to class instance.  */
419         audio -> ux_device_class_audio_class = audio_class;
420 
421         /* Save callbacks.  */
422         _ux_utility_memory_copy(&audio -> ux_device_class_audio_callbacks,
423             &audio_parameter -> ux_device_class_audio_parameter_callbacks,
424             sizeof(UX_DEVICE_CLASS_AUDIO_CALLBACKS)); /* Use case of memcpy is verified. */
425 
426 #if defined(UX_DEVICE_STANDALONE)
427 
428         /* Link task function.  */
429         audio_class -> ux_slave_class_task_function = _ux_device_class_audio_tasks_run;
430 #endif
431 
432         /* Return completion status.  */
433         return(UX_SUCCESS);
434     }
435 
436     /* Error trap!  */
437     _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status);
438 
439     /* Free allocated resources.  */
440     stream = audio -> ux_device_class_audio_streams;
441     for (i = 0; i < audio -> ux_device_class_audio_streams_nb; i ++)
442     {
443 #if defined(UX_DEVICE_CLASS_AUDIO_FEEDBACK_SUPPORT)
444 #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
445         if (stream -> ux_device_class_audio_stream_feedback_buffer)
446             _ux_utility_memory_free(stream -> ux_device_class_audio_stream_feedback_buffer);
447 #endif
448 #if !defined(UX_DEVICE_STANDALONE)
449         if (stream -> ux_device_class_audio_stream_feedback_thread_stack)
450         {
451             _ux_device_thread_delete(&stream -> ux_device_class_audio_stream_feedback_thread);
452             _ux_utility_memory_free(stream -> ux_device_class_audio_stream_feedback_thread_stack);
453         }
454 #endif
455 #endif
456 #if !defined(UX_DEVICE_STANDALONE)
457         if (stream -> ux_device_class_audio_stream_thread_stack)
458         {
459             _ux_device_thread_delete(&stream -> ux_device_class_audio_stream_thread);
460             _ux_utility_memory_free(stream -> ux_device_class_audio_stream_thread_stack);
461         }
462 #endif
463         if (stream -> ux_device_class_audio_stream_buffer)
464             _ux_utility_memory_free(stream -> ux_device_class_audio_stream_buffer);
465         stream ++;
466     }
467 #if defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT)
468 #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
469     if (audio -> ux_device_class_audio_interrupt_buffer)
470         _ux_utility_memory_free(audio -> ux_device_class_audio_interrupt_buffer);
471 #endif
472 #if !defined(UX_DEVICE_STANDALONE)
473     if (audio_class -> ux_slave_class_thread_stack)
474     {
475         _ux_device_thread_delete(&audio_class -> ux_slave_class_thread);
476         _ux_utility_memory_free(audio_class -> ux_slave_class_thread_stack);
477 
478         _ux_device_semaphore_delete(&audio -> ux_device_class_audio_status_semaphore);
479         _ux_device_mutex_delete(&audio -> ux_device_class_audio_status_mutex);
480     }
481 #else
482     if (audio -> ux_device_class_audio_status_queue)
483     {
484         _ux_utility_memory_free(audio -> ux_device_class_audio_status_queue);
485     }
486 #endif
487 #endif
488     _ux_utility_memory_free(audio);
489 
490     return(status);
491 }
492 
493 /**************************************************************************/
494 /*                                                                        */
495 /*  FUNCTION                                               RELEASE        */
496 /*                                                                        */
497 /*    _uxe_device_class_audio_initialize                  PORTABLE C      */
498 /*                                                           6.3.0        */
499 /*  AUTHOR                                                                */
500 /*                                                                        */
501 /*    Chaoqiong Xiao, Microsoft Corporation                               */
502 /*                                                                        */
503 /*  DESCRIPTION                                                           */
504 /*                                                                        */
505 /*    This function checks errors in audio initialization function call.  */
506 /*                                                                        */
507 /*  INPUT                                                                 */
508 /*                                                                        */
509 /*    command                               Pointer to audio command      */
510 /*                                                                        */
511 /*  OUTPUT                                                                */
512 /*                                                                        */
513 /*    Completion Status                                                   */
514 /*                                                                        */
515 /*  CALLS                                                                 */
516 /*                                                                        */
517 /*    _ux_device_class_audio_initialize     Initialize audio instance     */
518 /*                                                                        */
519 /*  CALLED BY                                                             */
520 /*                                                                        */
521 /*    Device Audio Class                                                  */
522 /*                                                                        */
523 /*  RELEASE HISTORY                                                       */
524 /*                                                                        */
525 /*    DATE              NAME                      DESCRIPTION             */
526 /*                                                                        */
527 /*  03-08-2023     Chaoqiong Xiao           Initial Version 6.2.1         */
528 /*  10-31-2023     Yajun Xia                Modified comment(s),          */
529 /*                                            fixed error checking issue, */
530 /*                                            resulting in version 6.3.0  */
531 /*                                                                        */
532 /**************************************************************************/
_uxe_device_class_audio_initialize(UX_SLAVE_CLASS_COMMAND * command)533 UINT  _uxe_device_class_audio_initialize(UX_SLAVE_CLASS_COMMAND *command)
534 {
535 
536 UX_DEVICE_CLASS_AUDIO_PARAMETER         *audio_parameter;
537 ULONG                                   i;
538 
539     /* Get the pointer to the application parameters for the audio class.  */
540     audio_parameter = (UX_DEVICE_CLASS_AUDIO_PARAMETER *)command -> ux_slave_class_command_parameter;
541 
542     /* Sanity checks.  */
543     if (audio_parameter == UX_NULL)
544         return(UX_INVALID_PARAMETER);
545 
546     /* There must be at least one stream.  */
547     if (audio_parameter -> ux_device_class_audio_parameter_streams == UX_NULL ||
548         audio_parameter -> ux_device_class_audio_parameter_streams_nb < 1)
549         return(UX_INVALID_PARAMETER);
550 
551     for (i = 0; i < audio_parameter -> ux_device_class_audio_parameter_streams_nb; i ++)
552     {
553         if ((audio_parameter -> ux_device_class_audio_parameter_streams[i].ux_device_class_audio_stream_parameter_max_frame_buffer_size == 0) ||
554             (audio_parameter -> ux_device_class_audio_parameter_streams[i].ux_device_class_audio_stream_parameter_max_frame_buffer_nb == 0))
555             return(UX_INVALID_PARAMETER);
556     }
557 
558 #if defined(UX_DEVICE_CLASS_AUDIO_INTERRUPT_SUPPORT)
559 
560     /* There must be status setting for event queue.  */
561     if (audio_parameter -> ux_device_class_audio_parameter_status_queue_size == 0 ||
562         audio_parameter -> ux_device_class_audio_parameter_status_size == 0)
563         return(UX_INVALID_PARAMETER);
564 #endif
565 
566     /* Do initialize.  */
567     return(_ux_device_class_audio_initialize(command));
568 }
569