1beacf11bSopenharmony_ci/* ----------------------------------------------------------------------------
2beacf11bSopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
3beacf11bSopenharmony_ci * Description: LiteOS USB Driver Audio Stream
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/usbd_audio.h"
38beacf11bSopenharmony_ci#include "gadget/f_uac.h"
39beacf11bSopenharmony_ci#include "implementation/global_implementation.h"
40beacf11bSopenharmony_ci
41beacf11bSopenharmony_ci#ifdef __cplusplus
42beacf11bSopenharmony_ci#if __cplusplus
43beacf11bSopenharmony_ciextern "C" {
44beacf11bSopenharmony_ci#endif /* __cplusplus */
45beacf11bSopenharmony_ci#endif /* __cplusplus */
46beacf11bSopenharmony_ci
47beacf11bSopenharmony_cistatic struct uac_softc *get_uac(void)
48beacf11bSopenharmony_ci{
49beacf11bSopenharmony_ci  devclass_t dc;
50beacf11bSopenharmony_ci  device_t dev;
51beacf11bSopenharmony_ci  struct composite_softc *cdev;
52beacf11bSopenharmony_ci  struct composite_devobj_s *devobj;
53beacf11bSopenharmony_ci  struct usbdevclass_driver_s *drvr;
54beacf11bSopenharmony_ci  struct uac_driver_s *driver;
55beacf11bSopenharmony_ci
56beacf11bSopenharmony_ci  dc = devclass_find("composite");
57beacf11bSopenharmony_ci  if (dc == NULL)
58beacf11bSopenharmony_ci    {
59beacf11bSopenharmony_ci      PRINT_ERR("%s is failed\n", __FUNCTION__);
60beacf11bSopenharmony_ci      return NULL;
61beacf11bSopenharmony_ci    }
62beacf11bSopenharmony_ci  dev = devclass_get_device(dc, 0);
63beacf11bSopenharmony_ci  if (dev == NULL)
64beacf11bSopenharmony_ci    {
65beacf11bSopenharmony_ci      PRINT_ERR("%s, get dev failed\n", __FUNCTION__);
66beacf11bSopenharmony_ci      return NULL;
67beacf11bSopenharmony_ci    }
68beacf11bSopenharmony_ci  cdev = (struct composite_softc *)device_get_softc(dev);
69beacf11bSopenharmony_ci  if (cdev == NULL)
70beacf11bSopenharmony_ci    {
71beacf11bSopenharmony_ci      PRINT_ERR("%s, get softc failed\n", __FUNCTION__);
72beacf11bSopenharmony_ci      return NULL;
73beacf11bSopenharmony_ci    }
74beacf11bSopenharmony_ci
75beacf11bSopenharmony_ci  devobj = usbclass_devobj_get(&cdev->dev, DEV_UAC);
76beacf11bSopenharmony_ci  if (devobj == NULL)
77beacf11bSopenharmony_ci    {
78beacf11bSopenharmony_ci      return NULL;
79beacf11bSopenharmony_ci    }
80beacf11bSopenharmony_ci
81beacf11bSopenharmony_ci  drvr = devobj->dev;
82beacf11bSopenharmony_ci  if (drvr == NULL)
83beacf11bSopenharmony_ci    {
84beacf11bSopenharmony_ci      PRINT_ERR("%s, get driver failed\n", __FUNCTION__);
85beacf11bSopenharmony_ci      return NULL;
86beacf11bSopenharmony_ci    }
87beacf11bSopenharmony_ci  driver = (struct uac_driver_s *)drvr;
88beacf11bSopenharmony_ci
89beacf11bSopenharmony_ci  return container_of(driver, struct uac_softc, drvr);
90beacf11bSopenharmony_ci}
91beacf11bSopenharmony_ci
92beacf11bSopenharmony_cistatic int fuac_host_connected(struct uac_dev_s *fuac)
93beacf11bSopenharmony_ci{
94beacf11bSopenharmony_ci  if (fuac == NULL)
95beacf11bSopenharmony_ci    {
96beacf11bSopenharmony_ci      return 0;
97beacf11bSopenharmony_ci    }
98beacf11bSopenharmony_ci
99beacf11bSopenharmony_ci  return fuac->connected;
100beacf11bSopenharmony_ci}
101beacf11bSopenharmony_ci
102beacf11bSopenharmony_cistatic int uac_wait_hot_sub(void)
103beacf11bSopenharmony_ci{
104beacf11bSopenharmony_ci  int ret;
105beacf11bSopenharmony_ci  struct uac_softc *fuac;
106beacf11bSopenharmony_ci  struct uac_dev_s *dev;
107beacf11bSopenharmony_ci
108beacf11bSopenharmony_ci  mtx_lock(&usb_mtx);
109beacf11bSopenharmony_ci  fuac = get_uac();
110beacf11bSopenharmony_ci  if (fuac == NULL)
111beacf11bSopenharmony_ci    {
112beacf11bSopenharmony_ci      mtx_unlock(&usb_mtx);
113beacf11bSopenharmony_ci      return UAC_ERROR_PTR;
114beacf11bSopenharmony_ci    }
115beacf11bSopenharmony_ci  dev = &fuac->dev;
116beacf11bSopenharmony_ci  ret = fuac_host_connected(dev) ;
117beacf11bSopenharmony_ci  mtx_unlock(&usb_mtx);
118beacf11bSopenharmony_ci
119beacf11bSopenharmony_ci  return ret;
120beacf11bSopenharmony_ci}
121beacf11bSopenharmony_ci
122beacf11bSopenharmony_ciint uac_wait_host(int wait_option)
123beacf11bSopenharmony_ci{
124beacf11bSopenharmony_ci  int ret;
125beacf11bSopenharmony_ci
126beacf11bSopenharmony_ci  switch (wait_option)
127beacf11bSopenharmony_ci    {
128beacf11bSopenharmony_ci    case UAC_WAIT_HOST_NOP:
129beacf11bSopenharmony_ci      ret = uac_wait_hot_sub();
130beacf11bSopenharmony_ci      if (ret == 0) /* Device is not connected. */
131beacf11bSopenharmony_ci        {
132beacf11bSopenharmony_ci          ret = UAC_ERROR_NOMATCH;
133beacf11bSopenharmony_ci        }
134beacf11bSopenharmony_ci      else if (ret == 1) /* Device is connected. */
135beacf11bSopenharmony_ci        {
136beacf11bSopenharmony_ci          ret = UAC_OK;
137beacf11bSopenharmony_ci        }
138beacf11bSopenharmony_ci      break;
139beacf11bSopenharmony_ci
140beacf11bSopenharmony_ci    case UAC_WAIT_HOST_FOREVER:
141beacf11bSopenharmony_ci      while (!(ret = uac_wait_hot_sub()))
142beacf11bSopenharmony_ci        {
143beacf11bSopenharmony_ci          (void)LOS_TaskDelay(10);
144beacf11bSopenharmony_ci        }
145beacf11bSopenharmony_ci
146beacf11bSopenharmony_ci      if (ret != UAC_ERROR_PTR)
147beacf11bSopenharmony_ci        {
148beacf11bSopenharmony_ci          ret = UAC_OK;
149beacf11bSopenharmony_ci        }
150beacf11bSopenharmony_ci      break;
151beacf11bSopenharmony_ci
152beacf11bSopenharmony_ci    default:
153beacf11bSopenharmony_ci      return UAC_ERROR_VALUE;
154beacf11bSopenharmony_ci    }
155beacf11bSopenharmony_ci
156beacf11bSopenharmony_ci  return ret;
157beacf11bSopenharmony_ci}
158beacf11bSopenharmony_ci
159beacf11bSopenharmony_cistruct uac_queue_node *uac_queue_node_alloc(unsigned len)
160beacf11bSopenharmony_ci{
161beacf11bSopenharmony_ci  struct uac_queue_node *queue_node;
162beacf11bSopenharmony_ci
163beacf11bSopenharmony_ci  queue_node = zalloc(sizeof(struct uac_queue_node));
164beacf11bSopenharmony_ci  if (queue_node == NULL)
165beacf11bSopenharmony_ci    {
166beacf11bSopenharmony_ci      PRINT_ERR("%s, malloc uac queue node failed\n", __FUNCTION__);
167beacf11bSopenharmony_ci      return NULL;
168beacf11bSopenharmony_ci    }
169beacf11bSopenharmony_ci
170beacf11bSopenharmony_ci  queue_node->buf_len  = len;
171beacf11bSopenharmony_ci  queue_node->buf_used = 0;
172beacf11bSopenharmony_ci  queue_node->buf      = malloc(len);
173beacf11bSopenharmony_ci  if (queue_node->buf == NULL)
174beacf11bSopenharmony_ci    {
175beacf11bSopenharmony_ci      free(queue_node);
176beacf11bSopenharmony_ci      PRINT_ERR("%s, malloc uac queue node buf failed\n", __FUNCTION__);
177beacf11bSopenharmony_ci      return NULL;
178beacf11bSopenharmony_ci    }
179beacf11bSopenharmony_ci
180beacf11bSopenharmony_ci  return queue_node;
181beacf11bSopenharmony_ci}
182beacf11bSopenharmony_ci
183beacf11bSopenharmony_civoid uac_queue_node_free(struct uac_queue_node *node)
184beacf11bSopenharmony_ci{
185beacf11bSopenharmony_ci  free(node->buf);
186beacf11bSopenharmony_ci  node->buf = NULL;
187beacf11bSopenharmony_ci  free(node);
188beacf11bSopenharmony_ci}
189beacf11bSopenharmony_ci
190beacf11bSopenharmony_civoid uac_send_data_sub(struct uac_dev_s *sc)
191beacf11bSopenharmony_ci{
192beacf11bSopenharmony_ci  struct uac_dev_s *fuac      = sc;
193beacf11bSopenharmony_ci  struct uac_queue_node *node = fuac->cur_node;
194beacf11bSopenharmony_ci  struct usbdev_req_s *req    = &fuac->inputreq;
195beacf11bSopenharmony_ci
196beacf11bSopenharmony_ci  atomic_set(&fuac->busy_flag, 1);
197beacf11bSopenharmony_ci
198beacf11bSopenharmony_ci  if (node->buf_len > g_uac_iso_data_size)
199beacf11bSopenharmony_ci    {
200beacf11bSopenharmony_ci      req->len = g_uac_iso_data_size;
201beacf11bSopenharmony_ci    }
202beacf11bSopenharmony_ci  else
203beacf11bSopenharmony_ci    {
204beacf11bSopenharmony_ci      req->len = node->buf_len;
205beacf11bSopenharmony_ci    }
206beacf11bSopenharmony_ci  req->buf = node->buf + node->buf_used;
207beacf11bSopenharmony_ci
208beacf11bSopenharmony_ci  node->buf_len  -= req->len;
209beacf11bSopenharmony_ci  node->buf_used += req->len;
210beacf11bSopenharmony_ci  (void)EP_SUBMIT(fuac->in_ep, req);
211beacf11bSopenharmony_ci}
212beacf11bSopenharmony_ci
213beacf11bSopenharmony_civoid uac_queue_free(struct uac_dev_s *sc)
214beacf11bSopenharmony_ci{
215beacf11bSopenharmony_ci  struct uac_queue_node *node;
216beacf11bSopenharmony_ci  struct uac_dev_s *fuac_sc = sc;
217beacf11bSopenharmony_ci
218beacf11bSopenharmony_ci  if (fuac_sc->cur_node != NULL)
219beacf11bSopenharmony_ci    {
220beacf11bSopenharmony_ci      uac_queue_node_free(fuac_sc->cur_node);
221beacf11bSopenharmony_ci      fuac_sc->cur_node = NULL;
222beacf11bSopenharmony_ci    }
223beacf11bSopenharmony_ci
224beacf11bSopenharmony_ci  while (!list_empty(&fuac_sc->uac_queue))
225beacf11bSopenharmony_ci    {
226beacf11bSopenharmony_ci      node = list_first_entry(&fuac_sc->uac_queue, struct uac_queue_node, irqqueue);
227beacf11bSopenharmony_ci      list_del_init(&node->irqqueue);
228beacf11bSopenharmony_ci      uac_queue_node_free(node);
229beacf11bSopenharmony_ci    }
230beacf11bSopenharmony_ci  INIT_LIST_HEAD(&fuac_sc->uac_queue);
231beacf11bSopenharmony_ci
232beacf11bSopenharmony_ci  fuac_sc->uac_queue_len = 0;
233beacf11bSopenharmony_ci}
234beacf11bSopenharmony_ci
235beacf11bSopenharmony_ciint fuac_send_message(const void *buf, int len)
236beacf11bSopenharmony_ci{
237beacf11bSopenharmony_ci  struct uac_softc *fuac;
238beacf11bSopenharmony_ci  struct uac_dev_s *dev;
239beacf11bSopenharmony_ci  struct uac_queue_node *node;
240beacf11bSopenharmony_ci  struct uac_queue_node *node_tx;
241beacf11bSopenharmony_ci  uint32_t flags;
242beacf11bSopenharmony_ci  int ret = 0;
243beacf11bSopenharmony_ci
244beacf11bSopenharmony_ci  if (buf == NULL || len < 0)
245beacf11bSopenharmony_ci    {
246beacf11bSopenharmony_ci      return UAC_ERROR_PTR;
247beacf11bSopenharmony_ci    }
248beacf11bSopenharmony_ci
249beacf11bSopenharmony_ci  node = uac_queue_node_alloc(len);
250beacf11bSopenharmony_ci  if (node == NULL)
251beacf11bSopenharmony_ci    {
252beacf11bSopenharmony_ci      return UAC_ERROR_MEMORY;
253beacf11bSopenharmony_ci    }
254beacf11bSopenharmony_ci  (void)memcpy_s(node->buf, len, buf, len);
255beacf11bSopenharmony_ci
256beacf11bSopenharmony_ci  mtx_lock(&usb_mtx);
257beacf11bSopenharmony_ci  fuac = get_uac();
258beacf11bSopenharmony_ci  if (fuac == NULL)
259beacf11bSopenharmony_ci    {
260beacf11bSopenharmony_ci      uac_queue_node_free(node);
261beacf11bSopenharmony_ci      PRINT_ERR("%s, get uac failed\n", __FUNCTION__);
262beacf11bSopenharmony_ci      ret = UAC_ERROR_PTR;
263beacf11bSopenharmony_ci      goto error;
264beacf11bSopenharmony_ci    }
265beacf11bSopenharmony_ci  dev = &fuac->dev;
266beacf11bSopenharmony_ci  spin_lock_irqsave(&dev->lock, flags);
267beacf11bSopenharmony_ci  if (!dev->connected)
268beacf11bSopenharmony_ci    {
269beacf11bSopenharmony_ci      uac_queue_node_free(node);
270beacf11bSopenharmony_ci      goto done;
271beacf11bSopenharmony_ci    }
272beacf11bSopenharmony_ci
273beacf11bSopenharmony_ci  if (dev->uac_queue_len > 8)
274beacf11bSopenharmony_ci    {
275beacf11bSopenharmony_ci      uac_queue_free(dev);
276beacf11bSopenharmony_ci    }
277beacf11bSopenharmony_ci
278beacf11bSopenharmony_ci  list_add_tail(&node->irqqueue, &dev->uac_queue);
279beacf11bSopenharmony_ci  dev->uac_queue_len++;
280beacf11bSopenharmony_ci
281beacf11bSopenharmony_ci  if (atomic_read(&dev->busy_flag))
282beacf11bSopenharmony_ci    {
283beacf11bSopenharmony_ci      goto done;
284beacf11bSopenharmony_ci    }
285beacf11bSopenharmony_ci
286beacf11bSopenharmony_ci  (void)EP_DISABLE(dev->in_ep);
287beacf11bSopenharmony_ci  (void)EP_CONFIGURE(dev->in_ep, (const usb_endpoint_descriptor_t *)&g_fuac_as_in_ep_desc, 0);
288beacf11bSopenharmony_ci
289beacf11bSopenharmony_ci  if (!list_empty(&dev->uac_queue))
290beacf11bSopenharmony_ci    {
291beacf11bSopenharmony_ci      node_tx = list_first_entry(&dev->uac_queue, struct uac_queue_node, irqqueue);
292beacf11bSopenharmony_ci      list_del_init(&node_tx->irqqueue);
293beacf11bSopenharmony_ci      dev->uac_queue_len--;
294beacf11bSopenharmony_ci      dev->cur_node = node_tx;
295beacf11bSopenharmony_ci      uac_send_data_sub(dev);
296beacf11bSopenharmony_ci    }
297beacf11bSopenharmony_ci
298beacf11bSopenharmony_cidone:
299beacf11bSopenharmony_ci  spin_unlock_irqrestore(&dev->lock, flags);
300beacf11bSopenharmony_ci
301beacf11bSopenharmony_cierror:
302beacf11bSopenharmony_ci  mtx_unlock(&usb_mtx);
303beacf11bSopenharmony_ci  return ret;
304beacf11bSopenharmony_ci}
305beacf11bSopenharmony_ci
306beacf11bSopenharmony_ci#ifdef __cplusplus
307beacf11bSopenharmony_ci#if __cplusplus
308beacf11bSopenharmony_ci}
309beacf11bSopenharmony_ci#endif /* __cplusplus */
310beacf11bSopenharmony_ci#endif /* __cplusplus */