1beacf11bSopenharmony_ci/* ---------------------------------------------------------------------------- 2beacf11bSopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved. 3beacf11bSopenharmony_ci * Description: LiteOS USB Driver Composite Devices 4beacf11bSopenharmony_ci * Author: Yannik Li 5beacf11bSopenharmony_ci * Create: 2021-02-21 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#include "usb_handle.h" 37beacf11bSopenharmony_ci#include "f_common.h" 38beacf11bSopenharmony_ci 39beacf11bSopenharmony_ci#ifdef __cplusplus 40beacf11bSopenharmony_ci#if __cplusplus 41beacf11bSopenharmony_ci//extern "C" { 42beacf11bSopenharmony_ci#endif /* __cplusplus */ 43beacf11bSopenharmony_ci#endif /* __cplusplus */ 44beacf11bSopenharmony_ci 45beacf11bSopenharmony_cistatic LINUX_LIST_HEAD(g_hanle_list); 46beacf11bSopenharmony_cistatic DEFINE_SPINLOCK(g_hanle_lock); 47beacf11bSopenharmony_cistatic unsigned int devmap = 0; 48beacf11bSopenharmony_ci 49beacf11bSopenharmony_cistatic int alloc_fd_for_handle(void) 50beacf11bSopenharmony_ci{ 51beacf11bSopenharmony_ci int bitsize = 0x8 * sizeof (devmap); 52beacf11bSopenharmony_ci bool found = false; 53beacf11bSopenharmony_ci int i; 54beacf11bSopenharmony_ci 55beacf11bSopenharmony_ci for (i = 1; i < bitsize; i++) 56beacf11bSopenharmony_ci { 57beacf11bSopenharmony_ci if ((devmap & (1 << i)) == 0) 58beacf11bSopenharmony_ci { 59beacf11bSopenharmony_ci devmap |= (1 << i); 60beacf11bSopenharmony_ci found = true; 61beacf11bSopenharmony_ci break; 62beacf11bSopenharmony_ci } 63beacf11bSopenharmony_ci } 64beacf11bSopenharmony_ci return found ? i : -1; 65beacf11bSopenharmony_ci} 66beacf11bSopenharmony_ci 67beacf11bSopenharmony_cistatic int free_fd_for_handle(int fd) 68beacf11bSopenharmony_ci{ 69beacf11bSopenharmony_ci if (fd <= 0 || fd > 31) 70beacf11bSopenharmony_ci { 71beacf11bSopenharmony_ci return -1; 72beacf11bSopenharmony_ci } 73beacf11bSopenharmony_ci devmap &= (~(1 << fd)); 74beacf11bSopenharmony_ci 75beacf11bSopenharmony_ci return 0; 76beacf11bSopenharmony_ci} 77beacf11bSopenharmony_ci 78beacf11bSopenharmony_cistatic struct usb_handle *handle_find_by_name(const char *devName) 79beacf11bSopenharmony_ci{ 80beacf11bSopenharmony_ci struct usb_handle *handle = NULL; 81beacf11bSopenharmony_ci bool found = false; 82beacf11bSopenharmony_ci uint32_t flags; 83beacf11bSopenharmony_ci 84beacf11bSopenharmony_ci if (!devName) 85beacf11bSopenharmony_ci { 86beacf11bSopenharmony_ci return NULL; 87beacf11bSopenharmony_ci } 88beacf11bSopenharmony_ci 89beacf11bSopenharmony_ci spin_lock_irqsave(&g_hanle_lock, flags); 90beacf11bSopenharmony_ci list_for_each_entry(handle, &g_hanle_list, entry) 91beacf11bSopenharmony_ci { 92beacf11bSopenharmony_ci if (strcmp(handle->name, devName) == 0) 93beacf11bSopenharmony_ci { 94beacf11bSopenharmony_ci found = true; 95beacf11bSopenharmony_ci break; 96beacf11bSopenharmony_ci } 97beacf11bSopenharmony_ci } 98beacf11bSopenharmony_ci spin_unlock_irqrestore(&g_hanle_lock, flags); 99beacf11bSopenharmony_ci 100beacf11bSopenharmony_ci return found ? handle : NULL; 101beacf11bSopenharmony_ci} 102beacf11bSopenharmony_ci 103beacf11bSopenharmony_cistatic struct usb_handle *handle_find_by_fd(int fd) 104beacf11bSopenharmony_ci{ 105beacf11bSopenharmony_ci struct usb_handle *handle = NULL; 106beacf11bSopenharmony_ci bool found = false; 107beacf11bSopenharmony_ci uint32_t flags; 108beacf11bSopenharmony_ci 109beacf11bSopenharmony_ci if (fd <= 0) 110beacf11bSopenharmony_ci { 111beacf11bSopenharmony_ci return NULL; 112beacf11bSopenharmony_ci } 113beacf11bSopenharmony_ci 114beacf11bSopenharmony_ci spin_lock_irqsave(&g_hanle_lock, flags); 115beacf11bSopenharmony_ci list_for_each_entry(handle, &g_hanle_list, entry) 116beacf11bSopenharmony_ci { 117beacf11bSopenharmony_ci if (handle->fd == fd) 118beacf11bSopenharmony_ci { 119beacf11bSopenharmony_ci found = true; 120beacf11bSopenharmony_ci break; 121beacf11bSopenharmony_ci } 122beacf11bSopenharmony_ci } 123beacf11bSopenharmony_ci spin_unlock_irqrestore(&g_hanle_lock, flags); 124beacf11bSopenharmony_ci 125beacf11bSopenharmony_ci return found ? handle : NULL; 126beacf11bSopenharmony_ci} 127beacf11bSopenharmony_ci 128beacf11bSopenharmony_ciint register_handle(char *devName, struct UsbHandleOps *ops, void *priv, struct usb_obj *obj) 129beacf11bSopenharmony_ci{ 130beacf11bSopenharmony_ci struct usb_handle *handle = NULL; 131beacf11bSopenharmony_ci uint32_t flags; 132beacf11bSopenharmony_ci 133beacf11bSopenharmony_ci if (devName == NULL || ops == NULL) { 134beacf11bSopenharmony_ci return -1; 135beacf11bSopenharmony_ci } 136beacf11bSopenharmony_ci handle = handle_find_by_name(devName); 137beacf11bSopenharmony_ci if (handle) 138beacf11bSopenharmony_ci { 139beacf11bSopenharmony_ci return -1; 140beacf11bSopenharmony_ci } 141beacf11bSopenharmony_ci handle = (struct usb_handle *)usbm_malloc(obj, sizeof(*handle)); 142beacf11bSopenharmony_ci if (!handle) 143beacf11bSopenharmony_ci { 144beacf11bSopenharmony_ci return -1; 145beacf11bSopenharmony_ci } 146beacf11bSopenharmony_ci handle->name = devName; 147beacf11bSopenharmony_ci handle->fd = -1; 148beacf11bSopenharmony_ci handle->ops = ops; 149beacf11bSopenharmony_ci handle->obj = obj; 150beacf11bSopenharmony_ci handle->priv = priv; 151beacf11bSopenharmony_ci spin_lock_irqsave(&g_hanle_lock, flags); 152beacf11bSopenharmony_ci list_add_tail(&handle->entry, &g_hanle_list); 153beacf11bSopenharmony_ci spin_unlock_irqrestore(&g_hanle_lock, flags); 154beacf11bSopenharmony_ci 155beacf11bSopenharmony_ci return 0; 156beacf11bSopenharmony_ci} 157beacf11bSopenharmony_ci 158beacf11bSopenharmony_ciint unregister_handle(const char *devName) 159beacf11bSopenharmony_ci{ 160beacf11bSopenharmony_ci uint32_t flags; 161beacf11bSopenharmony_ci struct usb_handle *handle = NULL; 162beacf11bSopenharmony_ci 163beacf11bSopenharmony_ci handle = handle_find_by_name(devName); 164beacf11bSopenharmony_ci if (handle == NULL) 165beacf11bSopenharmony_ci { 166beacf11bSopenharmony_ci return -1; 167beacf11bSopenharmony_ci } 168beacf11bSopenharmony_ci spin_lock_irqsave(&g_hanle_lock, flags); 169beacf11bSopenharmony_ci list_del_init(&handle->entry); 170beacf11bSopenharmony_ci spin_unlock_irqrestore(&g_hanle_lock, flags); 171beacf11bSopenharmony_ci usbm_free(handle->obj, handle->name); 172beacf11bSopenharmony_ci usbm_free(handle->obj, handle); 173beacf11bSopenharmony_ci 174beacf11bSopenharmony_ci return 0; 175beacf11bSopenharmony_ci} 176beacf11bSopenharmony_ci 177beacf11bSopenharmony_ciint handle_open(const char *name) 178beacf11bSopenharmony_ci{ 179beacf11bSopenharmony_ci int fd; 180beacf11bSopenharmony_ci struct usb_handle *handle = NULL; 181beacf11bSopenharmony_ci if (name == NULL) 182beacf11bSopenharmony_ci { 183beacf11bSopenharmony_ci return -1; 184beacf11bSopenharmony_ci } 185beacf11bSopenharmony_ci handle = handle_find_by_name(name); 186beacf11bSopenharmony_ci if (handle == NULL) 187beacf11bSopenharmony_ci { 188beacf11bSopenharmony_ci return -1; 189beacf11bSopenharmony_ci } 190beacf11bSopenharmony_ci if (handle->fd > 0) 191beacf11bSopenharmony_ci { 192beacf11bSopenharmony_ci return -1; 193beacf11bSopenharmony_ci } 194beacf11bSopenharmony_ci fd = alloc_fd_for_handle(); 195beacf11bSopenharmony_ci if (fd <= 0) 196beacf11bSopenharmony_ci { 197beacf11bSopenharmony_ci return -1; 198beacf11bSopenharmony_ci } 199beacf11bSopenharmony_ci handle->fd = fd; 200beacf11bSopenharmony_ci if (handle->ops && handle->ops->open) 201beacf11bSopenharmony_ci { 202beacf11bSopenharmony_ci handle->ops->open(handle); 203beacf11bSopenharmony_ci } 204beacf11bSopenharmony_ci return fd; 205beacf11bSopenharmony_ci} 206beacf11bSopenharmony_ci 207beacf11bSopenharmony_ciint handle_close(int fd) 208beacf11bSopenharmony_ci{ 209beacf11bSopenharmony_ci int ret = -1; 210beacf11bSopenharmony_ci struct usb_handle *handle = NULL; 211beacf11bSopenharmony_ci 212beacf11bSopenharmony_ci handle = handle_find_by_fd(fd); 213beacf11bSopenharmony_ci if (handle == NULL) 214beacf11bSopenharmony_ci { 215beacf11bSopenharmony_ci dprintf("%s, can not found hand, fd = %d\n", __func__, fd); 216beacf11bSopenharmony_ci return -1; 217beacf11bSopenharmony_ci } 218beacf11bSopenharmony_ci if (handle->ops && handle->ops->close) 219beacf11bSopenharmony_ci { 220beacf11bSopenharmony_ci ret = handle->ops->close(handle); 221beacf11bSopenharmony_ci if (ret) 222beacf11bSopenharmony_ci { 223beacf11bSopenharmony_ci return ret; 224beacf11bSopenharmony_ci } 225beacf11bSopenharmony_ci } 226beacf11bSopenharmony_ci handle->fd = -1; 227beacf11bSopenharmony_ci free_fd_for_handle(fd); 228beacf11bSopenharmony_ci 229beacf11bSopenharmony_ci return ret; 230beacf11bSopenharmony_ci} 231beacf11bSopenharmony_ci 232beacf11bSopenharmony_ciint handle_read(int fd, void *buffer, size_t len) 233beacf11bSopenharmony_ci{ 234beacf11bSopenharmony_ci int ret = -1; 235beacf11bSopenharmony_ci struct usb_handle *handle = NULL; 236beacf11bSopenharmony_ci 237beacf11bSopenharmony_ci handle = handle_find_by_fd(fd); 238beacf11bSopenharmony_ci if (handle == NULL) 239beacf11bSopenharmony_ci { 240beacf11bSopenharmony_ci dprintf("%s, can not found hand, fd = %d\n", __func__, fd); 241beacf11bSopenharmony_ci return -1; 242beacf11bSopenharmony_ci } 243beacf11bSopenharmony_ci if (handle->ops && handle->ops->read) 244beacf11bSopenharmony_ci { 245beacf11bSopenharmony_ci ret = handle->ops->read(handle, buffer, len); 246beacf11bSopenharmony_ci } 247beacf11bSopenharmony_ci 248beacf11bSopenharmony_ci return ret; 249beacf11bSopenharmony_ci} 250beacf11bSopenharmony_ci 251beacf11bSopenharmony_ciint handle_write(int fd, void *buffer, size_t len) 252beacf11bSopenharmony_ci{ 253beacf11bSopenharmony_ci int ret = -1; 254beacf11bSopenharmony_ci struct usb_handle *handle = NULL; 255beacf11bSopenharmony_ci 256beacf11bSopenharmony_ci handle = handle_find_by_fd(fd); 257beacf11bSopenharmony_ci if (handle == NULL) 258beacf11bSopenharmony_ci { 259beacf11bSopenharmony_ci dprintf("%s, can not found hand, fd = %d\n", __func__, fd); 260beacf11bSopenharmony_ci return -1; 261beacf11bSopenharmony_ci } 262beacf11bSopenharmony_ci if (handle->ops && handle->ops->write) 263beacf11bSopenharmony_ci { 264beacf11bSopenharmony_ci ret = handle->ops->write(handle, buffer, len); 265beacf11bSopenharmony_ci } 266beacf11bSopenharmony_ci 267beacf11bSopenharmony_ci return ret; 268beacf11bSopenharmony_ci} 269beacf11bSopenharmony_ci 270beacf11bSopenharmony_ciint handle_ioctl(int fd, int cmd, void *arg) 271beacf11bSopenharmony_ci{ 272beacf11bSopenharmony_ci int ret = -1; 273beacf11bSopenharmony_ci struct usb_handle *handle = NULL; 274beacf11bSopenharmony_ci 275beacf11bSopenharmony_ci handle = handle_find_by_fd(fd); 276beacf11bSopenharmony_ci if (handle == NULL) 277beacf11bSopenharmony_ci { 278beacf11bSopenharmony_ci dprintf("%s, can not found hand, fd = %d\n", __func__, fd); 279beacf11bSopenharmony_ci return -1; 280beacf11bSopenharmony_ci } 281beacf11bSopenharmony_ci if (handle->ops && handle->ops->ioctl) 282beacf11bSopenharmony_ci { 283beacf11bSopenharmony_ci ret = handle->ops->ioctl(handle, cmd, arg); 284beacf11bSopenharmony_ci } 285beacf11bSopenharmony_ci 286beacf11bSopenharmony_ci return ret; 287beacf11bSopenharmony_ci} 288beacf11bSopenharmony_ci 289beacf11bSopenharmony_civoid *handle_mmap(int fd, uint32_t size) 290beacf11bSopenharmony_ci{ 291beacf11bSopenharmony_ci void *mem = NULL; 292beacf11bSopenharmony_ci struct usb_handle *handle = NULL; 293beacf11bSopenharmony_ci 294beacf11bSopenharmony_ci handle = handle_find_by_fd(fd); 295beacf11bSopenharmony_ci if (handle == NULL) 296beacf11bSopenharmony_ci { 297beacf11bSopenharmony_ci dprintf("%s, can not found hand, fd = %d\n", __func__, fd); 298beacf11bSopenharmony_ci return NULL; 299beacf11bSopenharmony_ci } 300beacf11bSopenharmony_ci if (handle->ops && handle->ops->mmap) 301beacf11bSopenharmony_ci { 302beacf11bSopenharmony_ci mem = handle->ops->mmap(handle, size); 303beacf11bSopenharmony_ci } 304beacf11bSopenharmony_ci 305beacf11bSopenharmony_ci return mem; 306beacf11bSopenharmony_ci} 307beacf11bSopenharmony_ci 308beacf11bSopenharmony_ciint handle_poll(int fd, int timeout) 309beacf11bSopenharmony_ci{ 310beacf11bSopenharmony_ci int ret = -1; 311beacf11bSopenharmony_ci struct usb_handle *handle = NULL; 312beacf11bSopenharmony_ci 313beacf11bSopenharmony_ci handle = handle_find_by_fd(fd); 314beacf11bSopenharmony_ci if (handle == NULL) 315beacf11bSopenharmony_ci { 316beacf11bSopenharmony_ci dprintf("%s, can not found hand, fd = %d\n", __func__, fd); 317beacf11bSopenharmony_ci return -1; 318beacf11bSopenharmony_ci } 319beacf11bSopenharmony_ci if (handle->ops && handle->ops->poll) 320beacf11bSopenharmony_ci { 321beacf11bSopenharmony_ci ret = handle->ops->poll(handle, timeout); 322beacf11bSopenharmony_ci } 323beacf11bSopenharmony_ci 324beacf11bSopenharmony_ci return ret; 325beacf11bSopenharmony_ci} 326beacf11bSopenharmony_ci 327beacf11bSopenharmony_ci#ifdef __cplusplus 328beacf11bSopenharmony_ci#if __cplusplus 329beacf11bSopenharmony_ci//} 330beacf11bSopenharmony_ci#endif /* __cplusplus */ 331beacf11bSopenharmony_ci#endif /* __cplusplus */ 332