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