M471M/R1/S BSP V3.01.000
The Board Support Package for M4521
uac_driver.c
Go to the documentation of this file.
1/**************************************************************************/
9#include <stdio.h>
10#include <string.h>
11
12#include "NuMicro.h"
13
14#include "usb.h"
15#include "usbh_lib.h"
16#include "usbh_uac.h"
17#include "uac.h"
18
19
33
34static UAC_DEV_T g_uac_dev[CONFIG_UAC_MAX_DEV];
35
36static UAC_DEV_T *g_uac_list = NULL;
37
38
39static UAC_DEV_T *alloc_uac_device(void)
40{
41 int i;
42
43 for(i = 0; i < CONFIG_UAC_MAX_DEV; i++)
44 {
45 if(g_uac_dev[i].udev == NULL)
46 {
47 memset((char *)&g_uac_dev[i], 0, sizeof(UAC_DEV_T));
48 return &g_uac_dev[i];
49 }
50 }
51 return NULL;
52}
53
54static void free_uac_device(UAC_DEV_T *uac)
55{
56 uac->udev = NULL;
57}
58
59UAC_DEV_T *find_uac_device(UDEV_T *udev)
60{
61 int i;
62
63 if(udev == NULL)
64 return NULL;
65
66 for(i = 0; i < CONFIG_UAC_MAX_DEV; i++)
67 {
68 if(g_uac_dev[i].udev == udev)
69 {
70 return &g_uac_dev[i];
71 }
72 }
73 return NULL;
74}
75
76
77static int uac_probe(IFACE_T *iface)
78{
79 UDEV_T *udev = iface->udev;
80 ALT_IFACE_T *aif = iface->aif;
81 DESC_IF_T *ifd;
82 UAC_DEV_T *uac, *p;
83 uint8_t bAlternateSetting;
84 int ret;
85
86 ifd = aif->ifd;
87
88 /* Is this interface Audio class? */
89 if(ifd->bInterfaceClass != USB_CLASS_AUDIO)
91
92 if((ifd->bInterfaceSubClass != SUBCLS_AUDIOCONTROL) &&
93 (ifd->bInterfaceSubClass != SUBCLS_AUDIOSTREAMING))
94 {
95 UAC_ERRMSG("Audio class interface, but sub-class %x not supported!\n", ifd->bInterfaceSubClass);
97 }
98
99 UAC_DBGMSG("\nuac_probe - device (vid=0x%x, pid=0x%x), interface %d, type: %s\n",
100 udev->descriptor.idVendor, udev->descriptor.idProduct, iface->if_num, (ifd->bInterfaceSubClass == SUBCLS_AUDIOCONTROL) ? "CONTROL" : "STREAM");
101
102 uac = find_uac_device(udev);
103 if(uac == NULL)
104 {
105 /* UAC device should has not been created in the previous probe of the other interface */
106 /* return 0 to make USB core adding this interface to device working interface list. */
107 uac = alloc_uac_device();
108 if(uac == NULL)
110
111 uac->udev = udev;
112 uac->state = UAC_STATE_CONNECTING;
113
114 /* Add newly found Audio Class device to end of Audio Class device list.
115 */
116 if(g_uac_list == NULL)
117 {
118 g_uac_list = uac;
119 }
120 else
121 {
122 for(p = g_uac_list; p->next != NULL; p = p->next)
123 ;
124 p->next = uac;
125 }
126 }
127
128 iface->context = (void *)uac;
129
130 if(ifd->bInterfaceSubClass == SUBCLS_AUDIOSTREAMING)
131 {
132 if((usbh_uac_find_max_alt(iface, EP_ADDR_DIR_IN, EP_ATTR_TT_ISO, &bAlternateSetting) == 0) ||
133 (usbh_uac_find_max_alt(iface, EP_ADDR_DIR_OUT, EP_ATTR_TT_ISO, &bAlternateSetting) == 0))
134 {
135 ret = usbh_set_interface(iface, bAlternateSetting);
136 if(ret < 0)
137 {
138 UAC_ERRMSG("Failed to set interface %d, %d! (%d)\n", iface->if_num, bAlternateSetting, ret);
139 return UAC_RET_IO_ERR;
140 }
141 }
142 else
143 {
144 UAC_ERRMSG("Cannot find audio stream endpoints!\n");
146 }
147
148 ret = uac_parse_streaming_interface(uac, iface, bAlternateSetting);
149 if(ret < 0)
150 return ret;
151 }
152 else if(ifd->bInterfaceSubClass == SUBCLS_AUDIOCONTROL)
153 {
154 ret = uac_parse_control_interface(uac, iface);
155 if(ret < 0)
156 return ret;
157 }
158
159 UAC_DBGMSG("UAC device 0x%x ==>\n", (int)uac);
160 UAC_DBGMSG(" CONTROL IFACE: 0x%x\n", (int)uac->acif.iface);
161 UAC_DBGMSG(" STREAM IN IFACE: 0x%x\n", (int)uac->asif_in.iface);
162 UAC_DBGMSG(" STREAM OUT IFACE: 0x%x\n", (int)uac->asif_out.iface);
163
164 return ret;
165}
166
167static void uac_disconnect(IFACE_T *iface)
168{
169 UAC_DEV_T *uac, *p;
170 //ALT_IFACE_T *aif = iface->aif;
171 int i;
172
173 uac = (UAC_DEV_T *)iface->context;
174
175 uac->state = UAC_STATE_DISCONNECTING;
176
177 UAC_DBGMSG("uac_disconnect - device (vid=0x%x, pid=0x%x), interface %d removed.\n",
178 uac->udev->descriptor.idVendor, uac->udev->descriptor.idProduct, iface->if_num);
179
180 /*
181 * remove it from UAC device list
182 */
183 for(i = 0; i < CONFIG_UAC_MAX_DEV; i++)
184 {
185 if(g_uac_dev[i].udev == iface->udev)
186 {
187 uac = &g_uac_dev[i];
188
189 if(uac->acif.iface == iface)
190 {
191 uac->acif.iface = NULL;
192 }
193 else if(uac->asif_in.iface == iface)
194 {
196 uac->asif_in.iface = NULL;
197 }
198 else if(uac->asif_out.iface == iface)
199 {
201 uac->asif_out.iface = NULL;
202 }
203
204 if((uac->acif.iface != NULL) || (uac->asif_in.iface != NULL) || (uac->asif_out.iface != NULL))
205 continue;
206
207 /*
208 * All interface of UAC device are all disconnected. Remove it from UAC device list.
209 */
210
211 if(uac == g_uac_list)
212 {
213 g_uac_list = g_uac_list->next;
214 }
215 else
216 {
217 for(p = g_uac_list; p != NULL; p = p->next)
218 {
219 if(p->next == uac)
220 {
221 p->next = uac->next;
222 break;
223 }
224 }
225 }
226 UAC_DBGMSG("uac_disconnect - device (vid=0x%x, pid=0x%x), UAC device removed.\n",
227 uac->udev->descriptor.idVendor, uac->udev->descriptor.idProduct);
228 free_uac_device(uac);
229 }
230 }
231}
232
233UDEV_DRV_T uac_driver =
234{
235 uac_probe,
236 uac_disconnect,
237 NULL, /* suspend */
238 NULL, /* resume */
239};
240
241
243
249{
250 memset((char *)&g_uac_dev[0], 0, sizeof(g_uac_dev));
251 g_uac_list = NULL;
252 usbh_register_driver(&uac_driver);
253}
254
255
265{
266 return g_uac_list;
267}
268
269 /* end of group USBH_EXPORTED_FUNCTIONS */
271 /* end of group USBH_Library */
273 /* end of group LIBRARY */
275
276/*** (C) COPYRIGHT 2020 Nuvoton Technology Corp. ***/
277
NuMicro peripheral access layer header file.
#define NULL
Definition: M471M_R1_S.h:13908
#define USBH_ERR_NOT_MATCHED
Definition: usbh_lib.h:35
#define CONFIG_UAC_MAX_DEV
Definition: usbh_uac.h:30
#define UAC_RET_DEV_NOT_FOUND
Definition: usbh_lib.h:96
#define UAC_RET_OUT_OF_MEMORY
Definition: usbh_lib.h:101
#define UAC_RET_IO_ERR
Definition: usbh_lib.h:98
int usbh_uac_stop_audio_out(struct uac_dev_t *audev)
Stop UAC device audio out data stream.
Definition: uac_core.c:944
int usbh_uac_stop_audio_in(struct uac_dev_t *audev)
Stop UAC device audio in data stream.
Definition: uac_core.c:701
struct uac_dev_t * usbh_uac_get_device_list(void)
Get a list of currently connected USB Audio Class devices.
Definition: uac_driver.c:264
HIDDEN_SYMBOLS void usbh_uac_init(void)
Initialize USB Audio Class driver.
Definition: uac_driver.c:248
UAC_STATE_E state
Definition: usbh_uac.h:114
IFACE_T * iface
Definition: usbh_uac.h:80
struct uac_dev_t * next
Definition: usbh_uac.h:115
AC_IF_T acif
Definition: usbh_uac.h:108
IFACE_T * iface
Definition: usbh_uac.h:91
AS_IF_T asif_in
Definition: usbh_uac.h:109
UDEV_T * udev
Definition: usbh_uac.h:107
AS_IF_T asif_out
Definition: usbh_uac.h:110
USB Host Audio Class header file.
USB Host library header file.
USB Host library exported header file.
USB Host UAC class driver header file.