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_frame_write                  PORTABLE C      */
36 /*                                                           6.2.1        */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Chaoqiong Xiao, Microsoft Corporation                               */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function writes frame to the Audio class.                      */
44 /*                                                                        */
45 /*  INPUT                                                                 */
46 /*                                                                        */
47 /*    stream                                Address of audio stream       */
48 /*                                            instance                    */
49 /*    frame                                 Pointer to buffer to save     */
50 /*                                            frame data                  */
51 /*    length                                Frame length in bytes         */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    None                                                                */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _ux_utility_memory_copy               Copy data                     */
60 /*                                                                        */
61 /*  CALLED BY                                                             */
62 /*                                                                        */
63 /*    Application                                                         */
64 /*                                                                        */
65 /*  RELEASE HISTORY                                                       */
66 /*                                                                        */
67 /*    DATE              NAME                      DESCRIPTION             */
68 /*                                                                        */
69 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
70 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
71 /*                                            verified memset and memcpy  */
72 /*                                            cases,                      */
73 /*                                            resulting in version 6.1    */
74 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
75 /*                                            fixed frame length check,   */
76 /*                                            resulting in version 6.1.10 */
77 /*  03-08-2023     Chaoqiong Xiao           Modified comment(s),          */
78 /*                                            resulting in version 6.2.1  */
79 /*                                                                        */
80 /**************************************************************************/
_ux_device_class_audio_frame_write(UX_DEVICE_CLASS_AUDIO_STREAM * stream,UCHAR * frame,ULONG length)81 UINT _ux_device_class_audio_frame_write(UX_DEVICE_CLASS_AUDIO_STREAM *stream, UCHAR *frame, ULONG length)
82 {
83 
84 UX_SLAVE_ENDPOINT           *endpoint;
85 UX_SLAVE_DEVICE             *device;
86 UCHAR                       *next_frame_buffer;
87 ULONG                       frame_buffer_size;
88 
89 
90     /* Get the pointer to the device.  */
91     device =  &_ux_system_slave -> ux_system_slave_device;
92 
93     /* As long as the device is in the CONFIGURED state.  */
94     if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
95     {
96 
97         /* Cannot proceed with command, the interface is down.  */
98         return(UX_CONFIGURATION_HANDLE_UNKNOWN);
99     }
100 
101     /* Check if endpoint is available.  */
102     endpoint = stream -> ux_device_class_audio_stream_endpoint;
103     if (endpoint == UX_NULL)
104         return(UX_ERROR);
105 
106     /* Check if endpoint direction is OK (IN).  */
107     if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT)
108         return(UX_ERROR);
109 
110     /* Check frame length.  */
111     frame_buffer_size = stream -> ux_device_class_audio_stream_frame_buffer_size;
112     if ((frame_buffer_size - 8) < length)
113         return(UX_ERROR);
114 
115     /* Check overflow!!  */
116     if (stream -> ux_device_class_audio_stream_access_pos == stream -> ux_device_class_audio_stream_transfer_pos &&
117         stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length != 0)
118         return(UX_BUFFER_OVERFLOW);
119 
120     /* Calculate next frame buffer.  */
121     next_frame_buffer = (UCHAR *)stream -> ux_device_class_audio_stream_access_pos;
122     next_frame_buffer += frame_buffer_size;
123     if (next_frame_buffer >= stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size)
124         next_frame_buffer = stream -> ux_device_class_audio_stream_buffer;
125 
126     /* Copy frame.  */
127     _ux_utility_memory_copy(stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_data, frame, length); /* Use case of memcpy is verified. */
128     stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length = length;
129 
130     /* Move frame position.  */
131     stream -> ux_device_class_audio_stream_access_pos = (UX_DEVICE_CLASS_AUDIO_FRAME *)next_frame_buffer;
132 
133     return(UX_SUCCESS);
134 }
135 
136 /**************************************************************************/
137 /*                                                                        */
138 /*  FUNCTION                                               RELEASE        */
139 /*                                                                        */
140 /*    _uxe_device_class_audio_frame_write                 PORTABLE C      */
141 /*                                                           6.2.1        */
142 /*  AUTHOR                                                                */
143 /*                                                                        */
144 /*    Chaoqiong Xiao, Microsoft Corporation                               */
145 /*                                                                        */
146 /*  DESCRIPTION                                                           */
147 /*                                                                        */
148 /*    This function checks errors in writing frame function call.         */
149 /*                                                                        */
150 /*  INPUT                                                                 */
151 /*                                                                        */
152 /*    stream                                Address of audio stream       */
153 /*                                            instance                    */
154 /*    frame                                 Pointer to buffer to save     */
155 /*                                            frame data                  */
156 /*    length                                Frame length in bytes         */
157 /*                                                                        */
158 /*  OUTPUT                                                                */
159 /*                                                                        */
160 /*    None                                                                */
161 /*                                                                        */
162 /*  CALLS                                                                 */
163 /*                                                                        */
164 /*    _ux_device_class_audio_frame_write    Write frame to buffer to send */
165 /*                                                                        */
166 /*  CALLED BY                                                             */
167 /*                                                                        */
168 /*    Application                                                         */
169 /*                                                                        */
170 /*  RELEASE HISTORY                                                       */
171 /*                                                                        */
172 /*    DATE              NAME                      DESCRIPTION             */
173 /*                                                                        */
174 /*  03-08-2023     Chaoqiong Xiao           Initial Version 6.2.1         */
175 /*                                                                        */
176 /**************************************************************************/
_uxe_device_class_audio_frame_write(UX_DEVICE_CLASS_AUDIO_STREAM * stream,UCHAR * frame,ULONG length)177 UINT _uxe_device_class_audio_frame_write(UX_DEVICE_CLASS_AUDIO_STREAM *stream, UCHAR *frame, ULONG length)
178 {
179 
180     /* Sanity checks.  */
181     if (stream == UX_NULL || frame == UX_NULL || length == 0)
182         return(UX_INVALID_PARAMETER);
183 
184     /* Write to frame.  */
185     return(_ux_device_class_audio_frame_write(stream, frame, length));
186 }
187