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