#
common_exynos_dirs := \
- libcsc
+ libcsc \
+ libv4l2
include $(call all-named-subdir-makefiles,$(common_exynos_dirs))
--- /dev/null
+# Copyright (C) 2011 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ exynos_v4l2.c \
+ exynos_subdev.c \
+ exynos_mc.c
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/../include \
+ $(TOP)/hardware/samsung_slsi/exynos/libexynosutils
+
+LOCAL_SHARED_LIBRARIES := \
+ liblog \
+ libutils \
+ libexynosutils
+
+LOCAL_MODULE := libexynosv4l2
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_TAGS := eng
+
+include $(BUILD_SHARED_LIBRARY)
--- /dev/null
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+ * \file exynos_mc.c
+ * \brief source file for libexynosv4l2
+ * \author Jinsung Yang (jsgood.yang@samsung.com)
+ * \author Sangwoo Park (sw5771.park@samsung.com)
+ * \date 2012/01/17
+ *
+ * <b>Revision History: </b>
+ * - 2012/01/17: Jinsung Yang (jsgood.yang@samsung.com) \n
+ * Initial version
+ *
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <media.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+
+#include "exynos_v4l2.h"
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "libexynosv4l2-mc"
+#include <utils/Log.h>
+
+static inline unsigned int __media_entity_type(struct media_entity *entity)
+{
+ return entity->info.type & MEDIA_ENT_TYPE_MASK;
+}
+
+static void __media_debug_default(void *ptr, ...)
+{
+ va_list argptr;
+ va_start(argptr, ptr);
+ vprintf((const char*)ptr, argptr);
+ va_end(argptr);
+}
+
+static void __media_debug_set_handler(
+ struct media_device *media,
+ void (*debug_handler)(void *, ...),
+ void *debug_priv)
+{
+ if (debug_handler) {
+ media->debug_handler = debug_handler;
+ media->debug_priv = debug_priv;
+ } else {
+ media->debug_handler = __media_debug_default;
+ media->debug_priv = NULL;
+ }
+}
+
+static struct media_link *__media_entity_add_link(struct media_entity *entity)
+{
+ if (entity->num_links >= entity->max_links) {
+ struct media_link *links = entity->links;
+ unsigned int max_links = entity->max_links * 2;
+ unsigned int i;
+
+ links = (struct media_link*)realloc(links, max_links * sizeof *links);
+ if (links == NULL)
+ return NULL;
+
+ for (i = 0; i < entity->num_links; ++i)
+ links[i].twin->twin = &links[i];
+
+ entity->max_links = max_links;
+ entity->links = links;
+ }
+
+ return &entity->links[entity->num_links++];
+}
+
+
+static int __media_enum_links(struct media_device *media)
+{
+ ALOGD("%s: start", __func__);
+ __u32 id;
+ int ret = 0;
+
+ for (id = 1; id <= media->entities_count; id++) {
+ struct media_entity *entity = &media->entities[id - 1];
+ struct media_links_enum links;
+ unsigned int i;
+
+ links.entity = entity->info.id;
+ links.pads = (struct media_pad_desc*)malloc(entity->info.pads * sizeof(struct media_pad_desc));
+ links.links = (struct media_link_desc*)malloc(entity->info.links * sizeof(struct media_link_desc));
+
+ if (ioctl(media->fd, MEDIA_IOC_ENUM_LINKS, &links) < 0) {
+ ALOGE("Unable to enumerate pads and links (%s)", strerror(errno));
+ free(links.pads);
+ free(links.links);
+ return -errno;
+ }
+
+ for (i = 0; i < entity->info.pads; ++i) {
+ entity->pads[i].entity = entity;
+ entity->pads[i].index = links.pads[i].index;
+ entity->pads[i].flags = links.pads[i].flags;
+ }
+
+ for (i = 0; i < entity->info.links; ++i) {
+ struct media_link_desc *link = &links.links[i];
+ struct media_link *fwdlink;
+ struct media_link *backlink;
+ struct media_entity *source;
+ struct media_entity *sink;
+
+ source = exynos_media_get_entity_by_id(media, link->source.entity);
+ sink = exynos_media_get_entity_by_id(media, link->sink.entity);
+ if (source == NULL || sink == NULL) {
+ ALOGE("WARNING entity %u link %u from %u/%u to %u/%u is invalid!",
+ id, i, link->source.entity,
+ link->source.index,
+ link->sink.entity,
+ link->sink.index);
+ ret = -EINVAL;
+ } else {
+ fwdlink = __media_entity_add_link(source);
+ fwdlink->source = &source->pads[link->source.index];
+ fwdlink->sink = &sink->pads[link->sink.index];
+ fwdlink->flags = link->flags;
+
+ backlink = __media_entity_add_link(sink);
+ backlink->source = &source->pads[link->source.index];
+ backlink->sink = &sink->pads[link->sink.index];
+ backlink->flags = link->flags;
+
+ fwdlink->twin = backlink;
+ backlink->twin = fwdlink;
+ }
+ }
+
+ free(links.pads);
+ free(links.links);
+ }
+ return ret;
+}
+
+static int __media_get_devname_sysfs(struct media_entity *entity)
+{
+ //struct stat devstat;
+ char devname[32];
+ char sysname[32];
+ char target[1024];
+ char *p;
+ int ret;
+
+ sprintf(sysname, "/sys/dev/char/%u:%u", entity->info.v4l.major,
+ entity->info.v4l.minor);
+
+ ret = readlink(sysname, target, sizeof(target));
+ if (ret < 0)
+ return -errno;
+
+ target[ret] = '\0';
+ p = strrchr(target, '/');
+ if (p == NULL)
+ return -EINVAL;
+
+ sprintf(devname, "/tmp/%s", p + 1);
+
+ ret = mknod(devname, 0666 | S_IFCHR, MKDEV(81, entity->info.v4l.minor));
+ strcpy(entity->devname, devname);
+
+ return 0;
+}
+
+static int __media_get_media_fd(const char *filename, struct media_device *media)
+{
+ ssize_t num;
+ int media_node;
+ char *ptr;
+ char media_buf[6];
+
+ ALOGD("%s: %s", __func__, filename);
+
+ media->fd = open(filename, O_RDWR, 0);
+ if (media->fd < 0) {
+ ALOGE("Open sysfs media device failed, media->fd: %d", media->fd);
+ return -1;
+ }
+
+ ALOGD("%s: media->fd: %d", __func__, media->fd);
+
+ return media->fd;
+
+}
+
+static int __media_enum_entities(struct media_device *media)
+{
+ struct media_entity *entity, *temp_entity;
+ unsigned int size;
+ __u32 id;
+ int ret;
+
+ temp_entity = entity = (struct media_entity*)calloc(1, sizeof(struct media_entity));
+ for (id = 0, ret = 0; ; id = entity->info.id) {
+ size = (media->entities_count + 1) * sizeof(*media->entities);
+ media->entities = (struct media_entity*)realloc(media->entities, size);
+
+ entity = &media->entities[media->entities_count];
+ memset(entity, 0, sizeof(*entity));
+ entity->fd = -1;
+ entity->info.id = id | MEDIA_ENT_ID_FLAG_NEXT;
+ entity->media = media;
+
+ ret = ioctl(media->fd, MEDIA_IOC_ENUM_ENTITIES, &entity->info);
+
+ if (ret < 0) {
+ ret = errno != EINVAL ? -errno : 0;
+ break;
+ }
+
+ /* Number of links (for outbound links) plus number of pads (for
+ * inbound links) is a good safe initial estimate of the total
+ * number of links.
+ */
+ entity->max_links = entity->info.pads + entity->info.links;
+
+ entity->pads = (struct media_pad*)malloc(entity->info.pads * sizeof(*entity->pads));
+ entity->links = (struct media_link*)malloc(entity->max_links * sizeof(*entity->links));
+ if (entity->pads == NULL || entity->links == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ media->entities_count++;
+
+ /* Find the corresponding device name. */
+ if (__media_entity_type(entity) != MEDIA_ENT_T_DEVNODE &&
+ __media_entity_type(entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+ continue;
+
+ /* Fall back to get the device name via sysfs */
+ __media_get_devname_sysfs(entity);
+ if (ret < 0)
+ ALOGE("media_get_devname failed");
+ }
+ free(temp_entity);
+
+ return ret;
+}
+
+static struct media_device *__media_open_debug(
+ const char *filename,
+ void (*debug_handler)(void *, ...),
+ void *debug_priv)
+{
+ struct media_device *media;
+ int ret;
+
+ media = (struct media_device *)calloc(1, sizeof(struct media_device));
+ if (media == NULL) {
+ ALOGE("media: %p", media);
+ return NULL;
+ }
+
+ __media_debug_set_handler(media, debug_handler, debug_priv);
+
+ ALOGD("%s: Opening media device %s", __func__, filename);
+ ALOGD("%s: media: %p", __func__, media);
+
+ media->fd = __media_get_media_fd(filename, media);
+ if (media->fd < 0) {
+ exynos_media_close(media);
+ ALOGE("failed __media_get_media_fd %s", filename);
+ return NULL;
+ }
+
+ ALOGD("%s: media->fd: %d", __func__, media->fd);
+ ret = __media_enum_entities(media);
+
+ if (ret < 0) {
+ ALOGE("Unable to enumerate entities for device %s (%s)", filename, strerror(-ret));
+ exynos_media_close(media);
+ return NULL;
+ }
+
+ ALOGD("%s: Found %u entities", __func__, media->entities_count);
+ ALOGD("%s: Enumerating pads and links", __func__);
+
+ ret = __media_enum_links(media);
+ if (ret < 0) {
+ ALOGE("Unable to enumerate pads and links for device %s", filename);
+ exynos_media_close(media);
+ return NULL;
+ }
+
+ return media;
+}
+
+/**
+ * @brief Open a media device.
+ * @param filename - name (including path) of the device node.
+ *
+ * Open the media device referenced by @a filename and enumerate entities, pads and
+ * links.
+ *
+ * @return A pointer to a newly allocated media_device structure instance on
+ * success and NULL on failure. The returned pointer must be freed with
+ * exynos_media_close when the device isn't needed anymore.
+ */
+struct media_device *exynos_media_open(const char *filename)
+{
+ return __media_open_debug(filename, (void (*)(void *, ...))fprintf, stdout);
+}
+
+/**
+ * @brief Close a media device.
+ * @param media - device instance.
+ *
+ * Close the @a media device instance and free allocated resources. Access to the
+ * device instance is forbidden after this function returns.
+ */
+void exynos_media_close(struct media_device *media)
+{
+ unsigned int i;
+
+ if (media->fd != -1)
+ close(media->fd);
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ free(entity->pads);
+ free(entity->links);
+ if (entity->fd != -1)
+ close(entity->fd);
+ }
+
+ free(media->entities);
+ free(media);
+}
+
+/**
+ * @brief Locate the pad at the other end of a link.
+ * @param pad - sink pad at one end of the link.
+ *
+ * Locate the source pad connected to @a pad through an enabled link. As only one
+ * link connected to a sink pad can be enabled at a time, the connected source
+ * pad is guaranteed to be unique.
+ *
+ * @return A pointer to the connected source pad, or NULL if all links connected
+ * to @a pad are disabled. Return NULL also if @a pad is not a sink pad.
+ */
+struct media_pad *exynos_media_entity_remote_source(struct media_pad *pad)
+{
+ unsigned int i;
+
+ if (!(pad->flags & MEDIA_PAD_FL_SINK))
+ return NULL;
+
+ for (i = 0; i < pad->entity->num_links; ++i) {
+ struct media_link *link = &pad->entity->links[i];
+
+ if (!(link->flags & MEDIA_LNK_FL_ENABLED))
+ continue;
+
+ if (link->sink == pad)
+ return link->source;
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief Find an entity by its name.
+ * @param media - media device.
+ * @param name - entity name.
+ * @param length - size of @a name.
+ *
+ * Search for an entity with a name equal to @a name.
+ *
+ * @return A pointer to the entity if found, or NULL otherwise.
+ */
+struct media_entity *exynos_media_get_entity_by_name(struct media_device *media,
+ const char *name, size_t length)
+{
+ unsigned int i;
+ struct media_entity *entity;
+
+ for (i = 0; i < media->entities_count; ++i) {
+ entity = &media->entities[i];
+
+ if (strncmp(entity->info.name, name, length) == 0)
+ return entity;
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief Find an entity by its ID.
+ * @param media - media device.
+ * @param id - entity ID.
+ *
+ * Search for an entity with an ID equal to @a id.
+ *
+ * @return A pointer to the entity if found, or NULL otherwise.
+ */
+struct media_entity *exynos_media_get_entity_by_id(struct media_device *media,
+ __u32 id)
+{
+ unsigned int i;
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ if (entity->info.id == id)
+ return entity;
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief Configure a link.
+ * @param media - media device.
+ * @param source - source pad at the link origin.
+ * @param sink - sink pad at the link target.
+ * @param flags - configuration flags.
+ *
+ * Locate the link between @a source and @a sink, and configure it by applying
+ * the new @a flags.
+ *
+ * Only the MEDIA_LINK_FLAG_ENABLED flag is writable.
+ *
+ * @return 0 on success, -1 on failure:
+ * -ENOENT: link not found
+ * - other error codes returned by MEDIA_IOC_SETUP_LINK
+ */
+int exynos_media_setup_link(struct media_device *media,
+ struct media_pad *source,
+ struct media_pad *sink,
+ __u32 flags)
+{
+ struct media_link *link;
+ struct media_link_desc ulink;
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < source->entity->num_links; i++) {
+ link = &source->entity->links[i];
+
+ if (link->source->entity == source->entity &&
+ link->source->index == source->index &&
+ link->sink->entity == sink->entity &&
+ link->sink->index == sink->index)
+ break;
+ }
+
+ if (i == source->entity->num_links) {
+ ALOGE("Link not found");
+ return -ENOENT;
+ }
+
+ /* source pad */
+ ulink.source.entity = source->entity->info.id;
+ ulink.source.index = source->index;
+ ulink.source.flags = MEDIA_PAD_FL_SOURCE;
+
+ /* sink pad */
+ ulink.sink.entity = sink->entity->info.id;
+ ulink.sink.index = sink->index;
+ ulink.sink.flags = MEDIA_PAD_FL_SINK;
+
+ ulink.flags = flags | (link->flags & MEDIA_LNK_FL_IMMUTABLE);
+
+ ret = ioctl(media->fd, MEDIA_IOC_SETUP_LINK, &ulink);
+ if (ret == -1) {
+ ALOGE("Unable to setup link (%s)", strerror(errno));
+ return -errno;
+ }
+
+ link->flags = ulink.flags;
+ link->twin->flags = ulink.flags;
+ return 0;
+}
+
+/**
+ * @brief Reset all links to the disabled state.
+ * @param media - media device.
+ *
+ * Disable all links in the media device. This function is usually used after
+ * opening a media device to reset all links to a known state.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_media_reset_links(struct media_device *media)
+{
+ unsigned int i, j;
+ int ret;
+
+ for (i = 0; i < media->entities_count; ++i) {
+ struct media_entity *entity = &media->entities[i];
+
+ for (j = 0; j < entity->num_links; j++) {
+ struct media_link *link = &entity->links[j];
+
+ if (link->flags & MEDIA_LNK_FL_IMMUTABLE ||
+ link->source->entity != entity)
+ continue;
+
+ ret = exynos_media_setup_link(media, link->source, link->sink,
+ link->flags & ~MEDIA_LNK_FL_ENABLED);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+#ifdef HAVE_LIBUDEV
+
+#include <libudev.h>
+
+static inline int __media_udev_open(struct udev **udev)
+{
+ *udev = udev_new();
+ if (*udev == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+static inline void __media_udev_close(struct udev *udev)
+{
+ if (udev != NULL)
+ udev_unref(udev);
+}
+
+static int __media_get_devname_udev(struct udev *udev,
+ struct media_entity *entity)
+{
+ struct udev_device *device;
+ dev_t devnum;
+ const char *p;
+ int ret = -ENODEV;
+
+ if (udev == NULL)
+ return -EINVAL;
+
+ devnum = makedev(entity->info.v4l.major, entity->info.v4l.minor);
+ ALOGE("looking up device: %u:%u",
+ major(devnum), minor(devnum));
+ device = udev_device_new_from_devnum(udev, 'c', devnum);
+ if (device) {
+ p = udev_device_get_devnode(device);
+ if (p) {
+ strncpy(entity->devname, p, sizeof(entity->devname));
+ entity->devname[sizeof(entity->devname) - 1] = '\0';
+ }
+ ret = 0;
+ }
+
+ udev_device_unref(device);
+
+ return ret;
+}
+
+#else /* HAVE_LIBUDEV */
+
+struct udev;
+
+static inline int __media_udev_open(struct udev **udev) { return 0; }
+
+static inline void __media_udev_close(struct udev *udev) { }
+
+static inline int __media_get_devname_udev(struct udev *udev,
+ struct media_entity *entity)
+{
+ return -ENOTSUP;
+}
+
+#endif /* HAVE_LIBUDEV */
+
+/**
+ * @brief Parse string to a pad on the media device.
+ * @param media - media device.
+ * @param p - input string
+ * @param endp - pointer to string where parsing ended
+ *
+ * Parse NULL terminated string describing a pad and return its struct
+ * media_pad instance.
+ *
+ * @return Pointer to struct media_pad on success, NULL on failure.
+ */
+struct media_pad *exynos_media_parse_pad(struct media_device *media,
+ const char *p, char **endp)
+{
+ unsigned int entity_id, pad;
+ struct media_entity *entity;
+ char *end;
+
+ for (; isspace(*p); ++p);
+
+ if (*p == '"') {
+ for (end = (char *)p + 1; *end && *end != '"'; ++end);
+ if (*end != '"')
+ return NULL;
+
+ entity = exynos_media_get_entity_by_name(media, p + 1, end - p - 1);
+ if (entity == NULL)
+ return NULL;
+
+ ++end;
+ } else {
+ entity_id = strtoul(p, &end, 10);
+ entity = exynos_media_get_entity_by_id(media, entity_id);
+ if (entity == NULL)
+ return NULL;
+ }
+ for (; isspace(*end); ++end);
+
+ if (*end != ':')
+ return NULL;
+ for (p = end + 1; isspace(*p); ++p);
+
+ pad = strtoul(p, &end, 10);
+ for (p = end; isspace(*p); ++p);
+
+ if (pad >= entity->info.pads)
+ return NULL;
+
+ for (p = end; isspace(*p); ++p);
+ if (endp)
+ *endp = (char *)p;
+
+ return &entity->pads[pad];
+}
+
+/**
+ * @brief Parse string to a link on the media device.
+ * @param media - media device.
+ * @param p - input string
+ * @param endp - pointer to p where parsing ended
+ *
+ * Parse NULL terminated string p describing a link and return its struct
+ * media_link instance.
+ *
+ * @return Pointer to struct media_link on success, NULL on failure.
+ */
+struct media_link *exynos_media_parse_link(
+ struct media_device *media,
+ const char *p,
+ char **endp)
+{
+ struct media_link *link;
+ struct media_pad *source;
+ struct media_pad *sink;
+ unsigned int i;
+ char *end;
+
+ source = exynos_media_parse_pad(media, p, &end);
+ if (source == NULL)
+ return NULL;
+
+ if (end[0] != '-' || end[1] != '>')
+ return NULL;
+ p = end + 2;
+
+ sink = exynos_media_parse_pad(media, p, &end);
+ if (sink == NULL)
+ return NULL;
+
+ *endp = end;
+
+ for (i = 0; i < source->entity->num_links; i++) {
+ link = &source->entity->links[i];
+
+ if (link->source == source && link->sink == sink)
+ return link;
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief Parse string to a link on the media device and set it up.
+ * @param media - media device.
+ * @param p - input string
+ *
+ * Parse NULL terminated string p describing a link and its configuration
+ * and configure the link.
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_media_parse_setup_link(
+ struct media_device *media,
+ const char *p,
+ char **endp)
+{
+ struct media_link *link;
+ __u32 flags;
+ char *end;
+
+ link = exynos_media_parse_link(media, p, &end);
+ if (link == NULL) {
+ ALOGE("Unable to parse link");
+ return -EINVAL;
+ }
+
+ p = end;
+ if (*p++ != '[') {
+ ALOGE("Unable to parse link flags");
+ return -EINVAL;
+ }
+
+ flags = strtoul(p, &end, 10);
+ for (p = end; isspace(*p); p++);
+ if (*p++ != ']') {
+ ALOGE("Unable to parse link flags");
+ return -EINVAL;
+ }
+
+ for (; isspace(*p); p++);
+ *endp = (char *)p;
+
+ ALOGD("%s: Setting up link %u:%u -> %u:%u [%u]", __func__,
+ link->source->entity->info.id, link->source->index,
+ link->sink->entity->info.id, link->sink->index,
+ flags);
+
+ return exynos_media_setup_link(media, link->source, link->sink, flags);
+}
+
+/**
+ * @brief Parse string to link(s) on the media device and set it up.
+ * @param media - media device.
+ * @param p - input string
+ *
+ * Parse NULL terminated string p describing link(s) separated by
+ * commas (,) and configure the link(s).
+ *
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_media_parse_setup_links(struct media_device *media, const char *p)
+{
+ char *end;
+ int ret;
+
+ do {
+ ret = exynos_media_parse_setup_link(media, p, &end);
+ if (ret < 0)
+ return ret;
+
+ p = end + 1;
+ } while (*end == ',');
+
+ return *end ? -EINVAL : 0;
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+ * \file exynos_subdev.c
+ * \brief source file for libv4l2
+ * \author Jinsung Yang (jsgood.yang@samsung.com)
+ * \author Sangwoo Park (sw5771.park@samsung.com)
+ * \date 2012/01/17
+ *
+ * <b>Revision History: </b>
+ * - 2012/01/17: Jinsung Yang (jsgood.yang@samsung.com) \n
+ * Initial version
+ *
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+#include "exynos_v4l2.h"
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "libexynosv4l2-subdev"
+#include <utils/Log.h>
+
+#define SUBDEV_MINOR_MAX 191
+
+static int __subdev_open(const char *filename, int oflag, va_list ap)
+{
+ mode_t mode = 0;
+ int fd;
+
+ if (oflag & O_CREAT)
+ mode = va_arg(ap, int);
+
+ fd = open(filename, oflag, mode);
+
+ return fd;
+}
+
+int exynos_subdev_open(const char *filename, int oflag, ...)
+{
+ va_list ap;
+ int fd;
+
+ va_start(ap, oflag);
+ fd = __subdev_open(filename, oflag, ap);
+ va_end(ap);
+
+ return fd;
+}
+
+int exynos_subdev_open_devname(const char *devname, int oflag, ...)
+{
+ bool found = false;
+ int fd = -1;
+ struct stat s;
+ va_list ap;
+ FILE *stream_fd;
+ char filename[64], name[64];
+ int minor, size, i = 0;
+
+ do {
+ if (i > (SUBDEV_MINOR_MAX - 128))
+ break;
+
+ /* video device node */
+ sprintf(filename, "/dev/v4l-subdev%d", i++);
+
+ /* if the node is video device */
+ if ((lstat(filename, &s) == 0) && S_ISCHR(s.st_mode) &&
+ ((int)((unsigned short)(s.st_rdev) >> 8) == 81)) {
+ minor = (int)((unsigned short)(s.st_rdev & 0x3f));
+ ALOGD("try node: %s, minor: %d", filename, minor);
+ /* open sysfs entry */
+ sprintf(filename, "/sys/class/video4linux/v4l-subdev%d/name", minor);
+ stream_fd = fopen(filename, "r");
+ if (stream_fd == NULL) {
+ ALOGE("failed to open sysfs entry for subdev");
+ continue; /* try next */
+ }
+
+ /* read sysfs entry for device name */
+ size = (int)fgets(name, sizeof(name), stream_fd);
+ fclose(stream_fd);
+
+ /* check read size */
+ if (size == 0) {
+ ALOGE("failed to read sysfs entry for subdev");
+ } else {
+ /* matched */
+ if (strncmp(name, devname, strlen(devname)) == 0) {
+ ALOGI("node found for device %s: /dev/v4l-subdev%d", devname, minor);
+ found = true;
+ }
+ }
+ }
+ } while (found == false);
+
+ if (found) {
+ sprintf(filename, "/dev/v4l-subdev%d", minor);
+ va_start(ap, oflag);
+ fd = __subdev_open(filename, oflag, ap);
+ va_end(ap);
+
+ if (fd > 0)
+ ALOGI("open subdev device %s", filename);
+ else
+ ALOGE("failed to open subdev device %s", filename);
+ } else {
+ ALOGE("no subdev device found");
+ }
+
+ return fd;
+}
+
+/**
+ * @brief enum frame size on a pad.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_enum_frame_size(int fd, struct v4l2_subdev_frame_size_enum *frame_size_enum)
+{
+ int ret = -1;
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!frame_size_enum) {
+ ALOGE("%s: frame_size_enum is NULL", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_SUBDEV_ENUM_FRAME_SIZE, frame_size_enum);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_FRAME_SIZE");
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Retrieve the format on a pad.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_g_fmt(int fd, struct v4l2_subdev_format *fmt)
+{
+ int ret = -1;
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!fmt) {
+ ALOGE("%s: fmt is NULL", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_SUBDEV_G_FMT, fmt);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_FMT");
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Set the format on a pad.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_s_fmt(int fd, struct v4l2_subdev_format *fmt)
+{
+ int ret = -1;
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!fmt) {
+ ALOGE("%s: fmt is NULL", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_SUBDEV_S_FMT, fmt);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_FMT");
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Retrieve the crop rectangle on a pad.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_g_crop(int fd, struct v4l2_subdev_crop *crop)
+{
+ int ret = -1;
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!crop) {
+ ALOGE("%s: crop is NULL", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_SUBDEV_G_CROP, crop);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_CROP");
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Set the crop rectangle on a pad.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_s_crop(int fd, struct v4l2_subdev_crop *crop)
+{
+ int ret = -1;
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!crop) {
+ ALOGE("%s: crop is NULL", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_SUBDEV_S_CROP, crop);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_CROP");
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Retrieve the frame interval on a sub-device.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_enum_frame_interval(int fd, struct v4l2_subdev_frame_interval_enum *frame_internval_enum)
+{
+ int ret = -1;
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!frame_internval_enum) {
+ ALOGE("%s: frame_internval_enum is NULL", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL, frame_internval_enum);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL");
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Retrieve the frame interval on a sub-device.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_g_frame_interval(int fd, struct v4l2_subdev_frame_interval *frame_internval)
+{
+ int ret = -1;
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!frame_internval) {
+ ALOGE("%s: frame_internval is NULL", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_SUBDEV_G_FRAME_INTERVAL, frame_internval);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_SUBDEV_G_FRAME_INTERVAL");
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Set the frame interval on a sub-device.
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_s_frame_interval(int fd, struct v4l2_subdev_frame_interval *frame_internval)
+{
+ int ret = -1;
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!frame_internval) {
+ ALOGE("%s: frame_internval is NULL", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_SUBDEV_S_FRAME_INTERVAL, frame_internval);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_SUBDEV_S_FRAME_INTERVAL");
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief enum mbus code
+ * @return 0 on success, or a negative error code on failure.
+ */
+int exynos_subdev_enum_mbus_code(int fd, struct v4l2_subdev_mbus_code_enum *mbus_code_enum)
+{
+ int ret = -1;
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!mbus_code_enum) {
+ ALOGE("%s: mbus_code_enum is NULL", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_SUBDEV_ENUM_MBUS_CODE, mbus_code_enum);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_SUBDEV_ENUM_MBUS_CODE");
+ return ret;
+ }
+
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*!
+ * \file exynos_v4l2.c
+ * \brief source file for libv4l2
+ * \author Jinsung Yang (jsgood.yang@samsung.com)
+ * \author Sangwoo Park (sw5771.park@samsung.com)
+ * \date 2012/01/17
+ *
+ * <b>Revision History: </b>
+ * - 2012/01/17: Jinsung Yang (jsgood.yang@samsung.com) \n
+ * Initial version
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+
+#include "exynos_v4l2.h"
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "libexynosv4l2"
+#include <utils/Log.h>
+#include "Exynos_log.h"
+
+#define VIDEODEV_MINOR_MAX 63
+
+//#define EXYNOS_V4L2_TRACE 0
+#ifdef EXYNOS_V4L2_TRACE
+#define Exynos_v4l2_In() Exynos_Log(EXYNOS_DEV_LOG_DEBUG, LOG_TAG, "%s In , Line: %d", __FUNCTION__, __LINE__)
+#define Exynos_v4l2_Out() Exynos_Log(EXYNOS_DEV_LOG_DEBUG, LOG_TAG, "%s Out , Line: %d", __FUNCTION__, __LINE__)
+#else
+#define Exynos_v4l2_In() ((void *)0)
+#define Exynos_v4l2_Out() ((void *)0)
+#endif
+
+static bool __v4l2_check_buf_type(enum v4l2_buf_type type)
+{
+ bool supported;
+
+ switch (type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ supported = true;
+ break;
+
+ default:
+ supported = (type >= V4L2_BUF_TYPE_PRIVATE) ? true : false;
+ break;
+ }
+
+ return supported;
+}
+
+static int __v4l2_open(const char *filename, int oflag, va_list ap)
+{
+ mode_t mode = 0;
+ int fd;
+
+ if (oflag & O_CREAT)
+ mode = va_arg(ap, int);
+
+ fd = open(filename, oflag, mode);
+
+ return fd;
+}
+
+int exynos_v4l2_open(const char *filename, int oflag, ...)
+{
+ va_list ap;
+ int fd;
+
+ Exynos_v4l2_In();
+
+ va_start(ap, oflag);
+ fd = __v4l2_open(filename, oflag, ap);
+ va_end(ap);
+
+ Exynos_v4l2_Out();
+
+ return fd;
+}
+
+int exynos_v4l2_open_devname(const char *devname, int oflag, ...)
+{
+ bool found = false;
+ int fd = -1;
+ struct stat s;
+ va_list ap;
+ FILE *stream_fd;
+ char filename[64], name[64];
+ int minor, size, i = 0;
+
+ Exynos_v4l2_In();
+
+ do {
+ if (i > VIDEODEV_MINOR_MAX)
+ break;
+
+ /* video device node */
+ sprintf(filename, "/dev/video%d", i++);
+
+ /* if the node is video device */
+ if ((lstat(filename, &s) == 0) && S_ISCHR(s.st_mode) &&
+ ((int)((unsigned short)(s.st_rdev) >> 8) == 81)) {
+ minor = (int)((unsigned short)(s.st_rdev & 0x3f));
+ ALOGD("try node: %s, minor: %d", filename, minor);
+ /* open sysfs entry */
+ sprintf(filename, "/sys/class/video4linux/video%d/name", minor);
+ stream_fd = fopen(filename, "r");
+ if (stream_fd == NULL) {
+ ALOGE("failed to open sysfs entry for videodev");
+ continue; /* try next */
+ }
+
+ /* read sysfs entry for device name */
+ size = (int)fgets(name, sizeof(name), stream_fd);
+ fclose(stream_fd);
+
+ /* check read size */
+ if (size == 0) {
+ ALOGE("failed to read sysfs entry for videodev");
+ } else {
+ /* matched */
+ if (strncmp(name, devname, strlen(devname)) == 0) {
+ ALOGI("node found for device %s: /dev/video%d", devname, minor);
+ found = true;
+ }
+ }
+ }
+ } while (found == false);
+
+ if (found) {
+ sprintf(filename, "/dev/video%d", minor);
+ va_start(ap, oflag);
+ fd = __v4l2_open(filename, oflag, ap);
+ va_end(ap);
+
+ if (fd > 0)
+ ALOGI("open video device %s", filename);
+ else
+ ALOGE("failed to open video device %s", filename);
+ } else {
+ ALOGE("no video device found");
+ }
+
+ Exynos_v4l2_Out();
+
+ return fd;
+}
+
+int exynos_v4l2_close(int fd)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0)
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ else
+ ret = close(fd);
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+bool exynos_v4l2_enuminput(int fd, int index, char *input_name_buf)
+{
+ int ret = -1;
+ struct v4l2_input input;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return NULL;
+ }
+
+ input.index = index;
+ ret = ioctl(fd, VIDIOC_ENUMINPUT, &input);
+ if (ret) {
+ ALOGE("%s: no matching index founds", __func__);
+ return false;
+ }
+
+ ALOGI("Name of input channel[%d] is %s", input.index, input.name);
+
+ strcpy(input_name_buf, (const char *)input.name);
+
+ Exynos_v4l2_Out();
+
+ return true;
+}
+
+int exynos_v4l2_s_input(int fd, int index)
+{
+ int ret = -1;
+ struct v4l2_input input;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ input.index = index;
+
+ ret = ioctl(fd, VIDIOC_S_INPUT, &input);
+ if (ret){
+ ALOGE("failed to ioctl: VIDIOC_S_INPUT (%d - %s)", errno, strerror(errno));
+ return ret;
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+bool exynos_v4l2_querycap(int fd, unsigned int need_caps)
+{
+ struct v4l2_capability cap;
+ int ret;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return false;
+ }
+
+ if (!(need_caps & V4L2_CAP_VIDEO_CAPTURE) &&
+ !(need_caps & V4L2_CAP_VIDEO_CAPTURE_MPLANE) &&
+ !(need_caps & V4L2_CAP_VIDEO_OUTPUT) &&
+ !(need_caps & V4L2_CAP_VIDEO_OUTPUT_MPLANE) &&
+ !(need_caps & V4L2_CAP_VIDEO_OVERLAY)) {
+ ALOGE("%s: unsupported capabilities", __func__);
+ return false;
+ }
+
+ memset(&cap, 0, sizeof(cap));
+
+ ret = ioctl(fd, VIDIOC_QUERYCAP, &cap);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_QUERYCAP (%d - %s)", errno, strerror(errno));
+ return false;
+ }
+
+ if ((need_caps & cap.capabilities) != need_caps) {
+ ALOGE("%s: unsupported capabilities", __func__);
+ return false;
+ }
+
+ Exynos_v4l2_Out();
+
+ return true;
+}
+
+bool exynos_v4l2_enum_fmt(int fd, enum v4l2_buf_type type, unsigned int fmt)
+{
+ struct v4l2_fmtdesc fmtdesc;
+ int found = 0;
+
+ Exynos_v4l2_In();
+
+ fmtdesc.type = type;
+ fmtdesc.index = 0;
+
+ while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
+ if (fmtdesc.pixelformat == fmt) {
+ ALOGE("Passed fmt = %#x found pixel format[%d]: %s", fmt, fmtdesc.index, fmtdesc.description);
+ found = 1;
+ break;
+ }
+
+ fmtdesc.index++;
+ }
+
+ if (!found) {
+ ALOGE("%s: unsupported pixel format", __func__);
+ return false;
+ }
+
+ Exynos_v4l2_Out();
+
+ return true;
+}
+
+int exynos_v4l2_g_fmt(int fd, struct v4l2_format *fmt)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!fmt) {
+ ALOGE("%s: fmt is NULL", __func__);
+ return ret;
+ }
+
+ if (__v4l2_check_buf_type(fmt->type) == false) {
+ ALOGE("%s: unsupported buffer type", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_G_FMT, fmt);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_G_FMT (%d - %s)", errno, strerror(errno));
+ return ret;
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+static int __v4l2_s_fmt(int fd, unsigned int request, struct v4l2_format *fmt)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!fmt) {
+ ALOGE("%s: fmt is NULL", __func__);
+ return ret;
+ }
+
+ if (__v4l2_check_buf_type(fmt->type) == false) {
+ ALOGE("%s: unsupported buffer type", __func__);
+ return ret;
+ } else {
+ ret = ioctl(fd, request, fmt);
+ if (ret) {
+ if (request == VIDIOC_TRY_FMT)
+ ALOGE("failed to ioctl: VIDIOC_TRY_FMT (%d - %s)", errno, strerror(errno));
+ else
+ ALOGE("failed to ioctl: VIDIOC_S_FMT (%d - %s)", errno, strerror(errno));
+
+ return ret;
+ }
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_try_fmt(int fd, struct v4l2_format *fmt)
+{
+ return __v4l2_s_fmt(fd, VIDIOC_TRY_FMT, fmt);
+}
+
+int exynos_v4l2_s_fmt(int fd, struct v4l2_format *fmt)
+{
+ return __v4l2_s_fmt(fd, VIDIOC_S_FMT, fmt);
+}
+
+int exynos_v4l2_reqbufs(int fd, struct v4l2_requestbuffers *req)
+{
+ int ret = -1;
+ unsigned int count;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!req) {
+ ALOGE("%s: req is NULL", __func__);
+ return ret;
+ }
+
+ if ((req->memory != V4L2_MEMORY_MMAP) &&
+ (req->memory != V4L2_MEMORY_USERPTR) &&
+ (req->memory != V4L2_MEMORY_DMABUF)) {
+ ALOGE("%s: unsupported memory type", __func__);
+ return ret;
+ }
+
+ if (__v4l2_check_buf_type(req->type) == false) {
+ ALOGE("%s: unsupported buffer type", __func__);
+ return ret;
+ }
+
+ count = req->count;
+
+ ret = ioctl(fd, VIDIOC_REQBUFS, req);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_REQBUFS (%d - %s)", ret, strerror(errno));
+ return ret;
+ }
+
+ if (count != req->count) {
+ ALOGW("number of buffers had been changed: %d => %d", count, req->count);
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_querybuf(int fd, struct v4l2_buffer *buf)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!buf) {
+ ALOGE("%s: buf is NULL", __func__);
+ return ret;
+ }
+
+ if ((buf->memory != V4L2_MEMORY_MMAP) &&
+ (buf->memory != V4L2_MEMORY_DMABUF)) {
+ ALOGE("%s: unsupported memory type", __func__);
+ return ret;
+ }
+
+ if (__v4l2_check_buf_type(buf->type) == false) {
+ ALOGE("%s: unsupported buffer type", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_QUERYBUF, buf);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_QUERYBUF (%d - %s)", errno, strerror(errno));
+ return ret;
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_qbuf(int fd, struct v4l2_buffer *buf)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!buf) {
+ ALOGE("%s: buf is NULL", __func__);
+ return ret;
+ }
+
+ if ((buf->memory != V4L2_MEMORY_MMAP) &&
+ (buf->memory != V4L2_MEMORY_USERPTR) &&
+ (buf->memory != V4L2_MEMORY_DMABUF)) {
+ ALOGE("%s: unsupported memory type", __func__);
+ return ret;
+ }
+
+ if (__v4l2_check_buf_type(buf->type) == false) {
+ ALOGE("%s: unsupported buffer type", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_QBUF, buf);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_QBUF (%d - %s)", errno, strerror(errno));
+ return ret;
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_dqbuf(int fd, struct v4l2_buffer *buf)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!buf) {
+ ALOGE("%s: buf is NULL", __func__);
+ return ret;
+ }
+
+ if ((buf->memory != V4L2_MEMORY_MMAP) &&
+ (buf->memory != V4L2_MEMORY_USERPTR) &&
+ (buf->memory != V4L2_MEMORY_DMABUF)) {
+ ALOGE("%s: unsupported memory type", __func__);
+ return ret;
+ }
+
+ if (__v4l2_check_buf_type(buf->type) == false) {
+ ALOGE("%s: unsupported buffer type", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_DQBUF, buf);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_DQBUF (%d - %s)", errno, strerror(errno));
+ return ret;
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_streamon(int fd, enum v4l2_buf_type type)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (__v4l2_check_buf_type(type) == false) {
+ ALOGE("%s: unsupported buffer type", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_STREAMON, &type);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_STREAMON (%d - %s)", errno, strerror(errno));
+ return ret;
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_streamoff(int fd, enum v4l2_buf_type type)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (__v4l2_check_buf_type(type) == false) {
+ ALOGE("%s: unsupported buffer type", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_STREAMOFF, &type);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_STREAMOFF (%d - %s)", errno, strerror(errno));
+ return ret;
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_cropcap(int fd, struct v4l2_cropcap *crop)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!crop) {
+ ALOGE("%s: crop is NULL", __func__);
+ return ret;
+ }
+
+ if (__v4l2_check_buf_type(crop->type) == false) {
+ ALOGE("%s: unsupported buffer type", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_CROPCAP, crop);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_CROPCAP (%d - %s)", errno, strerror(errno));
+ return ret;
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_g_crop(int fd, struct v4l2_crop *crop)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!crop) {
+ ALOGE("%s: crop is NULL", __func__);
+ return ret;
+ }
+
+ if (__v4l2_check_buf_type(crop->type) == false) {
+ ALOGE("%s: unsupported buffer type", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_G_CROP, crop);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_G_CROP (%d - %s)", errno, strerror(errno));
+ return ret;
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_s_crop(int fd, struct v4l2_crop *crop)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (!crop) {
+ ALOGE("%s: crop is NULL", __func__);
+ return ret;
+ }
+
+ if (__v4l2_check_buf_type(crop->type) == false) {
+ ALOGE("%s: unsupported buffer type", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_S_CROP, crop);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_S_CROP (%d - %s)", errno, strerror(errno));
+ return ret;
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_g_ctrl(int fd, unsigned int id, int *value)
+{
+ int ret = -1;
+ struct v4l2_control ctrl;
+
+ Exynos_v4l2_In();
+
+ ctrl.id = id;
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_G_CTRL, &ctrl);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_G_CTRL (%d - %s)", errno, strerror(errno));
+ return ret;
+ }
+
+ *value = ctrl.value;
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_s_ctrl(int fd, unsigned int id, int value)
+{
+ int ret = -1;
+ struct v4l2_control ctrl;
+
+ Exynos_v4l2_In();
+
+ ctrl.id = id;
+ ctrl.value = value;
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_S_CTRL (%d)", errno);
+ return ret;
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_g_parm(int fd, struct v4l2_streamparm *streamparm)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (__v4l2_check_buf_type(streamparm->type) == false) {
+ ALOGE("%s: unsupported buffer type", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_G_PARM, streamparm);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_G_PARM (%d - %s)", errno, strerror(errno));
+ return ret;
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_s_parm(int fd, struct v4l2_streamparm *streamparm)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (__v4l2_check_buf_type(streamparm->type) == false) {
+ ALOGE("%s: unsupported buffer type", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_S_PARM, streamparm);
+ if (ret) {
+ ALOGE("failed to ioctl: VIDIOC_S_PARM (%d - %s)", errno, strerror(errno));
+ return ret;
+ }
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_g_ext_ctrl(int fd, struct v4l2_ext_controls *ctrl)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (ctrl == NULL) {
+ ALOGE("%s: ctrl is NULL", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_G_EXT_CTRLS, ctrl);
+ if (ret)
+ ALOGE("failed to ioctl: VIDIOC_G_EXT_CTRLS (%d - %s)", errno, strerror(errno));
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}
+
+int exynos_v4l2_s_ext_ctrl(int fd, struct v4l2_ext_controls *ctrl)
+{
+ int ret = -1;
+
+ Exynos_v4l2_In();
+
+ if (fd < 0) {
+ ALOGE("%s: invalid fd: %d", __func__, fd);
+ return ret;
+ }
+
+ if (ctrl == NULL) {
+ ALOGE("%s: ctrl is NULL", __func__);
+ return ret;
+ }
+
+ ret = ioctl(fd, VIDIOC_S_EXT_CTRLS, ctrl);
+ if (ret)
+ ALOGE("failed to ioctl: VIDIOC_S_EXT_CTRLS (%d - %s)", errno, strerror(errno));
+
+ Exynos_v4l2_Out();
+
+ return ret;
+}