[Title] add camera sources
authorJinhyung Jo <jinhyung.jo@samsung.com>
Mon, 5 Mar 2012 10:54:18 +0000 (19:54 +0900)
committerJinhyung Jo <jinhyung.jo@samsung.com>
Mon, 5 Mar 2012 10:54:18 +0000 (19:54 +0900)
[Type] Feature
[Module]
[Priority]
[CQ#]
[Redmine#]
[Problem]
[Cause]
[Solution]
[TestCase]

tizen/src/hw/maru_camera_common.h [new file with mode: 0644]
tizen/src/hw/maru_camera_common_pci.c [new file with mode: 0644]
tizen/src/hw/maru_camera_linux_pci.c [new file with mode: 0644]
tizen/src/hw/maru_camera_win32_pci.c [new file with mode: 0644]

diff --git a/tizen/src/hw/maru_camera_common.h b/tizen/src/hw/maru_camera_common.h
new file mode 100644 (file)
index 0000000..853b8a6
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Common header of MARU Virtual Camera device.
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ * JinHyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#ifndef _MARU_CAMERA_COMMON_H_
+#define _MARU_CAMERA_COMMON_H_
+
+#include "pci.h"
+#include <pthread.h>
+
+#define MARUCAM_MAX_PARAM       20
+
+/* must sync with GUEST camera_driver */
+#define MARUCAM_CMD_INIT           0x00
+#define MARUCAM_CMD_OPEN           0x04
+#define MARUCAM_CMD_CLOSE          0x08
+#define MARUCAM_CMD_ISSTREAM       0x0C
+#define MARUCAM_CMD_START_PREVIEW  0x10
+#define MARUCAM_CMD_STOP_PREVIEW   0x14
+#define MARUCAM_CMD_S_PARAM        0x18
+#define MARUCAM_CMD_G_PARAM        0x1C
+#define MARUCAM_CMD_ENUM_FMT       0x20
+#define MARUCAM_CMD_TRY_FMT        0x24
+#define MARUCAM_CMD_S_FMT          0x28
+#define MARUCAM_CMD_G_FMT          0x2C
+#define MARUCAM_CMD_QCTRL          0x30
+#define MARUCAM_CMD_S_CTRL         0x34
+#define MARUCAM_CMD_G_CTRL         0x38
+#define MARUCAM_CMD_ENUM_FSIZES    0x3C
+#define MARUCAM_CMD_ENUM_FINTV     0x40
+#define MARUCAM_CMD_S_DATA         0x44
+#define MARUCAM_CMD_G_DATA         0x48
+#define MARUCAM_CMD_CLRIRQ         0x4C
+#define MARUCAM_CMD_DATACLR        0x50
+#define MARUCAM_CMD_REQFRAME       0x54
+
+typedef struct MaruCamState MaruCamState;
+typedef struct MaruCamThreadInfo MaruCamThreadInfo;
+typedef struct MaruCamParam MaruCamParam;
+
+struct MaruCamParam {
+       uint32_t        top;
+       uint32_t        retVal;
+       uint32_t        errCode;
+       uint32_t        stack[MARUCAM_MAX_PARAM];
+};
+
+struct MaruCamThreadInfo {
+       MaruCamState*    state;
+       MaruCamParam*    param;
+
+       pthread_t        thread_id;
+       pthread_cond_t   thread_cond;
+       pthread_mutex_t  mutex_lock;
+};
+
+struct MaruCamState {
+       PCIDevice           dev;
+
+       void                *vaddr;             /* vram ptr */
+       uint32_t            streamon;
+       uint32_t            buf_size;
+       uint32_t            req_frame;
+
+    MemoryRegion        vram;
+    MemoryRegion        mmio;
+
+       MaruCamThreadInfo       *thread;
+};
+
+/* ----------------------------------------------------------------------------- */
+/* Fucntion prototype                                                                               */
+/* ----------------------------------------------------------------------------- */
+void marucam_device_init(MaruCamState *state);
+void marucam_device_open(MaruCamState *state);
+void marucam_device_close(MaruCamState *state);
+void marucam_device_start_preview(MaruCamState *state);
+void marucam_device_stop_preview(MaruCamState *state);
+void marucam_device_s_param(MaruCamState *state);
+void marucam_device_g_param(MaruCamState *state);
+void marucam_device_s_fmt(MaruCamState *state);
+void marucam_device_g_fmt(MaruCamState *state);
+void marucam_device_try_fmt(MaruCamState *state);
+void marucam_device_enum_fmt(MaruCamState *state);
+void marucam_device_qctrl(MaruCamState *state);
+void marucam_device_s_ctrl(MaruCamState *state);
+void marucam_device_g_ctrl(MaruCamState *state);
+void marucam_device_enum_fsizes(MaruCamState *state);
+void marucam_device_enum_fintv(MaruCamState *state);
+
+
+#endif /* _MARU_CAMERA_COMMON_H_ */
diff --git a/tizen/src/hw/maru_camera_common_pci.c b/tizen/src/hw/maru_camera_common_pci.c
new file mode 100644 (file)
index 0000000..1a59636
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Common implementation of MARU Virtual Camera device by PCI bus.
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ * JinHyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <signal.h>
+
+#include "qemu-common.h"
+#include "cpu-common.h"
+
+#include "pc.h"
+#include "pci.h"
+#include "pci_ids.h"
+
+#include "maru_camera_common.h"
+#include "tizen/src/debug_ch.h"
+
+MULTI_DEBUG_CHANNEL(tizen, camera_pci);
+
+#define MARU_PCI_CAMERA_DEVICE_NAME            "maru_camera_pci"
+
+#define MARUCAM_MEM_SIZE               (4 * 1024 * 1024)       // 4MB
+#define MARUCAM_REG_SIZE               (256)                           // 64 * 4
+
+/*
+ *  I/O functions
+ */
+static inline uint32_t marucam_mmio_read(void *opaque, target_phys_addr_t offset)
+{
+       uint32_t ret = 0;
+       MaruCamState *state = (MaruCamState*)opaque;
+
+       switch (offset & 0xFF) {
+       case MARUCAM_CMD_ISSTREAM:
+               pthread_mutex_lock(&state->thread->mutex_lock);
+               ret = state->streamon;
+               pthread_mutex_unlock(&state->thread->mutex_lock);
+               break;
+       case MARUCAM_CMD_G_DATA:
+               ret = state->thread->param->stack[state->thread->param->top++];
+               break;
+       case MARUCAM_CMD_OPEN:
+       case MARUCAM_CMD_CLOSE:
+       case MARUCAM_CMD_START_PREVIEW:
+       case MARUCAM_CMD_STOP_PREVIEW:
+       case MARUCAM_CMD_S_PARAM:
+       case MARUCAM_CMD_G_PARAM:
+       case MARUCAM_CMD_ENUM_FMT:
+       case MARUCAM_CMD_TRY_FMT:
+       case MARUCAM_CMD_S_FMT:
+       case MARUCAM_CMD_G_FMT:
+       case MARUCAM_CMD_QCTRL:
+       case MARUCAM_CMD_S_CTRL:
+       case MARUCAM_CMD_G_CTRL:
+       case MARUCAM_CMD_ENUM_FSIZES:
+       case MARUCAM_CMD_ENUM_FINTV:
+               ret = state->thread->param->errCode;
+               state->thread->param->errCode = 0;
+               break;
+       ldefault:
+               WARN("Not supported command!!\n");
+               break;
+       }
+       return ret;
+}
+
+static inline void marucam_mmio_write(void *opaque, target_phys_addr_t offset, uint32_t value)
+{
+       MaruCamState *state = (MaruCamState*)opaque;
+       
+       switch(offset & 0xFF) {
+       case MARUCAM_CMD_OPEN:
+               marucam_device_open(state);
+               break;
+       case MARUCAM_CMD_CLOSE:
+               marucam_device_close(state);
+               break;
+       case MARUCAM_CMD_START_PREVIEW:
+               marucam_device_start_preview(state);
+               break;
+       case MARUCAM_CMD_STOP_PREVIEW:
+               marucam_device_stop_preview(state);
+               break;
+       case MARUCAM_CMD_S_PARAM:
+               marucam_device_s_param(state);
+               break;
+       case MARUCAM_CMD_G_PARAM:
+               marucam_device_g_param(state);
+               break;
+       case MARUCAM_CMD_ENUM_FMT:
+               marucam_device_enum_fmt(state);
+               break;
+       case MARUCAM_CMD_TRY_FMT:
+               marucam_device_try_fmt(state);
+               break;
+       case MARUCAM_CMD_S_FMT:
+               marucam_device_s_fmt(state);
+               break;
+       case MARUCAM_CMD_G_FMT:
+               marucam_device_g_fmt(state);
+               break;
+       case MARUCAM_CMD_QCTRL:
+               marucam_device_qctrl(state);
+               break;
+       case MARUCAM_CMD_S_CTRL:
+               marucam_device_s_ctrl(state);
+               break;
+       case MARUCAM_CMD_G_CTRL:
+               marucam_device_g_ctrl(state);
+               break;
+       case MARUCAM_CMD_ENUM_FSIZES:
+               marucam_device_enum_fsizes(state);
+               break;
+       case MARUCAM_CMD_ENUM_FINTV:
+               marucam_device_enum_fintv(state);
+               break;
+       case MARUCAM_CMD_S_DATA:
+               state->thread->param->stack[state->thread->param->top++] = value;
+               break;
+       case MARUCAM_CMD_DATACLR:
+               memset(state->thread->param, 0, sizeof(MaruCamParam));
+               break;
+       case MARUCAM_CMD_CLRIRQ:
+               qemu_irq_lower(state->dev.irq[2]);
+               break;
+       case MARUCAM_CMD_REQFRAME:
+               pthread_mutex_lock(&state->thread->mutex_lock);
+               state->req_frame = value + 1;
+               pthread_mutex_unlock(&state->thread->mutex_lock);
+               break;
+       default:
+               WARN("Not supported command!!\n");
+               break;
+       }
+}
+
+static const MemoryRegionOps maru_camera_mmio_ops = {
+    .old_mmio = {
+        .read = {
+            marucam_mmio_read,
+            marucam_mmio_read,
+            marucam_mmio_read,
+        },
+        .write = {
+            marucam_mmio_write,
+            marucam_mmio_write,
+            marucam_mmio_write,
+        },
+    },
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+/*
+ *  Initialization function
+ */
+static int marucam_initfn(PCIDevice *dev)
+{
+       MaruCamState *s = DO_UPCAST(MaruCamState, dev, dev);
+       uint8_t *pci_conf = s->dev.config;
+       MaruCamThreadInfo *thread;
+       MaruCamParam *param;
+
+       pci_config_set_interrupt_pin(pci_conf, 0x03);
+
+    memory_region_init_ram(&s->vram, NULL, "marucamera.ram", MARUCAM_MEM_SIZE);
+    s->vaddr = memory_region_get_ram_ptr(&s->vram);
+
+    memory_region_init_io (&s->mmio, &maru_camera_mmio_ops, s, "maru-camera-mmio", MARUCAM_REG_SIZE);
+    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram);
+    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio);
+
+       /* for worker thread */
+       thread = (MaruCamThreadInfo*)g_malloc0(sizeof(MaruCamThreadInfo));
+       param = (MaruCamParam*)g_malloc0(sizeof(MaruCamParam));
+
+       thread->state = s;
+       thread->param = param;
+       s->thread = thread;
+
+       marucam_device_init(s);
+
+       return 0;
+}
+
+/*
+ *  Termination function
+ */
+static int marucam_exitfn(PCIBus *bus)
+{
+       MaruCamState *s = DO_UPCAST(MaruCamState, dev, dev);
+
+       g_free((gpointer)s->thread->param);
+       g_free((gpointer)s->thread);
+
+    memory_region_destroy (&s->vram);
+    memory_region_destroy (&s->mmio);
+    return 0;
+}
+
+int maru_camera_pci_init(PCIBus *bus)
+{
+    INFO("[%s] camera device was initialized.\n", __func__);
+    pci_create_simple(bus, -1, MARU_PCI_CAMERA_DEVICE_NAME);
+    return 0;
+}
+
+static PCIDeviceInfo maru_camera_info = {
+    .qdev.name    = MARU_PCI_CAMERA_DEVICE_NAME,
+    .qdev.desc    = "MARU Virtual Camera device for Tizen emulator",
+    .qdev.size    = sizeof(MaruCamState),
+    .no_hotplug   = 1,
+    .init         = marucam_initfn,
+    .exit         = marucam_exitfn,
+    .vendor_id    = PCI_VENDOR_ID_TIZEN,
+    .device_id    = PCI_DEVICE_ID_VIRTUAL_CAMERA,
+    .class_id     = PCI_CLASS_MULTIMEDIA_OTHER,
+};
+
+static void maru_camera_pci_register(void)
+{
+    pci_qdev_register(&maru_camera_info);
+}
+
+device_init(maru_camera_pci_register);
diff --git a/tizen/src/hw/maru_camera_linux_pci.c b/tizen/src/hw/maru_camera_linux_pci.c
new file mode 100644 (file)
index 0000000..2bdb16b
--- /dev/null
@@ -0,0 +1,664 @@
+/*
+ * Implementation of MARU Virtual Camera device by PCI bus on Linux.
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ * JinHyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+#include "qemu-common.h"
+#include "qemu-common.h"
+#include "maru_camera_common.h"
+#include "pci.h"
+#include "kvm.h"
+#include "tizen/src/debug_ch.h"
+
+#include <linux/videodev2.h>
+
+#include <libv4l2.h>
+#include <libv4lconvert.h>
+
+MULTI_DEBUG_CHANNEL(tizen, camera_linux);
+
+static int v4l2_fd;
+static int convert_trial;
+
+static struct v4l2_format dst_fmt;
+
+static int xioctl(int fd, int req, void *arg)
+{
+       int r;
+
+       do {
+               r = v4l2_ioctl(fd, req, arg);
+       } while ( r < 0 && errno == EINTR);
+
+       return r;
+}
+
+#define MARUCAM_CTRL_VALUE_MAX         20
+#define MARUCAM_CTRL_VALUE_MIN         1
+#define MARUCAM_CTRL_VALUE_MID         10
+#define MARUCAM_CTRL_VALUE_STEP                1
+
+struct marucam_qctrl {
+       uint32_t id;
+       uint32_t hit;
+       int32_t min;
+       int32_t max;
+       int32_t step;
+       int32_t init_val;
+};
+
+static struct marucam_qctrl qctrl_tbl[] = {
+       { V4L2_CID_BRIGHTNESS, 0, },
+       { V4L2_CID_CONTRAST, 0, },
+       { V4L2_CID_SATURATION,0, },
+       { V4L2_CID_SHARPNESS, 0, },
+};
+
+static void marucam_reset_controls(void)
+{
+       uint32_t i;
+       for (i = 0; i < ARRAY_SIZE(qctrl_tbl); i++) {
+               if (qctrl_tbl[i].hit) {
+                       struct v4l2_control ctrl = {0,};
+                       ctrl.id = qctrl_tbl[i].id;
+                       ctrl.value = qctrl_tbl[i].init_val;
+                       if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) {
+                               ERR("failed to set video control value while reset values : %s\n", strerror(errno));
+                       }
+               }
+       }
+}
+
+static int32_t value_convert_from_guest(int32_t min, int32_t max, int32_t value)
+{
+       double rate = 0.0;
+       int32_t dist = 0, ret = 0;
+
+       dist = max - min;
+
+       if (dist < MARUCAM_CTRL_VALUE_MAX) {
+               rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;
+               ret = min + (int32_t)(value / rate);
+       } else {
+               rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;
+               ret = min + (int32_t)(rate * value);
+       }
+       return ret;
+}
+
+static int32_t value_convert_to_guest(int32_t min, int32_t max, int32_t value)
+{
+       double rate  = 0.0;
+       int32_t dist = 0, ret = 0;
+
+       dist = max - min;
+
+       if (dist < MARUCAM_CTRL_VALUE_MAX) {
+               rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;
+               ret = (int32_t)((double)(value - min) * rate);
+       } else {
+               rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;
+               ret = (int32_t)((double)(value - min) / rate);
+       }
+
+       return ret;
+}
+
+static int __v4l2_grab(MaruCamState *state)
+{
+       fd_set fds;
+       static uint32_t index = 0;
+       struct timeval tv;
+       void *buf;
+       int ret;
+       
+       FD_ZERO(&fds);
+       FD_SET(v4l2_fd, &fds);
+
+       tv.tv_sec = 2;
+       tv.tv_usec = 0;
+
+       ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv);
+       if ( ret < 0) {
+               if (errno == EINTR)
+                       return 0;
+               ERR("select : %s\n", strerror(errno));
+               return -1;
+       }
+       if (!ret) {
+               WARN("Timed out\n");
+               return 0;
+       }
+
+       if (!v4l2_fd) {
+               WARN("file descriptor is closed or not opened \n");
+               return -1;
+       }
+
+       buf = state->vaddr + (state->buf_size * index);
+       ret = v4l2_read(v4l2_fd, buf, state->buf_size);
+       if ( ret < 0) {
+               switch (errno) {
+               case EINVAL:
+               case ENOMEM:
+                       ERR("v4l2_read failed : %s\n", strerror(errno));
+                       return -1;
+               case EAGAIN:
+               case EIO:
+               case EINTR:
+               default:
+                       if (convert_trial-- == -1) {
+                               ERR("Try count for v4l2_read is exceeded\n");
+                               return -1;
+                       }
+                       return 0;
+               }
+       }
+
+       index = !index;
+
+       pthread_mutex_lock(&state->thread->mutex_lock);
+       if (state->streamon) {
+               if (state->req_frame) {
+                       qemu_irq_raise(state->dev.irq[2]);
+                       state->req_frame = 0;
+               }
+               ret = 1;
+       } else {
+               ret = -1;
+       }
+       pthread_mutex_unlock(&state->thread->mutex_lock);
+
+       return ret;
+}
+
+// Worker thread
+static void *marucam_worker_thread(void *thread_param)
+{
+       MaruCamThreadInfo* thread = (MaruCamThreadInfo*)thread_param;
+
+wait_worker_thread:
+       pthread_mutex_lock(&thread->mutex_lock);
+       thread->state->streamon = 0;
+       convert_trial = 10;
+       pthread_cond_wait(&thread->thread_cond, &thread->mutex_lock);
+       pthread_mutex_unlock(&thread->mutex_lock);
+       INFO("Streaming on ......\n");
+
+       while (1)
+       {
+               pthread_mutex_lock(&thread->mutex_lock);
+               if (thread->state->streamon) {
+                       pthread_mutex_unlock(&thread->mutex_lock);
+                       if (__v4l2_grab(thread->state) < 0) {
+                               INFO("...... Streaming off\n");
+                               goto wait_worker_thread;
+                       }
+               } else {
+                       pthread_mutex_unlock(&thread->mutex_lock);
+                       goto wait_worker_thread;
+               }
+       }
+       pthread_exit(0);
+}
+
+void marucam_device_init(MaruCamState* state)
+{
+       MaruCamThreadInfo *thread = state->thread;
+
+       if (pthread_cond_init(&thread->thread_cond, NULL)) {
+               ERR("failed to initialize thread condition\n");
+               exit(61);
+       }
+       if (pthread_mutex_init(&thread->mutex_lock, NULL)) {
+               ERR("failed to initialize mutex\n");
+               exit(62);
+       }
+
+       if (pthread_create(&thread->thread_id, NULL, marucam_worker_thread, (void*)thread) != 0) {
+               perror("failed to create a worker thread for webcam connection\n");
+               exit(63);
+       }
+}
+
+// MARUCAM_CMD_OPEN
+void marucam_device_open(MaruCamState* state)
+{
+       struct v4l2_capability cap;
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       v4l2_fd = v4l2_open("/dev/video0", O_RDWR | O_NONBLOCK);
+       if (v4l2_fd < 0) {
+               ERR("v4l2 device open failed.(/dev/video0)\n");
+               param->errCode = EINVAL;
+               return;
+       }
+       if (xioctl(v4l2_fd, VIDIOC_QUERYCAP, &cap) < 0) {
+               ERR("Could not qeury video capabilities\n");
+               v4l2_close(v4l2_fd);
+               param->errCode = EINVAL;
+               return;
+       }
+       if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ||
+                       !(cap.capabilities & V4L2_CAP_STREAMING)) {
+               ERR("Not supported video driver.\n");
+               v4l2_close(v4l2_fd);
+               param->errCode = EINVAL;
+               return;
+       }
+
+       memset(&dst_fmt, 0, sizeof(dst_fmt));
+       INFO("Opened\n");
+}
+
+// MARUCAM_CMD_START_PREVIEW
+void marucam_device_start_preview(MaruCamState* state)
+{
+       pthread_mutex_lock(&state->thread->mutex_lock);
+       state->streamon = 1;
+       state->buf_size = dst_fmt.fmt.pix.sizeimage;
+       if (pthread_cond_signal(&state->thread->thread_cond))
+               ERR("failed to send a signal to the worker thread\n");
+       pthread_mutex_unlock(&state->thread->mutex_lock);
+}
+
+// MARUCAM_CMD_STOP_PREVIEW
+void marucam_device_stop_preview(MaruCamState* state)
+{
+       pthread_mutex_lock(&state->thread->mutex_lock);
+       state->streamon = 0;
+       state->buf_size = 0;
+       pthread_mutex_unlock(&state->thread->mutex_lock);
+       sleep(0);
+}
+
+void marucam_device_s_param(MaruCamState* state)
+{
+       struct v4l2_streamparm sp;
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       memset(&sp, 0, sizeof(struct v4l2_streamparm));
+       sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       sp.parm.capture.timeperframe.numerator = param->stack[0];
+       sp.parm.capture.timeperframe.denominator = param->stack[1];
+
+       if (xioctl(v4l2_fd, VIDIOC_S_PARM, &sp) < 0) {
+               ERR("failed to set FPS: %s\n", strerror(errno));
+               param->errCode = errno;
+       }
+}
+
+void marucam_device_g_param(MaruCamState* state)
+{
+       struct v4l2_streamparm sp;
+       MaruCamParam *param = state->thread->param;
+       
+       param->top = 0;
+       memset(&sp, 0, sizeof(struct v4l2_streamparm));
+       sp.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+       if (xioctl(v4l2_fd, VIDIOC_G_PARM, &sp) < 0) {
+               ERR("failed to get FPS: %s\n", strerror(errno));
+               param->errCode = errno;
+               return;
+       }
+       param->stack[0] = sp.parm.capture.capability;
+       param->stack[1] = sp.parm.capture.timeperframe.numerator;
+       param->stack[2] = sp.parm.capture.timeperframe.denominator;
+}
+
+void marucam_device_s_fmt(MaruCamState* state)
+{
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       memset(&dst_fmt, 0, sizeof(struct v4l2_format));
+       dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       dst_fmt.fmt.pix.width = param->stack[0];
+       dst_fmt.fmt.pix.height = param->stack[1];
+       dst_fmt.fmt.pix.pixelformat = param->stack[2];
+       dst_fmt.fmt.pix.field = param->stack[3];
+
+       if (xioctl(v4l2_fd, VIDIOC_S_FMT, &dst_fmt) < 0) {
+               ERR("failed to set video format: %s\n", strerror(errno));
+               param->errCode = errno;
+               return;
+       }
+
+       param->stack[0] = dst_fmt.fmt.pix.width;
+       param->stack[1] = dst_fmt.fmt.pix.height;
+       param->stack[2] = dst_fmt.fmt.pix.field;
+       param->stack[3] = dst_fmt.fmt.pix.pixelformat;
+       param->stack[4] = dst_fmt.fmt.pix.bytesperline;
+       param->stack[5] = dst_fmt.fmt.pix.sizeimage;
+       param->stack[6] = dst_fmt.fmt.pix.colorspace;
+       param->stack[7] = dst_fmt.fmt.pix.priv;
+}
+
+void marucam_device_g_fmt(MaruCamState* state)
+{
+       struct v4l2_format format;
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       memset(&format, 0, sizeof(struct v4l2_format));
+       format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+       if (xioctl(v4l2_fd, VIDIOC_G_FMT, &format) < 0) {
+               ERR("failed to get video format: %s\n", strerror(errno));
+               param->errCode = errno;         
+       } else {
+               param->stack[0] = format.fmt.pix.width;
+               param->stack[1] = format.fmt.pix.height;
+               param->stack[2] = format.fmt.pix.field;
+               param->stack[3] = format.fmt.pix.pixelformat;
+               param->stack[4] = format.fmt.pix.bytesperline;
+               param->stack[5] = format.fmt.pix.sizeimage;
+               param->stack[6] = format.fmt.pix.colorspace;
+               param->stack[7] = format.fmt.pix.priv;
+               memcpy(&dst_fmt, &format, sizeof(format));
+       }
+}
+
+void marucam_device_try_fmt(MaruCamState* state)
+{
+       struct v4l2_format format;
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       memset(&format, 0, sizeof(struct v4l2_format));
+       format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       format.fmt.pix.width = param->stack[0];
+       format.fmt.pix.height = param->stack[1];
+       format.fmt.pix.pixelformat = param->stack[2];
+       format.fmt.pix.field = param->stack[3];
+
+       if (xioctl(v4l2_fd, VIDIOC_TRY_FMT, &format) < 0) {
+               ERR("failed to check video format: %s\n", strerror(errno));
+               param->errCode = errno;
+               return;
+       }
+       param->stack[0] = format.fmt.pix.width;
+       param->stack[1] = format.fmt.pix.height;
+       param->stack[2] = format.fmt.pix.field;
+       param->stack[3] = format.fmt.pix.pixelformat;
+       param->stack[4] = format.fmt.pix.bytesperline;
+       param->stack[5] = format.fmt.pix.sizeimage;
+       param->stack[6] = format.fmt.pix.colorspace;
+       param->stack[7] = format.fmt.pix.priv;
+}
+
+void marucam_device_enum_fmt(MaruCamState* state)
+{
+       struct v4l2_fmtdesc format;
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       memset(&format, 0, sizeof(struct v4l2_fmtdesc));
+       format.index = param->stack[0];
+       format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+       if (xioctl(v4l2_fd, VIDIOC_ENUM_FMT, &format) < 0) {
+               if (errno != EINVAL)
+                       ERR("failed to enumerate video formats: %s\n", strerror(errno));
+               param->errCode = errno;
+               return;
+       }
+       param->stack[0] = format.index;
+       param->stack[1] = format.flags;
+       param->stack[2] = format.pixelformat;
+       /* set description */
+       memcpy(&param->stack[3], format.description, sizeof(format.description));
+}
+
+void marucam_device_qctrl(MaruCamState* state)
+{
+       uint32_t i;
+       char name[32] = {0,};
+       struct v4l2_queryctrl ctrl;
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       memset(&ctrl, 0, sizeof(struct v4l2_queryctrl));
+       ctrl.id = param->stack[0];
+
+       switch (ctrl.id) {
+       case V4L2_CID_BRIGHTNESS:
+               TRACE("Query : BRIGHTNESS\n");
+               memcpy((void*)name, (void*)"brightness", 32);
+               i = 0;
+               break;
+       case V4L2_CID_CONTRAST:
+               TRACE("Query : CONTRAST\n");
+               memcpy((void*)name, (void*)"contrast", 32);
+               i = 1;
+               break;
+       case V4L2_CID_SATURATION:
+               TRACE("Query : SATURATION\n");
+               memcpy((void*)name, (void*)"saturation", 32);
+               i = 2;
+               break;
+       case V4L2_CID_SHARPNESS:
+               TRACE("Query : SHARPNESS\n");
+               memcpy((void*)name, (void*)"sharpness", 32);
+               i = 3;
+               break;
+       default:
+               param->errCode = EINVAL;
+               return;
+       }
+
+       if (xioctl(v4l2_fd, VIDIOC_QUERYCTRL, &ctrl) < 0) {
+               if (errno != EINVAL)
+                       ERR("failed to query video controls : %s\n", strerror(errno));
+               param->errCode = errno;
+               return;
+       } else {
+               struct v4l2_control sctrl;
+               memset(&sctrl, 0, sizeof(struct v4l2_control));
+               sctrl.id = ctrl.id;
+               if ((ctrl.maximum + ctrl.minimum) == 0) {
+                       sctrl.value = 0;
+               } else {
+                       sctrl.value = (ctrl.maximum + ctrl.minimum) / 2;
+               }
+               if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &sctrl) < 0) {
+                       ERR("failed to set video control value : %s\n", strerror(errno));
+                       param->errCode = errno;
+                       return;
+               }
+               qctrl_tbl[i].hit = 1;
+               qctrl_tbl[i].min = ctrl.minimum;
+               qctrl_tbl[i].max = ctrl.maximum;
+               qctrl_tbl[i].step = ctrl.step;
+               qctrl_tbl[i].init_val = ctrl.default_value;
+       }
+
+       // set fixed values by FW configuration file
+       param->stack[0] = ctrl.id;
+       param->stack[1] = MARUCAM_CTRL_VALUE_MIN;       // minimum
+       param->stack[2] = MARUCAM_CTRL_VALUE_MAX;       // maximum
+       param->stack[3] = MARUCAM_CTRL_VALUE_STEP;// step
+       param->stack[4] = MARUCAM_CTRL_VALUE_MID;       // default_value
+       param->stack[5] = ctrl.flags;
+       /* name field setting */
+       memcpy(&param->stack[6], (void*)name, sizeof(ctrl.name));
+}
+
+void marucam_device_s_ctrl(MaruCamState* state)
+{
+       uint32_t i;
+       struct v4l2_control ctrl;
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       memset(&ctrl, 0, sizeof(struct v4l2_control));
+       ctrl.id = param->stack[0];
+
+       switch (ctrl.id) {
+       case V4L2_CID_BRIGHTNESS:
+               i = 0;
+               TRACE("%d is set to the value of the BRIGHTNESS\n", param->stack[1]);
+               break;
+       case V4L2_CID_CONTRAST:
+               i = 1;
+               TRACE("%d is set to the value of the CONTRAST\n", param->stack[1]);
+               break;
+       case V4L2_CID_SATURATION:
+               i = 2;
+               TRACE("%d is set to the value of the SATURATION\n", param->stack[1]);
+               break;
+       case V4L2_CID_SHARPNESS:
+               i = 3;
+               TRACE("%d is set to the value of the SHARPNESS\n", param->stack[1]);
+               break;
+       default:
+               ERR("our emulator does not support this control : 0x%x\n", ctrl.id);
+               param->errCode = EINVAL;
+               return;
+       }
+
+       ctrl.value = value_convert_from_guest(qctrl_tbl[i].min,
+                       qctrl_tbl[i].max, param->stack[1]);
+       if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) {
+               ERR("failed to set video control value : value(%d), %s\n", param->stack[1], strerror(errno));
+               param->errCode = errno;
+               return;
+       }
+}
+
+void marucam_device_g_ctrl(MaruCamState* state)
+{
+       uint32_t i;
+       struct v4l2_control ctrl;
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       memset(&ctrl, 0, sizeof(struct v4l2_control));
+       ctrl.id = param->stack[0];
+
+       switch (ctrl.id) {
+       case V4L2_CID_BRIGHTNESS:
+               TRACE("Gets the value of the BRIGHTNESS\n");
+               i = 0;
+               break;
+       case V4L2_CID_CONTRAST:
+               TRACE("Gets the value of the CONTRAST\n");
+               i = 1;
+               break;
+       case V4L2_CID_SATURATION:
+               TRACE("Gets the value of the SATURATION\n");
+               i = 2;
+               break;
+       case V4L2_CID_SHARPNESS:
+               TRACE("Gets the value of the SHARPNESS\n");
+               i = 3;
+               break;
+       default:
+               ERR("our emulator does not support this control : 0x%x\n", ctrl.id);
+               param->errCode = EINVAL;
+               return;
+       }
+
+       if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &ctrl) < 0) {
+               ERR("failed to get video control value : %s\n", strerror(errno));
+               param->errCode = errno;
+               return;
+       }
+       param->stack[0] = value_convert_to_guest(qctrl_tbl[i].min,
+                       qctrl_tbl[i].max, ctrl.value);
+       TRACE("Value : %d\n", param->stack[0]);
+}
+
+void marucam_device_enum_fsizes(MaruCamState* state)
+{
+       struct v4l2_frmsizeenum fsize;
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       memset(&fsize, 0, sizeof(struct v4l2_frmsizeenum));
+       fsize.index = param->stack[0];
+       fsize.pixel_format = param->stack[1];
+
+       if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMESIZES, &fsize) < 0) {
+               if (errno != EINVAL)
+                       ERR("failed to get frame sizes : %s\n", strerror(errno));
+               param->errCode = errno;
+               return;
+       }
+
+       if (fsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
+               param->stack[0] = fsize.discrete.width;
+               param->stack[1] = fsize.discrete.height;
+       } else {
+               param->errCode = EINVAL;
+               ERR("Not Supported mode, we only support DISCRETE\n");
+       }
+}
+
+void marucam_device_enum_fintv(MaruCamState* state)
+{
+       struct v4l2_frmivalenum ival;
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       memset(&ival, 0, sizeof(struct v4l2_frmivalenum));
+       ival.index = param->stack[0];
+       ival.pixel_format = param->stack[1];
+       ival.width = param->stack[2];
+       ival.height = param->stack[3];
+
+       if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &ival) < 0) {
+               if (errno != EINVAL)
+                       ERR("failed to get frame intervals : %s\n", strerror(errno));
+               param->errCode = errno;
+               return;
+       }
+
+       if (ival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
+               param->stack[0] = ival.discrete.numerator;
+               param->stack[1] = ival.discrete.denominator;
+       } else {
+               param->errCode = EINVAL;
+               ERR("Not Supported mode, we only support DISCRETE\n");
+       }
+}
+
+// MARUCAM_CMD_CLOSE
+void marucam_device_close(MaruCamState* state)
+{
+       pthread_mutex_lock(&state->thread->mutex_lock);
+       state->streamon = 0;
+       pthread_mutex_unlock(&state->thread->mutex_lock);
+
+       marucam_reset_controls();
+
+       v4l2_close(v4l2_fd);
+       v4l2_fd = 0;
+       INFO("Closed\n");
+}
diff --git a/tizen/src/hw/maru_camera_win32_pci.c b/tizen/src/hw/maru_camera_win32_pci.c
new file mode 100644 (file)
index 0000000..9dcb38c
--- /dev/null
@@ -0,0 +1,744 @@
+/*
+ * Implementation of MARU Virtual Camera device by PCI bus on Windows.
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ * JinHyung Jo <jinhyung.jo@samsung.com>
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ *
+ */
+
+
+#include "qemu-common.h"
+#include "maru_camera_common.h"
+#include "pci.h"
+#include "kvm.h"
+#include "tizen/src/debug_ch.h"
+
+#include "windows.h"
+#include "basetyps.h"
+#include "mmsystem.h"
+
+MULTI_DEBUG_CHANNEL(tizen, camera_win32);
+
+// V4L2 defines copy from videodev2.h
+#define V4L2_CTRL_FLAG_SLIDER          0x0020
+
+#define V4L2_CTRL_CLASS_USER           0x00980000
+#define V4L2_CID_BASE                          (V4L2_CTRL_CLASS_USER | 0x900)
+#define V4L2_CID_BRIGHTNESS                    (V4L2_CID_BASE+0)
+#define V4L2_CID_CONTRAST                      (V4L2_CID_BASE+1)
+#define V4L2_CID_SATURATION                    (V4L2_CID_BASE+2)
+#define V4L2_CID_SHARPNESS                     (V4L2_CID_BASE+27)
+
+#define V4L2_PIX_FMT_YUYV    MAKEFOURCC('Y', 'U', 'Y', 'V') /* 16  YUV 4:2:2     */
+#define V4L2_PIX_FMT_YUV420  MAKEFOURCC('Y', 'U', '1', '2') /* 12  YUV 4:2:0     */
+#define V4L2_PIX_FMT_YVU420  MAKEFOURCC('Y', 'V', '1', '2') /* 12  YVU 4:2:0     */
+
+enum {
+       HWC_OPEN,
+       HWC_CLOSE,
+       HWC_START,
+       HWC_STOP,
+       HWC_S_FPS,
+       HWC_G_FPS,
+       HWC_S_FMT,
+       HWC_G_FMT,
+       HWC_TRY_FMT,
+       HWC_ENUM_FMT,
+       HWC_QCTRL,
+       HWC_S_CTRL,
+       HWC_G_CTRL,
+       HWC_ENUM_FSIZES,
+       HWC_ENUM_INTERVALS
+};
+
+typedef enum tagVideoProcAmpProperty {
+  VideoProcAmp_Brightness,
+  VideoProcAmp_Contrast,
+  VideoProcAmp_Hue,
+  VideoProcAmp_Saturation,
+  VideoProcAmp_Sharpness,
+  VideoProcAmp_Gamma,
+  VideoProcAmp_ColorEnable,
+  VideoProcAmp_WhiteBalance,
+  VideoProcAmp_BacklightCompensation,
+  VideoProcAmp_Gain
+} VideoProcAmpProperty;
+
+typedef struct tagHWCParam {
+       long val1;
+       long val2;
+       long val3;
+       long val4;
+       long val5;
+} HWCParam;
+
+typedef struct tagMaruCamConvertPixfmt {
+       uint32_t fmt;   /* fourcc */
+       uint32_t bpp;   /* bits per pixel, 0 for compressed formats */
+       uint32_t needs_conversion;
+} MaruCamConvertPixfmt;
+
+static MaruCamConvertPixfmt supported_dst_pixfmts[] = {
+               { V4L2_PIX_FMT_YUYV, 16, 0 },
+               { V4L2_PIX_FMT_YUV420, 12, 0 },
+               { V4L2_PIX_FMT_YVU420, 12, 0 },
+};
+
+typedef struct tagMaruCamConvertFrameInfo {
+       uint32_t width;
+       uint32_t height;
+} MaruCamConvertFrameInfo;
+
+static MaruCamConvertFrameInfo supported_dst_frames[] = {
+               { 640, 480 },
+               { 352, 288 },
+               { 320, 240 },
+               { 176, 144 },
+               { 160, 120 },
+};
+
+#define MARUCAM_CTRL_VALUE_MAX         20
+#define MARUCAM_CTRL_VALUE_MIN         1
+#define MARUCAM_CTRL_VALUE_MID         10
+#define MARUCAM_CTRL_VALUE_STEP                1
+
+struct marucam_qctrl {
+       uint32_t id;
+       uint32_t hit;
+       long min;
+       long max;
+       long step;
+       long init_val;
+};
+
+static struct marucam_qctrl qctrl_tbl[] = {
+       { V4L2_CID_BRIGHTNESS, 0, },
+       { V4L2_CID_CONTRAST, 0, },
+       { V4L2_CID_SATURATION,0, },
+       { V4L2_CID_SHARPNESS, 0, },
+};
+
+typedef int (STDAPICALLTYPE *CallbackFn)(ULONG dwSize, BYTE *pBuffer);
+typedef HRESULT (STDAPICALLTYPE *CTRLFN)(UINT, UINT, LPVOID);
+typedef HRESULT (STDAPICALLTYPE *SETCALLBACKFN)(CallbackFn);
+
+
+static HINSTANCE g_hInst = NULL;
+static MaruCamState *g_state = NULL;
+
+static CTRLFN MaruCamCtrl;
+static SETCALLBACKFN MaruCamSetCallbackFn;
+
+static uint32_t cur_fmt_idx = 0;
+static uint32_t cur_frame_idx = 0;
+
+void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dest,
+               uint32_t width, uint32_t height, uint32_t yvu);
+
+
+static long value_convert_from_guest(long min, long max, long value)
+{
+       double rate = 0.0;
+       long dist = 0, ret = 0;
+
+       dist = max - min;
+
+       if (dist < MARUCAM_CTRL_VALUE_MAX) {
+               rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;
+               ret = min + (int32_t)(value / rate);
+       } else {
+               rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;
+               ret = min + (int32_t)(rate * value);
+       }
+       return ret;
+}
+
+static long value_convert_to_guest(long min, long max, long value)
+{
+       double rate  = 0.0;
+       long dist = 0, ret = 0;
+
+       dist = max - min;
+
+       if (dist < MARUCAM_CTRL_VALUE_MAX) {
+               rate = (double)MARUCAM_CTRL_VALUE_MAX / (double)dist;
+               ret = (int32_t)((double)(value - min) * rate);
+       } else {
+               rate = (double)dist / (double)MARUCAM_CTRL_VALUE_MAX;
+               ret = (int32_t)((double)(value - min) / rate);
+       }
+
+       return ret;
+}
+
+static int STDAPICALLTYPE marucam_device_callbackfn(ULONG dwSize, BYTE *pBuffer)
+{
+       static uint32_t index = 0;
+       uint32_t width, height;
+       width = supported_dst_frames[cur_frame_idx].width;
+       height = supported_dst_frames[cur_frame_idx].height;
+       void *buf = g_state->vaddr + (g_state->buf_size * index);
+
+       switch (supported_dst_pixfmts[cur_fmt_idx].fmt) {
+       case V4L2_PIX_FMT_YUV420:
+               v4lconvert_yuyv_to_yuv420(pBuffer, buf, width, height, 0);
+               break;
+       case V4L2_PIX_FMT_YVU420:
+               v4lconvert_yuyv_to_yuv420(pBuffer, buf, width, height, 1);
+               break;
+       case V4L2_PIX_FMT_YUYV:
+               memcpy(buf, (void*)pBuffer, dwSize);
+               break;
+       }
+       index = !index;
+
+       if (g_state->req_frame) {
+               qemu_irq_raise(g_state->dev.irq[2]);
+               g_state->req_frame = 0;
+       }
+       return 1;
+}
+
+// MARUCAM_CMD_INIT
+void marucam_device_init(MaruCamState* state)
+{
+       MaruCamThreadInfo *thread = state->thread;
+
+       pthread_cond_init(&thread->thread_cond, NULL);
+       pthread_mutex_init(&thread->mutex_lock, NULL);
+
+       g_state = state;
+}
+
+// MARUCAM_CMD_OPEN
+void marucam_device_open(MaruCamState* state)
+{
+       HRESULT hr;
+       MaruCamParam *param = state->thread->param;
+       param->top = 0;
+
+       g_hInst = LoadLibrary("hwcfilter.dll");
+
+       if (!g_hInst) {
+               g_hInst = LoadLibrary("bin\\hwcfilter.dll");
+               if (!g_hInst) {
+                       ERR("load library failed!!!!\n");
+                       param->errCode = EINVAL;
+                       return;
+               }
+       }
+
+       MaruCamCtrl = (CTRLFN)GetProcAddress(g_hInst, "HWCCtrl");
+       if (!MaruCamCtrl) {
+               ERR("HWCCtrl get failed!!!\n");
+               FreeLibrary(g_hInst);
+               param->errCode = EINVAL;
+               return;
+       }
+
+       MaruCamSetCallbackFn = (SETCALLBACKFN)GetProcAddress(g_hInst, "HWCSetCallback");
+       if (!MaruCamSetCallbackFn) {
+               ERR("HWCSetCallback get failed!!!\n");
+               FreeLibrary(g_hInst);
+               param->errCode = EINVAL;
+               return;
+       }
+
+       hr = MaruCamCtrl(HWC_OPEN, 0, NULL);
+       if (FAILED(hr)) {
+               param->errCode = EINVAL;
+               FreeLibrary(g_hInst);
+               ERR("camera device open failed!!!, [HRESULT : 0x%x]\n", hr);
+               return;
+       }
+       hr = MaruCamSetCallbackFn((CallbackFn)marucam_device_callbackfn);
+       if (FAILED(hr)) {
+               param->errCode = EINVAL;
+               MaruCamCtrl(HWC_CLOSE, 0, NULL);
+               FreeLibrary(g_hInst);
+               ERR("call back function set failed!!!, [HRESULT : 0x%x]\n", hr);
+       }
+
+       TRACE("camera device open success!!!, [HRESULT : 0x%x]\n", hr);
+}
+
+// MARUCAM_CMD_CLOSE
+void marucam_device_close(MaruCamState* state)
+{
+       HRESULT hr;
+       MaruCamParam *param = state->thread->param;
+       param->top = 0;
+       hr = MaruCamCtrl(HWC_CLOSE, 0, NULL);
+       if (FAILED(hr)) {
+               param->errCode = EINVAL;
+               ERR("camera device close failed!!!, [HRESULT : 0x%x]\n", hr);
+       }
+       FreeLibrary(g_hInst);
+       TRACE("camera device close success!!!, [HRESULT : 0x%x]\n", hr);
+}
+
+// MARUCAM_CMD_START_PREVIEW
+void marucam_device_start_preview(MaruCamState* state)
+{
+       HRESULT hr;
+       uint32_t width, height;
+       MaruCamParam *param = state->thread->param;
+       TRACE("marucam_device_start_preview\n");
+       param->top = 0;
+       hr = MaruCamCtrl(HWC_START, 0, NULL);
+       if (FAILED(hr)) {
+               param->errCode = EINVAL;
+               ERR("start preview failed!!!, [HRESULT : 0x%x]\n", hr);
+               return;
+       }
+       pthread_mutex_lock(&state->thread->mutex_lock);
+       state->streamon = 1;
+       pthread_mutex_unlock(&state->thread->mutex_lock);
+
+       width = supported_dst_frames[cur_frame_idx].width;
+       height = supported_dst_frames[cur_frame_idx].height;
+       state->buf_size = height * ((width * supported_dst_pixfmts[cur_fmt_idx].bpp) >> 3);
+}
+
+// MARUCAM_CMD_STOP_PREVIEW
+void marucam_device_stop_preview(MaruCamState* state)
+{
+       HRESULT hr;
+       MaruCamParam *param = state->thread->param;
+       TRACE("marucam_device_stop_preview\n");
+       param->top = 0;
+       hr = MaruCamCtrl(HWC_STOP, 0, NULL);
+       if (FAILED(hr)) {
+               param->errCode = EINVAL;
+               ERR("stop preview failed!!!, [HRESULT : 0x%x]\n", hr);
+       }
+       pthread_mutex_lock(&state->thread->mutex_lock);
+       state->streamon = 0;
+       pthread_mutex_unlock(&state->thread->mutex_lock);
+       state->buf_size = 0;
+}
+
+// MARUCAM_CMD_S_PARAM
+void marucam_device_s_param(MaruCamState* state)
+{
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       TRACE("setting fps : %d/%d\n", param->stack[0], param->stack[1]);
+}
+
+// MARUCAM_CMD_G_PARAM
+void marucam_device_g_param(MaruCamState* state)
+{
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       TRACE("getting fps : 30/1\n");
+
+       param->stack[0] = 0x1000; // V4L2_CAP_TIMEPERFRAME
+       param->stack[1] = 1; // numerator;
+       param->stack[2] = 30; // denominator;
+}
+
+// MARUCAM_CMD_S_FMT
+void marucam_device_s_fmt(MaruCamState* state)
+{
+       uint32_t width, height, pixfmt, pidx, fidx;
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       width = param->stack[0];                // width
+       height = param->stack[1];               // height
+       pixfmt = param->stack[2];               // pixelformat
+
+       for (fidx = 0; fidx < ARRAY_SIZE(supported_dst_frames); fidx++) {
+               if ((supported_dst_frames[fidx].width == width) &&
+                               (supported_dst_frames[fidx].height == height)) {
+                       break;
+               }
+       }
+       if (fidx == ARRAY_SIZE(supported_dst_frames)) {
+               param->errCode = EINVAL;
+               return;
+       }
+       for (pidx = 0; pidx < ARRAY_SIZE(supported_dst_pixfmts); pidx++) {
+               if (supported_dst_pixfmts[pidx].fmt == pixfmt) {
+                       break;
+               }
+       }
+       if (pidx == ARRAY_SIZE(supported_dst_pixfmts)) {
+               param->errCode = EINVAL;
+               return;
+       }
+
+       if ((supported_dst_frames[cur_frame_idx].width != width) &&
+                       (supported_dst_frames[cur_frame_idx].height != height)) {
+               HWCParam inParam = {0,};
+               inParam.val1 = width;
+               inParam.val2 = height;
+               HRESULT hr = MaruCamCtrl(HWC_S_FMT, sizeof(HWCParam), &inParam);
+               if (FAILED(hr)) {
+                       param->errCode = EINVAL;
+                       return;
+               }
+       }
+
+       param->stack[0] = width;
+       param->stack[1] = height;
+       param->stack[2] = 1; // V4L2_FIELD_NONE
+       param->stack[3] = pixfmt;
+       // bytes per line = (width * bpp) / 8
+       param->stack[4] = (width * supported_dst_pixfmts[pidx].bpp) >> 3;
+       param->stack[5] = param->stack[4] * height;     // height * bytesperline
+       param->stack[6] = 0;
+       param->stack[7] = 0;
+
+       cur_frame_idx = fidx;
+       cur_fmt_idx = pidx;
+}
+
+// MARUCAM_CMD_G_FMT
+void marucam_device_g_fmt(MaruCamState* state)
+{
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+
+       param->stack[0] = supported_dst_frames[cur_frame_idx].width;    // width
+       param->stack[1] = supported_dst_frames[cur_frame_idx].height;   // height
+       param->stack[2] = 1; // V4L2_FIELD_NONE
+       param->stack[3] = supported_dst_pixfmts[cur_fmt_idx].fmt;       // pixelformat
+       // bytes per line = (width * bpp) / 8
+       param->stack[4] = (param->stack[0] * supported_dst_pixfmts[cur_fmt_idx].bpp) >> 3;
+       param->stack[5] = param->stack[1] * param->stack[4];    // height * bytesperline
+       param->stack[6] = 0;
+       param->stack[7] = 0;
+}
+
+void marucam_device_try_fmt(MaruCamState* state)
+{
+       uint32_t width, height, pixfmt, i;
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       width = param->stack[0];                // width
+       height = param->stack[1];               // height
+       pixfmt = param->stack[2];               // pixelformat
+
+       for (i = 0; i < ARRAY_SIZE(supported_dst_frames); i++) {
+               if ((supported_dst_frames[i].width == width) &&
+                               (supported_dst_frames[i].height == height)) {
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(supported_dst_frames)) {
+               param->errCode = EINVAL;
+               return;
+       }
+       for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
+               if (supported_dst_pixfmts[i].fmt == pixfmt) {
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
+               param->errCode = EINVAL;
+               return;
+       }
+
+       param->stack[0] = width;
+       param->stack[1] = height;
+       param->stack[2] = 1; // V4L2_FIELD_NONE
+       param->stack[3] = pixfmt;
+       // bytes per line = (width * bpp) / 8
+       param->stack[4] = (width * supported_dst_pixfmts[i].bpp) >> 3;
+       param->stack[5] = param->stack[4] * height;     // height * bytesperline
+       param->stack[6] = 0;
+       param->stack[7] = 0;
+}
+
+void marucam_device_enum_fmt(MaruCamState* state)
+{
+       uint32_t index;
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       index = param->stack[0];
+
+       if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {
+               param->errCode = EINVAL;
+               return;
+       }
+       param->stack[1] = 0;                                                    // flags = NONE;
+       param->stack[2] = supported_dst_pixfmts[index].fmt;     // pixelformat;
+       /* set description */
+       switch (supported_dst_pixfmts[index].fmt) {
+       case V4L2_PIX_FMT_YUYV:
+               memcpy(&param->stack[3], "YUY2", 32);
+               break;
+       case V4L2_PIX_FMT_YUV420:
+               memcpy(&param->stack[3], "YU12", 32);
+               break;
+       case V4L2_PIX_FMT_YVU420:
+               memcpy(&param->stack[3], "YV12", 32);
+               break;
+       }
+}
+
+void marucam_device_qctrl(MaruCamState* state)
+{
+       HRESULT hr;
+       uint32_t id, i;
+       HWCParam inParam = {0,};
+       char name[32] = {0,};
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       id = param->stack[0];
+
+       switch (id) {
+       case V4L2_CID_BRIGHTNESS:
+               TRACE("V4L2_CID_BRIGHTNESS\n");
+               inParam.val1 = VideoProcAmp_Brightness;
+               memcpy((void*)name, (void*)"brightness", 32);
+               i = 0;
+               break;
+       case V4L2_CID_CONTRAST:
+               TRACE("V4L2_CID_CONTRAST\n");
+               inParam.val1 = VideoProcAmp_Contrast;
+               memcpy((void*)name, (void*)"contrast", 32);
+               i = 1;
+               break;
+       case V4L2_CID_SATURATION:
+               TRACE("V4L2_CID_SATURATION\n");
+               inParam.val1 = VideoProcAmp_Saturation;
+               memcpy((void*)name, (void*)"saturation", 32);
+               i = 2;
+               break;
+       case V4L2_CID_SHARPNESS:
+               TRACE("V4L2_CID_SHARPNESS\n");
+               inParam.val1 = VideoProcAmp_Sharpness;
+               memcpy((void*)name, (void*)"sharpness", 32);
+               i = 3;
+               break;
+       default:
+               param->errCode = EINVAL;
+               return;
+       }
+       hr = MaruCamCtrl(HWC_QCTRL, sizeof(inParam), &inParam);
+       if (FAILED(hr)) {
+               param->errCode = EINVAL;
+               ERR("failed to query video controls [HRESULT : 0x%x]\n", hr);
+               return;
+       } else {
+               qctrl_tbl[i].hit = 1;
+               qctrl_tbl[i].min = inParam.val2;
+               qctrl_tbl[i].max = inParam.val3;
+               qctrl_tbl[i].step = inParam.val4;
+               qctrl_tbl[i].init_val = inParam.val5;
+
+               if ((qctrl_tbl[i].min + qctrl_tbl[i].max) == 0) {
+                       inParam.val2 = 0;
+               } else {
+                       inParam.val2 = (qctrl_tbl[i].min + qctrl_tbl[i].max) / 2;
+               }
+               hr = MaruCamCtrl(HWC_S_CTRL, sizeof(inParam), &inParam);
+               if (FAILED(hr)) {
+                       param->errCode = EINVAL;
+                       ERR("failed to set video control value, [HRESULT : 0x%x]\n", hr);
+                       return;
+               }
+       }
+
+       param->stack[0] = id;
+       param->stack[1] = MARUCAM_CTRL_VALUE_MIN;       // minimum
+       param->stack[2] = MARUCAM_CTRL_VALUE_MAX;       // maximum
+       param->stack[3] = MARUCAM_CTRL_VALUE_STEP;// step
+       param->stack[4] = MARUCAM_CTRL_VALUE_MID;       // default_value
+       param->stack[5] = V4L2_CTRL_FLAG_SLIDER;
+       /* name field setting */
+       memcpy(&param->stack[6], (void*)name, sizeof(name)/sizeof(name[0]));
+}
+
+void marucam_device_s_ctrl(MaruCamState* state)
+{
+       HRESULT hr;
+       uint32_t i;
+       HWCParam inParam = {0,};
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+
+       switch (param->stack[0]) {
+       case V4L2_CID_BRIGHTNESS:
+               i = 0;
+               inParam.val1 = VideoProcAmp_Brightness;
+               break;
+       case V4L2_CID_CONTRAST:
+               i = 1;
+               inParam.val1 = VideoProcAmp_Contrast;
+               break;
+       case V4L2_CID_SATURATION:
+               i = 2;
+               inParam.val1 = VideoProcAmp_Saturation;
+               break;
+       case V4L2_CID_SHARPNESS:
+               i = 3;
+               inParam.val1 = VideoProcAmp_Sharpness;
+               break;
+       default:
+               param->errCode = EINVAL;
+               return;
+       }
+       inParam.val2 = value_convert_from_guest(qctrl_tbl[i].min,
+                       qctrl_tbl[i].max, (long)param->stack[1]);
+       hr = MaruCamCtrl(HWC_S_CTRL, sizeof(inParam), &inParam);
+       if (FAILED(hr)) {
+               param->errCode = EINVAL;
+               ERR("failed to set video control value, [HRESULT : 0x%x]\n", hr);
+               return;
+       }
+}
+
+void marucam_device_g_ctrl(MaruCamState* state)
+{
+       HRESULT hr;
+       uint32_t i;
+       HWCParam inParam = {0,};
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       switch (param->stack[0]) {
+       case V4L2_CID_BRIGHTNESS:
+               i = 0;
+               inParam.val1 = VideoProcAmp_Brightness;
+               break;
+       case V4L2_CID_CONTRAST:
+               i = 1;
+               inParam.val1 = VideoProcAmp_Contrast;
+               break;
+       case V4L2_CID_SATURATION:
+               i = 2;
+               inParam.val1 = VideoProcAmp_Saturation;
+               break;
+       case V4L2_CID_SHARPNESS:
+               i = 3;
+               inParam.val1 = VideoProcAmp_Sharpness;
+               break;
+       default:
+               param->errCode = EINVAL;
+               return;
+       }
+
+       hr = MaruCamCtrl(HWC_G_CTRL, sizeof(inParam), &inParam);
+       if (FAILED(hr)) {
+               param->errCode = EINVAL;
+               ERR("failed to get video control value!!!, [HRESULT : 0x%x]\n", hr);
+               return;
+       }
+       param->stack[0] = (uint32_t)value_convert_to_guest(qctrl_tbl[i].min,
+                               qctrl_tbl[i].max, inParam.val2);
+}
+
+void marucam_device_enum_fsizes(MaruCamState* state)
+{
+       uint32_t index, pixfmt, i;
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+       index = param->stack[0];
+       pixfmt = param->stack[1];
+
+       if (index >= ARRAY_SIZE(supported_dst_frames)) {
+               param->errCode = EINVAL;
+               return;
+       }
+       for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
+               if (supported_dst_pixfmts[i].fmt == pixfmt)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
+               param->errCode = EINVAL;
+               return;
+       }
+
+       param->stack[0] = supported_dst_frames[index].width;
+       param->stack[1] = supported_dst_frames[index].height;
+}
+
+void marucam_device_enum_fintv(MaruCamState* state)
+{
+       MaruCamParam *param = state->thread->param;
+
+       param->top = 0;
+
+       // switch by index(param->stack[0])
+       switch (param->stack[0]) {
+       case 0:
+               param->stack[1] = 30;   // denominator
+               break;
+       default:
+               param->errCode = EINVAL;
+               return;
+       }
+       param->stack[0] = 1;    // numerator
+}
+
+void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dest,
+               uint32_t width, uint32_t height, uint32_t yvu)
+{
+       uint32_t i, j;
+       const unsigned char *src1;
+       unsigned char *udest, *vdest;
+
+       /* copy the Y values */
+       src1 = src;
+       for (i = 0; i < height; i++) {
+               for (j = 0; j < width; j += 2) {
+                       *dest++ = src1[0];
+                       *dest++ = src1[2];
+                       src1 += 4;
+               }
+       }
+
+       /* copy the U and V values */
+       src++;                          /* point to V */
+       src1 = src + width * 2;         /* next line */
+       if (yvu) {
+               vdest = dest;
+               udest = dest + width * height / 4;
+       } else {
+               udest = dest;
+               vdest = dest + width * height / 4;
+       }
+       for (i = 0; i < height; i += 2) {
+               for (j = 0; j < width; j += 2) {
+                       *udest++ = ((int) src[0] + src1[0]) / 2;        /* U */
+                       *vdest++ = ((int) src[2] + src1[2]) / 2;        /* V */
+                       src += 4;
+                       src1 += 4;
+               }
+               src = src1;
+               src1 += width * 2;
+       }
+}