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.
18 * \file exynos_subdev.c
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
33 #include <sys/types.h>
34 #include <sys/ioctl.h>
37 #include "exynos_v4l2.h"
39 //#define LOG_NDEBUG 0
40 #define LOG_TAG "libexynosv4l2-subdev"
41 #ifndef TIZEN_FEATURE_E3250 /* build env */
42 #include <utils/Log.h>
44 #include "Exynos_OSAL_Log.h"
47 #define SUBDEV_MINOR_MAX 191
49 static int __subdev_open(const char *filename, int oflag, va_list ap)
55 mode = va_arg(ap, int);
57 fd = open(filename, oflag, mode);
62 int exynos_subdev_open(const char *filename, int oflag, ...)
68 fd = __subdev_open(filename, oflag, ap);
74 int exynos_subdev_open_devname(const char *devname, int oflag, ...)
81 char filename[64], name[64];
82 int minor, size, i = 0;
85 if (i > (SUBDEV_MINOR_MAX - 128))
88 /* video device node */
89 sprintf(filename, "/dev/v4l-subdev%d", i++);
91 /* if the node is video device */
92 if ((lstat(filename, &s) == 0) && S_ISCHR(s.st_mode) &&
93 ((int)((unsigned short)(s.st_rdev) >> 8) == 81)) {
94 minor = (int)((unsigned short)(s.st_rdev & 0x3f));
95 ALOGD("try node: %s, minor: %d", filename, minor);
96 /* open sysfs entry */
97 sprintf(filename, "/sys/class/video4linux/v4l-subdev%d/name", minor);
98 stream_fd = fopen(filename, "r");
99 if (stream_fd == NULL) {
100 ALOGE("failed to open sysfs entry for subdev");
101 continue; /* try next */
104 /* read sysfs entry for device name */
105 size = (int)fgets(name, sizeof(name), stream_fd);
108 /* check read size */
110 ALOGE("failed to read sysfs entry for subdev");
113 if (strncmp(name, devname, strlen(devname)) == 0) {
114 ALOGI("node found for device %s: /dev/v4l-subdev%d", devname, minor);
119 } while (found == false);
122 sprintf(filename, "/dev/v4l-subdev%d", minor);
124 fd = __subdev_open(filename, oflag, ap);
128 ALOGI("open subdev device %s", filename);
130 ALOGE("failed to open subdev device %s", filename);
132 ALOGE("no subdev device found");
139 * @brief enum frame size on a pad.
140 * @return 0 on success, or a negative error code on failure.
142 int exynos_subdev_enum_frame_size(int fd, struct v4l2_subdev_frame_size_enum *frame_size_enum)
147 ALOGE("%s: invalid fd: %d", __func__, fd);
151 if (!frame_size_enum) {
152 ALOGE("%s: frame_size_enum is NULL", __func__);
156 ret = ioctl(fd, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, frame_size_enum);
158 ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE");
166 * @brief Retrieve the format on a pad.
167 * @return 0 on success, or a negative error code on failure.
169 int exynos_subdev_g_fmt(int fd, struct v4l2_subdev_format *fmt)
174 ALOGE("%s: invalid fd: %d", __func__, fd);
179 ALOGE("%s: fmt is NULL", __func__);
183 ret = ioctl(fd, VIDIOC_SUBDEV_G_FMT, fmt);
185 ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_FMT");
193 * @brief Set the format on a pad.
194 * @return 0 on success, or a negative error code on failure.
196 int exynos_subdev_s_fmt(int fd, struct v4l2_subdev_format *fmt)
201 ALOGE("%s: invalid fd: %d", __func__, fd);
206 ALOGE("%s: fmt is NULL", __func__);
210 ret = ioctl(fd, VIDIOC_SUBDEV_S_FMT, fmt);
212 ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_FMT");
220 * @brief Retrieve the crop rectangle on a pad.
221 * @return 0 on success, or a negative error code on failure.
223 int exynos_subdev_g_crop(int fd, struct v4l2_subdev_crop *crop)
228 ALOGE("%s: invalid fd: %d", __func__, fd);
233 ALOGE("%s: crop is NULL", __func__);
237 ret = ioctl(fd, VIDIOC_SUBDEV_G_CROP, crop);
239 ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_CROP");
247 * @brief Set the crop rectangle on a pad.
248 * @return 0 on success, or a negative error code on failure.
250 int exynos_subdev_s_crop(int fd, struct v4l2_subdev_crop *crop)
255 ALOGE("%s: invalid fd: %d", __func__, fd);
260 ALOGE("%s: crop is NULL", __func__);
264 ret = ioctl(fd, VIDIOC_SUBDEV_S_CROP, crop);
266 ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_CROP");
274 * @brief Retrieve the frame interval on a sub-device.
275 * @return 0 on success, or a negative error code on failure.
277 int exynos_subdev_enum_frame_interval(int fd, struct v4l2_subdev_frame_interval_enum *frame_internval_enum)
282 ALOGE("%s: invalid fd: %d", __func__, fd);
286 if (!frame_internval_enum) {
287 ALOGE("%s: frame_internval_enum is NULL", __func__);
291 ret = ioctl(fd, VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, frame_internval_enum);
293 ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL");
301 * @brief Retrieve the frame interval on a sub-device.
302 * @return 0 on success, or a negative error code on failure.
304 int exynos_subdev_g_frame_interval(int fd, struct v4l2_subdev_frame_interval *frame_internval)
309 ALOGE("%s: invalid fd: %d", __func__, fd);
313 if (!frame_internval) {
314 ALOGE("%s: frame_internval is NULL", __func__);
318 ret = ioctl(fd, VIDIOC_SUBDEV_G_FRAME_INTERVAL, frame_internval);
320 ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_FRAME_INTERVAL");
328 * @brief Set the frame interval on a sub-device.
329 * @return 0 on success, or a negative error code on failure.
331 int exynos_subdev_s_frame_interval(int fd, struct v4l2_subdev_frame_interval *frame_internval)
336 ALOGE("%s: invalid fd: %d", __func__, fd);
340 if (!frame_internval) {
341 ALOGE("%s: frame_internval is NULL", __func__);
345 ret = ioctl(fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, frame_internval);
347 ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_FRAME_INTERVAL");
355 * @brief enum mbus code
356 * @return 0 on success, or a negative error code on failure.
358 int exynos_subdev_enum_mbus_code(int fd, struct v4l2_subdev_mbus_code_enum *mbus_code_enum)
363 ALOGE("%s: invalid fd: %d", __func__, fd);
367 if (!mbus_code_enum) {
368 ALOGE("%s: mbus_code_enum is NULL", __func__);
372 ret = ioctl(fd, VIDIOC_SUBDEV_ENUM_MBUS_CODE, mbus_code_enum);
374 ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE");