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 */