1 /* ----------------------------------------------------------------------------
2 * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
3 * Description: LiteOS USB Driver Video Stream
4 * Author: huangjieliang
5 * Create: 2017-04-17
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 <los_mux.h>
38 #include "gadget/f_uvc.h"
39 #include "implementation/global_implementation.h"
40 #ifdef LOSCFG_DRIVERS_USB2_DEVICE_CONTROLLER
41 #include "controller/usb_device/dwc_otgreg.h"
42 #include "controller/usb_device/dwc_otg_pcd.h"
43 #endif
44 #ifdef LOSCFG_DRIVERS_USB3_DEVICE_CONTROLLER
45 #include "controller/usb_device/pcd.h"
46 #endif
47
48 #ifdef __cplusplus
49 #if __cplusplus
50 extern "C" {
51 #endif /* __cplusplus */
52 #endif /* __cplusplus */
53
54 /*
55 * module local variables
56 */
57
58 uint32_t g_uvc_mutex = UVC_INVALID_HANDLE;
59
60 /* private pointer to the UVC handle structure */
61
62 static struct uvc_handle *volatile g_uvc = (struct uvc_handle *)UVC_INVALID_HANDLE;
63
64 /* private pointer to the F_UVC structure */
65
66 struct uvc_dev_s *volatile g_f_uvc = (struct uvc_dev_s *)UVC_INVALID_HANDLE;
67
68 static int uvc_copy_continue(struct uvc_handle *uvc, struct uvc_isoc_transfer *tran);
69 static int uvc_nocp_continue(struct uvc_handle *uvc, struct uvc_isoc_transfer *tran);
70
uvc_release_mutex(void)71 static void uvc_release_mutex(void)
72 {
73 uint32_t ret;
74 ret = LOS_MuxPost(g_uvc_mutex);
75 if (ret != LOS_OK)
76 {
77 usb_err("Failed to unlock mutex: %#x\n", ret);
78 }
79 }
80
uvc_delete_mutex(void)81 void uvc_delete_mutex(void)
82 {
83 (void)LOS_MuxDelete(g_uvc_mutex);
84 g_uvc_mutex = UVC_INVALID_HANDLE;
85 }
86
uvc_is_running(void)87 bool uvc_is_running(void)
88 {
89 return (g_uvc == (struct uvc_handle *)UVC_INVALID_HANDLE) ? false : true;
90 }
91
92 /*
93 * Check the UVC handle provided by external source
94 */
95
uvc_check_handle(uvc_t hdl)96 static int uvc_check_handle(uvc_t hdl)
97 {
98 uint32_t ret;
99 struct uvc_handle *uvc;
100
101 /* catch NULL pointer */
102
103 if (hdl == NULL)
104 {
105 return UVC_ERROR_PTR;
106 }
107
108 ret = LOS_MuxPend(g_uvc_mutex, LOS_WAIT_FOREVER);
109 if (ret != LOS_OK)
110 {
111 usb_err("Failed to acquire UVC mutex: %#x, %p\n", ret, __builtin_return_address(0));
112 return UVC_ERROR_VALUE;
113 }
114
115 /* check whether the provided handle matches the one privated stored */
116
117 uvc = g_uvc;
118 if (uvc == (struct uvc_handle *)UVC_INVALID_HANDLE ||
119 hdl != (uvc_t)uvc)
120 {
121 uvc_release_mutex();
122 return UVC_ERROR_HANDLE;
123 }
124
125 return UVC_OK;
126 }
127
uvc_format_status_check(void)128 enum format_switch_status uvc_format_status_check(void)
129 {
130 struct uvc_dev_s *fuvc = g_f_uvc;
131
132 if (fuvc == (struct uvc_dev_s *)UVC_INVALID_HANDLE)
133 {
134 usb_err("uvc is not initialization\n");
135 return FORMAT_SWITCH_FINISH;
136 }
137
138 return (enum format_switch_status)fuvc->format_info.status;
139 }
140
uvc_format_info_get(struct uvc_format_info * info)141 int uvc_format_info_get(struct uvc_format_info *info)
142 {
143 struct uvc_format_info *format_info;
144 struct uvc_dev_s *fuvc = g_f_uvc;
145
146 if (info == NULL)
147 {
148 usb_err("the info is NULL\n");
149 return UVC_ERROR_PTR;
150 }
151
152 if (fuvc == (struct uvc_dev_s *)UVC_INVALID_HANDLE)
153 {
154 usb_err("uvc is not initialization\n");
155 return UVC_ERROR_PTR;
156 }
157
158 format_info = &fuvc->format_info;
159 if (format_info->status == FORMAT_SWITCH_PENDING)
160 {
161 if (format_info->format != V4L2_PIX_FMT_YUYV &&
162 format_info->format != V4L2_PIX_FMT_H264 &&
163 format_info->format != V4L2_PIX_FMT_MJPEG)
164 {
165 return UVC_ERROR_NOMATCH;
166 }
167
168 info->height = format_info->height;
169 info->width = format_info->width;
170 info->format = format_info->format;
171
172 fuvc->format_info.status = FORMAT_SWITCH_FINISH;
173
174 return UVC_OK;
175 }
176 else
177 {
178 usb_err("the uvc format status is not update\n");
179 return UVC_ERROR_NOMATCH;
180 }
181 }
182
uvc_wait_host_sub(uvc_t hdl,int * connected)183 static int uvc_wait_host_sub(uvc_t hdl, int *connected)
184 {
185 int ret;
186 struct uvc_handle *uvc;
187 struct uvc_dev_s *fuvc;
188
189 ret = uvc_check_handle(hdl);
190 if (ret != UVC_OK)
191 {
192 return ret;
193 }
194 uvc = (struct uvc_handle *)hdl;
195
196 fuvc = uvc->fuvc;
197 if (fuvc == NULL || fuvc != g_f_uvc)
198 {
199 uvc_release_mutex();
200 return UVC_ERROR_PTR;
201 }
202
203 if ((*connected = fuvc_host_connected(fuvc)) != 0)
204 {
205 if (uvc->state == UVC_STATE_IDLE)
206 {
207 uvc->state = UVC_STATE_CONN;
208 }
209 }
210
211 uvc_release_mutex();
212 return ret;
213 }
214
uvc_wait_host(uvc_t hdl,int wait_option,int * connected)215 int uvc_wait_host(uvc_t hdl, int wait_option, int *connected)
216 {
217 int ret;
218
219 if (connected == NULL)
220 {
221 return UVC_ERROR_PTR;
222 }
223
224 switch (wait_option)
225 {
226 case UVC_WAIT_HOST_NOP:
227 ret = uvc_wait_host_sub(hdl, connected);
228 break;
229
230 case UVC_WAIT_HOST_FOREVER:
231 while (1)
232 {
233 ret = uvc_wait_host_sub(hdl, connected);
234 if (ret != UVC_OK || *connected)
235 {
236 break;
237 }
238 (void) LOS_TaskDelay(10);
239 }
240 break;
241
242 default:
243 ret = UVC_ERROR_VALUE;
244 }
245
246 return ret;
247 }
248
uvc_open_device(uvc_t * hdl,struct uvc_open_param * param)249 int uvc_open_device(uvc_t *hdl, struct uvc_open_param *param)
250 {
251 uint32_t rval;
252 struct uvc_handle *uvc;
253 struct uvc_dev_s *fuvc;
254
255 /* NULL pointers are not allowed */
256
257 if (hdl == NULL || param == NULL)
258 {
259 return UVC_ERROR_PTR;
260 }
261
262 /* check the function input video parameter */
263
264 if (param->vid_width <= 0x1 || param->vid_width > UVC_VIDEO_WIDTH_MAX)
265 {
266 return UVC_ERROR_VALUE;
267 }
268 if (param->vid_height <= 0x1 || param->vid_height > UVC_VIDEO_HEIGHT_MAX)
269 {
270 return UVC_ERROR_VALUE;
271 }
272 if (param->vid_format != UVC_VFF_YUY2 &&
273 param->vid_format != UVC_VFF_H264 &&
274 param->vid_format != UVC_VFF_MJPG)
275 {
276 return UVC_ERROR_VALUE;
277 }
278
279 rval = LOS_MuxPend(g_uvc_mutex, LOS_WAIT_FOREVER);
280 if (rval != LOS_OK)
281 {
282 usb_err("Failed to lock UVC mutex: %#x\n", rval);
283 return UVC_ERROR_VALUE;
284 }
285
286 uvc = g_uvc;
287 if (uvc != (struct uvc_handle *)UVC_INVALID_HANDLE)
288 {
289 uvc_release_mutex();
290 return UVC_ERROR_HANDLE; /* already opened */
291 }
292
293 /* check whether F_UVC module has been initialized */
294
295 fuvc = g_f_uvc;
296 if (fuvc == (struct uvc_dev_s *)UVC_INVALID_HANDLE)
297 {
298 uvc_release_mutex();
299 return UVC_ERROR_VALUE;
300 }
301
302 /* allocate memory for uvc_handle structure */
303
304 uvc = calloc(0x1, sizeof(struct uvc_handle));
305 if (uvc == NULL)
306 {
307 uvc_release_mutex();
308 return UVC_ERROR_MEMORY;
309 }
310
311 /* initialize the UVC handle */
312
313 uvc->vid_w = param->vid_width;
314 uvc->vid_h = param->vid_height;
315 uvc->vid_f = param->vid_format;
316 uvc->state = UVC_STATE_IDLE;
317 uvc->fuvc = fuvc;
318 fuvc->uvc_handle = (void *)uvc;
319
320 fuvc->bulk_size = param->bulk_size;
321 fuvc->imgsize = param->imgsize;
322
323 /* store a private copy of UVC handle */
324
325 g_uvc = uvc;
326
327 /* return the UVC handle */
328
329 *hdl = (uvc_t)uvc;
330 uvc_release_mutex();
331 return UVC_OK;
332 }
333
334 /*
335 * local function to stop video stream transmission process
336 * return error only when a transmission cannot be stopped
337 */
338
uvc_video_tran_stop(struct uvc_handle * uvc)339 static int uvc_video_tran_stop(struct uvc_handle *uvc)
340 {
341 switch (uvc->state)
342 {
343 case UVC_STATE_TRAN_COPY:
344 uvc->copy_func = NULL;
345 break;
346
347 case UVC_STATE_TRAN_NOCP:
348 uvc->next_func = NULL;
349 break;
350
351 default:
352 return UVC_OK;
353 }
354
355 uvc->_priv = NULL;
356
357 /* update UVC handle state */
358
359 if (uvc->fuvc != NULL)
360 {
361 uvc->state = fuvc_host_connected(uvc->fuvc) ? UVC_STATE_CONN : UVC_STATE_IDLE;
362 }
363 else
364 {
365 uvc->state = UVC_STATE_IDLE;
366 }
367 return UVC_OK;
368 }
369
uvc_video_stop(uvc_t hdl)370 int uvc_video_stop(uvc_t hdl)
371 {
372 int ret;
373
374 ret = uvc_check_handle(hdl);
375 if (ret != UVC_OK)
376 {
377 return ret;
378 }
379
380 ret = uvc_video_tran_stop((struct uvc_handle *)hdl);
381 uvc_release_mutex();
382 return ret;
383 }
384
uvc_close_device(uvc_t hdl)385 int uvc_close_device(uvc_t hdl)
386 {
387 int ret;
388 struct uvc_handle *uvc;
389 struct uvc_dev_s *fuvc;
390 uint32_t flags;
391
392 ret = uvc_check_handle(hdl);
393 if (ret != UVC_OK)
394 {
395 return ret;
396 }
397 uvc = (struct uvc_handle *)hdl;
398
399 /* stop Video transmission first */
400
401 if (uvc->state == UVC_STATE_TRAN_COPY ||
402 uvc->state == UVC_STATE_TRAN_NOCP)
403 {
404 (void)uvc_video_tran_stop(uvc);
405 }
406
407 fuvc = uvc->fuvc;
408 if (fuvc == NULL)
409 {
410 uvc_release_mutex();
411 return UVC_ERROR_PTR;
412 }
413 spin_lock_irqsave(&fuvc->lock, flags);
414 fuvc->uvc_handle = (void *)UVC_INVALID_HANDLE;
415
416 /* set the global handle to NULL, and free the handle structure */
417
418 g_uvc = (struct uvc_handle *)UVC_INVALID_HANDLE;
419 uvc->fuvc = NULL;
420 spin_unlock_irqrestore(&fuvc->lock, flags);
421 free(uvc);
422 uvc_release_mutex();
423 return UVC_OK;
424 }
425
uvc_get_state(uvc_t hdl,uint32_t * state)426 int uvc_get_state(uvc_t hdl, uint32_t *state)
427 {
428 int ret;
429 struct uvc_handle *uvc;
430
431 /* validate function parameters */
432
433 if (state == NULL)
434 {
435 return UVC_ERROR_PTR;
436 }
437
438 ret = uvc_check_handle(hdl);
439 if (ret != UVC_OK)
440 {
441 return ret;
442 }
443
444 uvc = (struct uvc_handle *)hdl;
445 if (uvc->state == UVC_STATE_IDLE && uvc->fuvc &&
446 fuvc_host_connected(uvc->fuvc))
447 {
448 uvc->state = UVC_STATE_CONN;
449 }
450
451 *state = uvc->state;
452 uvc_release_mutex();
453 return UVC_OK;
454 }
455
uvc_video_tran_nocp(uvc_t hdl,uvc_continue_func next_func,void * priv)456 int uvc_video_tran_nocp(uvc_t hdl, uvc_continue_func next_func, void *priv)
457 {
458 int ret;
459 struct uvc_handle *uvc;
460 struct nocp_reserve *res;
461
462 /* function reference & private pointer should not be NULL */
463
464 if (next_func == NULL || priv == NULL)
465 {
466 return UVC_ERROR_PTR;
467 }
468
469 ret = uvc_check_handle(hdl);
470 if (ret != UVC_OK)
471 {
472 return ret;
473 }
474 uvc = (struct uvc_handle *)hdl;
475
476 if (uvc->fuvc == NULL)
477 {
478 uvc_release_mutex();
479 return UVC_ERROR_PTR;
480 }
481
482 if (uvc->state != UVC_STATE_CONN)
483 {
484 uvc_release_mutex();
485 return UVC_ERROR_NOMATCH;
486 }
487
488 /* initialize related UVC handle field members */
489
490 uvc->frame_off = 0;
491 uvc->tdata.data = NULL;
492 uvc->tdata.length = 0;
493 uvc->tdata.last = 0;
494
495 /* store callback function and parameter */
496
497 uvc->copy_func = NULL;
498 uvc->next_func = next_func;
499 uvc->_priv = priv;
500
501 /* initialize reserve structure */
502
503 res = &(uvc->reserve);
504 res->res = NULL;
505 res->resl = 0;
506
507 /* get the first frame of video data */
508
509 ret = next_func(hdl, &(uvc->tdata), priv);
510 if (ret != UVC_OK)
511 {
512 uvc_release_mutex();
513 return ret;
514 }
515
516 uvc->state = UVC_STATE_TRAN_NOCP;
517 ret = fuvc_transfer_initiate(uvc->fuvc);
518 if (ret != UVC_OK)
519 {
520 uvc->state = UVC_STATE_ERR;
521 uvc_release_mutex();
522 return ret;
523 }
524 uvc_release_mutex();
525 return UVC_OK;
526 }
527
uvc_video_tran_copy(uvc_t hdl,uvc_continue_func copy_func,void * priv)528 int uvc_video_tran_copy(uvc_t hdl, uvc_continue_func copy_func, void *priv)
529 {
530 int ret;
531 struct uvc_handle *uvc;
532 struct uvc_dev_s *fuvc;
533
534 if (copy_func == NULL || priv == NULL)
535 {
536 return UVC_ERROR_PTR;
537 }
538
539 ret = uvc_check_handle(hdl);
540 if (ret != UVC_OK)
541 {
542 return ret;
543 }
544
545 uvc = (struct uvc_handle *)hdl;
546 if (uvc->fuvc == NULL)
547 {
548 uvc_release_mutex();
549 return UVC_ERROR_PTR;
550 }
551
552 fuvc = uvc->fuvc;
553
554 if (g_start_transfer == 0)
555 {
556 fuvc->connected = 0;
557 uvc_release_mutex();
558 usb_err("uvc can not start transfer!\n");
559 return UVC_ERROR_PTR;
560 }
561
562 /* check whether UVC state matches */
563
564 if (uvc->state != UVC_STATE_CONN)
565 {
566 uvc_release_mutex();
567 return UVC_ERROR_NOMATCH;
568 }
569
570 /* initialize related UVC handle field members */
571
572 uvc->frame_off = 0;
573 uvc->tdata.data = NULL;
574 uvc->tdata.length = 0;
575 uvc->tdata.last = 0;
576
577 /* set the callback function and parameter */
578
579 uvc->next_func = NULL;
580 uvc->copy_func = copy_func;
581
582 if (fuvc->transfer_status == STREAM_OFF)
583 {
584 uvc_release_mutex();
585 usb_err("uvc transfer status is stream off!\n");
586 return UVC_ERROR_PTR;
587 }
588
589 uvc->_priv = priv;
590
591 /* update UVC handle state */
592
593 uvc->state = UVC_STATE_TRAN_COPY;
594 ret = fuvc_transfer_initiate(uvc->fuvc);
595 if (ret != UVC_OK)
596 {
597 uvc->state = UVC_STATE_ERR;
598 uvc_release_mutex();
599 return ret;
600 }
601 uvc_release_mutex();
602
603 ret = LOS_EventRead(&g_uvc_event, 0x01, LOS_WAITMODE_OR |
604 LOS_WAITMODE_CLR, 100);
605 if (ret == LOS_ERRNO_EVENT_READ_TIMEOUT)
606 {
607 usb_err("Transfer timeout!\n");
608 ret = uvc_check_handle(hdl);
609 if (ret)
610 {
611 return ret;
612 }
613 usbclass_uvc_stream_ep_reset(fuvc);
614 uvc_release_mutex();
615 return UVC_ERROR_VALUE;
616 }
617
618 return UVC_OK;
619 }
620
uvc_continue_transfer(struct uvc_dev_s * fuvc,struct uvc_isoc_transfer * tran)621 int uvc_continue_transfer(struct uvc_dev_s *fuvc, struct uvc_isoc_transfer *tran)
622 {
623 struct uvc_handle *uvc;
624 uint32_t flags;
625 int ret = UVC_ERROR_PTR;
626
627 spin_lock_irqsave(&fuvc->lock, flags);
628 uvc = (struct uvc_handle *)fuvc->uvc_handle;
629 if (uvc == (struct uvc_handle *)UVC_INVALID_HANDLE)
630 {
631 goto done;
632 }
633
634 if (uvc->copy_func)
635 {
636 ret = uvc_copy_continue(uvc, tran);
637 goto done;
638 }
639 if (uvc->next_func)
640 {
641 ret = uvc_nocp_continue(uvc, tran);
642 }
643
644 done:
645 spin_unlock_irqrestore(&fuvc->lock, flags);
646 return ret;
647 }
648
uvc_nocp_continue(struct uvc_handle * uvc,struct uvc_isoc_transfer * tran)649 static int uvc_nocp_continue(struct uvc_handle *uvc, struct uvc_isoc_transfer *tran)
650 {
651 uvc_continue_func next_func;
652 struct nocp_reserve *reserve;
653 struct uvc_transfer_data *transfer;
654 uint32_t length, offset, res;
655
656 /* initialize local variables */
657
658 length = tran->length;
659 offset = uvc->frame_off;
660 transfer = &(uvc->tdata);
661 reserve = &(uvc->reserve);
662
663 /* restore the reserved data */
664
665 if (reserve->res != NULL)
666 {
667 uint32_t i, j;
668 j = (reserve->resl > NOCP_RESERVE_MAX) ? NOCP_RESERVE_MAX : reserve->resl;
669 for (i = 0; i < j; ++i)
670 {
671 reserve->res[i] = reserve->res_buf[i];
672 }
673 }
674
675 /* determine how where the transfer should start */
676
677 if (transfer->data == NULL)
678 {
679 return UVC_ERROR_PTR;
680 }
681
682 tran->data = &(transfer->data[offset]);
683 res = tran->reserved;
684 if (offset < res)
685 {
686 res = 0;
687 tran->reserved = 0;
688
689 /* do not reserve */
690
691 reserve->res = NULL;
692 reserve->resl = res;
693 }
694 else
695 {
696 uint32_t i, j;
697 uint8_t *p;
698
699 j = (res > NOCP_RESERVE_MAX) ? NOCP_RESERVE_MAX : res;
700 p = tran->data - j;
701
702 for (i = 0; i < j; ++i)
703 {
704 reserve->res_buf[i] = p[i];
705 }
706 reserve->resl = j;
707 reserve->res = p;
708 }
709
710 /* determine whether reached the frame end */
711
712 if ((offset + length) >= transfer->length)
713 {
714 tran->length = transfer->length - offset;
715 transfer->data = NULL;
716
717 /* get the next frame of video data */
718
719 if ((next_func = uvc->next_func) != NULL)
720 {
721 int ret;
722 ret = next_func(uvc, transfer, uvc->_priv);
723 if (ret != UVC_OK)
724 {
725 dprintf("next_func %p returned: %d\n", next_func, ret);
726 }
727 }
728 offset = 0;
729 tran->last = 1;
730 }
731 else
732 {
733 uintptr_t ptr;
734
735 ptr = (uintptr_t)tran->data;
736 ptr -= tran->res_next;
737
738 /* make sure that next transimission buffer aligns at 4-byte boundary */
739
740 if ((ptr + length) & 0x3)
741 {
742 while ((ptr + length) & 0x3)
743 {
744 if (length == 0)
745 {
746 break;
747 }
748 length--;
749 }
750 tran->length = length;
751 }
752
753 /* increment frame offset */
754
755 offset += length;
756 tran->last = 0;
757 }
758
759 /* write back computed values */
760
761 uvc->frame_off = offset;
762 return UVC_OK;
763 }
764
uvc_copy_continue(struct uvc_handle * uvc,struct uvc_isoc_transfer * tran)765 static int uvc_copy_continue(struct uvc_handle *uvc, struct uvc_isoc_transfer *tran)
766 {
767 int ret;
768 uint32_t cplen;
769 uvc_continue_func copy;
770 struct uvc_transfer_data *frame;
771
772 copy = uvc->copy_func;
773 if (copy == NULL)
774 {
775 return UVC_ERROR_PTR;
776 }
777
778 frame = &(uvc->tdata);
779 frame->data = tran->data;
780 frame->length = tran->length;
781 frame->last = 0;
782 cplen = tran->length;
783
784 ret = copy(uvc, frame, uvc->_priv);
785 if (ret != UVC_OK)
786 {
787 usb_err("copy(...) has failed: %d\n", ret);
788 return ret;
789 }
790
791 if (cplen != frame->length)
792 {
793 tran->length = frame->length;
794 }
795 tran->last = frame->last;
796
797 return UVC_OK;
798 }
799
uvc_stream_init(struct uvc_dev_s * fuvc)800 int uvc_stream_init(struct uvc_dev_s *fuvc)
801 {
802 uint32_t ret;
803
804 g_f_uvc = fuvc;
805
806 g_uvc_mutex = 0;
807 ret = LOS_MuxCreate(&g_uvc_mutex);
808 if (ret != LOS_OK)
809 {
810 usb_err("Failed to create Mutex for UVC: %#x\n", ret);
811 return -1;
812 }
813
814 fuvc_fill_streaming_control(fuvc, &fuvc->probe, 0, 0);
815 fuvc_fill_streaming_control(fuvc, &fuvc->commit, 0, 0);
816
817 return 0;
818 }
819
820 #define GET_BYTE(data, bits) (((data) >> (bits)) & 0xFF)
usb_format_yuv_semiplanar_420(char * buf_virt_y,char * buf_virt_c,uint8_t * frame_mem,uint32_t frame_len,uint32_t frame_height,uint32_t frame_width)821 void usb_format_yuv_semiplanar_420(char *buf_virt_y, char *buf_virt_c, uint8_t *frame_mem,
822 uint32_t frame_len, uint32_t frame_height, uint32_t frame_width)
823 {
824 uint32_t height = frame_height;
825 uint32_t width = frame_width;
826 char *temp_buf_virt_y = buf_virt_y;
827 char *temp_buf_virt_c = buf_virt_c;
828 char *py, *end;
829 uint32_t *pyy, *pc;
830 uint32_t *p, *pp;
831 register uint32_t r1, r2, rr1, rr2;
832 register uint32_t c[2];
833 uint32_t i;
834 uint32_t reg;
835
836 reg = GET_UINT32(0x12020ee0);
837 reg >>= 24;
838 if (reg == 0x4 || reg == 0 || reg == 0x10)
839 {
840 for(i = 0; i < height / 2; i++)
841 {
842 py = temp_buf_virt_y + (i * 2) * width;
843 pyy = (uint32_t *)(py + width);
844 end = (char *)pyy;
845 pc = (uint32_t *)(temp_buf_virt_c + i * width);
846 p = (uint32_t *)(frame_mem + frame_len + (i * 4) * width);
847 pp = (uint32_t *)(frame_mem + frame_len + (i * 4 + 2) * width);
848 for(; py < end; py += 8)
849 {
850 c[0] = *(pc++);
851 c[1] = *(pc++);
852
853 r1 = *((uint32_t *)py);
854 r2 = *((uint32_t *)py + 1);
855 *(p++) = ((GET_BYTE(r1, 0)) | (GET_BYTE(c[0], 8) << 8) |
856 (GET_BYTE(r1, 8) << 16) | (GET_BYTE(c[0], 0) << 24));
857 *(p++) = ((GET_BYTE(r1, 16)) | (GET_BYTE(c[0], 24) << 8) |
858 (GET_BYTE(r1, 24) << 16) | (GET_BYTE(c[0], 16) << 24));
859 *(p++) = ((GET_BYTE(r2, 0)) | (GET_BYTE(c[1], 8) << 8) |
860 (GET_BYTE(r2, 8) << 16) | (GET_BYTE(c[1], 0) << 24));
861 *(p++) = ((GET_BYTE(r2, 16)) | (GET_BYTE(c[1], 24) << 8) |
862 (GET_BYTE(r2, 24) << 16) | (GET_BYTE(c[1], 16) << 24));
863
864 rr1 = *(pyy++);
865 rr2 = *(pyy++);
866 *(pp++) = ((GET_BYTE(rr1, 0)) | (GET_BYTE(c[0], 8) << 8) |
867 (GET_BYTE(rr1, 8) << 16) | (GET_BYTE(c[0], 0) << 24));
868 *(pp++) = ((GET_BYTE(rr1, 16)) | (GET_BYTE(c[0], 24) << 8) |
869 (GET_BYTE(rr1, 24) << 16) | (GET_BYTE(c[0], 16) << 24));
870 *(pp++) = ((GET_BYTE(rr2, 0)) | (GET_BYTE(c[1], 8) << 8) |
871 (GET_BYTE(rr2, 8) << 16) | (GET_BYTE(c[1], 0) << 24));
872 *(pp++) = ((GET_BYTE(rr2, 16)) | (GET_BYTE(c[1], 24) << 8) |
873 (GET_BYTE(rr2, 24) << 16) | (GET_BYTE(c[1], 16) << 24));
874 }
875 }
876 }
877 }
878
879 #ifdef __cplusplus
880 #if __cplusplus
881 }
882 #endif /* __cplusplus */
883 #endif /* __cplusplus */