libv4l2: Support non-blocking mode for dqbuf
[GitHub/LineageOS/android_hardware_samsung_slsi_exynos.git] / libv4l2 / exynos_v4l2.c
CommitLineData
1eb637c1
YK
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*!
18 * \file exynos_v4l2.c
19 * \brief source file for libv4l2
20 * \author Jinsung Yang (jsgood.yang@samsung.com)
21 * \author Sangwoo Park (sw5771.park@samsung.com)
22 * \date 2012/01/17
23 *
24 * <b>Revision History: </b>
25 * - 2012/01/17: Jinsung Yang (jsgood.yang@samsung.com) \n
26 * Initial version
27 *
28 */
29
30#include <stdio.h>
31#include <errno.h>
32#include <stdarg.h>
33#include <fcntl.h>
34#include <string.h>
35#include <sys/types.h>
36#include <sys/ioctl.h>
37#include <sys/stat.h>
38
39#include "exynos_v4l2.h"
40
41//#define LOG_NDEBUG 0
42#define LOG_TAG "libexynosv4l2"
43#include <utils/Log.h>
44#include "Exynos_log.h"
45
46#define VIDEODEV_MINOR_MAX 63
47
48//#define EXYNOS_V4L2_TRACE 0
49#ifdef EXYNOS_V4L2_TRACE
50#define Exynos_v4l2_In() Exynos_Log(EXYNOS_DEV_LOG_DEBUG, LOG_TAG, "%s In , Line: %d", __FUNCTION__, __LINE__)
51#define Exynos_v4l2_Out() Exynos_Log(EXYNOS_DEV_LOG_DEBUG, LOG_TAG, "%s Out , Line: %d", __FUNCTION__, __LINE__)
52#else
53#define Exynos_v4l2_In() ((void *)0)
54#define Exynos_v4l2_Out() ((void *)0)
55#endif
56
57static bool __v4l2_check_buf_type(enum v4l2_buf_type type)
58{
59 bool supported;
60
61 switch (type) {
62 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
63 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
64 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
65 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
66 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
67 supported = true;
68 break;
69
70 default:
71 supported = (type >= V4L2_BUF_TYPE_PRIVATE) ? true : false;
72 break;
73 }
74
75 return supported;
76}
77
78static int __v4l2_open(const char *filename, int oflag, va_list ap)
79{
80 mode_t mode = 0;
81 int fd;
82
83 if (oflag & O_CREAT)
84 mode = va_arg(ap, int);
85
86 fd = open(filename, oflag, mode);
87
88 return fd;
89}
90
91int exynos_v4l2_open(const char *filename, int oflag, ...)
92{
93 va_list ap;
94 int fd;
95
96 Exynos_v4l2_In();
97
98 va_start(ap, oflag);
99 fd = __v4l2_open(filename, oflag, ap);
100 va_end(ap);
101
102 Exynos_v4l2_Out();
103
104 return fd;
105}
106
107int exynos_v4l2_open_devname(const char *devname, int oflag, ...)
108{
109 bool found = false;
110 int fd = -1;
111 struct stat s;
112 va_list ap;
113 FILE *stream_fd;
114 char filename[64], name[64];
115 int minor, size, i = 0;
116
117 Exynos_v4l2_In();
118
119 do {
120 if (i > VIDEODEV_MINOR_MAX)
121 break;
122
123 /* video device node */
124 sprintf(filename, "/dev/video%d", i++);
125
126 /* if the node is video device */
127 if ((lstat(filename, &s) == 0) && S_ISCHR(s.st_mode) &&
128 ((int)((unsigned short)(s.st_rdev) >> 8) == 81)) {
129 minor = (int)((unsigned short)(s.st_rdev & 0x3f));
130 ALOGD("try node: %s, minor: %d", filename, minor);
131 /* open sysfs entry */
132 sprintf(filename, "/sys/class/video4linux/video%d/name", minor);
133 stream_fd = fopen(filename, "r");
134 if (stream_fd == NULL) {
135 ALOGE("failed to open sysfs entry for videodev");
136 continue; /* try next */
137 }
138
139 /* read sysfs entry for device name */
140 size = (int)fgets(name, sizeof(name), stream_fd);
141 fclose(stream_fd);
142
143 /* check read size */
144 if (size == 0) {
145 ALOGE("failed to read sysfs entry for videodev");
146 } else {
147 /* matched */
148 if (strncmp(name, devname, strlen(devname)) == 0) {
149 ALOGI("node found for device %s: /dev/video%d", devname, minor);
150 found = true;
151 }
152 }
153 }
154 } while (found == false);
155
156 if (found) {
157 sprintf(filename, "/dev/video%d", minor);
158 va_start(ap, oflag);
159 fd = __v4l2_open(filename, oflag, ap);
160 va_end(ap);
161
162 if (fd > 0)
163 ALOGI("open video device %s", filename);
164 else
165 ALOGE("failed to open video device %s", filename);
166 } else {
167 ALOGE("no video device found");
168 }
169
170 Exynos_v4l2_Out();
171
172 return fd;
173}
174
175int exynos_v4l2_close(int fd)
176{
177 int ret = -1;
178
179 Exynos_v4l2_In();
180
181 if (fd < 0)
182 ALOGE("%s: invalid fd: %d", __func__, fd);
183 else
184 ret = close(fd);
185
186 Exynos_v4l2_Out();
187
188 return ret;
189}
190
191bool exynos_v4l2_enuminput(int fd, int index, char *input_name_buf)
192{
193 int ret = -1;
194 struct v4l2_input input;
195
196 Exynos_v4l2_In();
197
198 if (fd < 0) {
199 ALOGE("%s: invalid fd: %d", __func__, fd);
200 return NULL;
201 }
202
203 input.index = index;
204 ret = ioctl(fd, VIDIOC_ENUMINPUT, &input);
205 if (ret) {
206 ALOGE("%s: no matching index founds", __func__);
207 return false;
208 }
209
210 ALOGI("Name of input channel[%d] is %s", input.index, input.name);
211
212 strcpy(input_name_buf, (const char *)input.name);
213
214 Exynos_v4l2_Out();
215
216 return true;
217}
218
219int exynos_v4l2_s_input(int fd, int index)
220{
221 int ret = -1;
222 struct v4l2_input input;
223
224 Exynos_v4l2_In();
225
226 if (fd < 0) {
227 ALOGE("%s: invalid fd: %d", __func__, fd);
228 return ret;
229 }
230
231 input.index = index;
232
233 ret = ioctl(fd, VIDIOC_S_INPUT, &input);
234 if (ret){
235 ALOGE("failed to ioctl: VIDIOC_S_INPUT (%d - %s)", errno, strerror(errno));
236 return ret;
237 }
238
239 Exynos_v4l2_Out();
240
241 return ret;
242}
243
244bool exynos_v4l2_querycap(int fd, unsigned int need_caps)
245{
246 struct v4l2_capability cap;
247 int ret;
248
249 Exynos_v4l2_In();
250
251 if (fd < 0) {
252 ALOGE("%s: invalid fd: %d", __func__, fd);
253 return false;
254 }
255
256 if (!(need_caps & V4L2_CAP_VIDEO_CAPTURE) &&
257 !(need_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) &&
258 !(need_caps & V4L2_CAP_VIDEO_OUTPUT) &&
259 !(need_caps & V4L2_CAP_VIDEO_OUTPUT_MPLANE) &&
260 !(need_caps & V4L2_CAP_VIDEO_OVERLAY)) {
261 ALOGE("%s: unsupported capabilities", __func__);
262 return false;
263 }
264
265 memset(&cap, 0, sizeof(cap));
266
267 ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
268 if (ret) {
269 ALOGE("failed to ioctl: VIDIOC_QUERYCAP (%d - %s)", errno, strerror(errno));
270 return false;
271 }
272
273 if ((need_caps & cap.capabilities) != need_caps) {
274 ALOGE("%s: unsupported capabilities", __func__);
275 return false;
276 }
277
278 Exynos_v4l2_Out();
279
280 return true;
281}
282
283bool exynos_v4l2_enum_fmt(int fd, enum v4l2_buf_type type, unsigned int fmt)
284{
285 struct v4l2_fmtdesc fmtdesc;
286 int found = 0;
287
288 Exynos_v4l2_In();
289
290 fmtdesc.type = type;
291 fmtdesc.index = 0;
292
293 while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
294 if (fmtdesc.pixelformat == fmt) {
295 ALOGE("Passed fmt = %#x found pixel format[%d]: %s", fmt, fmtdesc.index, fmtdesc.description);
296 found = 1;
297 break;
298 }
299
300 fmtdesc.index++;
301 }
302
303 if (!found) {
304 ALOGE("%s: unsupported pixel format", __func__);
305 return false;
306 }
307
308 Exynos_v4l2_Out();
309
310 return true;
311}
312
313int exynos_v4l2_g_fmt(int fd, struct v4l2_format *fmt)
314{
315 int ret = -1;
316
317 Exynos_v4l2_In();
318
319 if (fd < 0) {
320 ALOGE("%s: invalid fd: %d", __func__, fd);
321 return ret;
322 }
323
324 if (!fmt) {
325 ALOGE("%s: fmt is NULL", __func__);
326 return ret;
327 }
328
329 if (__v4l2_check_buf_type(fmt->type) == false) {
330 ALOGE("%s: unsupported buffer type", __func__);
331 return ret;
332 }
333
334 ret = ioctl(fd, VIDIOC_G_FMT, fmt);
335 if (ret) {
336 ALOGE("failed to ioctl: VIDIOC_G_FMT (%d - %s)", errno, strerror(errno));
337 return ret;
338 }
339
340 Exynos_v4l2_Out();
341
342 return ret;
343}
344
345static int __v4l2_s_fmt(int fd, unsigned int request, struct v4l2_format *fmt)
346{
347 int ret = -1;
348
349 Exynos_v4l2_In();
350
351 if (fd < 0) {
352 ALOGE("%s: invalid fd: %d", __func__, fd);
353 return ret;
354 }
355
356 if (!fmt) {
357 ALOGE("%s: fmt is NULL", __func__);
358 return ret;
359 }
360
361 if (__v4l2_check_buf_type(fmt->type) == false) {
362 ALOGE("%s: unsupported buffer type", __func__);
363 return ret;
364 } else {
365 ret = ioctl(fd, request, fmt);
366 if (ret) {
367 if (request == VIDIOC_TRY_FMT)
368 ALOGE("failed to ioctl: VIDIOC_TRY_FMT (%d - %s)", errno, strerror(errno));
369 else
370 ALOGE("failed to ioctl: VIDIOC_S_FMT (%d - %s)", errno, strerror(errno));
371
372 return ret;
373 }
374 }
375
376 Exynos_v4l2_Out();
377
378 return ret;
379}
380
381int exynos_v4l2_try_fmt(int fd, struct v4l2_format *fmt)
382{
383 return __v4l2_s_fmt(fd, VIDIOC_TRY_FMT, fmt);
384}
385
386int exynos_v4l2_s_fmt(int fd, struct v4l2_format *fmt)
387{
388 return __v4l2_s_fmt(fd, VIDIOC_S_FMT, fmt);
389}
390
391int exynos_v4l2_reqbufs(int fd, struct v4l2_requestbuffers *req)
392{
393 int ret = -1;
394 unsigned int count;
395
396 Exynos_v4l2_In();
397
398 if (fd < 0) {
399 ALOGE("%s: invalid fd: %d", __func__, fd);
400 return ret;
401 }
402
403 if (!req) {
404 ALOGE("%s: req is NULL", __func__);
405 return ret;
406 }
407
408 if ((req->memory != V4L2_MEMORY_MMAP) &&
409 (req->memory != V4L2_MEMORY_USERPTR) &&
410 (req->memory != V4L2_MEMORY_DMABUF)) {
411 ALOGE("%s: unsupported memory type", __func__);
412 return ret;
413 }
414
415 if (__v4l2_check_buf_type(req->type) == false) {
416 ALOGE("%s: unsupported buffer type", __func__);
417 return ret;
418 }
419
420 count = req->count;
421
422 ret = ioctl(fd, VIDIOC_REQBUFS, req);
423 if (ret) {
424 ALOGE("failed to ioctl: VIDIOC_REQBUFS (%d - %s)", ret, strerror(errno));
425 return ret;
426 }
427
428 if (count != req->count) {
429 ALOGW("number of buffers had been changed: %d => %d", count, req->count);
430 }
431
432 Exynos_v4l2_Out();
433
434 return ret;
435}
436
437int exynos_v4l2_querybuf(int fd, struct v4l2_buffer *buf)
438{
439 int ret = -1;
440
441 Exynos_v4l2_In();
442
443 if (fd < 0) {
444 ALOGE("%s: invalid fd: %d", __func__, fd);
445 return ret;
446 }
447
448 if (!buf) {
449 ALOGE("%s: buf is NULL", __func__);
450 return ret;
451 }
452
453 if ((buf->memory != V4L2_MEMORY_MMAP) &&
454 (buf->memory != V4L2_MEMORY_DMABUF)) {
455 ALOGE("%s: unsupported memory type", __func__);
456 return ret;
457 }
458
459 if (__v4l2_check_buf_type(buf->type) == false) {
460 ALOGE("%s: unsupported buffer type", __func__);
461 return ret;
462 }
463
464 ret = ioctl(fd, VIDIOC_QUERYBUF, buf);
465 if (ret) {
466 ALOGE("failed to ioctl: VIDIOC_QUERYBUF (%d - %s)", errno, strerror(errno));
467 return ret;
468 }
469
470 Exynos_v4l2_Out();
471
472 return ret;
473}
474
475int exynos_v4l2_qbuf(int fd, struct v4l2_buffer *buf)
476{
477 int ret = -1;
478
479 Exynos_v4l2_In();
480
481 if (fd < 0) {
482 ALOGE("%s: invalid fd: %d", __func__, fd);
483 return ret;
484 }
485
486 if (!buf) {
487 ALOGE("%s: buf is NULL", __func__);
488 return ret;
489 }
490
491 if ((buf->memory != V4L2_MEMORY_MMAP) &&
492 (buf->memory != V4L2_MEMORY_USERPTR) &&
493 (buf->memory != V4L2_MEMORY_DMABUF)) {
494 ALOGE("%s: unsupported memory type", __func__);
495 return ret;
496 }
497
498 if (__v4l2_check_buf_type(buf->type) == false) {
499 ALOGE("%s: unsupported buffer type", __func__);
500 return ret;
501 }
502
503 ret = ioctl(fd, VIDIOC_QBUF, buf);
504 if (ret) {
505 ALOGE("failed to ioctl: VIDIOC_QBUF (%d - %s)", errno, strerror(errno));
506 return ret;
507 }
508
509 Exynos_v4l2_Out();
510
511 return ret;
512}
513
514int exynos_v4l2_dqbuf(int fd, struct v4l2_buffer *buf)
515{
516 int ret = -1;
517
518 Exynos_v4l2_In();
519
520 if (fd < 0) {
521 ALOGE("%s: invalid fd: %d", __func__, fd);
522 return ret;
523 }
524
525 if (!buf) {
526 ALOGE("%s: buf is NULL", __func__);
527 return ret;
528 }
529
530 if ((buf->memory != V4L2_MEMORY_MMAP) &&
531 (buf->memory != V4L2_MEMORY_USERPTR) &&
532 (buf->memory != V4L2_MEMORY_DMABUF)) {
533 ALOGE("%s: unsupported memory type", __func__);
534 return ret;
535 }
536
537 if (__v4l2_check_buf_type(buf->type) == false) {
538 ALOGE("%s: unsupported buffer type", __func__);
539 return ret;
540 }
541
542 ret = ioctl(fd, VIDIOC_DQBUF, buf);
543 if (ret) {
b8723591
HC
544 if (errno == EAGAIN)
545 return -errno;
546
0d9f8880 547 ALOGW("failed to ioctl: VIDIOC_DQBUF (%d - %s)", errno, strerror(errno));
1eb637c1
YK
548 return ret;
549 }
550
551 Exynos_v4l2_Out();
552
553 return ret;
554}
555
556int exynos_v4l2_streamon(int fd, enum v4l2_buf_type type)
557{
558 int ret = -1;
559
560 Exynos_v4l2_In();
561
562 if (fd < 0) {
563 ALOGE("%s: invalid fd: %d", __func__, fd);
564 return ret;
565 }
566
567 if (__v4l2_check_buf_type(type) == false) {
568 ALOGE("%s: unsupported buffer type", __func__);
569 return ret;
570 }
571
572 ret = ioctl(fd, VIDIOC_STREAMON, &type);
573 if (ret) {
574 ALOGE("failed to ioctl: VIDIOC_STREAMON (%d - %s)", errno, strerror(errno));
575 return ret;
576 }
577
578 Exynos_v4l2_Out();
579
580 return ret;
581}
582
583int exynos_v4l2_streamoff(int fd, enum v4l2_buf_type type)
584{
585 int ret = -1;
586
587 Exynos_v4l2_In();
588
589 if (fd < 0) {
590 ALOGE("%s: invalid fd: %d", __func__, fd);
591 return ret;
592 }
593
594 if (__v4l2_check_buf_type(type) == false) {
595 ALOGE("%s: unsupported buffer type", __func__);
596 return ret;
597 }
598
599 ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
600 if (ret) {
601 ALOGE("failed to ioctl: VIDIOC_STREAMOFF (%d - %s)", errno, strerror(errno));
602 return ret;
603 }
604
605 Exynos_v4l2_Out();
606
607 return ret;
608}
609
610int exynos_v4l2_cropcap(int fd, struct v4l2_cropcap *crop)
611{
612 int ret = -1;
613
614 Exynos_v4l2_In();
615
616 if (fd < 0) {
617 ALOGE("%s: invalid fd: %d", __func__, fd);
618 return ret;
619 }
620
621 if (!crop) {
622 ALOGE("%s: crop is NULL", __func__);
623 return ret;
624 }
625
626 if (__v4l2_check_buf_type(crop->type) == false) {
627 ALOGE("%s: unsupported buffer type", __func__);
628 return ret;
629 }
630
631 ret = ioctl(fd, VIDIOC_CROPCAP, crop);
632 if (ret) {
633 ALOGE("failed to ioctl: VIDIOC_CROPCAP (%d - %s)", errno, strerror(errno));
634 return ret;
635 }
636
637 Exynos_v4l2_Out();
638
639 return ret;
640}
641
642int exynos_v4l2_g_crop(int fd, struct v4l2_crop *crop)
643{
644 int ret = -1;
645
646 Exynos_v4l2_In();
647
648 if (fd < 0) {
649 ALOGE("%s: invalid fd: %d", __func__, fd);
650 return ret;
651 }
652
653 if (!crop) {
654 ALOGE("%s: crop is NULL", __func__);
655 return ret;
656 }
657
658 if (__v4l2_check_buf_type(crop->type) == false) {
659 ALOGE("%s: unsupported buffer type", __func__);
660 return ret;
661 }
662
663 ret = ioctl(fd, VIDIOC_G_CROP, crop);
664 if (ret) {
665 ALOGE("failed to ioctl: VIDIOC_G_CROP (%d - %s)", errno, strerror(errno));
666 return ret;
667 }
668
669 Exynos_v4l2_Out();
670
671 return ret;
672}
673
674int exynos_v4l2_s_crop(int fd, struct v4l2_crop *crop)
675{
676 int ret = -1;
677
678 Exynos_v4l2_In();
679
680 if (fd < 0) {
681 ALOGE("%s: invalid fd: %d", __func__, fd);
682 return ret;
683 }
684
685 if (!crop) {
686 ALOGE("%s: crop is NULL", __func__);
687 return ret;
688 }
689
690 if (__v4l2_check_buf_type(crop->type) == false) {
691 ALOGE("%s: unsupported buffer type", __func__);
692 return ret;
693 }
694
695 ret = ioctl(fd, VIDIOC_S_CROP, crop);
696 if (ret) {
697 ALOGE("failed to ioctl: VIDIOC_S_CROP (%d - %s)", errno, strerror(errno));
698 return ret;
699 }
700
701 Exynos_v4l2_Out();
702
703 return ret;
704}
705
706int exynos_v4l2_g_ctrl(int fd, unsigned int id, int *value)
707{
708 int ret = -1;
709 struct v4l2_control ctrl;
710
711 Exynos_v4l2_In();
712
713 ctrl.id = id;
714
715 if (fd < 0) {
716 ALOGE("%s: invalid fd: %d", __func__, fd);
717 return ret;
718 }
719
720 ret = ioctl(fd, VIDIOC_G_CTRL, &ctrl);
721 if (ret) {
722 ALOGE("failed to ioctl: VIDIOC_G_CTRL (%d - %s)", errno, strerror(errno));
723 return ret;
724 }
725
726 *value = ctrl.value;
727
728 Exynos_v4l2_Out();
729
730 return ret;
731}
732
733int exynos_v4l2_s_ctrl(int fd, unsigned int id, int value)
734{
735 int ret = -1;
736 struct v4l2_control ctrl;
737
738 Exynos_v4l2_In();
739
740 ctrl.id = id;
741 ctrl.value = value;
742
743 if (fd < 0) {
744 ALOGE("%s: invalid fd: %d", __func__, fd);
745 return ret;
746 }
747
748 ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
749 if (ret) {
750 ALOGE("failed to ioctl: VIDIOC_S_CTRL (%d)", errno);
751 return ret;
752 }
753
754 Exynos_v4l2_Out();
755
756 return ret;
757}
758
759int exynos_v4l2_g_parm(int fd, struct v4l2_streamparm *streamparm)
760{
761 int ret = -1;
762
763 Exynos_v4l2_In();
764
765 if (fd < 0) {
766 ALOGE("%s: invalid fd: %d", __func__, fd);
767 return ret;
768 }
769
770 if (__v4l2_check_buf_type(streamparm->type) == false) {
771 ALOGE("%s: unsupported buffer type", __func__);
772 return ret;
773 }
774
775 ret = ioctl(fd, VIDIOC_G_PARM, streamparm);
776 if (ret) {
777 ALOGE("failed to ioctl: VIDIOC_G_PARM (%d - %s)", errno, strerror(errno));
778 return ret;
779 }
780
781 Exynos_v4l2_Out();
782
783 return ret;
784}
785
786int exynos_v4l2_s_parm(int fd, struct v4l2_streamparm *streamparm)
787{
788 int ret = -1;
789
790 Exynos_v4l2_In();
791
792 if (fd < 0) {
793 ALOGE("%s: invalid fd: %d", __func__, fd);
794 return ret;
795 }
796
797 if (__v4l2_check_buf_type(streamparm->type) == false) {
798 ALOGE("%s: unsupported buffer type", __func__);
799 return ret;
800 }
801
802 ret = ioctl(fd, VIDIOC_S_PARM, streamparm);
803 if (ret) {
804 ALOGE("failed to ioctl: VIDIOC_S_PARM (%d - %s)", errno, strerror(errno));
805 return ret;
806 }
807
808 Exynos_v4l2_Out();
809
810 return ret;
811}
812
813int exynos_v4l2_g_ext_ctrl(int fd, struct v4l2_ext_controls *ctrl)
814{
815 int ret = -1;
816
817 Exynos_v4l2_In();
818
819 if (fd < 0) {
820 ALOGE("%s: invalid fd: %d", __func__, fd);
821 return ret;
822 }
823
824 if (ctrl == NULL) {
825 ALOGE("%s: ctrl is NULL", __func__);
826 return ret;
827 }
828
829 ret = ioctl(fd, VIDIOC_G_EXT_CTRLS, ctrl);
830 if (ret)
831 ALOGE("failed to ioctl: VIDIOC_G_EXT_CTRLS (%d - %s)", errno, strerror(errno));
832
833 Exynos_v4l2_Out();
834
835 return ret;
836}
837
838int exynos_v4l2_s_ext_ctrl(int fd, struct v4l2_ext_controls *ctrl)
839{
840 int ret = -1;
841
842 Exynos_v4l2_In();
843
844 if (fd < 0) {
845 ALOGE("%s: invalid fd: %d", __func__, fd);
846 return ret;
847 }
848
849 if (ctrl == NULL) {
850 ALOGE("%s: ctrl is NULL", __func__);
851 return ret;
852 }
853
854 ret = ioctl(fd, VIDIOC_S_EXT_CTRLS, ctrl);
855 if (ret)
856 ALOGE("failed to ioctl: VIDIOC_S_EXT_CTRLS (%d - %s)", errno, strerror(errno));
857
858 Exynos_v4l2_Out();
859
860 return ret;
861}