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