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