• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
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_subdev.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 <stdarg.h>
32 #include <fcntl.h>
33 #include <sys/types.h>
34 #include <sys/ioctl.h>
35 #include <sys/stat.h>
36 
37 #include "exynos_v4l2.h"
38 
39 //#define LOG_NDEBUG 0
40 #define LOG_TAG "libexynosv4l2-subdev"
41 #include <utils/Log.h>
42 
43 #define SUBDEV_MINOR_MAX 191
44 
__subdev_open(const char * filename,int oflag,va_list ap)45 static int __subdev_open(const char *filename, int oflag, va_list ap)
46 {
47     mode_t mode = 0;
48     int fd;
49 
50     if (oflag & O_CREAT)
51         mode = va_arg(ap, int);
52 
53     fd = open(filename, oflag, mode);
54 
55     return fd;
56 }
57 
exynos_subdev_open(const char * filename,int oflag,...)58 int exynos_subdev_open(const char *filename, int oflag, ...)
59 {
60     va_list ap;
61     int fd;
62 
63     va_start(ap, oflag);
64     fd = __subdev_open(filename, oflag, ap);
65     va_end(ap);
66 
67     return fd;
68 }
69 
exynos_subdev_open_devname(const char * devname,int oflag,...)70 int exynos_subdev_open_devname(const char *devname, int oflag, ...)
71 {
72     bool found = false;
73     int fd = -1;
74     struct stat s;
75     va_list ap;
76     FILE *stream_fd;
77     char filename[64], name[64];
78     int minor, size, i = 0;
79 
80     do {
81         if (i > (SUBDEV_MINOR_MAX - 128))
82             break;
83 
84         /* video device node */
85         sprintf(filename, "/dev/v4l-subdev%d", i++);
86 
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 */
98             }
99 
100             /* read sysfs entry for device name */
101             size = (int)fgets(name, sizeof(name), stream_fd);
102             fclose(stream_fd);
103 
104             /* check read size */
105             if (size == 0) {
106                 ALOGE("failed to read sysfs entry for subdev");
107             } else {
108                 /* matched */
109                 if (strncmp(name, devname, strlen(devname)) == 0) {
110                     ALOGI("node found for device %s: /dev/v4l-subdev%d", devname, minor);
111                     found = true;
112                 }
113             }
114         }
115     } while (found == false);
116 
117     if (found) {
118         sprintf(filename, "/dev/v4l-subdev%d", minor);
119         va_start(ap, oflag);
120         fd = __subdev_open(filename, oflag, ap);
121         va_end(ap);
122 
123         if (fd > 0)
124             ALOGI("open subdev device %s", filename);
125         else
126             ALOGE("failed to open subdev device %s", filename);
127     } else {
128         ALOGE("no subdev device found");
129     }
130 
131     return fd;
132 }
133 
134 /**
135  * @brief enum frame size on a pad.
136  * @return 0 on success, or a negative error code on failure.
137  */
exynos_subdev_enum_frame_size(int fd,struct v4l2_subdev_frame_size_enum * frame_size_enum)138 int exynos_subdev_enum_frame_size(int fd, struct v4l2_subdev_frame_size_enum *frame_size_enum)
139 {
140     int ret = -1;
141 
142     if (fd < 0) {
143         ALOGE("%s: invalid fd: %d", __func__, fd);
144         return ret;
145     }
146 
147     if (!frame_size_enum) {
148         ALOGE("%s: frame_size_enum is NULL", __func__);
149         return ret;
150     }
151 
152     ret = ioctl(fd, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, frame_size_enum);
153     if (ret) {
154         ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE");
155         return ret;
156     }
157 
158     return ret;
159 }
160 
161 /**
162  * @brief Retrieve the format on a pad.
163  * @return 0 on success, or a negative error code on failure.
164  */
exynos_subdev_g_fmt(int fd,struct v4l2_subdev_format * fmt)165 int exynos_subdev_g_fmt(int fd, struct v4l2_subdev_format *fmt)
166 {
167     int ret = -1;
168 
169     if (fd < 0) {
170         ALOGE("%s: invalid fd: %d", __func__, fd);
171         return ret;
172     }
173 
174     if (!fmt) {
175         ALOGE("%s: fmt is NULL", __func__);
176         return ret;
177     }
178 
179     ret = ioctl(fd, VIDIOC_SUBDEV_G_FMT, fmt);
180     if (ret) {
181         ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_FMT");
182         return ret;
183     }
184 
185     return ret;
186 }
187 
188 /**
189  * @brief Set the format on a pad.
190  * @return 0 on success, or a negative error code on failure.
191  */
exynos_subdev_s_fmt(int fd,struct v4l2_subdev_format * fmt)192 int exynos_subdev_s_fmt(int fd, struct v4l2_subdev_format *fmt)
193 {
194     int ret = -1;
195 
196     if (fd < 0) {
197         ALOGE("%s: invalid fd: %d", __func__, fd);
198         return ret;
199     }
200 
201     if (!fmt) {
202         ALOGE("%s: fmt is NULL", __func__);
203         return ret;
204     }
205 
206     ret = ioctl(fd, VIDIOC_SUBDEV_S_FMT, fmt);
207     if (ret) {
208         ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_FMT");
209         return ret;
210     }
211 
212     return ret;
213 }
214 
215 /**
216  * @brief Retrieve the crop rectangle on a pad.
217  * @return 0 on success, or a negative error code on failure.
218  */
exynos_subdev_g_crop(int fd,struct v4l2_subdev_crop * crop)219 int exynos_subdev_g_crop(int fd, struct v4l2_subdev_crop *crop)
220 {
221     int ret = -1;
222 
223     if (fd < 0) {
224         ALOGE("%s: invalid fd: %d", __func__, fd);
225         return ret;
226     }
227 
228     if (!crop) {
229         ALOGE("%s: crop is NULL", __func__);
230         return ret;
231     }
232 
233     ret = ioctl(fd, VIDIOC_SUBDEV_G_CROP, crop);
234     if (ret) {
235         ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_CROP");
236         return ret;
237     }
238 
239     return ret;
240 }
241 
242 /**
243  * @brief Set the crop rectangle on a pad.
244  * @return 0 on success, or a negative error code on failure.
245  */
exynos_subdev_s_crop(int fd,struct v4l2_subdev_crop * crop)246 int exynos_subdev_s_crop(int fd, struct v4l2_subdev_crop *crop)
247 {
248     int ret = -1;
249 
250     if (fd < 0) {
251         ALOGE("%s: invalid fd: %d", __func__, fd);
252         return ret;
253     }
254 
255     if (!crop) {
256         ALOGE("%s: crop is NULL", __func__);
257         return ret;
258     }
259 
260     ret = ioctl(fd, VIDIOC_SUBDEV_S_CROP, crop);
261     if (ret) {
262         ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_CROP");
263         return ret;
264     }
265 
266     return ret;
267 }
268 
269 /**
270  * @brief Retrieve the frame interval on a sub-device.
271  * @return 0 on success, or a negative error code on failure.
272  */
exynos_subdev_enum_frame_interval(int fd,struct v4l2_subdev_frame_interval_enum * frame_internval_enum)273 int exynos_subdev_enum_frame_interval(int fd, struct v4l2_subdev_frame_interval_enum *frame_internval_enum)
274 {
275     int ret = -1;
276 
277     if (fd < 0) {
278         ALOGE("%s: invalid fd: %d", __func__, fd);
279         return ret;
280     }
281 
282     if (!frame_internval_enum) {
283         ALOGE("%s: frame_internval_enum is NULL", __func__);
284         return ret;
285     }
286 
287     ret = ioctl(fd, VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, frame_internval_enum);
288     if (ret) {
289         ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL");
290         return ret;
291     }
292 
293     return ret;
294 }
295 
296 /**
297  * @brief Retrieve the frame interval on a sub-device.
298  * @return 0 on success, or a negative error code on failure.
299  */
exynos_subdev_g_frame_interval(int fd,struct v4l2_subdev_frame_interval * frame_internval)300 int exynos_subdev_g_frame_interval(int fd, struct v4l2_subdev_frame_interval *frame_internval)
301 {
302     int ret = -1;
303 
304     if (fd < 0) {
305         ALOGE("%s: invalid fd: %d", __func__, fd);
306         return ret;
307     }
308 
309     if (!frame_internval) {
310         ALOGE("%s: frame_internval is NULL", __func__);
311         return ret;
312     }
313 
314     ret = ioctl(fd, VIDIOC_SUBDEV_G_FRAME_INTERVAL, frame_internval);
315     if (ret) {
316         ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_FRAME_INTERVAL");
317         return ret;
318     }
319 
320     return ret;
321 }
322 
323 /**
324  * @brief Set the frame interval on a sub-device.
325  * @return 0 on success, or a negative error code on failure.
326  */
exynos_subdev_s_frame_interval(int fd,struct v4l2_subdev_frame_interval * frame_internval)327 int exynos_subdev_s_frame_interval(int fd, struct v4l2_subdev_frame_interval *frame_internval)
328 {
329     int ret = -1;
330 
331     if (fd < 0) {
332         ALOGE("%s: invalid fd: %d", __func__, fd);
333         return ret;
334     }
335 
336     if (!frame_internval) {
337         ALOGE("%s: frame_internval is NULL", __func__);
338         return ret;
339     }
340 
341     ret = ioctl(fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, frame_internval);
342     if (ret) {
343         ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_FRAME_INTERVAL");
344         return ret;
345     }
346 
347     return ret;
348 }
349 
350 /**
351  * @brief enum mbus code
352  * @return 0 on success, or a negative error code on failure.
353  */
exynos_subdev_enum_mbus_code(int fd,struct v4l2_subdev_mbus_code_enum * mbus_code_enum)354 int exynos_subdev_enum_mbus_code(int fd, struct v4l2_subdev_mbus_code_enum *mbus_code_enum)
355 {
356     int ret = -1;
357 
358     if (fd < 0) {
359         ALOGE("%s: invalid fd: %d", __func__, fd);
360         return ret;
361     }
362 
363     if (!mbus_code_enum) {
364         ALOGE("%s: mbus_code_enum is NULL", __func__);
365         return ret;
366     }
367 
368     ret = ioctl(fd, VIDIOC_SUBDEV_ENUM_MBUS_CODE, mbus_code_enum);
369     if (ret) {
370         ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE");
371         return ret;
372     }
373 
374     return ret;
375 }
376