1 /* ----------------------------------------------------------------------------
2 * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
3 * Description: LiteOS USB Driver UAC Protocol
4 * Author: huangjieliang
5 * Create: 2017-12-12
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
14 * to endorse or promote products derived from this software without specific prior written
15 * permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * --------------------------------------------------------------------------- */
28 /* ----------------------------------------------------------------------------
29 * Notice of Export Control Law
30 * ===============================================
31 * Huawei LiteOS may be subject to applicable export control laws and regulations, which might
32 * include those applicable to Huawei LiteOS of U.S. and the country in which you are located.
33 * Import, export and usage of Huawei LiteOS in any manner by you shall be in compliance with such
34 * applicable export control laws and regulations.
35 * --------------------------------------------------------------------------- */
36
37 #include "gadget/f_uac.h"
38 #include "gadget/usbd_audio.h"
39 #include "controller/usb_device/dwc_otg_pcd.h"
40 #include "implementation/global_implementation.h"
41
42 #ifdef __cplusplus
43 #if __cplusplus
44 extern "C" {
45 #endif /* __cplusplus */
46 #endif /* __cplusplus */
47
48 int usbdev_uac_initialize(struct module *mod, int n, void *arg);
49
50 /* device driver structure definition */
51
52 static const driver_t g_fuac_driver =
53 {
54 .name = "fuac",
55 .methods = NULL,
56 .size = sizeof(struct uac_softc)
57 };
58
59 /* private device class information */
60
61 static devclass_t g_fuac_devclass;
62 DRIVER_MODULE(fuac, simple, g_fuac_driver, g_fuac_devclass, usbdev_uac_initialize, 0);
63
64 static int usbclass_uac_bind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev);
65 static int usbclass_uac_unbind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev);
66 static int usbclass_uac_setup(struct usbdevclass_driver_s *driver, struct usbdev_s *dev,
67 const struct usb_device_request *ctrl, uint8_t *dataout, size_t outlen);
68 static void usbclass_uac_disconnect(struct usbdevclass_driver_s *driver, struct usbdev_s *dev);
69
70 /* USB driver operations */
71
72 static const struct usbdevclass_driverops_s g_uac_driverops =
73 {
74 usbclass_uac_bind,
75 usbclass_uac_unbind,
76 usbclass_uac_setup,
77 usbclass_uac_disconnect,
78 NULL,
79 NULL
80 };
81
82 static const char g_fuac_str_lang[] =
83 {
84 4, UDESC_STRING,
85 0x09, 0x04
86 };
87
88 #define STR_AC_IF 4
89 static const char g_fuac_str_ac_if[] =
90 {
91 38, UDESC_STRING,
92 'H', 0, 'i', 0, 's', 0, 'i', 0, 'l', 0, 'i', 0, 'c', 0, 'o', 0, 'n', 0,
93 ' ', 0, 'H', 0, 'D', 0, ' ', 0, 'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0
94 };
95
96 static const char g_fuac_str_manufacturer[] =
97 {
98 14, UDESC_STRING,
99 'H', 0, 'U', 0, 'A', 0, 'W', 0, 'E', 0, 'I', 0
100 };
101
102 #define UAC_STR_IDX_PRODUCT 2
103 static const char g_fuac_str_product[] =
104 {
105 48, UDESC_STRING,
106 'L', 0, 'i', 0, 't', 0, 'e', 0, 'O', 0, 'S', 0, ' ', 0, 'U', 0, 'S', 0,
107 'B', 0, ' ', 0, 'A', 0, 'u', 0, 'd', 0, 'i', 0, 'o', 0, ' ', 0, 'G', 0,
108 'a', 0, 'd', 0, 'g', 0, 'e', 0, 't', 0
109 };
110
111 #define UAC_IN_TERMINAL 8
112 static const char g_fuac_input_terminal[] =
113 {
114 46, UDESC_STRING,
115 'C', 0, 'a', 0, 'p', 0, 't', 0, 'u', 0, 'r', 0, 'e', 0, ' ', 0, 'I', 0,
116 'n', 0, 'p', 0, 'u', 0, 't', 0, ' ', 0, 't', 0, 'e', 0, 'r', 0, 'm', 0,
117 'i', 0, 'n', 0, 'a', 0, 'l', 0
118 };
119
120 static const char g_fuac_output_terminal[] =
121 {
122 48, UDESC_STRING,
123 'C', 0, 'a', 0, 'p', 0, 't', 0, 'u', 0, 'r', 0, 'e', 0, ' ', 0, 'O', 0,
124 'u', 0, 't', 0, 'p', 0, 'u', 0, 't', 0, ' ', 0, 't', 0, 'e', 0, 'r', 0,
125 'm', 0, 'i', 0, 'n', 0, 'a', 0, 'l', 0
126 };
127
128 #define ISO_DATA_SIZE 200
129 size_t g_uac_iso_data_size = 16;
130
131 #define UAC_DEF_CCHMASK 0x3
132 #define UAC_DEF_CSRATE 48000
133 #define UAC_DEF_CSSIZE 2
134 #define UAC_DEF_PCHMASK 0x3 /* Playback support dual channel. */
135 #define UAC_DEF_PSRATE 8000
136 #define UAC_DEF_PSSIZE 2
137
138 struct uac_opts g_uac_opts =
139 {
140 UAC_DEF_CCHMASK, UAC_DEF_CSRATE, UAC_DEF_CSSIZE,
141 UAC_DEF_PCHMASK, UAC_DEF_PSRATE, UAC_DEF_PSSIZE
142 };
143
fuac_channel_num_get(uint32_t channel_mask)144 static uint32_t fuac_channel_num_get(uint32_t channel_mask)
145 {
146 uint32_t num = 0;
147
148 while (channel_mask)
149 {
150 if (channel_mask & 1)
151 {
152 num++;
153 }
154 channel_mask >>= 1;
155 }
156
157 return num;
158 }
159
fuac_opts_set(struct uac_opts * opts)160 int fuac_opts_set(struct uac_opts *opts)
161 {
162 if (opts == NULL)
163 {
164 usb_err("opts is NULL\n");
165 return -1;
166 }
167
168 (void)memcpy_s(&g_uac_opts, sizeof(g_uac_opts), opts, sizeof(struct uac_opts));
169
170 return 0;
171 }
172
173 static size_t g_uac_rate = 0;
fuac_rate_get(void)174 uint32_t fuac_rate_get(void)
175 {
176 if (g_uac_rate != 0)
177 {
178 return g_uac_rate;
179 }
180
181 return 0;
182 }
183
184 static const struct usb_device_descriptor g_fuac_device_desc __attribute__((aligned(4))) =
185 {
186 .bLength = sizeof(struct usb_device_descriptor),
187 .bDescriptorType = UDESC_DEVICE, /* Constant for device descriptor */
188 HSETW(.bcdUSB, UD_BCD_USB), /* USB version required: 2.0 */
189 .bDeviceClass = UICLASS_IAD, /* Miscellaneous Device Class */
190 .bDeviceSubClass = 0x2, /* Common Class */
191 .bDeviceProtocol = 0x1, /* Interface Association Descriptor */
192 .bMaxPacketSize = 64, /* Control Endpoint packet size */
193 HSETW(.idVendor, 0x1d6b), /* Vendor ID of Huawei Technologies */
194 HSETW(.idProduct, 0x0101), /* Product ID, webcamera ? */
195 HSETW(.bcdDevice, 0x318), /* Device release code */
196 .iManufacturer = 1, /* Manufacturer name, string index */
197 .iProduct = 2, /* Product name, string index */
198 .iSerialNumber = 0, /* Not Used */
199 .bNumConfigurations = 1 /* One Configuration */
200 };
201
202 static struct usb_config_descriptor g_fuac_config_desc =
203 {
204 .bLength = sizeof(struct usb_config_descriptor),
205 .bDescriptorType = UDESC_CONFIG,
206 HSETW(.wTotalLength, 0x006c), /* Size of all descriptors, set later */
207 .bNumInterface = 0x2, /* Two Interfaces */
208 .bConfigurationValue = 0x1, /* ID of this configuration */
209 .iConfiguration = 0x0, /* Index of string descriptor */
210 .bmAttributes = 0xc0, /* Self-powered */
211 .bMaxPower = 0x1 /* Maximum power consumption from the bus */
212 };
213
214 static struct usb_interface_assoc_descriptor g_fuac_iad =
215 {
216 .bLength = sizeof(struct usb_interface_assoc_descriptor),
217 .bDescriptorType = UDESC_IFACE_ASSOC,
218 .bFirstInterface = 0, /* Interface number of VideoControl interface */
219 .bInterfaceCount = 2, /* Number of contiguous Video interfaces */
220 .bFunctionClass = UICLASS_AUDIO,
221 .bFunctionSubClass = 0,
222 .bFunctionProtocol = 0,
223 .iFunction = STR_AC_IF /* index of string descriptor */
224 };
225
226 static struct usb_interface_descriptor g_fuac_ac_intf_desc =
227 {
228 .bLength = sizeof(struct usb_interface_descriptor),
229 .bDescriptorType = UDESC_INTERFACE,
230 .bInterfaceNumber = 0, /* index number of this interface */
231 .bAlternateSetting = 0, /* index of this settings */
232 .bNumEndpoints = 0, /* one endpoint */
233 .bInterfaceClass = UICLASS_AUDIO,
234 .bInterfaceSubClass = 1,
235 .bInterfaceProtocol = 0,
236 .iInterface = STR_AC_IF /* index of string descriptor */
237 };
238
239 static struct uac_ac_header_descriptor g_fuac_ac_head_desc =
240 {
241 .bLength = sizeof(struct uac_ac_header_descriptor),
242 .bDescriptorType = UAC_CS_INTERFACE,
243 .bDescriptorSubtype = UAC_HEADER,
244 .bcdADC = 0x0100, /* UAC specification version, 1.0 */
245 .wTotalLength = 0x1e, /* total length, currently not set */
246 .bInCollection = 1, /* Number of streaming interfaces */
247 .baInterfaceNr = {0x01} /* Associated Audio Streaming Interface */
248 };
249
250 static const struct uac1_input_terminal_descriptor g_fuac_input_terminal_desc =
251 {
252 .bLength = sizeof(struct uac1_input_terminal_descriptor),
253 .bDescriptorType = UAC_CS_INTERFACE,
254 .bDescriptorSubtype = UAC_INPUT_TERMINAL,
255 .bTerminalID = 0x03,
256 .wTerminalType = UAC_INPUT_TERMINAL_MICROPHONE,
257 .bAssocTerminal = 0,
258 .bNrChannels = 0x1,
259 .wChannelConfig = 0x0001,
260 .iChannelNames = 0x10,
261 .iTerminal = 0x8,
262 };
263
264 static const struct uac_output_terminal_descriptor g_fuac_output_terminal_desc =
265 {
266 .bLength = sizeof(struct uac_output_terminal_descriptor),
267 .bDescriptorType = UAC_CS_INTERFACE,
268 .bDescriptorSubtype = UAC_OUTPUT_TERMINAL,
269 .bTerminalID = 4,
270 .wTerminalType = 0x101,
271 .bAssocTerminal = 0,
272 .bSourceID = 3,
273 .iTerminal = 0xb,
274 };
275
276 static struct usb_interface_descriptor g_fuac_as_interface_alt_0_desc =
277 {
278 .bLength = sizeof(struct usb_interface_descriptor),
279 .bDescriptorType = UDESC_INTERFACE,
280 .bInterfaceNumber = 1,
281 .bAlternateSetting = 0,
282 .bNumEndpoints = 0,
283 .bInterfaceClass = UICLASS_AUDIO,
284 .bInterfaceSubClass = 2,
285 .bInterfaceProtocol = 0,
286 .iInterface = 0,
287 };
288
289 static struct usb_interface_descriptor g_fuac_as_interface_alt_1_desc =
290 {
291 .bLength = sizeof(struct usb_interface_descriptor),
292 .bDescriptorType = UDESC_INTERFACE,
293 .bInterfaceNumber = 1,
294 .bAlternateSetting = 1,
295 .bNumEndpoints = 1,
296 .bInterfaceClass = UICLASS_AUDIO,
297 .bInterfaceSubClass = 2,
298 .bInterfaceProtocol = 0,
299 .iInterface = 0,
300 };
301
302 static const struct uac_as_header_descriptor g_fuac_as_head_desc =
303 {
304 .bLength = sizeof(struct uac_as_header_descriptor),
305 .bDescriptorType = UAC_CS_INTERFACE,
306 .bDescriptorSubtype = UAC_HEADER,
307 .bTerminalLink = 4,
308 .bDelay = 0,
309 .wFormatTag = 1,
310 };
311
312 static const struct uac_format_type_i_discrete_descriptor g_fuac_as_type_i_desc =
313 {
314 .bLength = sizeof(struct uac_format_type_i_discrete_descriptor),
315 .bDescriptorType = UAC_CS_INTERFACE,
316 .bDescriptorSubtype = UAC_FORMAT_TYPE,
317 .bFormatType = 1,
318 .bNrChannels = 1,
319 .bSubframeSize = 2,
320 .bBitResolution = 16,
321 .bSamFreqType = 4,
322 HSETM(.tSamFreq[0], 0x001f40),
323 HSETM(.tSamFreq[1], 0x003e80),
324 HSETM(.tSamFreq[2], 0x007d00),
325 HSETM(.tSamFreq[3], 0x00bb80)
326 };
327
328 /* Standard ISO OUT Endpoint Descriptor */
329
330 static struct uac_endpoint_descriptor g_fuac_as_out_ep_desc =
331 {
332 .bLength = sizeof(struct uac_endpoint_descriptor),
333 .bDescriptorType = UDESC_ENDPOINT,
334 .bEndpointAddress = 0,
335 .bmAttributes = 0x0d,
336 HSETW(.wMaxPacketSize, ISO_DATA_SIZE),
337 .bInterval = 4,
338 .bRefresh = 0,
339 .bSynchAddress = 0,
340 };
341
342 /* Standard ISO IN Endpoint Descriptor */
343
344 struct uac_endpoint_descriptor g_fuac_as_in_ep_desc =
345 {
346 .bLength = sizeof(struct uac_endpoint_descriptor),
347 .bDescriptorType = UDESC_ENDPOINT,
348
349 /* Hi3516ev200 platform needs to specify endpoint number, otherwise the camera audio works abnormally.
350 * This way is compatible with other platforms.
351 */
352
353 .bEndpointAddress = UE_DIR_IN | 0x1,
354 .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_XFER_SYNC,
355 HSETW(.wMaxPacketSize, ISO_DATA_SIZE),
356 .bInterval = 4,
357 .bRefresh = 0,
358 .bSynchAddress = 0,
359 };
360
361 static const struct uac2_iso_endpoint_descriptor g_fuac_as_iso_in_desc =
362 {
363 .bLength = sizeof(struct uac2_iso_endpoint_descriptor),
364 .bDescriptorType = UDESC_CS_ENDPOINT,
365
366 .bDescriptorSubtype = 1,
367 .bmAttributes = 1,
368 .bmControls = 0,
369 .bLockDelayUnits = 0,
370 .wLockDelay = 0,
371 };
372
373 const uint8_t *g_fuac_descriptors_array[] =
374 {
375 (const uint8_t *)&g_fuac_config_desc,
376 (const uint8_t *)&g_fuac_iad,
377 (const uint8_t *)&g_fuac_ac_intf_desc,
378 (const uint8_t *)&g_fuac_ac_head_desc,
379
380 (const uint8_t *)&g_fuac_input_terminal_desc,
381 (const uint8_t *)&g_fuac_output_terminal_desc,
382 (const uint8_t *)&g_fuac_as_interface_alt_0_desc,
383 (const uint8_t *)&g_fuac_as_interface_alt_1_desc,
384 (const uint8_t *)&g_fuac_as_head_desc,
385 (const uint8_t *)&g_fuac_as_type_i_desc,
386 (const uint8_t *)&g_fuac_as_in_ep_desc,
387 (const uint8_t *)&g_fuac_as_iso_in_desc,
388 NULL,
389 };
390
link_fuac_descriptors(uint8_t * prefer,uint16_t ps,uint16_t * total_size)391 uint8_t *link_fuac_descriptors(uint8_t *prefer, uint16_t ps, uint16_t *total_size)
392 {
393 int i;
394 uint8_t *des;
395 uint8_t *pdes;
396 uint16_t cs;
397 errno_t err;
398 uint16_t ds = 0;
399
400 (void)prefer;
401 (void)ps;
402
403 /* Add the length of descriptors one by one */
404
405 for (i = 0; g_fuac_descriptors_array[i]; ++i)
406 {
407 ds += (uint16_t)(*g_fuac_descriptors_array[i]);
408 }
409
410 if (total_size != NULL)
411 {
412 *total_size = ds;
413 }
414
415 des = memalign(64, SKB_DATA_ALIGN(ds));
416 if (des == NULL)
417 {
418 usb_err("System out of memory! Descriptors length: %u\n", ds);
419 return NULL;
420 }
421 (void)memset_s(des, SKB_DATA_ALIGN(ds), 0, SKB_DATA_ALIGN(ds));
422
423 pdes = des;
424
425 /* configuration descriptor needs to have the full length of rest of descriptors */
426
427 g_fuac_config_desc.wTotalLength[0] = (uint8_t)ds;
428 g_fuac_config_desc.wTotalLength[1] = (uint8_t)(ds >> 8);
429
430 /* Add the length of audio control descriptors */
431
432 cs = (uint32_t)g_fuac_ac_head_desc.bLength;
433 cs += (uint32_t)g_fuac_input_terminal_desc.bLength;
434 cs += (uint32_t)g_fuac_output_terminal_desc.bLength;
435
436 g_fuac_ac_head_desc.wTotalLength = (uint16_t)cs;
437
438 for (i = 0; g_fuac_descriptors_array[i]; ++i)
439 {
440 const u8 *des_src = g_fuac_descriptors_array[i];
441 u8 des_len = *des_src;
442 err = memcpy_s(pdes, des_len, des_src, des_len);
443 if (err != EOK)
444 {
445 usb_err("memcpy fail!\n");
446 free(des);
447 return NULL;
448 }
449 pdes += des_len;
450 }
451
452 return des;
453 }
454
fuac_request_complete(struct usbdev_ep_s * ep,struct usbdev_req_s * req)455 static void fuac_request_complete(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
456 {
457 struct uac_dev_s *uac = (struct uac_dev_s *)req->priv;
458 volatile uint32_t rate;
459
460 (void) ep; /* ignored */
461 switch (uac->control)
462 {
463 case ~0u:
464 break;
465
466 case UAC_VS_COMMIT_CONTROL:
467 spin_lock(&uac->lock);
468 uac->connected = 0x1;
469 spin_unlock(&uac->lock);
470 uac->control = ~0;
471 break;
472
473 case UAC_SETCUR_COMPLETE:
474 rate = (((uint8_t *)req->buf)[0] | (((uint8_t *)req->buf)[1] << 8) |
475 (((uint8_t *)req->buf)[2] << 16));
476
477 if (uac->count == 0 || rate != g_uac_rate)
478 {
479 uac->count = 1;
480 spin_lock(&uac->lock);
481 uac_queue_free(uac);
482 uac->busy_flag = 0;
483 uac->connected = 1;
484 spin_unlock(&uac->lock);
485 g_uac_iso_data_size = (rate / 1000) * g_uac_opts.p_ssize * fuac_channel_num_get(g_uac_opts.p_chmask);
486 g_uac_rate = rate;
487 PRINTK("<<<rate:%u, size:%u>>>\n", rate, g_uac_iso_data_size);
488 (void)EP_DISABLE(uac->in_ep);
489 (void)EP_FLUSH(uac->in_ep);
490 (void)EP_CONFIGURE(uac->in_ep, (const usb_endpoint_descriptor_t *)&g_fuac_as_in_ep_desc, 0);
491 }
492 uac->control = ~0;
493 break;
494
495 default:
496 uac->control = ~0;
497 break;
498 }
499 }
500
fuac_output_request_complete(struct usbdev_ep_s * ep,struct usbdev_req_s * req)501 static void fuac_output_request_complete(struct usbdev_ep_s *ep,
502 struct usbdev_req_s *req)
503 {
504 (void)ep;
505 (void)req;
506 }
507
fuac_input_req_complete(struct usbdev_ep_s * ep,struct usbdev_req_s * req)508 void fuac_input_req_complete(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
509 {
510 struct uac_dev_s *uac = &((struct uac_softc *)(ep->priv))->dev;
511 struct uac_queue_node *node_tx;
512 struct usbdev_req_s *req_temp = &uac->inputreq;
513
514 spin_lock(&uac->lock);
515 if (req->result != 0)
516 {
517 uac_queue_free(uac);
518 spin_unlock(&uac->lock);
519 return;
520 }
521
522 if (uac->cur_node != NULL)
523 {
524 node_tx = uac->cur_node;
525 if (node_tx->buf_len == 0)
526 {
527 uac_queue_node_free(node_tx);
528 uac->cur_node = NULL;
529 }
530 else
531 {
532 uac_send_data_sub(uac);
533 spin_unlock(&uac->lock);
534 return;
535 }
536 }
537
538 if (!list_empty(&uac->uac_queue))
539 {
540 node_tx = list_first_entry(&uac->uac_queue, struct uac_queue_node, irqqueue);
541 uac->cur_node = node_tx;
542 list_del_init(&node_tx->irqqueue);
543 uac->uac_queue_len--;
544 uac_send_data_sub(uac);
545 }
546 else
547 {
548 req_temp->len = 0;
549 (void)EP_SUBMIT(uac->in_ep, req_temp);
550 }
551 spin_unlock(&uac->lock);
552 }
553
audio_set_endpoint_req(struct usbdev_s * dev,struct usbdev_req_s * req,const struct usb_device_request * ctrl)554 static int audio_set_endpoint_req(struct usbdev_s *dev, struct usbdev_req_s *req,
555 const struct usb_device_request *ctrl)
556 {
557 uint8_t request = ctrl->bRequest;
558 uint8_t new_req = 0;
559 switch (request)
560 {
561 case SET_CUR_UAC:
562 case SET_MIN_UAC:
563 case SET_MAX_UAC:
564 case SET_RES_UAC:
565 req->len = UGETW(ctrl->wLength);
566 new_req++;
567 break;
568
569 default:
570 PRINT_ERR("Unknown index in [%s]: %#x\n", __FUNCTION__, (uint8_t)request);
571 break;
572 }
573
574 if (new_req)
575 {
576 (void)EP_SUBMIT(dev->ep0, req);
577 }
578 return 0;
579 }
580
audio_get_endpoint_req(struct usbdev_s * dev,struct usbdev_req_s * req,const struct usb_device_request * ctrl)581 static int audio_get_endpoint_req(struct usbdev_s *dev, struct usbdev_req_s *req,
582 const struct usb_device_request *ctrl)
583 {
584 uint8_t request = ctrl->bRequest;
585 uint8_t new_req = 0;
586 uint8_t *buf = (uint8_t *)req->buf;
587
588 switch (request)
589 {
590 case GET_CUR_UAC:
591 case GET_MIN_UAC:
592 case GET_MAX_UAC:
593 case GET_RES_UAC:
594 req->len = UGETW(ctrl->wLength);
595 buf[0] = (uint8_t)g_uac_rate;
596 buf[1] = (uint8_t)(g_uac_rate >> 8);
597 buf[2] = (uint8_t)(g_uac_rate >> 16);
598 new_req++;
599 break;
600
601 case GET_MEM_UAC:
602 break;
603
604 default:
605 PRINT_ERR("Unknown index in [%s]: %#x\n", __FUNCTION__, request);
606 break;
607 }
608 if (new_req)
609 {
610 (void)EP_SUBMIT(dev->ep0, req);
611 }
612 return 0;
613 }
614
fuac_source_free(struct usbdevclass_driver_s * driver,struct usbdev_s * dev)615 static void fuac_source_free(struct usbdevclass_driver_s *driver, struct usbdev_s *dev)
616 {
617 struct uac_driver_s *drvr;
618 struct uac_dev_s *uac;
619
620 drvr = (struct uac_driver_s *)driver;
621 uac = drvr->dev;
622 if (uac == NULL)
623 {
624 return;
625 }
626
627 DEV_FREEEP(dev, uac->out_ep);
628 DEV_FREEEP(dev, uac->in_ep);
629 }
630
usbclass_uac_bind(struct usbdevclass_driver_s * driver,struct usbdev_s * dev)631 static int usbclass_uac_bind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev)
632 {
633 struct usbdev_ep_s *ep;
634 struct uac_driver_s *drvr;
635 struct composite_dev_s *cdev;
636 struct uac_dev_s *uac;
637 struct composite_devobj_s *devobj;
638 struct usbdev_devinfo_s *devinfo;
639
640 if (driver == NULL || dev == NULL)
641 {
642 return -1;
643 }
644
645 cdev = dev->ep0->priv;
646 drvr = (struct uac_driver_s *)driver;
647 uac = drvr->dev;
648 if (uac == NULL)
649 {
650 return -1;
651 }
652
653 INIT_LIST_HEAD(&uac->uac_queue);
654 uac->busy_flag = 0;
655 uac->uac_queue_len = 0;
656 uac->cur_node = NULL;
657 uac->count = 0;
658 spin_lock_init(&uac->lock);
659
660 devobj = usbclass_devobj_get(cdev, DEV_UAC);
661 if (devobj == NULL)
662 {
663 return -1;
664 }
665 devinfo = &devobj->compdesc.devinfo;
666
667 /* initialize control endpoint */
668
669 ep = DEV_ALLOCEP(dev, g_fuac_as_out_ep_desc.bEndpointAddress,
670 (struct usb_endpoint_descriptor *)&g_fuac_as_out_ep_desc);
671 if (ep == NULL)
672 {
673 return -1;
674 }
675 ep->priv = (void *)uac;
676 (void)memset_s(&(uac->outputreq), sizeof(struct usbdev_req_s), 0, sizeof(struct usbdev_req_s));
677 uac->outputreq.callback = fuac_output_request_complete;
678 uac->outputreq.priv = (void *)uac;
679 ep->handle_req = &uac->outputreq;
680 uac->out_ep = ep;
681 devinfo->epno[0] = ep->eplog;
682
683 /* initialize AudioStreaming endpoint */
684
685 ep = DEV_ALLOCEP(dev, g_fuac_as_in_ep_desc.bEndpointAddress,
686 (struct usb_endpoint_descriptor *)&g_fuac_as_in_ep_desc);
687 if (ep == NULL)
688 {
689 goto fail;
690 }
691 (void)memset_s(&uac->inputreq, sizeof(struct usbdev_req_s), 0, sizeof(struct usbdev_req_s));
692 uac->inputreq.callback = fuac_input_req_complete;
693 uac->inputreq.priv = (void *)uac;
694 uac->inputreq.buf = NULL;
695 ep->priv = (void *)uac;
696 ep->handle_req = &uac->inputreq;
697 uac->in_ep = ep;
698 devinfo->epno[1] = ep->eplog;
699 uac->control = ~0;
700
701 return 0;
702 fail:
703 (void)usbclass_uac_unbind(driver, dev);
704 return -1;
705 }
706
usbclass_uac_unbind(struct usbdevclass_driver_s * driver,struct usbdev_s * dev)707 static int usbclass_uac_unbind(struct usbdevclass_driver_s *driver, struct usbdev_s *dev)
708 {
709 struct composite_dev_s *cdev;
710 struct composite_devobj_s *devobj;
711 struct usbdev_devinfo_s *devinfo;
712
713 if (driver == NULL || dev == NULL)
714 {
715 return -1;
716 }
717
718 usbclass_uac_disconnect(driver, dev);
719
720 cdev = dev->ep0->priv;
721 if (cdev == NULL)
722 {
723 return -1;
724 }
725
726 devobj = usbclass_devobj_get(cdev, DEV_UAC);
727 if (devobj == NULL)
728 {
729 return -1;
730 }
731 devinfo = &devobj->compdesc.devinfo;
732 (void)memset_s(devinfo, sizeof(struct usbdev_devinfo_s), 0, sizeof(struct usbdev_devinfo_s));
733
734 fuac_source_free(driver, dev);
735 return 0;
736 }
737
usbclass_uac_set_alt(struct uac_dev_s * dev,unsigned intf,unsigned alt)738 static int usbclass_uac_set_alt(struct uac_dev_s *dev, unsigned intf, unsigned alt)
739 {
740 (void)intf;
741 (void)alt;
742
743 dev->busy_flag = 0;
744 if (dev->in_ep_enabled == true)
745 {
746 (void)EP_DISABLE(dev->in_ep);
747 dev->in_ep_enabled = false;
748 }
749
750 (void)EP_CONFIGURE(dev->in_ep, (const usb_endpoint_descriptor_t *)&g_fuac_as_in_ep_desc, 0);
751 dev->in_ep_enabled = true;
752
753 return 0;
754 }
755
usbclass_uac_setup(struct usbdevclass_driver_s * driver,struct usbdev_s * dev,const struct usb_device_request * ctrl,uint8_t * dataout,size_t outlen)756 static int usbclass_uac_setup(struct usbdevclass_driver_s *driver, struct usbdev_s *dev,
757 const struct usb_device_request *ctrl, uint8_t *dataout, size_t outlen)
758 {
759 uint8_t req_type;
760 struct uac_dev_s *uac;
761 struct uac_driver_s *drvr;
762 struct usbdev_req_s *req;
763
764 (void)dataout;
765 (void)outlen;
766
767 if (dev == NULL || driver == NULL || ctrl == NULL)
768 {
769 return -1;
770 }
771
772 drvr = (struct uac_driver_s *)driver;
773 uac = drvr->dev;
774 if (uac == NULL)
775 {
776 return -1;
777 }
778
779 req = dev->ep0->handle_req;
780 req_type = ctrl->bmRequestType;
781 req->callback = fuac_request_complete;
782 req->priv = uac;
783
784 if (UT_GET_TYPE(req_type) == UT_STANDARD)
785 {
786 switch (ctrl->bRequest)
787 {
788 case USB_REQ_SET_CONFIGURATION:
789 case USB_REQ_SET_INTERFACE:
790 (void)usbclass_uac_set_alt(uac, UGETW(ctrl->wIndex), UGETW(ctrl->wValue));
791 break;
792
793 default:
794 break;
795 }
796 }
797 else
798 {
799 switch (req_type)
800 {
801 case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT:
802 (void)audio_set_endpoint_req(dev, req, ctrl);
803 uac->control = UAC_SETCUR_COMPLETE;
804 break;
805
806 case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER:
807 case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_OTHER:
808 case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
809 case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
810 break;
811
812 case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT:
813 (void)audio_get_endpoint_req(dev, req, ctrl);
814 break;
815
816 default:
817 break;
818 }
819 }
820 return 0;
821 }
822
usbclass_uac_disconnect(struct usbdevclass_driver_s * driver,struct usbdev_s * dev)823 static void usbclass_uac_disconnect(struct usbdevclass_driver_s *driver, struct usbdev_s *dev)
824 {
825 struct uac_driver_s *uac_drvr;
826 struct uac_dev_s *uac_dev;
827
828 uac_drvr = (struct uac_driver_s *)driver;
829 uac_dev = uac_drvr->dev;
830 if (uac_dev == NULL)
831 {
832 return;
833 }
834
835 if (uac_dev->in_ep_enabled == true)
836 {
837 (void)EP_DISABLE(uac_dev->in_ep);
838 uac_dev->in_ep_enabled = false;
839 }
840 }
841
842 struct usbd_string g_fuac_device_strings[7] =
843 {
844 { 0, g_fuac_str_lang },
845 { 1, g_fuac_str_manufacturer },
846 { 2, g_fuac_str_product },
847 { 4, g_fuac_str_ac_if },
848 { 8, g_fuac_input_terminal },
849 { 11, g_fuac_output_terminal },
850 USBD_DEVICE_STRINGS_END
851 };
852
uac_mkdevdesc(uint8_t * buf)853 void uac_mkdevdesc(uint8_t *buf)
854 {
855 errno_t ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, &g_fuac_device_desc, sizeof(g_fuac_device_desc));
856 if (ret != EOK)
857 {
858 usb_err("memcpy_s fail!, ret:%d\n", ret);
859 return;
860 }
861 }
862
uac_mkcfgdesc(uint8_t * buf,struct usbdev_devinfo_s * devinfo)863 int16_t uac_mkcfgdesc(uint8_t *buf, struct usbdev_devinfo_s *devinfo)
864 {
865 uint16_t total_len;
866 uint8_t *des;
867 errno_t ret;
868
869 g_fuac_iad.bFirstInterface = devinfo->ifnobase;
870 g_fuac_ac_intf_desc.bInterfaceNumber = devinfo->ifnobase;
871 g_fuac_as_interface_alt_0_desc.bInterfaceNumber = devinfo->ifnobase + 1;
872 g_fuac_as_interface_alt_1_desc.bInterfaceNumber = devinfo->ifnobase + 1;
873 g_fuac_ac_head_desc.baInterfaceNr[0] = devinfo->ifnobase + 1;
874
875 des = link_fuac_descriptors(NULL, 0, &total_len);
876 if (des != NULL)
877 {
878 ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, des, total_len);
879 if (ret != EOK)
880 {
881 usb_err("memcpy_s fail!, ret:%d\n", ret);
882 free(des);
883 return 0;
884 }
885 free(des);
886 }
887
888 return (int16_t)total_len;
889 }
890
uac_mkstrdesc(uint8_t id,uint8_t * buf)891 int uac_mkstrdesc(uint8_t id, uint8_t *buf)
892 {
893 errno_t ret;
894 const char *str;
895 int i;
896
897 for (i = 0; g_fuac_device_strings[i].s != NULL; i++)
898 {
899 str = g_fuac_device_strings[i].s;
900 if (g_fuac_device_strings[i].id == id)
901 {
902 ret = memcpy_s(buf, USB_COMP_EP0_BUFSIZ, str, str[0]);
903 if (ret != EOK)
904 {
905 usb_err("memcpy_s failed, ret = %d\n", ret);
906 return -1;
907 }
908 return str[0];
909 }
910 }
911
912 usb_err("Can not find the id = %u of string\n", id);
913 return -1;
914 }
915
916 #define UAC_NCONFIGS 1
917 #define UAC_CONFIGID 0
918 #define UAC_NINTERFACES 2
919 #define UAC_NSTRIDS 6
920 #define UAC_NUM_EPS 2
uac_get_composite_devdesc(struct composite_devdesc_s * dev)921 void uac_get_composite_devdesc(struct composite_devdesc_s *dev)
922 {
923 (void)memset_s(dev, sizeof(struct composite_devdesc_s), 0, sizeof(struct composite_devdesc_s));
924
925 dev->mkdevdesc = uac_mkdevdesc;
926 dev->mkconfdesc = uac_mkcfgdesc;
927 dev->mkstrdesc = uac_mkstrdesc;
928
929 dev->nconfigs = UAC_NCONFIGS; /* Number of configurations supported */
930 dev->configid = UAC_CONFIGID; /* The only supported configuration ID */
931
932 /* Interfaces.
933 *
934 * ifnobase must be provided by board-specific logic
935 */
936
937 dev->devinfo.ninterfaces = UAC_NINTERFACES; /* Number of interfaces in the configuration */
938
939 /* Strings.
940 *
941 * strbase must be provided by board-specific logic
942 */
943
944 dev->devinfo.nstrings = UAC_NSTRIDS; /* Number of Strings */
945
946 /* Endpoints.
947 *
948 * Endpoint numbers must be provided by board-specific logic.
949 */
950
951 dev->devinfo.nendpoints = UAC_NUM_EPS;
952 }
953
uac_classobject(int minor,struct usbdev_devinfo_s * devinfo,struct usbdevclass_driver_s ** classdev)954 int uac_classobject(int minor, struct usbdev_devinfo_s *devinfo,
955 struct usbdevclass_driver_s **classdev)
956 {
957 struct uac_softc *uac_s;
958 struct uac_dev_s *priv;
959 struct uac_driver_s *drvr;
960
961 (void)minor;
962 (void)devinfo;
963
964 /* Allocate the structures needed */
965
966 uac_s = (struct uac_softc *)malloc(sizeof(struct uac_softc));
967 if (uac_s == NULL)
968 {
969 return -1;
970 }
971
972 /* Convenience pointers into the allocated blob */
973
974 priv = &uac_s->dev;
975 drvr = &uac_s->drvr;
976
977 /* Initialize the USB serial driver structure */
978
979 (void)memset_s(priv, sizeof(struct uac_dev_s), 0, sizeof(struct uac_dev_s));
980
981 /* Initialize the USB class driver structure */
982
983 drvr->drvr.speed = USB_SPEED_HIGH;
984 drvr->drvr.ops = &g_uac_driverops;
985 drvr->dev = priv;
986
987 *classdev = &drvr->drvr;
988 return 0;
989 }
990
uac_uninitialize(struct usbdevclass_driver_s * classdev)991 void uac_uninitialize(struct usbdevclass_driver_s *classdev)
992 {
993 struct uac_driver_s *uac_drvr = (struct uac_driver_s *)classdev;
994 struct uac_dev_s *priv;
995 struct uac_softc *uac_s;
996
997 if (uac_drvr == NULL)
998 {
999 return;
1000 }
1001
1002 priv = uac_drvr->dev;
1003 if (priv == NULL)
1004 {
1005 return;
1006 }
1007
1008 uac_s = container_of(uac_drvr, struct uac_softc, drvr);
1009 free(uac_s);
1010 }
1011
usbdev_uac_initialize_sub(struct composite_devdesc_s * dev,int ifnobase,int minor)1012 void usbdev_uac_initialize_sub(struct composite_devdesc_s *dev, int ifnobase, int minor)
1013 {
1014 /* Ask the UAC driver to fill in the constants we didn't
1015 * know here.
1016 */
1017
1018 uac_get_composite_devdesc(dev);
1019
1020 /* Overwrite and correct some values... */
1021 /* The callback functions for the UAC class */
1022
1023 dev->classobject = uac_classobject;
1024 dev->uninitialize = uac_uninitialize;
1025
1026 /* Interfaces */
1027
1028 dev->devinfo.ifnobase = ifnobase; /* Offset to Interface-IDs */
1029 dev->minor = minor; /* The minor interface number */
1030
1031 /* Strings */
1032
1033 dev->devinfo.strbase = 0; /* Offset to String Numbers */
1034 }
1035
usbdev_uac_initialize(struct module * mod,int n,void * arg)1036 int usbdev_uac_initialize(struct module *mod, int n, void *arg)
1037 {
1038 struct composite_softc *com_s = (struct composite_softc *)arg;
1039 struct composite_devdesc_s dev;
1040 int ret;
1041
1042 (void)mod;
1043 (void)n;
1044 if (com_s == NULL)
1045 {
1046 return -1;
1047 }
1048
1049 usbdev_uac_initialize_sub(&dev, 0, DEV_UAC);
1050
1051 ret = composite_initialize(com_s, 1, &dev);
1052 if (ret < 0)
1053 {
1054 return -1;
1055 }
1056
1057 PRINTK(" ** uac device initialized successfully! **\n");
1058 return 0;
1059 }
1060
1061 #ifdef __cplusplus
1062 #if __cplusplus
1063 }
1064 #endif /* __cplusplus */
1065 #endif /* __cplusplus */