new file mode 100644
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ *
+ * Contact: Yordan Kamenov <ykamenov@mm-sol.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <glob.h>
+#include <linux/videodev2.h>
+#include <mediactl/media.h>
+
+#include "libv4l2-plugin.h"
+#include "libv4l2plugin-omap3mc.h"
+#include "paths.h"
+#include "operations.h"
+
+#if __GNUC__ >= 4
+#define PLUGIN_PUBLIC __attribute__ ((visibility("default")))
+#define PLUGIN_HIDDEN __attribute__ ((visibility("hidden")))
+#else
+#define PLUGIN_PUBLIC
+#define PLUGIN_HIDDEN
+#endif
+
+/* Check if /dev/media0 is already open*/
+int media_in_use()
+{
+ int glob_ret, file, ret = 0;
+ glob_t globbuf;
+ ssize_t link_len;
+ char file_name[16];
+
+ glob_ret = glob("/proc/self/fd/*", 0, NULL, &globbuf);
+
+ if (glob_ret == GLOB_NOSPACE)
+ return ret;
+
+ if (glob_ret == GLOB_ABORTED || glob_ret == GLOB_NOMATCH)
+ goto leave;
+
+ for (file = 0; file < globbuf.gl_pathc; file++) {
+ link_len = readlink(globbuf.gl_pathv[file],
+ file_name, strlen(MEDIA_DEVICE));
+ if (link_len == strlen(MEDIA_DEVICE))
+ file_name[link_len] = '\0';
+ else
+ continue;
+
+ if (!strncmp(file_name, MEDIA_DEVICE, strlen(MEDIA_DEVICE))) {
+ ret = 1;
+ break;
+ }
+ }
+
+leave:
+ globfree(&globbuf);
+
+ return ret;
+}
+
+PLUGIN_HIDDEN void * omap3mc_init(int fd)
+{
+ int ret = -1, primary;
+ struct omap3mcplugin *plugin;
+ const struct capture_pipeline *pipe = NULL;
+ struct sub_module *dst_sub_module = NULL;
+ char link_path[20];
+ ssize_t link_len;
+ char file[VIDEO_NODE_LENGTH + 1];
+
+ /* Get filename from fd */
+ sprintf(link_path, "/proc/self/fd/%d", fd);
+ link_len = readlink(link_path, file, VIDEO_NODE_LENGTH);
+ if (link_len == VIDEO_NODE_LENGTH)
+ link_path[link_len] = '\0';
+ else
+ return NULL;
+
+ /* FIXME: What we do if the application is aware of video nodes
+ and tries to open() real /dev/video0 (CSI2 capture) */
+ if (strncmp(file, VIDEO_PRIMARY, strlen(VIDEO_PRIMARY)) == 0)
+ primary = 1;
+ else if (strncmp(file, VIDEO_SECONDARY, strlen(VIDEO_SECONDARY)) == 0)
+ primary = 0;
+ else
+ return NULL;
+
+ if (media_in_use())
+ return NULL;
+
+ plugin = calloc(1, sizeof(*plugin));
+ if (plugin == NULL)
+ return NULL;
+
+ plugin->media = media_open(MEDIA_DEVICE, 1);
+ if (plugin->media == NULL) {
+ free(plugin);
+ return NULL;
+ }
+
+ pipe = pipe_sensor_yuv(primary);
+
+ if (pipe)
+ plugin->path = path_allocate(plugin->media, pipe);
+
+ if (plugin->path)
+ dst_sub_module = path_destination_submodule(plugin->path);
+
+ if (dst_sub_module)
+ ret = path_power_on(plugin->path, fd);
+
+ if (ret == 0)
+ ret = path_connect_entities(plugin->media, plugin->path);
+
+ plugin->fd = dst_sub_module->entity->fd;
+
+ if (ret != 0) {
+ path_disconnect_entities(plugin->media, plugin->path);
+ path_power_off(plugin->path);
+
+ media_close(plugin->media);
+ free(plugin);
+ plugin = NULL;
+ }
+
+ return plugin;
+}
+
+PLUGIN_HIDDEN void omap3mc_close(void *dev_ops_priv)
+{
+ struct omap3mcplugin *plugin;
+
+ if (dev_ops_priv == NULL)
+ return;
+
+ plugin = (struct omap3mcplugin *)dev_ops_priv;
+
+ path_disconnect_entities(plugin->media, plugin->path);
+ path_power_off(plugin->path);
+
+ media_close(plugin->media);
+
+ free(plugin);
+}
+
+PLUGIN_HIDDEN int omap3mc_ioctl(void *dev_ops_priv, int fd,
+ unsigned long int request, void *arg)
+{
+ int ret = -1;
+ struct omap3mcplugin *plugin;
+
+ plugin = (struct omap3mcplugin *)dev_ops_priv;
+
+ switch (request) {
+ case VIDIOC_STREAMON:
+ ret = mc_vidioc_streamon(plugin, request, arg);
+ break;
+ case VIDIOC_STREAMOFF:
+ ret = mc_vidioc_streamoff(plugin, request, arg);
+ break;
+ case VIDIOC_S_FMT:
+ ret = mc_vidioc_s_fmt(plugin, request, arg);
+ break;
+ case VIDIOC_G_FMT:
+ ret = mc_vidioc_g_fmt(plugin, request, arg);
+ break;
+ case VIDIOC_TRY_FMT:
+ ret = mc_vidioc_try_fmt(plugin, request, arg);
+ break;
+ case VIDIOC_S_CROP:
+ ret = mc_vidioc_s_crop(plugin, request, arg);
+ break;
+ case VIDIOC_G_CROP:
+ ret = mc_vidioc_g_crop(plugin, request, arg);
+ break;
+ case VIDIOC_QUERYCTRL:
+ ret = mc_vidioc_queryctrl(plugin, request, arg);
+ break;
+ case VIDIOC_G_CTRL:
+ ret = mc_vidioc_g_ctrl(plugin, request, arg);
+ break;
+ case VIDIOC_S_CTRL:
+ ret = mc_vidioc_s_ctrl(plugin, request, arg);
+ break;
+ case VIDIOC_QUERYCAP:
+ ret = mc_vidioc_querycap(plugin, request, arg);
+ break;
+ case VIDIOC_ENUM_FMT:
+ ret = mc_vidioc_enum_fmt(plugin, request, arg);
+ break;
+ case VIDIOC_ENUM_FRAMESIZES:
+ ret = mc_vidioc_enum_framesizes(plugin, request, arg);
+ break;
+ case VIDIOC_ENUM_FRAMEINTERVALS:
+ ret = mc_vidioc_enum_frameintervals(plugin, request, arg);
+ break;
+ case VIDIOC_REQBUFS:
+ ret = mc_vidioc_reqbufs(plugin, request, arg);
+ break;
+ case VIDIOC_QUERYBUF:
+ ret = mc_vidioc_querybuf(plugin, request, arg);
+ break;
+ case VIDIOC_QBUF:
+ ret = mc_vidioc_qbuf(plugin, request, arg);
+ break;
+ case VIDIOC_DQBUF:
+ ret = mc_vidioc_dqbuf(plugin, request, arg);
+ break;
+ default:
+ errno = EINVAL;
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
+PLUGIN_PUBLIC const struct libv4l2_dev_ops libv4l2_plugin = {
+ .init = &omap3mc_init,
+ .close = &omap3mc_close,
+ .ioctl = &omap3mc_ioctl,
+ .read = NULL
+};
new file mode 100644
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011 Nokia Corporation
+ *
+ * Contact: Yordan Kamenov <ykamenov@mm-sol.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ */
+
+#ifndef __LIBV4L2PLUGIN_OMAP3MC_H__
+#define __LIBV4L2PLUGIN_OMAP3MC_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <mediactl/media.h>
+
+#include "sl_list.h"
+
+#define SYS_OPEN(file, oflag, mode) \
+ syscall(SYS_open, (const char *)(file), (int)(oflag), (mode_t)(mode))
+#define SYS_CLOSE(fd) \
+ syscall(SYS_close, (int)(fd))
+#define SYS_IOCTL(fd, cmd, arg) \
+ syscall(SYS_ioctl, (int)(fd), (unsigned long)(cmd), (void *)(arg))
+
+
+#define VIDEO_PRIMARY "/dev/video0"
+#define VIDEO_SECONDARY "/dev/video1"
+#define VIDEO_NODE_LENGTH 11
+#define MEDIA_DEVICE "/dev/media0"
+
+#define PIPELINE_MAX_ELEMENTS 32
+#define SUBDEVICE_MAX_NAME_LEN 32
+#define PIXELFMT_MAX_ELEMENTS 10
+
+#define MC_PLUGIN_VERBOSE
+#ifdef MC_PLUGIN_VERBOSE
+#define MC_PLUGIN_PRINTF(str,args...) \
+ printf("%s():%d: " str, __FUNCTION__,__LINE__,##args)
+#endif
+
+
+
+/* pixel formats */
+enum mc_plugin_pixelformat {
+ MC_PLUGIN_PIX_FMT_INVALID = 0,
+ MC_PLUGIN_PIX_FMT_BAYER8_SBGGR,
+ MC_PLUGIN_PIX_FMT_BAYER8_SGBRG,
+ MC_PLUGIN_PIX_FMT_BAYER8_SGRBG,
+ MC_PLUGIN_PIX_FMT_BAYER10_SGRBG,
+ MC_PLUGIN_PIX_FMT_BAYER10_SRGGB,
+ MC_PLUGIN_PIX_FMT_BAYER10_SBGGR,
+ MC_PLUGIN_PIX_FMT_BAYER10_SGBRG,
+ MC_PLUGIN_PIX_FMT_BAYER10DPCM8_SGRBG,
+ MC_PLUGIN_PIX_FMT_YUYV,
+ MC_PLUGIN_PIX_FMT_UYVY
+};
+
+struct capture_pipeline {
+ char path[PIPELINE_MAX_ELEMENTS][SUBDEVICE_MAX_NAME_LEN];
+ enum mc_plugin_pixelformat in_pixfmt[PIXELFMT_MAX_ELEMENTS];
+ enum mc_plugin_pixelformat out_pixfmt[PIXELFMT_MAX_ELEMENTS];
+};
+
+struct ipipe_descriptor {
+ const struct capture_pipeline *pipe;
+ struct list_head container;
+};
+struct sub_module {
+ struct media_entity *entity;
+ struct list_head list;
+};
+
+
+struct omap3mcplugin {
+ struct media_device *media;
+ struct ipipe_descriptor *path;
+ int fd;
+};
+
+#endif /* __LIBV4L2PLUGIN_OMAP3MC_H__ */
Add interface functions init(), close() and ioctl(), called by libv4l2. Signed-off-by: Yordan Kamenov <ykamenov@mm-sol.com> --- libv4l2plugin-omap3mc.c | 241 +++++++++++++++++++++++++++++++++++++++++++++++ libv4l2plugin-omap3mc.h | 91 ++++++++++++++++++ 2 files changed, 332 insertions(+), 0 deletions(-) create mode 100644 libv4l2plugin-omap3mc.c create mode 100644 libv4l2plugin-omap3mc.h