• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */