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