| M480 BSP V3.05.001 The Board Support Package for M480 Series

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