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