for callback invoke when resolution is changed
[platform/adaptation/ap_samsung/libomxil-e3250-v4l2.git] / exynos / libv4l2 / exynos_v4l2.c
1 /*
2  * Copyright 2012 Samsung Electronics S.LSI Co. LTD
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 #ifndef TIZEN_FEATURE_E3250 /* build env */
44 #include <utils/Log.h>
45 #else
46 #include "Exynos_OSAL_Log.h"
47 #endif
48
49 #define VIDEODEV_MAX 255
50
51 static bool __v4l2_check_buf_type(enum v4l2_buf_type type)
52 {
53     bool supported;
54
55     switch (type) {
56     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
57     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
58     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
59     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
60     case V4L2_BUF_TYPE_VIDEO_OVERLAY:
61         supported = true;
62         break;
63
64     default:
65         supported = (type >= V4L2_BUF_TYPE_PRIVATE) ? true : false;
66         break;
67     }
68
69     return supported;
70 }
71
72 static int __v4l2_open(const char *filename, int oflag, va_list ap)
73 {
74     mode_t mode = 0;
75     int fd;
76
77     if (oflag & O_CREAT)
78         mode = va_arg(ap, int);
79
80     fd = open(filename, oflag, mode);
81
82     return fd;
83 }
84
85 int exynos_v4l2_open(const char *filename, int oflag, ...)
86 {
87     va_list ap;
88     int fd;
89
90     va_start(ap, oflag);
91     fd = __v4l2_open(filename, oflag, ap);
92     va_end(ap);
93
94     return fd;
95 }
96
97 int exynos_v4l2_open_devname(const char *devname, int oflag, ...)
98 {
99     bool found = false;
100     int fd = -1;
101     struct stat s;
102     va_list ap;
103     FILE *stream_fd;
104     char filename[64], name[64];
105     int size, i = 0;
106
107     do {
108         if (i > VIDEODEV_MAX)
109             break;
110
111         /* video device node */
112         snprintf(filename, sizeof(filename), "/dev/video%d", i);
113
114         /* if the node is video device */
115         if ((lstat(filename, &s) == 0) && S_ISCHR(s.st_mode) &&
116                 ((int)((unsigned short)(s.st_rdev) >> 8) == 81)) {
117             ALOGD("try node: %s", filename);
118             /* open sysfs entry */
119             snprintf(filename, sizeof(filename), "/sys/class/video4linux/video%d/name", i);
120             if (S_ISLNK(s.st_mode)) {
121                 ALOGE("symbolic link detected");
122                 return -1;
123             }
124             stream_fd = fopen(filename, "r");
125             if (stream_fd == NULL) {
126                 ALOGE("failed to open sysfs entry for videodev");
127                 i++;
128                 continue;   /* try next */
129             }
130
131             /* read sysfs entry for device name */
132             size = (int)fgets(name, sizeof(name), stream_fd);
133             fclose(stream_fd);
134
135             /* check read size */
136             if (size == 0) {
137                 ALOGE("failed to read sysfs entry for videodev");
138             } else {
139                 /* matched */
140                 if (strncmp(name, devname, strlen(devname)) == 0) {
141                     ALOGI("node found for device %s: /dev/video%d", devname, i);
142                     found = true;
143                     break;
144                 }
145             }
146         }
147         i++;
148     } while (found == false);
149
150     if (found) {
151         snprintf(filename, sizeof(filename), "/dev/video%d", i);
152         va_start(ap, oflag);
153         fd = __v4l2_open(filename, oflag, ap);
154         va_end(ap);
155
156         if (fd > 0)
157             ALOGI("open video device %s", filename);
158         else
159             ALOGE("failed to open video device %s", filename);
160     } else {
161         ALOGE("no video device found");
162     }
163
164     return fd;
165 }
166
167 int exynos_v4l2_close(int fd)
168 {
169     int ret = -1;
170
171     if (fd < 0)
172         ALOGE("%s: invalid fd: %d", __func__, fd);
173     else
174         ret = close(fd);
175
176     return ret;
177 }
178
179 bool exynos_v4l2_enuminput(int fd, int index, char *input_name_buf)
180 {
181     int ret = -1;
182     struct v4l2_input input;
183
184     if (fd < 0) {
185         ALOGE("%s: invalid fd: %d", __func__, fd);
186         return NULL;
187     }
188
189     input.index = index;
190     ret = ioctl(fd, VIDIOC_ENUMINPUT, &input);
191     if (ret) {
192         ALOGE("%s: no matching index founds", __func__);
193         return false;
194     }
195
196     ALOGI("Name of input channel[%d] is %s", input.index, input.name);
197
198     strcpy(input_name_buf, (const char *)input.name);
199
200     return true;
201 }
202
203 int exynos_v4l2_s_input(int fd, int index)
204 {
205     int ret = -1;
206     struct v4l2_input input;
207
208     if (fd < 0) {
209         ALOGE("%s: invalid fd: %d", __func__, fd);
210         return ret;
211     }
212
213     input.index = index;
214
215     ret = ioctl(fd, VIDIOC_S_INPUT, &input);
216     if (ret){
217         ALOGE("failed to ioctl: VIDIOC_S_INPUT (%d - %s)", errno, strerror(errno));
218         return ret;
219     }
220
221     return ret;
222 }
223
224 bool exynos_v4l2_querycap(int fd, unsigned int need_caps)
225 {
226     struct v4l2_capability cap;
227     int ret;
228
229     if (fd < 0) {
230         ALOGE("%s: invalid fd: %d", __func__, fd);
231         return false;
232     }
233
234     if (!(need_caps & V4L2_CAP_VIDEO_CAPTURE) &&
235             !(need_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) &&
236             !(need_caps & V4L2_CAP_VIDEO_OUTPUT) &&
237             !(need_caps & V4L2_CAP_VIDEO_OUTPUT_MPLANE) &&
238             !(need_caps & V4L2_CAP_VIDEO_OVERLAY)) {
239         ALOGE("%s: unsupported capabilities", __func__);
240         return false;
241     }
242
243     memset(&cap, 0, sizeof(cap));
244
245     ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
246     if (ret) {
247         ALOGE("failed to ioctl: VIDIOC_QUERYCAP (%d - %s)", errno, strerror(errno));
248         return false;
249     }
250
251     if ((need_caps & cap.capabilities) != need_caps) {
252         ALOGE("%s: unsupported capabilities", __func__);
253         return false;
254     }
255
256     return true;
257 }
258
259 bool exynos_v4l2_enum_fmt(int fd, enum v4l2_buf_type type, unsigned int fmt)
260 {
261     struct v4l2_fmtdesc fmtdesc;
262     int found = 0;
263
264     fmtdesc.type = type;
265     fmtdesc.index = 0;
266
267     while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
268         if (fmtdesc.pixelformat == fmt) {
269             ALOGE("Passed fmt = %#x found pixel format[%d]: %s", fmt, fmtdesc.index, fmtdesc.description);
270             found = 1;
271             break;
272         }
273
274         fmtdesc.index++;
275     }
276
277     if (!found) {
278         ALOGE("%s: unsupported pixel format", __func__);
279         return false;
280     }
281
282     return true;
283 }
284
285 int exynos_v4l2_g_fmt(int fd, struct v4l2_format *fmt)
286 {
287     int ret = -1;
288
289     if (fd < 0) {
290         ALOGE("%s: invalid fd: %d", __func__, fd);
291         return ret;
292     }
293
294     if (!fmt) {
295         ALOGE("%s: fmt is NULL", __func__);
296         return ret;
297     }
298
299     if (__v4l2_check_buf_type(fmt->type) == false) {
300         ALOGE("%s: unsupported buffer type", __func__);
301         return ret;
302     }
303
304     ret = ioctl(fd, VIDIOC_G_FMT, fmt);
305     if (ret) {
306         ALOGE("failed to ioctl: VIDIOC_G_FMT (%d - %s)", errno, strerror(errno));
307         return ret;
308     }
309
310     return ret;
311 }
312
313 static int __v4l2_s_fmt(int fd, unsigned int request, struct v4l2_format *fmt)
314 {
315     int ret = -1;
316
317     if (fd < 0) {
318         ALOGE("%s: invalid fd: %d", __func__, fd);
319         return ret;
320     }
321
322     if (!fmt) {
323         ALOGE("%s: fmt is NULL", __func__);
324         return ret;
325     }
326
327     if (__v4l2_check_buf_type(fmt->type) == false) {
328         ALOGE("%s: unsupported buffer type", __func__);
329         return ret;
330     } else {
331         ret = ioctl(fd, request, fmt);
332         if (ret) {
333             if (request == VIDIOC_TRY_FMT)
334                 ALOGE("failed to ioctl: VIDIOC_TRY_FMT (%d - %s)", errno, strerror(errno));
335             else
336                 ALOGE("failed to ioctl: VIDIOC_S_FMT (%d - %s)", errno, strerror(errno));
337
338             return ret;
339         }
340     }
341
342     return ret;
343 }
344
345 int exynos_v4l2_try_fmt(int fd, struct v4l2_format *fmt)
346 {
347     return __v4l2_s_fmt(fd, VIDIOC_TRY_FMT, fmt);
348 }
349
350 int exynos_v4l2_s_fmt(int fd, struct v4l2_format *fmt)
351 {
352     return __v4l2_s_fmt(fd, VIDIOC_S_FMT, fmt);
353 }
354
355 int exynos_v4l2_reqbufs(int fd, struct v4l2_requestbuffers *req)
356 {
357     int ret = -1;
358     unsigned int count;
359
360     if (fd < 0) {
361         ALOGE("%s: invalid fd: %d", __func__, fd);
362         return ret;
363     }
364
365     if (!req) {
366         ALOGE("%s: req is NULL", __func__);
367         return ret;
368     }
369
370     if ((req->memory != V4L2_MEMORY_MMAP) &&
371         (req->memory != V4L2_MEMORY_USERPTR) &&
372         (req->memory != V4L2_MEMORY_DMABUF)) {
373         ALOGE("%s: unsupported memory type", __func__);
374         return ret;
375     }
376
377     if (__v4l2_check_buf_type(req->type) == false) {
378         ALOGE("%s: unsupported buffer type", __func__);
379         return ret;
380     }
381
382     count = req->count;
383
384     ret = ioctl(fd, VIDIOC_REQBUFS, req);
385     if (ret) {
386         ALOGE("failed to ioctl: VIDIOC_REQBUFS (%d - %s)", ret, strerror(errno));
387         return ret;
388     }
389
390     if (count != req->count) {
391         ALOGW("number of buffers had been changed: %d => %d", count, req->count);
392     }
393
394     return ret;
395 }
396
397 int exynos_v4l2_querybuf(int fd, struct v4l2_buffer *buf)
398 {
399     int ret = -1;
400
401     if (fd < 0) {
402         ALOGE("%s: invalid fd: %d", __func__, fd);
403         return ret;
404     }
405
406     if (!buf) {
407         ALOGE("%s: buf is NULL", __func__);
408         return ret;
409     }
410
411     if ((buf->memory != V4L2_MEMORY_MMAP) &&
412         (buf->memory != V4L2_MEMORY_DMABUF)) {
413         ALOGE("%s: unsupported memory type", __func__);
414         return ret;
415     }
416
417     if (__v4l2_check_buf_type(buf->type) == false) {
418         ALOGE("%s: unsupported buffer type", __func__);
419         return ret;
420     }
421
422     ret = ioctl(fd, VIDIOC_QUERYBUF, buf);
423     if (ret) {
424         ALOGE("failed to ioctl: VIDIOC_QUERYBUF (%d - %s)", errno, strerror(errno));
425         return ret;
426     }
427
428     return ret;
429 }
430
431 #ifdef TIZEN_FEATURE_E3250 /*dmabuf */
432
433 #ifndef VIDIOC_EXPBUF
434 struct v4l2_exportbuffer {
435     __u32 fd;
436     __u32 reserved0;
437     __u32 mem_offset;
438     __u32 flags;
439     __u32 reserved[12];
440 };
441 #define VIDIOC_EXPBUF _IOWR('V', 16, struct v4l2_exportbuffer)
442 #endif
443
444 int exynos_v4l2_expbuf(int fd, int *buf_fd, __u32 mem_offset)
445 {
446     int ret = -1;
447     struct v4l2_exportbuffer expbuf;
448
449     if (fd < 0) {
450         ALOGE("%s: invalid fd: %d", __func__, fd);
451         ALOGE("%s: invalid fd: %d", __func__, fd);
452         return ret;
453     }
454
455     expbuf.flags = O_CLOEXEC;
456     //expbuf.mem_offset = mem_offset;
457     ALOGE("%s: fd:%d mem_offset:%d", __func__, fd, mem_offset);
458
459     ret = ioctl(fd, VIDIOC_EXPBUF, &expbuf);
460     if (ret) {
461         ALOGE("failed to ioctl: VIDIOC_EXPBUF (%d - %s)", errno, strerror(errno));
462         return ret;
463     }
464     ALOGE("%s: got fd: %d", __func__, expbuf.fd);
465     *buf_fd = expbuf.fd;
466
467     return ret;
468 }
469 #endif
470
471 int exynos_v4l2_qbuf(int fd, struct v4l2_buffer *buf)
472 {
473     int ret = -1;
474
475     if (fd < 0) {
476         ALOGE("%s: invalid fd: %d", __func__, fd);
477         return ret;
478     }
479
480     if (!buf) {
481         ALOGE("%s: buf is NULL", __func__);
482         return ret;
483     }
484
485     if ((buf->memory != V4L2_MEMORY_MMAP) &&
486         (buf->memory != V4L2_MEMORY_USERPTR) &&
487         (buf->memory != V4L2_MEMORY_DMABUF)) {
488         ALOGE("%s: unsupported memory type", __func__);
489         return ret;
490     }
491
492     if (__v4l2_check_buf_type(buf->type) == false) {
493         ALOGE("%s: unsupported buffer type", __func__);
494         return ret;
495     }
496
497     ret = ioctl(fd, VIDIOC_QBUF, buf);
498     if (ret) {
499         ALOGE("failed to ioctl: VIDIOC_QBUF (%d - %s)", errno, strerror(errno));
500         return ret;
501     }
502
503     return ret;
504 }
505
506 int exynos_v4l2_dqbuf(int fd, struct v4l2_buffer *buf)
507 {
508     int ret = -1;
509
510     if (fd < 0) {
511         ALOGE("%s: invalid fd: %d", __func__, fd);
512         return ret;
513     }
514
515     if (!buf) {
516         ALOGE("%s: buf is NULL", __func__);
517         return ret;
518     }
519
520     if ((buf->memory != V4L2_MEMORY_MMAP) &&
521         (buf->memory != V4L2_MEMORY_USERPTR) &&
522         (buf->memory != V4L2_MEMORY_DMABUF)) {
523         ALOGE("%s: unsupported memory type", __func__);
524         return ret;
525     }
526
527     if (__v4l2_check_buf_type(buf->type) == false) {
528         ALOGE("%s: unsupported buffer type", __func__);
529         return ret;
530     }
531
532     ret = ioctl(fd, VIDIOC_DQBUF, buf);
533
534     return ret;
535 }
536
537 int exynos_v4l2_streamon(int fd, enum v4l2_buf_type type)
538 {
539     int ret = -1;
540
541     if (fd < 0) {
542         ALOGE("%s: invalid fd: %d", __func__, fd);
543         return ret;
544     }
545
546     if (__v4l2_check_buf_type(type) == false) {
547         ALOGE("%s: unsupported buffer type", __func__);
548         return ret;
549     }
550
551     ret = ioctl(fd, VIDIOC_STREAMON, &type);
552     if (ret) {
553         ALOGE("failed to ioctl: VIDIOC_STREAMON (%d - %s)", errno, strerror(errno));
554         return ret;
555     }
556
557     return ret;
558 }
559
560 int exynos_v4l2_streamoff(int fd, enum v4l2_buf_type type)
561 {
562     int ret = -1;
563
564     if (fd < 0) {
565         ALOGE("%s: invalid fd: %d", __func__, fd);
566         return ret;
567     }
568
569     if (__v4l2_check_buf_type(type) == false) {
570         ALOGE("%s: unsupported buffer type", __func__);
571         return ret;
572     }
573
574     ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
575     if (ret) {
576         ALOGE("failed to ioctl: VIDIOC_STREAMOFF (%d - %s)", errno, strerror(errno));
577         return ret;
578     }
579
580     return ret;
581 }
582
583 int exynos_v4l2_cropcap(int fd, struct v4l2_cropcap *crop)
584 {
585     int ret = -1;
586
587     if (fd < 0) {
588         ALOGE("%s: invalid fd: %d", __func__, fd);
589         return ret;
590     }
591
592     if (!crop) {
593         ALOGE("%s: crop is NULL", __func__);
594         return ret;
595     }
596
597     if (__v4l2_check_buf_type(crop->type) == false) {
598         ALOGE("%s: unsupported buffer type", __func__);
599         return ret;
600     }
601
602     ret = ioctl(fd, VIDIOC_CROPCAP, crop);
603     if (ret) {
604         ALOGE("failed to ioctl: VIDIOC_CROPCAP (%d - %s)", errno, strerror(errno));
605         return ret;
606     }
607
608     return ret;
609 }
610
611 int exynos_v4l2_g_crop(int fd, struct v4l2_crop *crop)
612 {
613     int ret = -1;
614
615     if (fd < 0) {
616         ALOGE("%s: invalid fd: %d", __func__, fd);
617         return ret;
618     }
619
620     if (!crop) {
621         ALOGE("%s: crop is NULL", __func__);
622         return ret;
623     }
624
625     if (__v4l2_check_buf_type(crop->type) == false) {
626         ALOGE("%s: unsupported buffer type", __func__);
627         return ret;
628     }
629
630     ret = ioctl(fd, VIDIOC_G_CROP, crop);
631     if (ret) {
632         ALOGE("failed to ioctl: VIDIOC_G_CROP (%d - %s)", errno, strerror(errno));
633         return ret;
634     }
635
636     return ret;
637 }
638
639 int exynos_v4l2_s_crop(int fd, struct v4l2_crop *crop)
640 {
641     int ret = -1;
642
643     if (fd < 0) {
644         ALOGE("%s: invalid fd: %d", __func__, fd);
645         return ret;
646     }
647
648     if (!crop) {
649         ALOGE("%s: crop is NULL", __func__);
650         return ret;
651     }
652
653     if (__v4l2_check_buf_type(crop->type) == false) {
654         ALOGE("%s: unsupported buffer type", __func__);
655         return ret;
656     }
657
658     ret = ioctl(fd, VIDIOC_S_CROP, crop);
659     if (ret) {
660         ALOGE("failed to ioctl: VIDIOC_S_CROP (%d - %s)", errno, strerror(errno));
661         return ret;
662     }
663
664     return ret;
665 }
666
667 int exynos_v4l2_g_ctrl(int fd, unsigned int id, int *value)
668 {
669     int ret = -1;
670     struct v4l2_control ctrl;
671
672     ctrl.id = id;
673
674     if (fd < 0) {
675         ALOGE("%s: invalid fd: %d", __func__, fd);
676         return ret;
677     }
678
679     ret = ioctl(fd, VIDIOC_G_CTRL, &ctrl);
680     if (ret) {
681         ALOGE("failed to ioctl: VIDIOC_G_CTRL id: %x  (%d - %s)", id, errno, strerror(errno));
682         return ret;
683     }
684
685     *value = ctrl.value;
686
687     return ret;
688 }
689
690 int exynos_v4l2_s_ctrl(int fd, unsigned int id, int value)
691 {
692     int ret = -1;
693     struct v4l2_control ctrl;
694
695     ctrl.id = id;
696     ctrl.value = value;
697
698     if (fd < 0) {
699         ALOGE("%s: invalid fd: %d", __func__, fd);
700         return ret;
701     }
702
703     ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
704     if (ret) {
705         ALOGE("failed to ioctl: VIDIOC_S_CTRL id: %x (errno: %d)", id, errno);
706         return ret;
707     }
708
709     return ret;
710 }
711
712 int exynos_v4l2_g_parm(int fd, struct v4l2_streamparm *streamparm)
713 {
714     int ret = -1;
715
716     if (fd < 0) {
717         ALOGE("%s: invalid fd: %d", __func__, fd);
718         return ret;
719     }
720
721     if (__v4l2_check_buf_type(streamparm->type) == false) {
722         ALOGE("%s: unsupported buffer type", __func__);
723         return ret;
724     }
725
726     ret = ioctl(fd, VIDIOC_G_PARM, streamparm);
727     if (ret) {
728         ALOGE("failed to ioctl: VIDIOC_G_PARM (%d - %s)", errno, strerror(errno));
729         return ret;
730     }
731
732     return ret;
733 }
734
735 int exynos_v4l2_s_parm(int fd, struct v4l2_streamparm *streamparm)
736 {
737     int ret = -1;
738
739     if (fd < 0) {
740         ALOGE("%s: invalid fd: %d", __func__, fd);
741         return ret;
742     }
743
744     if (__v4l2_check_buf_type(streamparm->type) == false) {
745         ALOGE("%s: unsupported buffer type", __func__);
746         return ret;
747     }
748
749     ret = ioctl(fd, VIDIOC_S_PARM, streamparm);
750     if (ret) {
751         ALOGE("failed to ioctl: VIDIOC_S_PARM (%d - %s)", errno, strerror(errno));
752         return ret;
753     }
754
755     return ret;
756 }
757
758 int exynos_v4l2_g_ext_ctrl(int fd, struct v4l2_ext_controls *ctrl)
759 {
760     int ret = -1;
761
762     if (fd < 0) {
763         ALOGE("%s: invalid fd: %d", __func__, fd);
764         return ret;
765     }
766
767     if (ctrl == NULL) {
768         ALOGE("%s: ctrl is NULL", __func__);
769         return ret;
770     }
771
772     ret = ioctl(fd, VIDIOC_G_EXT_CTRLS, ctrl);
773     if (ret)
774         ALOGE("failed to ioctl: VIDIOC_G_EXT_CTRLS (%d - %s)", errno, strerror(errno));
775
776     return ret;
777 }
778
779 int exynos_v4l2_s_ext_ctrl(int fd, struct v4l2_ext_controls *ctrl)
780 {
781     int ret = -1;
782
783     if (fd < 0) {
784         ALOGE("%s: invalid fd: %d", __func__, fd);
785         return ret;
786     }
787
788     if (ctrl == NULL) {
789         ALOGE("%s: ctrl is NULL", __func__);
790         return ret;
791     }
792
793     ret = ioctl(fd, VIDIOC_S_EXT_CTRLS, ctrl);
794     if (ret)
795         ALOGE("failed to ioctl: VIDIOC_S_EXT_CTRLS (%d - %s)", errno, strerror(errno));
796
797     return ret;
798 }