2 * Copyright (C) 2011 The Android Open Source Project
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 #include <utils/Log.h>
43 #define SUBDEV_MINOR_MAX 191
45 static int __subdev_open(const char *filename
, int oflag
, va_list ap
)
51 mode
= va_arg(ap
, int);
53 fd
= open(filename
, oflag
, mode
);
58 int exynos_subdev_open(const char *filename
, int oflag
, ...)
64 fd
= __subdev_open(filename
, oflag
, ap
);
70 int exynos_subdev_get_node_num(const char *devname
, int oflag
, ...)
77 char filename
[64], name
[64];
78 int minor
, size
, i
= 0;
81 if (i
> (SUBDEV_MINOR_MAX
- 128))
84 /* video device node */
85 sprintf(filename
, "/dev/v4l-subdev%d", i
++);
87 /* if the node is video device */
88 if ((lstat(filename
, &s
) == 0) && S_ISCHR(s
.st_mode
) &&
89 ((int)((unsigned short)(s
.st_rdev
) >> 8) == 81)) {
90 minor
= (int)((unsigned short)(s
.st_rdev
& 0x3f));
91 ALOGD("try node: %s, minor: %d", filename
, minor
);
92 /* open sysfs entry */
93 sprintf(filename
, "/sys/class/video4linux/v4l-subdev%d/name", minor
);
94 stream_fd
= fopen(filename
, "r");
95 if (stream_fd
== NULL
) {
96 ALOGE("failed to open sysfs entry for subdev");
97 continue; /* try next */
100 /* read sysfs entry for device name */
101 size
= (int)fgets(name
, sizeof(name
), stream_fd
);
104 /* check read size */
106 ALOGE("failed to read sysfs entry for subdev");
109 if (strncmp(name
, devname
, strlen(devname
)) == 0) {
110 ALOGI("node found for device %s: /dev/v4l-subdev%d", devname
, minor
);
115 } while (found
== false);
120 ALOGE("no subdev device found");
125 int exynos_subdev_open_devname(const char *devname
, int oflag
, ...)
132 char filename
[64], name
[64];
133 int minor
, size
, i
= 0;
136 if (i
> (SUBDEV_MINOR_MAX
- 128))
139 /* video device node */
140 sprintf(filename
, "/dev/v4l-subdev%d", i
++);
142 /* if the node is video device */
143 if ((lstat(filename
, &s
) == 0) && S_ISCHR(s
.st_mode
) &&
144 ((int)((unsigned short)(s
.st_rdev
) >> 8) == 81)) {
145 minor
= (int)((unsigned short)(s
.st_rdev
& 0x3f));
146 ALOGD("try node: %s, minor: %d", filename
, minor
);
147 /* open sysfs entry */
148 sprintf(filename
, "/sys/class/video4linux/v4l-subdev%d/name", minor
);
149 stream_fd
= fopen(filename
, "r");
150 if (stream_fd
== NULL
) {
151 ALOGE("failed to open sysfs entry for subdev");
152 continue; /* try next */
155 /* read sysfs entry for device name */
156 size
= (int)fgets(name
, sizeof(name
), stream_fd
);
159 /* check read size */
161 ALOGE("failed to read sysfs entry for subdev");
164 if (strncmp(name
, devname
, strlen(devname
)) == 0) {
165 ALOGI("node found for device %s: /dev/v4l-subdev%d", devname
, minor
);
170 } while (found
== false);
173 sprintf(filename
, "/dev/v4l-subdev%d", minor
);
175 fd
= __subdev_open(filename
, oflag
, ap
);
179 ALOGI("open subdev device %s", filename
);
181 ALOGE("failed to open subdev device %s", filename
);
183 ALOGE("no subdev device found");
189 int exynos_subdev_close(int fd
)
194 ALOGE("%s: invalid fd: %d", __func__
, fd
);
202 * @brief enum frame size on a pad.
203 * @return 0 on success, or a negative error code on failure.
205 int exynos_subdev_enum_frame_size(int fd
, struct v4l2_subdev_frame_size_enum
*frame_size_enum
)
210 ALOGE("%s: invalid fd: %d", __func__
, fd
);
214 if (!frame_size_enum
) {
215 ALOGE("%s: frame_size_enum is NULL", __func__
);
219 ret
= ioctl(fd
, VIDIOC_SUBDEV_ENUM_FRAME_SIZE
, frame_size_enum
);
221 ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE");
229 * @brief Retrieve the format on a pad.
230 * @return 0 on success, or a negative error code on failure.
232 int exynos_subdev_g_fmt(int fd
, struct v4l2_subdev_format
*fmt
)
237 ALOGE("%s: invalid fd: %d", __func__
, fd
);
242 ALOGE("%s: fmt is NULL", __func__
);
246 ret
= ioctl(fd
, VIDIOC_SUBDEV_G_FMT
, fmt
);
248 ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_FMT");
256 * @brief Set the format on a pad.
257 * @return 0 on success, or a negative error code on failure.
259 int exynos_subdev_s_fmt(int fd
, struct v4l2_subdev_format
*fmt
)
264 ALOGE("%s: invalid fd: %d", __func__
, fd
);
269 ALOGE("%s: fmt is NULL", __func__
);
273 ret
= ioctl(fd
, VIDIOC_SUBDEV_S_FMT
, fmt
);
275 ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_FMT");
283 * @brief Retrieve the crop rectangle on a pad.
284 * @return 0 on success, or a negative error code on failure.
286 int exynos_subdev_g_crop(int fd
, struct v4l2_subdev_crop
*crop
)
291 ALOGE("%s: invalid fd: %d", __func__
, fd
);
296 ALOGE("%s: crop is NULL", __func__
);
300 ret
= ioctl(fd
, VIDIOC_SUBDEV_G_CROP
, crop
);
302 ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_CROP");
310 * @brief Set the crop rectangle on a pad.
311 * @return 0 on success, or a negative error code on failure.
313 int exynos_subdev_s_crop(int fd
, struct v4l2_subdev_crop
*crop
)
318 ALOGE("%s: invalid fd: %d", __func__
, fd
);
323 ALOGE("%s: crop is NULL", __func__
);
327 ret
= ioctl(fd
, VIDIOC_SUBDEV_S_CROP
, crop
);
329 ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_CROP");
337 * @brief Retrieve the frame interval on a sub-device.
338 * @return 0 on success, or a negative error code on failure.
340 int exynos_subdev_enum_frame_interval(int fd
, struct v4l2_subdev_frame_interval_enum
*frame_internval_enum
)
345 ALOGE("%s: invalid fd: %d", __func__
, fd
);
349 if (!frame_internval_enum
) {
350 ALOGE("%s: frame_internval_enum is NULL", __func__
);
354 ret
= ioctl(fd
, VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL
, frame_internval_enum
);
356 ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL");
364 * @brief Retrieve the frame interval on a sub-device.
365 * @return 0 on success, or a negative error code on failure.
367 int exynos_subdev_g_frame_interval(int fd
, struct v4l2_subdev_frame_interval
*frame_internval
)
372 ALOGE("%s: invalid fd: %d", __func__
, fd
);
376 if (!frame_internval
) {
377 ALOGE("%s: frame_internval is NULL", __func__
);
381 ret
= ioctl(fd
, VIDIOC_SUBDEV_G_FRAME_INTERVAL
, frame_internval
);
383 ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_FRAME_INTERVAL");
391 * @brief Set the frame interval on a sub-device.
392 * @return 0 on success, or a negative error code on failure.
394 int exynos_subdev_s_frame_interval(int fd
, struct v4l2_subdev_frame_interval
*frame_internval
)
399 ALOGE("%s: invalid fd: %d", __func__
, fd
);
403 if (!frame_internval
) {
404 ALOGE("%s: frame_internval is NULL", __func__
);
408 ret
= ioctl(fd
, VIDIOC_SUBDEV_S_FRAME_INTERVAL
, frame_internval
);
410 ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_FRAME_INTERVAL");
418 * @brief enum mbus code
419 * @return 0 on success, or a negative error code on failure.
421 int exynos_subdev_enum_mbus_code(int fd
, struct v4l2_subdev_mbus_code_enum
*mbus_code_enum
)
426 ALOGE("%s: invalid fd: %d", __func__
, fd
);
430 if (!mbus_code_enum
) {
431 ALOGE("%s: mbus_code_enum is NULL", __func__
);
435 ret
= ioctl(fd
, VIDIOC_SUBDEV_ENUM_MBUS_CODE
, mbus_code_enum
);
437 ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE");