• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ----------------------------------------------------------------------------
2  * Copyright (c) Huawei Technologies Co., Ltd. 2016-2019. All rights reserved.
3  * Description: LiteOS USB Driver Generic Function
4  * Author: Yannik Li
5  * Create: 2021-02-04
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 <poll.h>
38 #include "implementation/global_implementation.h"
39 #include "f_common.h"
40 #include "los_vm_iomap.h"
41 
42 #ifdef __cplusplus
43 #if __cplusplus
44 //extern "C" {
45 #endif /* __cplusplus */
46 #endif /* __cplusplus */
47 
48 extern EVENT_CB_S eps_event_all;
49 extern uint32_t eps_event_mask;
50 
51 static void generic_epfile_submit_request(struct generic_epfile *epfile);
52 extern struct usb_memory *generic_find_memory_area(struct usb_obj *obj,
53                                                    const void *buf, size_t len);
54 
generic_epfile_req_sync_complete(struct usbdev_ep_s * ep,struct usbdev_req_s * req)55 static void generic_epfile_req_sync_complete(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
56 {
57   struct generic_epfile *epfile = (struct generic_epfile *)req->priv;
58   int ret;
59 
60   if (ep == NULL || epfile == NULL || req == NULL)
61     {
62       usb_err("Illegal request or ep!\n");
63       return;
64     }
65 
66   ret = LOS_EventWrite(&epfile->sync_event, USB_GENERIC_COMPLETE_EVENT);
67   if (ret != OK)
68     {
69       usb_err("%s: write event failed!\r\n", __FUNCTION__);
70     }
71 }
72 
generic_epfile_submit_sync(struct generic_epfile * epfile,struct IoData * ioData)73 static int generic_epfile_submit_sync(struct generic_epfile *epfile, struct IoData *ioData)
74 {
75   struct usbdev_req_s *req = epfile->ep->req;
76   uint32_t timeout = ioData->timeout > 0 ? ioData->timeout : LOS_WAIT_FOREVER;
77   int ret;
78 
79   if (atomic_read(&epfile->busy_flag) == 1) {
80     usb_err("epfile is busy\n");
81     return -EFAULT;
82   }
83   atomic_set(&epfile->busy_flag, 1);
84   req->priv    = epfile;
85   req->callback = generic_epfile_req_sync_complete;
86   req->len    = ioData->len;
87   req->buf    = (uint8_t *)ioData->buf;
88   req->dma = (DMA_ADDR_T)VMM_TO_UNCACHED_ADDR((unsigned long)req->buf);
89   ret = EP_SUBMIT(epfile->ep->ep, req);
90   if (ret != EOK) {
91     usb_err("EP_SUBMIT failed, ret = %d\n", ret);
92     atomic_set(&epfile->busy_flag, 0);
93     return -EFAULT;
94   }
95   ret = LOS_EventRead(&epfile->sync_event, USB_GENERIC_COMPLETE_EVENT,
96     LOS_WAITMODE_OR | LOS_WAITMODE_CLR, timeout);
97   if (ret == USB_GENERIC_COMPLETE_EVENT) {
98     if (req->result == 0) {
99       ret = req->xfrd;
100     } else {
101       usb_err("ep failed, ret = %d\n", req->result);
102       atomic_set(&epfile->busy_flag, 0);
103       return -EFAULT;
104     }
105   } else {
106     usb_err("read timeout, ret = %d\n", ret);
107     atomic_set(&epfile->busy_flag, 0);
108     return -EFAULT;
109   }
110   atomic_set(&epfile->busy_flag, 0);
111   return ret;
112 }
113 
generic_epfile_do_submit(struct generic_epfile * epfile)114 static void generic_epfile_do_submit(struct generic_epfile *epfile)
115 {
116   struct generic_request *req;
117 
118   if (!list_empty(&epfile->req_list))
119     {
120       req = list_first_entry(&epfile->req_list, struct generic_request, entry);
121       list_del_init(&req->entry);
122       epfile->req_count--;
123       epfile->cur_req = req;
124       generic_epfile_submit_request(epfile);
125     }
126 }
127 
generic_epfile_req_complete(struct usbdev_ep_s * ep,struct usbdev_req_s * req)128 static void generic_epfile_req_complete(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
129 {
130   struct generic_epfile *epfile = (struct generic_epfile *)req->priv;
131   int ret;
132   uint32_t list_flags;
133   if (ep == NULL || epfile == NULL || req == NULL)
134     {
135       usb_err("Illegal request or ep!\n");
136       return;
137     }
138   spin_lock_irqsave(&epfile->list_lock, list_flags);
139   atomic_set(&epfile->busy_flag, 0);
140 
141   if (epfile->cur_req != NULL)
142     {
143       struct generic_request *cur_req = epfile->cur_req;
144       epfile->cur_req = NULL;
145 
146       cur_req->io_data.result = req->result;
147       cur_req->io_data.xfrd   = req->xfrd;
148       cur_req->io_data.buf    = (uint32_t)cur_req->user_buf;
149       list_add_tail(&cur_req->entry, &epfile->comp_list);
150 
151       ret = LOS_EventWrite(&eps_event_all, epfile->event_mask);
152       if (ret != OK)
153         {
154           usb_err("%s: write event failed!\r\n", __FUNCTION__);
155         }
156     }
157   if(req->result == 0)
158     {
159       generic_epfile_do_submit(epfile);
160     }
161   spin_unlock_irqrestore(&epfile->list_lock, list_flags);
162 }
163 
generic_epfile_submit_request(struct generic_epfile * epfile)164 static void generic_epfile_submit_request(struct generic_epfile *epfile)
165 {
166   struct usbdev_req_s *req;
167   int ret;
168 
169   if (epfile->ep == NULL) {
170     goto fail;
171   }
172   req = epfile->ep->req;
173   atomic_set(&epfile->busy_flag, 1);
174 
175   req->priv     = epfile;
176   req->callback = generic_epfile_req_complete;
177   req->len      = epfile->cur_req->io_data.len;
178   req->buf      = (void *)epfile->cur_req->io_data.buf;
179   req->dma = (DMA_ADDR_T)VMM_TO_UNCACHED_ADDR((unsigned long)req->buf);
180 
181   ret = EP_SUBMIT(epfile->ep->ep, req);
182   if (ret != OK)
183     {
184       usb_err("can not send data to host\r\n");
185     }
186   return;
187 fail:
188   struct generic_request *cur_req = epfile->cur_req;
189   epfile->cur_req = NULL;
190   cur_req->io_data.result = -USB_ERR_NO_PIPE;
191   cur_req->io_data.xfrd = 0;
192   cur_req->io_data.buf = (uint32_t)cur_req->user_buf;
193   list_add_tail(&cur_req->entry, &epfile->comp_list);
194   ret = LOS_EventWrite(&eps_event_all, epfile->event_mask);
195   if (ret != OK)
196     {
197       usb_err("%s: write event failed!\r\n", __FUNCTION__);
198     }
199   generic_epfile_do_submit(epfile);
200 }
201 
generic_epfile_cancel_cur_request(struct generic_epfile * epfile)202 static int generic_epfile_cancel_cur_request(struct generic_epfile *epfile)
203 {
204   if (atomic_read(&epfile->busy_flag) == 1)
205     {
206       return EP_CANCEL(epfile->ep->ep, epfile->ep->req);
207     }
208 
209   return -1;
210 }
211 
generic_epfile_cancel_pending_request(struct generic_epfile * epfile,void * buffer)212 static int generic_epfile_cancel_pending_request(struct generic_epfile *epfile,
213                                                  void *buffer)
214 {
215   struct generic_request *req_iter, *tmp;
216   bool found = false;
217   unsigned long flags;
218   int ret;
219 
220   spin_lock_irqsave(&epfile->dev->eps_lock, flags);
221   list_for_each_entry_safe(req_iter, tmp, &epfile->req_list, entry)
222     {
223       if (req_iter->user_buf == buffer)
224         {
225           list_del_init(&req_iter->entry);
226           found = true;
227           break;
228         }
229     }
230   spin_unlock_irqrestore(&epfile->dev->eps_lock, flags);
231 
232   if (!found)
233     {
234       usb_err("%s: can not find the buffer\n", __FUNCTION__);
235       return -1;
236     }
237 
238   req_iter->io_data.result = -USB_ERR_CANCELLED;
239   req_iter->io_data.xfrd            = 0;
240 
241   spin_lock_irqsave(&epfile->dev->eps_lock, flags);
242   list_add_tail(&req_iter->entry, &epfile->comp_list);
243   ret = LOS_EventWrite(&eps_event_all, epfile->event_mask);
244   if (ret != OK)
245     {
246       usb_err("%s: write event failed!\r\n", __FUNCTION__);
247     }
248   generic_epfile_do_submit(epfile);
249   spin_unlock_irqrestore(&epfile->dev->eps_lock, flags);
250 
251   return 0;
252 }
253 
generic_epfile_request_status(struct generic_epfile * epfile,void * buffer)254 static int generic_epfile_request_status(struct generic_epfile *epfile,
255                                                  void *buffer)
256 {
257   struct generic_request *req_iter, *tmp;
258   unsigned long flags;
259 
260   spin_lock_irqsave(&epfile->dev->eps_lock, flags);
261   list_for_each_entry_safe(req_iter, tmp, &epfile->comp_list, entry)
262     {
263       if (req_iter->user_buf == buffer)
264         {
265           spin_unlock_irqrestore(&epfile->dev->eps_lock, flags);
266           return req_iter->io_data.result;
267         }
268     }
269   list_for_each_entry_safe(req_iter, tmp, &epfile->req_list, entry)
270     {
271       if (req_iter->user_buf == buffer)
272         {
273           spin_unlock_irqrestore(&epfile->dev->eps_lock, flags);
274           return USB_ERR_NOT_STARTED;
275         }
276     }
277   spin_unlock_irqrestore(&epfile->dev->eps_lock, flags);
278 
279   return -1;
280 }
281 
generic_epfile_free_memory(struct generic_epfile * epfile)282 static void generic_epfile_free_memory(struct generic_epfile *epfile)
283 {
284   /* free all requests */
285   usbobj_put(&epfile->obj);
286   /* free all memory */
287   usbobj_put(&epfile->memory_obj);
288 }
289 
generic_epfile_handle_open(struct usb_handle * handle)290 static int generic_epfile_handle_open(struct usb_handle *handle)
291 {
292   struct generic_epfile *epfile = (struct generic_epfile *)handle->priv;
293 
294   if (epfile->dev->state != GENERIC_ACTIVE)
295     {
296       usb_err("%s: state is not active\n", __FUNCTION__);
297       return -1;
298     }
299   generic_dev_opened(epfile->dev);
300 
301   return 0;
302 }
303 
generic_epfile_handle_close(struct usb_handle * handle)304 static int generic_epfile_handle_close(struct usb_handle *handle)
305 {
306   struct generic_epfile *epfile = (struct generic_epfile *)handle->priv;
307 
308   if (epfile == NULL)
309     {
310       usb_err("%s: epfile is null\n", __FUNCTION__);
311       return -1;
312     }
313   generic_dev_closed(epfile->dev);
314 
315   return 0;
316 }
317 
generic_epfile_handle_read(struct usb_handle * handle,void * buffer,size_t len)318 static ssize_t generic_epfile_handle_read(struct usb_handle *handle, void *buffer, size_t len)
319 {
320   struct generic_epfile *epfile = (struct generic_epfile *)handle->priv;
321   struct generic_request *req = NULL;
322   uint32_t flags;
323   uint32_t list_flags;
324   int ret;
325   uint32_t copied = 0;
326   struct generic_io_data_ret io_ret;
327 
328   if (epfile == NULL)
329     {
330       usb_err("Invalid parameter!\n");
331       return -1;
332     }
333 
334   if (epfile->dev->state != GENERIC_ACTIVE)
335     {
336       usb_err("%s: state is not active\n", __FUNCTION__);
337       return -1;
338     }
339   spin_lock_irqsave(&epfile->list_lock, list_flags);
340   spin_lock_irqsave(&epfile->dev->eps_lock, flags);
341   (VOID)LOS_EventClear(&eps_event_all, ~epfile->event_mask);
342   while (!list_empty(&epfile->comp_list))
343     {
344       req = list_first_entry(&epfile->comp_list, struct generic_request, entry);
345       io_ret.buf = req->io_data.buf;
346       io_ret.actual = req->io_data.xfrd;
347       io_ret.status = req->io_data.result;
348 
349       ret = memcpy_s((uint8_t *)buffer + copied, sizeof(struct generic_io_data_ret), &io_ret, sizeof(struct generic_io_data_ret));
350       if (ret != EOK) {
351         usb_err("copy failed\n");
352         spin_unlock_irqrestore(&epfile->dev->eps_lock, flags);
353         spin_unlock_irqrestore(&epfile->list_lock, list_flags);
354         return -EFAULT;
355       }
356       list_del_init(&req->entry);
357       copied += sizeof(struct generic_io_data_ret);
358       usbm_free(&epfile->obj, req);
359     }
360   spin_unlock_irqrestore(&epfile->dev->eps_lock, flags);
361   spin_unlock_irqrestore(&epfile->list_lock, list_flags);
362   return copied;
363 }
364 
generic_epfile_handle_write(struct usb_handle * handle,void * buffer,size_t len)365 static ssize_t generic_epfile_handle_write(struct usb_handle *handle, void *buffer, size_t len)
366 {
367   struct generic_epfile *epfile = (struct generic_epfile *)handle->priv;
368   struct usb_memory *usbm;
369   struct generic_request *req;
370   uint32_t flags;
371   uint32_t list_flags;
372   if (epfile == NULL)
373     {
374       usb_err("%s: Invalid parameter!\n", __FUNCTION__);
375       return -1;
376     }
377 
378   if (epfile->dev->state != GENERIC_ACTIVE)
379     {
380       usb_err("%s: state is not active\n", __FUNCTION__);
381       return -1;
382     }
383 
384   usbm = generic_find_memory_area(&epfile->memory_obj, buffer, len);
385   if (usbm == NULL)
386     {
387       return -1;
388     }
389 
390   req = usbm_malloc(&epfile->obj, sizeof(*req));
391   if (req == NULL)
392     {
393       usb_err("%s malloc failed!\n", __FUNCTION__);
394       return -1;
395     }
396   spin_lock_irqsave(&epfile->list_lock, list_flags);
397   INIT_LIST_HEAD(&req->entry);
398   req->io_data.buf = (uint32_t)(buffer);
399   req->io_data.len = len;
400   req->user_buf    = buffer;
401 
402   spin_lock_irqsave(&epfile->dev->eps_lock, flags);
403   list_add_tail(&req->entry, &epfile->req_list);
404   epfile->req_count++;
405   if (!atomic_read(&epfile->busy_flag))
406     {
407       generic_epfile_do_submit(epfile);
408     }
409 
410   spin_unlock_irqrestore(&epfile->dev->eps_lock, flags);
411   spin_unlock_irqrestore(&epfile->list_lock, list_flags);
412   return 0;
413 }
414 
generic_epfile_handle_ioctl(struct usb_handle * handle,int cmd,void * arg)415 static int generic_epfile_handle_ioctl(struct usb_handle *handle, int cmd, void *arg)
416 {
417   struct generic_epfile *epfile = (struct generic_epfile *)handle->priv;
418   void *argp = (void __user *)(uintptr_t)arg;
419   struct usb_memory *usbm;
420   struct generic_memory mem;
421   int ret = -1;
422 
423   switch (cmd)
424     {
425     case GENERIC_CMD_FREE_MEM:
426       ret = memcpy_s(&mem, sizeof(mem), argp, sizeof(mem));
427       if (ret != EOK)
428         {
429           usb_err("copy from user failed\n");
430           return -EFAULT;
431         }
432       usbm = generic_find_memory_area(&epfile->memory_obj, (void *)mem.buf, mem.size);
433       if (usbm == NULL)
434         {
435           break;
436         }
437       usbobj_put(&usbm->obj);
438       LOS_DmaMemFree((void *)usbm->mem);
439       usbm_free(&epfile->memory_obj, usbm);
440       ret = 0;
441       break;
442     case GENERIC_CMD_ENDPOINT_IO:
443       {
444         struct IoData ioData;
445         ret = memcpy_s(&ioData, sizeof(ioData), argp, sizeof(ioData));
446         if (ret != EOK)
447           {
448             usb_err("copy from user failed\n");
449             return -EFAULT;
450           }
451         ret = generic_epfile_submit_sync(epfile, &ioData);
452       }
453       break;
454     case GENERIC_CMD_CANCEL_REQUEST:
455       ret = memcpy_s(&mem, sizeof(mem), argp, sizeof(mem));
456       if (ret != EOK)
457         {
458           usb_err("copy from user failed\n");
459           return -EFAULT;
460         }
461       if ((epfile->cur_req != NULL) && \
462         (epfile->cur_req->user_buf == (void *)mem.buf))
463         {
464           ret = generic_epfile_cancel_cur_request(epfile);
465         }
466       else
467         {
468           ret = generic_epfile_cancel_pending_request(epfile, (void *)mem.buf);
469         }
470       break;
471     case GENERIC_CMD_GET_REQ_STATUS:
472       {
473         struct IoData ioData;
474         int ret;
475         ret = memcpy_s(&ioData, sizeof(ioData), argp, sizeof(ioData));
476         if (ret != EOK)
477           {
478             usb_err("copy from user failed\n");
479             return -EFAULT;
480           }
481         ret = generic_epfile_request_status(epfile, (void *)ioData.buf);
482       }
483       break;
484     case GENERIC_CMD_GET_PIPE_INFO:
485       {
486         int desc_idx;
487         struct generic_dev_s *dev = epfile->dev;
488         int ep_index = 0;
489         usb_endpoint_descriptor_t *desc;
490 
491         switch (epfile->dev->speed)
492           {
493           case USB_SPEED_SUPER:
494             desc_idx = 2;
495             break;
496           case USB_SPEED_HIGH:
497             desc_idx = 1;
498             break;
499           default:
500             desc_idx = 1;
501           }
502         ep_index = atoi(epfile->name + 2);
503         if (ep_index < 1 || ep_index > dev->eps_count)
504           {
505             usb_err("invail ep_index = %d\n", ep_index);
506             return -EFAULT;
507           }
508         desc = dev->eps_descs[ep_index - 1][desc_idx];
509         ret = memcpy_s(arg, sizeof(*desc), desc, sizeof(*desc));
510         if (ret != EOK)
511           {
512             usb_err("copy from user failed\n");
513             return -EFAULT;
514           }
515         return ret;
516       }
517       break;
518     default:
519       usb_err("%s: the cmd %d is not supporten", __FUNCTION__);
520       break;
521     }
522 
523   return ret;
524 }
525 
generic_epfile_handle_mmap(struct usb_handle * handle,uint32_t size)526 static void *generic_epfile_handle_mmap(struct usb_handle *handle, uint32_t size)
527 {
528   struct generic_epfile *epfile = (struct generic_epfile *)handle->priv;
529   struct usb_memory *usbm;
530   void *mem;
531 
532   if (epfile == NULL)
533     {
534       usb_err("Invalid private parameter!\n");
535       return NULL;
536     }
537 
538   usbm = usbm_malloc(&epfile->memory_obj, sizeof(*usbm) + size);
539   if (usbm == NULL)
540     {
541       usb_err("%s alloc memory failed!\n", __FUNCTION__);
542       return NULL;
543     }
544   usbobj_init(&usbm->obj, epfile->name, usbobj_default_release);
545   DMA_ADDR_T paddr;
546   mem = LOS_DmaMemAlloc(&paddr, size, USB_CACHE_ALIGN_SIZE, DMA_NOCACHE);
547   usbm->mem      = (unsigned long)mem;
548   usbm->size     = size;
549   usbm->vm_start = (unsigned long)mem;
550 
551   usbobj_add(&usbm->obj, &epfile->memory_obj);
552   return mem;
553 }
554 
generic_epfile_handle_poll(struct usb_handle * handle,int timeout)555 static int generic_epfile_handle_poll(struct usb_handle *handle, int timeout)
556 {
557   struct generic_epfile *epfile = (struct generic_epfile *)handle->priv;
558   uint32_t revents = POLLRDNORM;
559   uint32_t ret;
560   uint32_t value = POLLIN;
561 
562   if (epfile == NULL)
563     {
564       usb_err("Invalid parameter!\n");
565       return POLLERR;
566     }
567 
568   if (value)
569     {
570       ret = LOS_EventRead(&eps_event_all, eps_event_mask,
571                           LOS_WAITMODE_OR, timeout > 0 ? timeout:LOS_WAIT_FOREVER);
572       if (ret & epfile->event_mask)
573         {
574           revents |= value;
575         }
576     }
577 
578   return (int)revents;
579 }
580 
581 static struct UsbHandleOps generic_epfile_handle_ops = {
582   .open   = generic_epfile_handle_open,
583   .close  = generic_epfile_handle_close,
584   .read   = generic_epfile_handle_read,
585   .write  = generic_epfile_handle_write,
586   .ioctl  = generic_epfile_handle_ioctl,
587   .mmap   = generic_epfile_handle_mmap,
588   .poll   = generic_epfile_handle_poll,
589 };
590 
generic_epfile_release(struct usb_obj * obj)591 void generic_epfile_release(struct usb_obj *obj)
592 {
593   struct generic_epfile *epfile;
594   char dev_name[GENERIC_PATH_LEN];
595 
596   epfile = container_of(obj, struct generic_epfile, obj);
597   if (epfile->is_created)
598     {
599       (void)snprintf_s(dev_name, sizeof(dev_name), sizeof(dev_name) - 1,
600                        "/dev/%s/%s", epfile->dev->name, epfile->name);
601       (void)unregister_handle(dev_name);
602     }
603   generic_epfile_free_memory(epfile);
604   usbm_free(&epfile->dev->obj, epfile);
605 }
606 
generic_remove_epfiles(struct generic_dev_s * dev)607 int  generic_remove_epfiles(struct generic_dev_s *dev)
608 {
609   char epfile_name[5] = {0};
610   unsigned i, count;
611   struct usb_obj *obj;
612 
613   count = dev->eps_count;
614   for (i = 1; i <= count; ++i)
615     {
616       sprintf(epfile_name, "ep%u", i);
617       obj = usbobj_find(&dev->epfiles_obj, usbobj_default_match, epfile_name);
618       if (!obj)
619         {
620           dprintf("%s, usbobj_find %s obj failed\n", __func__, epfile_name);
621           return -1;
622         }
623       usbobj_put(obj);
624     }
625   return 0;
626 }
627 
generic_epfiles_create(struct generic_dev_s * dev)628 int generic_epfiles_create(struct generic_dev_s *dev)
629 {
630   struct generic_epfile *epfile;
631   char *dev_name = NULL;
632   unsigned i, count, ret;
633 
634   count = dev->eps_count;
635   for (i = 1; i <= count; ++i)
636     {
637       epfile = usbm_zalloc(&dev->obj, sizeof(*epfile));
638       if (!epfile)
639         {
640           return -ENOMEM;
641         }
642       dev_name = usbm_zalloc(&dev->obj, GENERIC_PATH_LEN);
643       if (!dev_name)
644         {
645           usbm_free(&dev->obj, epfile);
646           return -ENOMEM;
647         }
648       epfile->dev = dev;
649       sprintf(epfile->name, "ep%u", i);
650       mtx_init(&epfile->mutex, epfile->name, NULL, 0);
651       INIT_LIST_HEAD(&epfile->req_list);
652       INIT_LIST_HEAD(&epfile->comp_list);
653       spin_lock_init(&epfile->list_lock);
654       usbobj_init(&epfile->obj, epfile->name, generic_epfile_release);
655       usbobj_init(&epfile->memory_obj, epfile->name, NULL);
656 
657       ret = snprintf_s(dev_name, GENERIC_PATH_LEN, GENERIC_PATH_LEN - 1,
658                        "/dev/%s/%s", dev->name, epfile->name);
659       if (ret < 0)
660         {
661           usb_err("make directory path error! ret = %d, errono = %d\n",
662                   ret, get_errno());
663           usbobj_put(&dev->epfiles_obj);
664           return ret;
665         }
666       ret = register_handle(dev_name, &generic_epfile_handle_ops, epfile, &dev->obj);
667       if (ret != 0)
668         {
669           usb_err("chardev register failed!");
670           usbobj_put(&dev->epfiles_obj);
671           return ret;
672         }
673       epfile->is_created = true;
674       uint32_t mask = 1 << (dev->minor_offset * EVENT_FOR_FUNCTION + 1 + i);
675       eps_event_mask |= mask;
676       epfile->event_mask = mask;
677       (VOID)LOS_EventInit(&epfile->sync_event);
678       usbobj_add(&epfile->obj, &dev->epfiles_obj);
679     }
680 
681   return 0;
682 }
683 
generic_eps_disable(struct generic_dev_s * dev)684 void generic_eps_disable(struct generic_dev_s *dev)
685 {
686   struct generic_ep *ep = dev->eps;
687   uint32_t count = dev->eps_count;
688   struct generic_epfile *epfile;
689   unsigned long flags;
690 
691   spin_lock_irqsave(&dev->eps_lock, flags);
692   while (count--)
693     {
694       if (ep->ep)
695         {
696           EP_DISABLE(ep->ep);
697         }
698 
699       if (ep->priv)
700         {
701           epfile = ep->priv;
702           epfile->ep = NULL;
703           ep->priv   = NULL;
704         }
705       ++ep;
706     }
707   dev->eps_enbale = false;
708   spin_unlock_irqrestore(&dev->eps_lock, flags);
709 }
710 
epfile_match_unused(struct usb_obj * obj,void * match_data)711 static int epfile_match_unused(struct usb_obj *obj, void *match_data)
712 {
713   struct generic_epfile *epfile = container_of(obj, struct generic_epfile, obj);
714 
715   return epfile->ep == NULL;
716 }
717 
generic_eps_enable(struct generic_dev_s * dev)718 int generic_eps_enable(struct generic_dev_s *dev)
719 {
720   struct generic_ep *ep         = dev->eps;
721   uint32_t count                = dev->eps_count;
722   struct generic_epfile *epfile;
723   struct usb_obj *obj;
724   unsigned long flags;
725   int ret = 0;
726 
727   dprintf("%s, dev->eps_count = %d \n",__func__, dev->eps_count);
728 
729   spin_lock_irqsave(&dev->eps_lock, flags);
730   while (count--)
731     {
732       usb_endpoint_descriptor_t *desc;
733       /* find a unused epfile and bind to a endpoint */
734       obj = usbobj_find(&dev->epfiles_obj, epfile_match_unused, NULL);
735       if (obj == NULL)
736         {
737           usb_err("can't find a unused epfile\n");
738           break;
739         }
740       ep->ep->priv = ep;
741       EP_DISABLE(ep->ep);
742       switch (dev->speed)
743         {
744         case USB_SPEED_SUPER:
745           desc = ep->descs[2];
746           break;
747         case USB_SPEED_HIGH:
748           desc = ep->descs[1];
749           break;
750         default:
751           desc = ep->descs[1];
752           break;
753         }
754       ret = EP_CONFIGURE(ep->ep, desc, 0);
755       if (ret < 0)
756         {
757           usb_err("Config ep%d failed!\n", ep->num);
758           break;
759         }
760 
761       epfile = container_of(obj, struct generic_epfile, obj);
762       ep->priv     = epfile;
763       epfile->ep   = ep;
764       epfile->in   = USB_ISEPIN(desc->bEndpointAddress);
765       epfile->isoc = ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
766                      USB_ENDPOINT_XFER_ISOC);
767       ++ep;
768     }
769   dev->eps_enbale = true;
770   spin_unlock_irqrestore(&dev->eps_lock, flags);
771 
772   return ret;
773 }
774 
775 #ifdef __cplusplus
776 #if __cplusplus
777 //}
778 #endif /* __cplusplus */
779 #endif /* __cplusplus */
780