NUC472_NUC442_BSP V3.03.004
The Board Support Package for NUC472/NUC442
uac_driver.c
Go to the documentation of this file.
1/**************************************************************************/
13#include <stdio.h>
14#include <string.h>
15
16#include "NUC472_442.h"
17#include "usbh_core.h"
18
19#include "usbh_uac.h"
20#include "uac.h"
21
22
36
37static UAC_DEV_T g_au_dev[CONFIG_AU_MAX_DEV];
38static UAC_INFO_T g_uac_info[CONFIG_AU_MAX_DEV];
39
40static UAC_DEV_T *g_audev_list = NULL;
41
42int au_parsing_descriptors(UAC_DEV_T *audev);
43
44static UAC_DEV_T *alloc_as_device(void)
45{
46 int i;
47
48 for (i = 0; i < CONFIG_AU_MAX_DEV; i++)
49 {
50 if (g_au_dev[i].udev == NULL)
51 {
52 memset((char *)&g_au_dev[i], 0, sizeof(UAC_DEV_T));
53 g_au_dev[i].ctrl_ifnum = -1;
54 g_au_dev[i].au_in_ifnum = -1;
55 g_au_dev[i].au_out_ifnum = -1;
56 memset((char *)&g_uac_info[i], 0, sizeof(UAC_INFO_T));
57 g_au_dev[i].priv = (void *)&g_uac_info[i];
58 return &g_au_dev[i];
59 }
60 }
61 return NULL;
62}
63
64static void free_au_device(UAC_DEV_T *audev)
65{
66 audev->udev = NULL;
67}
68
69UAC_DEV_T *find_as_deivce_by_udev(USB_DEV_T *udev)
70{
71 int i;
72
73 if (udev == NULL)
74 return NULL;
75
76 for (i = 0; i < CONFIG_AU_MAX_DEV; i++)
77 {
78 if (g_au_dev[i].udev == udev)
79 {
80 return &g_au_dev[i];
81 }
82 }
83 return NULL;
84}
85
86int find_as_device(UAC_DEV_T *hdev)
87{
88 int i;
89
90 for (i = 0; i < CONFIG_AU_MAX_DEV; i++)
91 {
92 if (&g_au_dev[i] == hdev)
93 {
94 return TRUE;
95 }
96 }
97 return FALSE;
98}
99
100
101static int au_probe(USB_DEV_T *dev, USB_IF_DESC_T *ifd, const USB_DEV_ID_T *id)
102{
103 EP_INFO_T *ep_info;
104 int ifnum;
105 UAC_DEV_T *audev, *p;
106 int i;
107
108 if ((ifd->bInterfaceSubClass != SUBCLS_AUDIOCONTROL) &&
109 (ifd->bInterfaceSubClass != SUBCLS_AUDIOSTREAMING))
110 {
111 printf("Does not support audio sub-class %x\n", ifd->bInterfaceSubClass);
113 }
114
115
116 ifnum = ifd->bInterfaceNumber;
117
118 audev = find_as_deivce_by_udev(dev);
119 if (audev == NULL)
120 {
121 audev = alloc_as_device();
122 if (audev == NULL)
123 return USB_ERR_NODEV;
124 }
125
126 audev->udev = dev;
127 audev->next = NULL;
128
129 USBAS_DBGMSG("au_probe called for ifnum %d\n", ifnum);
130
131 if (ifd->bInterfaceSubClass == SUBCLS_AUDIOSTREAMING)
132 {
133 ep_info = NULL;
134 for (i = 0; i < dev->ep_list_cnt; i++)
135 {
136 if ((dev->ep_list[i].ifnum == ifnum) &&
137 ((dev->ep_list[i].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC))
138 {
139 ep_info = &dev->ep_list[i];
140 USBAS_DBGMSG("Isochronous Endpoint 0x%x found.\n", ep_info->bEndpointAddress);
141 }
142 }
143 if (ep_info == NULL)
144 {
145 USBAS_DBGMSG("couldn't find isochronous endpoints\n");
146 return USB_ERR_NODEV;
147 }
148
149 if ((ep_info->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
150 {
151 audev->ep_au_in = ep_info;
152 audev->au_in_ifnum = ifnum;
153 USBAS_DBGMSG("Audio in stream interface is %d\n", ifnum);
154 }
155 else
156 {
157 audev->ep_au_out = ep_info;
158 audev->au_out_ifnum = ifnum;
159 USBAS_DBGMSG("Audio out stream interface is %d\n", ifnum);
160 }
161 }
162 else
163 {
164 audev->ctrl_ifnum = ifnum;
165 USBAS_DBGMSG("Audio control interface is %d\n", ifnum);
166 }
167
168 /*
169 * Chaining newly found Audio Class device to end of Audio Class device list.
170 */
171 if (g_audev_list == NULL)
172 g_audev_list = audev;
173 else
174 {
175 for (p = g_audev_list; p->next != NULL; p = p->next)
176 ;
177 p->next = audev;
178 }
179
180 return uac_config_parser(audev);
181}
182
183
184static void au_disconnect(USB_DEV_T *dev)
185{
186 UAC_DEV_T *audev, *p;
187 int i;
188
189 USBAS_DBGMSG("Audio Class device disconnected!\n");
190
191 audev = find_as_deivce_by_udev(dev);
192 if (audev == NULL)
193 return;
194
195 for (i = 0; i < ISO_IN_URB_CNT; i++)
196 {
197 if (audev->urbin[i])
198 {
199 USBH_UnlinkUrb(audev->urbin[i]);
200 USBH_FreeUrb(audev->urbin[i]);
201 }
202 }
203
204 for (i = 0; i < ISO_OUT_URB_CNT; i++)
205 {
206 if (audev->urbout[i])
207 {
208 USBH_UnlinkUrb(audev->urbout[i]);
209 USBH_FreeUrb(audev->urbout[i]);
210 }
211 }
212
213 /*
214 * Remove this Audio Class device from device list.
215 */
216 if (audev == g_audev_list)
217 g_audev_list = g_audev_list->next;
218 else
219 {
220 for (p = g_audev_list; p != NULL; p = p->next)
221 {
222 if (p->next == audev)
223 {
224 p->next = audev->next;
225 break;
226 }
227 }
228 }
229 free_au_device(audev);
230}
231
232
233static USB_DEV_ID_T au_id_table[] =
234{
235 USB_DEVICE_ID_MATCH_INT_CLASS, /* match_flags */
236 0, 0, 0, 0, 0, 0, 0,
237 UAC_IFACE_CODE, /* Audio Interface Class Code */
238 0, /* Audio Interface Subclass Codes, support streaming only */
239 0, 0
240};
241
242
243static USB_DRIVER_T au_driver =
244{
245 "audio class driver",
246 au_probe,
247 au_disconnect,
248 au_id_table,
249 NULL, /* suspend */
250 NULL, /* resume */
251 {NULL,NULL} /* driver_list */
252};
253
254
256
261void UAC_Init(void)
262{
263 memset((char *)&g_au_dev[0], 0, sizeof(g_au_dev));
264 g_audev_list = NULL;
265 USBH_RegisterDriver(&au_driver);
266}
267
268
278{
279 return g_audev_list;
280}
281
282 /* end of group NUC472_442_USBH_AS_EXPORTED_FUNCTIONS */
284 /* end of group NUC472_442_USBH_AS_Driver */
286 /* end of group NUC472_442_Device_Driver */
288
289/*** (C) COPYRIGHT 2014 Nuvoton Technology Corp. ***/
290
NUC472/NUC442 peripheral access layer header file. This file contains all the peripheral register's d...
#define CONFIG_AU_MAX_DEV
Definition: usbh_uac.h:19
#define ISO_OUT_URB_CNT
Definition: usbh_uac.h:23
#define UAC_RET_DRV_NOT_SUPPORTED
Definition: usbh_uac.h:40
#define ISO_IN_URB_CNT
Definition: usbh_uac.h:22
int ctrl_ifnum
Definition: usbh_uac.h:102
EP_INFO_T * ep_au_out
Definition: usbh_uac.h:112
EP_INFO_T * ep_au_in
Definition: usbh_uac.h:111
void * priv
Definition: usbh_uac.h:105
int au_out_ifnum
Definition: usbh_uac.h:104
USB_DEV_T * udev
Definition: usbh_uac.h:101
struct uac_dev_t * next
Definition: usbh_uac.h:106
void UAC_Init(void)
Initialize this USB Audio Class driver.
Definition: uac_driver.c:261
URB_T * urbout[ISO_OUT_URB_CNT]
Definition: usbh_uac.h:114
int au_in_ifnum
Definition: usbh_uac.h:103
UAC_DEV_T * UAC_GetDeviceList(void)
Get a list of currently connected USB Audio Class devices.
Definition: uac_driver.c:277
URB_T * urbin[ISO_IN_URB_CNT]
Definition: usbh_uac.h:113
#define USB_ERR_NODEV
Definition: usbh_err_code.h:23
int32_t USBH_RegisterDriver(USB_DRIVER_T *new_driver)
Register a device driver to USB Host Core driver.
Definition: usbh_core.c:78
int32_t USBH_UnlinkUrb(URB_T *urb)
Cancel an URB which has been submit to USB core.
Definition: usbh_core.c:236
void USBH_FreeUrb(URB_T *)
Free the URB allocated from USBH_AllocUrb()
Definition: usbh_support.c:113
USB_IF_DESC_T
Definition: usbh_core.h:335
HIDDEN_SYMBOLS struct usb_device USB_DEV_T
#define NULL
NULL pointer.
Definition: NUC472_442.h:29018
#define TRUE
Boolean true, define to use in API parameters or return value.
Definition: NUC472_442.h:29021
#define FALSE
Boolean false, define to use in API parameters or return value.
Definition: NUC472_442.h:29022
USB Host core driver header file.