2 * Copyright 2012 Samsung Electronics S.LSI Co. LTD
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * \brief source file for libv4l2
20 * \author Jinsung Yang (jsgood.yang@samsung.com)
21 * \author Sangwoo Park (sw5771.park@samsung.com)
24 * <b>Revision History: </b>
25 * - 2012/01/17: Jinsung Yang (jsgood.yang@samsung.com) \n
35 #include <sys/types.h>
36 #include <sys/ioctl.h>
39 #include "exynos_v4l2.h"
41 //#define LOG_NDEBUG 0
42 #define LOG_TAG "libexynosv4l2"
43 #ifndef SLP_PLATFORM /* build env */
44 #include <utils/Log.h>
46 #include "Exynos_OSAL_Log.h"
49 #define VIDEODEV_MAX 255
51 static bool __v4l2_check_buf_type(enum v4l2_buf_type 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:
65 supported = (type >= V4L2_BUF_TYPE_PRIVATE) ? true : false;
72 static int __v4l2_open(const char *filename, int oflag, va_list ap)
78 mode = va_arg(ap, int);
80 fd = open(filename, oflag, mode);
85 int exynos_v4l2_open(const char *filename, int oflag, ...)
91 fd = __v4l2_open(filename, oflag, ap);
97 int exynos_v4l2_open_devname(const char *devname, int oflag, ...)
104 char filename[64], name[64];
108 if (i > VIDEODEV_MAX)
111 /* video device node */
112 snprintf(filename, sizeof(filename), "/dev/video%d", i);
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");
124 stream_fd = fopen(filename, "r");
125 if (stream_fd == NULL) {
126 ALOGE("failed to open sysfs entry for videodev");
128 continue; /* try next */
131 /* read sysfs entry for device name */
132 size = (int)fgets(name, sizeof(name), stream_fd);
135 /* check read size */
137 ALOGE("failed to read sysfs entry for videodev");
140 if (strncmp(name, devname, strlen(devname)) == 0) {
141 ALOGI("node found for device %s: /dev/video%d", devname, i);
148 } while (found == false);
151 snprintf(filename, sizeof(filename), "/dev/video%d", i);
153 fd = __v4l2_open(filename, oflag, ap);
157 ALOGI("open video device %s", filename);
159 ALOGE("failed to open video device %s", filename);
161 ALOGE("no video device found");
167 int exynos_v4l2_close(int fd)
172 ALOGE("%s: invalid fd: %d", __func__, fd);
179 bool exynos_v4l2_enuminput(int fd, int index, char *input_name_buf)
182 struct v4l2_input input;
185 ALOGE("%s: invalid fd: %d", __func__, fd);
190 ret = ioctl(fd, VIDIOC_ENUMINPUT, &input);
192 ALOGE("%s: no matching index founds", __func__);
196 ALOGI("Name of input channel[%d] is %s", input.index, input.name);
198 strcpy(input_name_buf, (const char *)input.name);
203 int exynos_v4l2_s_input(int fd, int index)
206 struct v4l2_input input;
209 ALOGE("%s: invalid fd: %d", __func__, fd);
215 ret = ioctl(fd, VIDIOC_S_INPUT, &input);
217 ALOGE("failed to ioctl: VIDIOC_S_INPUT (%d - %s)", errno, strerror(errno));
224 bool exynos_v4l2_querycap(int fd, unsigned int need_caps)
226 struct v4l2_capability cap;
230 ALOGE("%s: invalid fd: %d", __func__, fd);
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__);
243 memset(&cap, 0, sizeof(cap));
245 ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
247 ALOGE("failed to ioctl: VIDIOC_QUERYCAP (%d - %s)", errno, strerror(errno));
251 if ((need_caps & cap.capabilities) != need_caps) {
252 ALOGE("%s: unsupported capabilities", __func__);
259 bool exynos_v4l2_enum_fmt(int fd, enum v4l2_buf_type type, unsigned int fmt)
261 struct v4l2_fmtdesc fmtdesc;
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);
278 ALOGE("%s: unsupported pixel format", __func__);
285 int exynos_v4l2_g_fmt(int fd, struct v4l2_format *fmt)
290 ALOGE("%s: invalid fd: %d", __func__, fd);
295 ALOGE("%s: fmt is NULL", __func__);
299 if (__v4l2_check_buf_type(fmt->type) == false) {
300 ALOGE("%s: unsupported buffer type", __func__);
304 ret = ioctl(fd, VIDIOC_G_FMT, fmt);
306 ALOGE("failed to ioctl: VIDIOC_G_FMT (%d - %s)", errno, strerror(errno));
313 static int __v4l2_s_fmt(int fd, unsigned int request, struct v4l2_format *fmt)
318 ALOGE("%s: invalid fd: %d", __func__, fd);
323 ALOGE("%s: fmt is NULL", __func__);
327 if (__v4l2_check_buf_type(fmt->type) == false) {
328 ALOGE("%s: unsupported buffer type", __func__);
331 ret = ioctl(fd, request, fmt);
333 if (request == VIDIOC_TRY_FMT)
334 ALOGE("failed to ioctl: VIDIOC_TRY_FMT (%d - %s)", errno, strerror(errno));
336 ALOGE("failed to ioctl: VIDIOC_S_FMT (%d - %s)", errno, strerror(errno));
345 int exynos_v4l2_try_fmt(int fd, struct v4l2_format *fmt)
347 return __v4l2_s_fmt(fd, VIDIOC_TRY_FMT, fmt);
350 int exynos_v4l2_s_fmt(int fd, struct v4l2_format *fmt)
352 return __v4l2_s_fmt(fd, VIDIOC_S_FMT, fmt);
355 int exynos_v4l2_reqbufs(int fd, struct v4l2_requestbuffers *req)
361 ALOGE("%s: invalid fd: %d", __func__, fd);
366 ALOGE("%s: req is NULL", __func__);
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__);
377 if (__v4l2_check_buf_type(req->type) == false) {
378 ALOGE("%s: unsupported buffer type", __func__);
384 ret = ioctl(fd, VIDIOC_REQBUFS, req);
386 ALOGE("failed to ioctl: VIDIOC_REQBUFS (%d - %s)", ret, strerror(errno));
390 if (count != req->count) {
391 ALOGW("number of buffers had been changed: %d => %d", count, req->count);
397 int exynos_v4l2_querybuf(int fd, struct v4l2_buffer *buf)
402 ALOGE("%s: invalid fd: %d", __func__, fd);
407 ALOGE("%s: buf is NULL", __func__);
411 if ((buf->memory != V4L2_MEMORY_MMAP) &&
412 (buf->memory != V4L2_MEMORY_DMABUF)) {
413 ALOGE("%s: unsupported memory type", __func__);
417 if (__v4l2_check_buf_type(buf->type) == false) {
418 ALOGE("%s: unsupported buffer type", __func__);
422 ret = ioctl(fd, VIDIOC_QUERYBUF, buf);
424 ALOGE("failed to ioctl: VIDIOC_QUERYBUF (%d - %s)", errno, strerror(errno));
431 #ifdef SLP_PLATFORM /*dmabuf */
433 #ifndef VIDIOC_EXPBUF
434 struct v4l2_exportbuffer {
441 #define VIDIOC_EXPBUF _IOWR('V', 16, struct v4l2_exportbuffer)
444 int exynos_v4l2_expbuf(int fd, int *buf_fd, __u32 mem_offset)
447 struct v4l2_exportbuffer expbuf;
450 ALOGE("%s: invalid fd: %d", __func__, fd);
451 ALOGE("%s: invalid fd: %d", __func__, fd);
455 expbuf.flags = O_CLOEXEC;
456 //expbuf.mem_offset = mem_offset;
457 ALOGE("%s: fd:%d mem_offset:%d", __func__, fd, mem_offset);
459 ret = ioctl(fd, VIDIOC_EXPBUF, &expbuf);
461 ALOGE("failed to ioctl: VIDIOC_EXPBUF (%d - %s)", errno, strerror(errno));
464 ALOGE("%s: got fd: %d", __func__, expbuf.fd);
471 int exynos_v4l2_qbuf(int fd, struct v4l2_buffer *buf)
476 ALOGE("%s: invalid fd: %d", __func__, fd);
481 ALOGE("%s: buf is NULL", __func__);
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__);
492 if (__v4l2_check_buf_type(buf->type) == false) {
493 ALOGE("%s: unsupported buffer type", __func__);
497 ret = ioctl(fd, VIDIOC_QBUF, buf);
499 ALOGE("failed to ioctl: VIDIOC_QBUF (%d - %s)", errno, strerror(errno));
506 int exynos_v4l2_dqbuf(int fd, struct v4l2_buffer *buf)
511 ALOGE("%s: invalid fd: %d", __func__, fd);
516 ALOGE("%s: buf is NULL", __func__);
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__);
527 if (__v4l2_check_buf_type(buf->type) == false) {
528 ALOGE("%s: unsupported buffer type", __func__);
532 ret = ioctl(fd, VIDIOC_DQBUF, buf);
537 int exynos_v4l2_streamon(int fd, enum v4l2_buf_type type)
542 ALOGE("%s: invalid fd: %d", __func__, fd);
546 if (__v4l2_check_buf_type(type) == false) {
547 ALOGE("%s: unsupported buffer type", __func__);
551 ret = ioctl(fd, VIDIOC_STREAMON, &type);
553 ALOGE("failed to ioctl: VIDIOC_STREAMON (%d - %s)", errno, strerror(errno));
560 int exynos_v4l2_streamoff(int fd, enum v4l2_buf_type type)
565 ALOGE("%s: invalid fd: %d", __func__, fd);
569 if (__v4l2_check_buf_type(type) == false) {
570 ALOGE("%s: unsupported buffer type", __func__);
574 ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
576 ALOGE("failed to ioctl: VIDIOC_STREAMOFF (%d - %s)", errno, strerror(errno));
583 int exynos_v4l2_cropcap(int fd, struct v4l2_cropcap *crop)
588 ALOGE("%s: invalid fd: %d", __func__, fd);
593 ALOGE("%s: crop is NULL", __func__);
597 if (__v4l2_check_buf_type(crop->type) == false) {
598 ALOGE("%s: unsupported buffer type", __func__);
602 ret = ioctl(fd, VIDIOC_CROPCAP, crop);
604 ALOGE("failed to ioctl: VIDIOC_CROPCAP (%d - %s)", errno, strerror(errno));
611 int exynos_v4l2_g_crop(int fd, struct v4l2_crop *crop)
616 ALOGE("%s: invalid fd: %d", __func__, fd);
621 ALOGE("%s: crop is NULL", __func__);
625 if (__v4l2_check_buf_type(crop->type) == false) {
626 ALOGE("%s: unsupported buffer type", __func__);
630 ret = ioctl(fd, VIDIOC_G_CROP, crop);
632 ALOGE("failed to ioctl: VIDIOC_G_CROP (%d - %s)", errno, strerror(errno));
639 int exynos_v4l2_s_crop(int fd, struct v4l2_crop *crop)
644 ALOGE("%s: invalid fd: %d", __func__, fd);
649 ALOGE("%s: crop is NULL", __func__);
653 if (__v4l2_check_buf_type(crop->type) == false) {
654 ALOGE("%s: unsupported buffer type", __func__);
658 ret = ioctl(fd, VIDIOC_S_CROP, crop);
660 ALOGE("failed to ioctl: VIDIOC_S_CROP (%d - %s)", errno, strerror(errno));
667 int exynos_v4l2_g_ctrl(int fd, unsigned int id, int *value)
670 struct v4l2_control ctrl;
675 ALOGE("%s: invalid fd: %d", __func__, fd);
679 ret = ioctl(fd, VIDIOC_G_CTRL, &ctrl);
681 ALOGE("failed to ioctl: VIDIOC_G_CTRL id: %x (%d - %s)", id, errno, strerror(errno));
690 int exynos_v4l2_s_ctrl(int fd, unsigned int id, int value)
693 struct v4l2_control ctrl;
699 ALOGE("%s: invalid fd: %d", __func__, fd);
703 ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
705 ALOGE("failed to ioctl: VIDIOC_S_CTRL id: %x (errno: %d)", id, errno);
712 int exynos_v4l2_g_parm(int fd, struct v4l2_streamparm *streamparm)
717 ALOGE("%s: invalid fd: %d", __func__, fd);
721 if (__v4l2_check_buf_type(streamparm->type) == false) {
722 ALOGE("%s: unsupported buffer type", __func__);
726 ret = ioctl(fd, VIDIOC_G_PARM, streamparm);
728 ALOGE("failed to ioctl: VIDIOC_G_PARM (%d - %s)", errno, strerror(errno));
735 int exynos_v4l2_s_parm(int fd, struct v4l2_streamparm *streamparm)
740 ALOGE("%s: invalid fd: %d", __func__, fd);
744 if (__v4l2_check_buf_type(streamparm->type) == false) {
745 ALOGE("%s: unsupported buffer type", __func__);
749 ret = ioctl(fd, VIDIOC_S_PARM, streamparm);
751 ALOGE("failed to ioctl: VIDIOC_S_PARM (%d - %s)", errno, strerror(errno));
758 int exynos_v4l2_g_ext_ctrl(int fd, struct v4l2_ext_controls *ctrl)
763 ALOGE("%s: invalid fd: %d", __func__, fd);
768 ALOGE("%s: ctrl is NULL", __func__);
772 ret = ioctl(fd, VIDIOC_G_EXT_CTRLS, ctrl);
774 ALOGE("failed to ioctl: VIDIOC_G_EXT_CTRLS (%d - %s)", errno, strerror(errno));
779 int exynos_v4l2_s_ext_ctrl(int fd, struct v4l2_ext_controls *ctrl)
784 ALOGE("%s: invalid fd: %d", __func__, fd);
789 ALOGE("%s: ctrl is NULL", __func__);
793 ret = ioctl(fd, VIDIOC_S_EXT_CTRLS, ctrl);
795 ALOGE("failed to ioctl: VIDIOC_S_EXT_CTRLS (%d - %s)", errno, strerror(errno));