maru-camera: Code refactoring 42/37242/1
authorjinhyung.jo <jinhyung.jo@samsung.com>
Mon, 23 Mar 2015 09:10:43 +0000 (18:10 +0900)
committerjinhyung.jo <jinhyung.jo@samsung.com>
Mon, 23 Mar 2015 09:10:43 +0000 (18:10 +0900)
Modified the common & the linux module.

Change-Id: I0239158aac07a217b8a47f8df239f96bc38f45ea
Signed-off-by: Jinhyung Jo <jinhyung.jo@samsung.com>
tizen/src/hw/pci/maru_camera.c
tizen/src/hw/pci/maru_camera.h
tizen/src/hw/pci/maru_camera_linux.c

index 112c2866b4d5bf0e12817c4fbc929cf87a4aa431..4103f2698d5a0034875c84e0963cd213e7df68bd 100644 (file)
@@ -47,8 +47,10 @@ MULTI_DEBUG_CHANNEL(tizen, camera);
 
 #define MARU_PCI_CAMERA_DEVICE_NAME     "maru-camera"
 
-#define MARUCAM_MEM_SIZE    (4 * 1024 * 1024)   /* 4MB */
-#define MARUCAM_REG_SIZE    (256)               /* 64 * 4Byte */
+/* WQXGA(2560x1600) * RGBA(4Byte) */
+#define MARUCAM_MEM_SIZE      (2560 * 1600 * 4)
+#define MARUCAM_REG_SIZE      (256)             /* 64 * 4Byte */
+#define MARUCAM_IOMEM_SIZE    (512)             /* 512Byte */
 
 /*
  *  I/O functions
@@ -69,27 +71,6 @@ marucam_mmio_read(void *opaque, hwaddr offset)
         }
         qemu_mutex_unlock(&state->thread_mutex);
         break;
-    case MARUCAM_CMD_G_DATA:
-        ret = state->param->stack[state->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->param->errCode;
-        state->param->errCode = 0;
-        break;
     default:
         ERR("Not supported command: 0x%x\n", offset);
         ret = EINVAL;
@@ -105,56 +86,49 @@ marucam_mmio_write(void *opaque, hwaddr offset, uint32_t value)
 
     switch (offset & 0xFF) {
     case MARUCAM_CMD_OPEN:
-        marucam_device_open(state);
+        state->backend->open(state);
         break;
     case MARUCAM_CMD_CLOSE:
-        marucam_device_close(state);
+        state->backend->close(state);
         break;
-    case MARUCAM_CMD_START_PREVIEW:
-        marucam_device_start_preview(state);
+    case MARUCAM_CMD_STREAMON:
+        state->backend->stream_on(state);
         break;
-    case MARUCAM_CMD_STOP_PREVIEW:
-        marucam_device_stop_preview(state);
-        memset(state->vaddr, 0, MARUCAM_MEM_SIZE);
+    case MARUCAM_CMD_STREAMOFF:
+        state->backend->stream_off(state);
         break;
-    case MARUCAM_CMD_S_PARAM:
-        marucam_device_s_param(state);
+    case MARUCAM_CMD_S_PARM:
+        state->backend->s_parm(state);
         break;
-    case MARUCAM_CMD_G_PARAM:
-        marucam_device_g_param(state);
+    case MARUCAM_CMD_G_PARM:
+        state->backend->g_parm(state);
         break;
     case MARUCAM_CMD_ENUM_FMT:
-        marucam_device_enum_fmt(state);
+        state->backend->enum_fmt(state);
         break;
     case MARUCAM_CMD_TRY_FMT:
-        marucam_device_try_fmt(state);
+        state->backend->try_fmt(state);
         break;
     case MARUCAM_CMD_S_FMT:
-        marucam_device_s_fmt(state);
+        state->backend->s_fmt(state);
         break;
     case MARUCAM_CMD_G_FMT:
-        marucam_device_g_fmt(state);
+        state->backend->g_fmt(state);
         break;
-    case MARUCAM_CMD_QCTRL:
-        marucam_device_qctrl(state);
+    case MARUCAM_CMD_QUERYCTRL:
+        state->backend->query_ctrl(state);
         break;
     case MARUCAM_CMD_S_CTRL:
-        marucam_device_s_ctrl(state);
+        state->backend->s_ctrl(state);
         break;
     case MARUCAM_CMD_G_CTRL:
-        marucam_device_g_ctrl(state);
+        state->backend->g_ctrl(state);
         break;
     case MARUCAM_CMD_ENUM_FSIZES:
-        marucam_device_enum_fsizes(state);
+        state->backend->enum_framesizes(state);
         break;
     case MARUCAM_CMD_ENUM_FINTV:
-        marucam_device_enum_fintv(state);
-        break;
-    case MARUCAM_CMD_S_DATA:
-        state->param->stack[state->param->top++] = value;
-        break;
-    case MARUCAM_CMD_DATACLR:
-        memset(state->param, 0, sizeof(MaruCamParam));
+        state->backend->enum_frameintervals(state);
         break;
     case MARUCAM_CMD_REQFRAME:
         qemu_mutex_lock(&state->thread_mutex);
@@ -209,7 +183,7 @@ static int marucam_initfn(PCIDevice *dev)
     /* Check available webcam
      * If there is not one, you can't use the camera.
      */
-    if (!marucam_device_check(1)) {
+    if (!marucam_device_check()) {
         s->initialized = false;
         ERR("Failed to check the camera device, "
             "You can *not* use the camera\n");
@@ -218,26 +192,32 @@ static int marucam_initfn(PCIDevice *dev)
 
     pci_config_set_interrupt_pin(pci_conf, 0x03);
 
-    memory_region_init_ram(&s->vram, OBJECT(s), "marucamera.ram", MARUCAM_MEM_SIZE,
-                            &error_abort);
-    s->vaddr = memory_region_get_ram_ptr(&s->vram);
-    memset(s->vaddr, 0, MARUCAM_MEM_SIZE);
+    memory_region_init_ram(&s->fbmem, OBJECT(s), "marucamera.fbmem",
+                           MARUCAM_MEM_SIZE, &error_abort);
+    s->fb_ptr = memory_region_get_ram_ptr(&s->fbmem);
+    memset(s->fb_ptr, 0, MARUCAM_MEM_SIZE);
+
+    memory_region_init_ram(&s->iomem, OBJECT(s), "marucamera.iomem",
+                           MARUCAM_IOMEM_SIZE, &error_abort);
+    s->io_ptr = (ArgsMem *)memory_region_get_ram_ptr(&s->iomem);
+    memset((void *)s->io_ptr, 0, MARUCAM_IOMEM_SIZE);
 
-    memory_region_init_io(&s->mmio, OBJECT(s),
+    memory_region_init_io(&s->ioreg, OBJECT(s),
                           &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);
+    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->fbmem);
+    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ioreg);
+    pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->iomem);
 
     /* for worker thread */
-    s->param = (MaruCamParam *)g_malloc0(sizeof(MaruCamParam));
     qemu_cond_init(&s->thread_cond);
     qemu_mutex_init(&s->thread_mutex);
 
-    marucam_device_init(s);
+    s->backend = marucam_backend_create(s);
+    s->backend->init(s);
 
     s->tx_bh = qemu_bh_new(marucam_tx_bh, s);
     s->initialized = true;
@@ -255,8 +235,7 @@ static void marucam_exitfn(PCIDevice *pci_dev)
         OBJECT_CHECK(MaruCamState, pci_dev, MARU_PCI_CAMERA_DEVICE_NAME);
 
     if (s->initialized) {
-        marucam_device_exit(s);
-        g_free(s->param);
+        s->backend->release(s);
         qemu_cond_destroy(&s->thread_cond);
         qemu_mutex_destroy(&s->thread_mutex);
     }
@@ -269,12 +248,12 @@ static void marucam_resetfn(DeviceState *d)
     MaruCamState *s = (MaruCamState *)d;
 
     if (s->initialized) {
-        marucam_device_close(s);
+        s->backend->reset(s);
         qemu_mutex_lock(&s->thread_mutex);
         s->isr = s->streamon = s->req_frame = s->buf_size = 0;
         qemu_mutex_unlock(&s->thread_mutex);
-        memset(s->vaddr, 0, MARUCAM_MEM_SIZE);
-        memset(s->param, 0x00, sizeof(MaruCamParam));
+        memset(s->fb_ptr, 0, MARUCAM_MEM_SIZE);
+        memset((void *)s->io_ptr, 0, MARUCAM_IOMEM_SIZE);
         INFO("reset maru-camera device\n");
     }
 }
index 429446023e353bbe097e09e0eb95c99ec3872c4d..c321f0849f629ab6fe848692d09793e261230dac 100644 (file)
 #include "hw/pci/pci.h"
 #include "qemu/thread.h"
 
-#define MARUCAM_MAX_PARAM    20
 #define MARUCAM_SKIPFRAMES    2
 
+#define MARUCAM_THREAD_NAME    "marucam_worker_thread"
+
 /* must sync with GUEST camera_driver */
 #define MARUCAM_CMD_INIT           0x00
 #define MARUCAM_CMD_OPEN           0x04
 #define MARUCAM_CMD_CLOSE          0x08
 #define MARUCAM_CMD_ISR            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_STREAMON       0x10
+#define MARUCAM_CMD_STREAMOFF      0x14
+#define MARUCAM_CMD_S_PAR        0x18
+#define MARUCAM_CMD_G_PAR        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_QUERYCTRL      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_DATACLR        0x50
-#define MARUCAM_CMD_REQFRAME       0x54
+#define MARUCAM_CMD_REQFRAME       0x44
+#define MARUCAM_CMD_EXIT           0x48
+
+enum {
+    _MC_THREAD_PAUSED,
+    _MC_THREAD_STREAMON,
+    _MC_THREAD_STREAMOFF,
+};
+
+#define MARUCAM_CTRL_VALUE_MAX      20
+#define MARUCAM_CTRL_VALUE_MIN      1
+#define MARUCAM_CTRL_VALUE_MID      10
+#define MARUCAM_CTRL_VALUE_STEP     1
 
 typedef struct MaruCamState MaruCamState;
-typedef struct MaruCamParam MaruCamParam;
 
-struct MaruCamParam {
-    uint32_t    top;
-    uint32_t    retVal;
-    uint32_t    errCode;
-    uint32_t    stack[MARUCAM_MAX_PARAM];
-};
+typedef struct MaruCamBackend {
+    MaruCamState        *state;
+
+    uint32_t            type;
+
+    void (*init)(MaruCamState *state);
+    void (*release)(MaruCamState *state);
+    void (*reset)(MaruCamState *state);
+    void (*open)(MaruCamState *state);
+    void (*close)(MaruCamState *state);
+    void (*stream_on)(MaruCamState *state);
+    void (*stream_off)(MaruCamState *state);
+    void (*s_parm)(MaruCamState *state);
+    void (*g_parm)(MaruCamState *state);
+    void (*enum_fmt)(MaruCamState *state);
+    void (*try_fmt)(MaruCamState *state);
+    void (*s_fmt)(MaruCamState *state);
+    void (*g_fmt)(MaruCamState *state);
+    void (*query_ctrl)(MaruCamState *state);
+    void (*s_ctrl)(MaruCamState *state);
+    void (*g_ctrl)(MaruCamState *state);
+    void (*enum_framesizes)(MaruCamState *state);
+    void (*enum_frameintervals)(MaruCamState *state);
+} MaruCamBackend;
+
+typedef struct ArgsMem {
+    uint32_t    index;
+    uint32_t    type;
+    size_t      size;
+    int32_t     ret_val;
+    int32_t     err_code;
+    void        *data;
+} ArgsMem;
 
 struct MaruCamState {
     PCIDevice           dev;
-    MaruCamParam        *param;
     QemuThread          thread_id;
     QemuMutex           thread_mutex;;
     QemuCond            thread_cond;
@@ -79,37 +114,23 @@ struct MaruCamState {
 
     bool                initialized;
     bool                destroying;
-    void                *vaddr;     /* vram ptr */
+    void                *fb_ptr;     /* fbmem ptr */
+    ArgsMem             *io_ptr;     /* iomem ptr */
     uint32_t            isr;
     uint32_t            streamon;
     uint32_t            buf_size;
     uint32_t            req_frame;
 
-    MemoryRegion        vram;
-    MemoryRegion        mmio;
+    MemoryRegion        fbmem;
+    MemoryRegion        iomem;
+    MemoryRegion        ioreg;
+
+    MaruCamBackend      *backend;
 };
 
-/* ------------------------------------------------------------------------- */
-/* Fucntion prototype                                                        */
-/* ------------------------------------------------------------------------- */
-int marucam_device_check(int log_flag);
-void marucam_device_init(MaruCamState *state);
-void marucam_device_exit(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);
+MaruCamBackend *marucam_backend_create(MaruCamState *state);
+
+int marucam_device_check(void);
 
 int maru_camera_pci_init(PCIBus *bus);
 
index 2a76c07ab13c6d0d09e5aef5fd8f8c57498b5d65..8748a8c17d2273d0414d3e5862850d18f5264803 100644 (file)
 
 MULTI_DEBUG_CHANNEL(tizen, camera);
 
-#define MARUCAM_THREAD_NAME    "marucam_worker_thread"
+#define MAKE_BACKEND_V4L2(state) \
+    MCBackendV4l2 *backend = (MCBackendV4l2 *)(state->backend)
 
 #define CLEAR(x) memset(&(x), 0, sizeof(x))
 
 #define MARUCAM_DEFAULT_BUFFER_COUNT    4
 
-#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 MCFormat {
+    uint32_t fmt;   /* fourcc */
+};
+
+static struct MCFormat support_fmts[] = {
+        { V4L2_PIX_FMT_YUYV },
+        { V4L2_PIX_FMT_YUV420 },
+        { V4L2_PIX_FMT_YVU420 },
+};
+
+struct MCFrame {
+    uint32_t width;
+    uint32_t height;
+};
+
+static struct MCFrame support_frames[] = {
+        { 640, 480 },
+        { 352, 288 },
+        { 320, 240 },
+        { 176, 144 },
+        { 160, 120 },
+};
+
+struct MCControls {
+    uint32_t id;
+    uint32_t hit;
+    int32_t min;
+    int32_t max;
+    int32_t step;
+    int32_t init_val;
+};
 
-enum {
-    _MC_THREAD_PAUSED,
-    _MC_THREAD_STREAMON,
-    _MC_THREAD_STREAMOFF,
+static struct MCControls ctrl_tbl[] = {
+    { V4L2_CID_BRIGHTNESS, 0, },
+    { V4L2_CID_CONTRAST, 0, },
+    { V4L2_CID_SATURATION, 0, },
+    { V4L2_CID_SHARPNESS, 0, },
 };
 
-typedef struct marucam_framebuffer {
+typedef struct MCBuffer {
     void *data;
     size_t size;
-} marucam_framebuffer;
+} MCBuffer;
 
-struct marucam_saved_frame {
+struct MCStoredFrame {
     void *data;
     uint32_t pixelformat;
     uint32_t width;
@@ -73,19 +102,24 @@ struct marucam_saved_frame {
     uint32_t size;
 };
 
-static struct marucam_saved_frame saved_frame;
-static char has_success_frame;
-static int n_framebuffer;
-static int previous_frame_index = -1;
-static struct marucam_framebuffer *framebuffer;
+typedef struct MCBackendV4l2 {
+    MaruCamBackend base;
+
+    char *dev_name;
+    int fd;
+    int convert_trial;
+    int ready_count;
+    int timeout;
+    int has_success;
+    int prev_index;
+    int fb_num;
 
-static const char *dev_name = "/dev/video0";
-static int v4l2_fd;
-static int convert_trial;
-static int ready_count;
-static int timeout_n;
+    struct v4l2_format src_fmt;
+    struct v4l2_format dst_fmt;
 
-static struct v4l2_format dst_fmt;
+    struct MCStoredFrame stored;
+    struct MCBuffer *fbs;
+} MCBackendV4l2;
 
 static void ScalePlaneSimple(int src_width, int src_height,
                              int dst_width, int dst_height,
@@ -183,56 +217,17 @@ static int xioctl(int fd, int req, void *arg)
     return r;
 }
 
-typedef struct tagMaruCamConvertPixfmt {
-    uint32_t fmt;   /* fourcc */
-} MaruCamConvertPixfmt;
-
-static MaruCamConvertPixfmt supported_dst_pixfmts[] = {
-        { V4L2_PIX_FMT_YUYV },
-        { V4L2_PIX_FMT_YUV420 },
-        { V4L2_PIX_FMT_YVU420 },
-};
-
-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 },
-};
-
-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)
+static void backend_v4l2_reset_controls(MCBackendV4l2 *backend)
 {
     uint32_t i;
-    for (i = 0; i < ARRAY_SIZE(qctrl_tbl); i++) {
-        if (qctrl_tbl[i].hit) {
+    for (i = 0; i < ARRAY_SIZE(ctrl_tbl); i++) {
+        if (ctrl_tbl[i].hit) {
             struct v4l2_control ctrl = {0,};
-            ctrl.id = qctrl_tbl[i].id;
-            ctrl.value = qctrl_tbl[i].init_val;
-            qctrl_tbl[i].hit = qctrl_tbl[i].init_val = 0;
-            qctrl_tbl[i].min = qctrl_tbl[i].max = qctrl_tbl[i].step = 0;
-            if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &ctrl) < 0) {
+            ctrl.id = ctrl_tbl[i].id;
+            ctrl.value = ctrl_tbl[i].init_val;
+            ctrl_tbl[i].hit = ctrl_tbl[i].init_val = 0;
+            ctrl_tbl[i].min = ctrl_tbl[i].max = ctrl_tbl[i].step = 0;
+            if (xioctl(backend->fd, VIDIOC_S_CTRL, &ctrl) < 0) {
                 ERR("Failed to reset control value: id(0x%x), errstr(%s)\n",
                     ctrl.id, strerror(errno));
             }
@@ -276,7 +271,7 @@ static int32_t value_convert_to_guest(int32_t min, int32_t max, int32_t value)
     return ret;
 }
 
-static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format,
+static void set_maxframeinterval(int fd, uint32_t pixel_format,
                         uint32_t width, uint32_t height)
 {
     struct v4l2_frmivalenum fival;
@@ -288,7 +283,7 @@ static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format,
     fival.width = width;
     fival.height = height;
 
-    if (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) {
+    if (xioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) < 0) {
         ERR("Unable to enumerate intervals for pixelformat(0x%x), (%d:%d)\n",
             pixel_format, width, height);
         return;
@@ -307,7 +302,7 @@ static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format,
             TRACE("Discrete frame interval %u/%u supported\n",
                  fival.discrete.numerator, fival.discrete.denominator);
             fival.index++;
-        } while (xioctl(v4l2_fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) >= 0);
+        } while (xioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival) >= 0);
     } else if ((fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) ||
                 (fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS)) {
         TRACE("Frame intervals from %u/%u to %u/%u supported",
@@ -335,86 +330,118 @@ static void set_maxframeinterval(MaruCamState *state, uint32_t pixel_format,
     sp.parm.capture.timeperframe.numerator = min_num;
     sp.parm.capture.timeperframe.denominator = min_denom;
 
-    if (xioctl(v4l2_fd, VIDIOC_S_PARM, &sp) < 0) {
+    if (xioctl(fd, VIDIOC_S_PARM, &sp) < 0) {
         ERR("Failed to set to minimum FPS(%u/%u)\n", min_num, min_denom);
     }
 }
 
-static uint32_t stop_capturing(void)
+static uint32_t stop_capturing(MCBackendV4l2 *backend)
 {
     enum v4l2_buf_type type;
 
     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    if (xioctl(v4l2_fd, VIDIOC_STREAMOFF, &type) < 0) {
+    if (xioctl(backend->fd, VIDIOC_STREAMOFF, &type) < 0) {
         ERR("Failed to ioctl() with VIDIOC_STREAMOFF: %s\n", strerror(errno));
         return errno;
     }
     return 0;
 }
 
-static uint32_t start_capturing(void)
+static uint32_t start_capturing(MCBackendV4l2 *backend)
 {
     enum v4l2_buf_type type;
 
     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-    if (xioctl(v4l2_fd, VIDIOC_STREAMON, &type) < 0) {
+    if (xioctl(backend->fd, VIDIOC_STREAMON, &type) < 0) {
         ERR("Failed to ioctl() with VIDIOC_STREAMON: %s\n", strerror(errno));
         return errno;
     }
     return 0;
 }
 
-static void free_framebuffers(marucam_framebuffer *fb, int buf_num)
+static void backend_v4l2_storedframe_clear(MCBackendV4l2 *backend)
+{
+    if (backend->stored.data) {
+        g_free(backend->stored.data);
+        backend->stored.data = NULL;
+    }
+    memset(&backend->stored, 0x00, sizeof(struct MCStoredFrame));
+}
+
+static void backend_v4l2_storedframe_set(MCBackendV4l2 *backend)
+{
+    backend->stored.width = backend->dst_fmt.fmt.pix.width;
+    backend->stored.height = backend->dst_fmt.fmt.pix.height;
+    backend->stored.pixelformat = backend->dst_fmt.fmt.pix.pixelformat;
+    backend->stored.size = backend->dst_fmt.fmt.pix.sizeimage;
+    if (backend->stored.data) {
+        g_free(backend->stored.data);
+        backend->stored.data = NULL;
+    }
+    backend->stored.data = (void *)g_malloc0(backend->stored.size);
+    memcpy(backend->stored.data,
+           backend->fbs[backend->prev_index].data,
+           backend->stored.size);
+    TRACE("Saves a frame data\n");
+}
+
+static void free_framebuffers(MCBackendV4l2 *backend)
 {
     int i;
 
-    if (fb == NULL) {
+    if (backend->fbs == NULL) {
         ERR("The framebuffer is NULL. Failed to release the framebuffer\n");
         return;
-    } else if (buf_num == 0) {
+    } else if (backend->fb_num == 0) {
         ERR("The buffer count is 0. Failed to release the framebuffer\n");
         return;
     } else {
-        TRACE("[%s]:fb(0x%p), buf_num(%d)\n", __func__, fb, buf_num);
+        TRACE("[%s]: fbs(0x%p), buf_num(%d)\n",
+              __func__, backend->fbs, backend->fb_num);
     }
 
     /* Unmap framebuffers. */
-    for (i = 0; i < buf_num; i++) {
-        if (fb[i].data != NULL) {
-            v4l2_munmap(fb[i].data, fb[i].size);
-            fb[i].data = NULL;
-            fb[i].size = 0;
+    for (i = 0; i < backend->fb_num; i++) {
+        if (backend->fbs[i].data != NULL) {
+            v4l2_munmap(backend->fbs[i].data, backend->fbs[i].size);
+            backend->fbs[i].data = NULL;
+            backend->fbs[i].size = 0;
         } else {
             ERR("framebuffer[%d].data is NULL.\n", i);
         }
     }
-    previous_frame_index = -1;
+    backend->prev_index = -1;
+    g_free(backend->fbs);
+    backend->fbs = NULL;
+    backend->fb_num = 0;
 }
 
 static uint32_t
-mmap_framebuffers(marucam_framebuffer **fb, int *buf_num)
+mmap_framebuffers(MCBackendV4l2 *backend)
 {
     struct v4l2_requestbuffers req;
+    MCBuffer **fb = &backend->fbs;
+    int *buf_num = &backend->fb_num;
 
     CLEAR(req);
     req.count   = MARUCAM_DEFAULT_BUFFER_COUNT;
     req.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     req.memory  = V4L2_MEMORY_MMAP;
-    if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &req) < 0) {
+    if (xioctl(backend->fd, VIDIOC_REQBUFS, &req) < 0) {
         if (errno == EINVAL) {
             ERR("%s does not support memory mapping: %s\n",
-                dev_name, strerror(errno));
+                backend->dev_name, strerror(errno));
         } else {
             ERR("Failed to request bufs: %s\n", strerror(errno));
         }
         return errno;
     }
     if (req.count == 0) {
-        ERR("Insufficient buffer memory on %s\n", dev_name);
+        ERR("Insufficient buffer memory on %s\n", backend->dev_name);
         return EINVAL;
     }
 
-    *fb = g_new0(marucam_framebuffer, req.count);
+    *fb = g_new0(MCBuffer, req.count);
     if (*fb == NULL) {
         ERR("Not enough memory to allocate framebuffers\n");
         return ENOMEM;
@@ -426,7 +453,7 @@ mmap_framebuffers(marucam_framebuffer **fb, int *buf_num)
         buf.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
         buf.memory  = V4L2_MEMORY_MMAP;
         buf.index   = *buf_num;
-        if (xioctl(v4l2_fd, VIDIOC_QUERYBUF, &buf) < 0) {
+        if (xioctl(backend->fd, VIDIOC_QUERYBUF, &buf) < 0) {
             ERR("Failed to ioctl() with VIDIOC_QUERYBUF: %s\n",
                 strerror(errno));
             return errno;
@@ -437,7 +464,7 @@ mmap_framebuffers(marucam_framebuffer **fb, int *buf_num)
                      buf.length,
                      PROT_READ | PROT_WRITE,
                      MAP_SHARED,
-                     v4l2_fd, buf.m.offset);
+                     backend->fd, buf.m.offset);
         if (MAP_FAILED == (*fb)[*buf_num].data) {
             ERR("Failed to mmap: %s\n", strerror(errno));
             return errno;
@@ -448,7 +475,7 @@ mmap_framebuffers(marucam_framebuffer **fb, int *buf_num)
         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
         buf.memory = V4L2_MEMORY_MMAP;
         buf.index = *buf_num;
-        if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) {
+        if (xioctl(backend->fd, VIDIOC_QBUF, &buf) < 0) {
             ERR("Failed to ioctl() with VIDIOC_QBUF: %s\n", strerror(errno));
             return errno;
         }
@@ -478,27 +505,31 @@ static int is_stream_paused(MaruCamState *state)
 /* TODO: add other pixel format method */
 static void __raise_dummy_intr(MaruCamState *state)
 {
+    MAKE_BACKEND_V4L2(state);
     void *buf = NULL;
+
     qemu_mutex_lock(&state->thread_mutex);
     if (state->streamon == _MC_THREAD_STREAMON && state->req_frame) {
-        buf = state->vaddr + state->buf_size * (state->req_frame - 1);
-        if (saved_frame.data) {
-            if (saved_frame.width == dst_fmt.fmt.pix.width &&
-                saved_frame.height == dst_fmt.fmt.pix.height) {
+        buf = state->fb_ptr + state->buf_size * (state->req_frame - 1);
+        if (backend->stored.data) {
+            if (backend->stored.width == backend->dst_fmt.fmt.pix.width &&
+                backend->stored.height == backend->dst_fmt.fmt.pix.height) {
                 TRACE("Copies the previuos frame\n");
-                memcpy(buf, saved_frame.data, state->buf_size);
+                memcpy(buf, backend->stored.data, state->buf_size);
             } else {
                 TRACE("Resizes the previous frame\n");
-                marucam_scale_yuv420(saved_frame.data, saved_frame.width,
-                                     saved_frame.height,
-                                     buf, dst_fmt.fmt.pix.width,
-                                     dst_fmt.fmt.pix.height);
+                marucam_scale_yuv420(backend->stored.data,
+                                     backend->stored.width,
+                                     backend->stored.height,
+                                     buf,
+                                     backend->dst_fmt.fmt.pix.width,
+                                     backend->dst_fmt.fmt.pix.height);
             }
         } else {
             TRACE("Sends a black frame\n");
             make_yu12_black(buf,
-                            dst_fmt.fmt.pix.width,
-                            dst_fmt.fmt.pix.height);
+                            backend->dst_fmt.fmt.pix.width,
+                            backend->dst_fmt.fmt.pix.height);
         }
         state->req_frame = 0; /* clear request */
         state->isr |= 0x01;   /* set a flag of raising a interrupt */
@@ -521,14 +552,15 @@ static void __raise_err_intr(MaruCamState *state)
 static void
 notify_buffer_ready(MaruCamState *state, uint32_t buf_index)
 {
+    MAKE_BACKEND_V4L2(state);
     void *buf = NULL;
 
     qemu_mutex_lock(&state->thread_mutex);
     if (state->streamon == _MC_THREAD_STREAMON) {
-        if (ready_count < MARUCAM_SKIPFRAMES) {
+        if (backend->ready_count < MARUCAM_SKIPFRAMES) {
             /* skip a frame cause first some frame are distorted */
-            ++ready_count;
-            TRACE("Skip %d frame\n", ready_count);
+            ++backend->ready_count;
+            TRACE("Skip %d frame\n", backend->ready_count);
             qemu_mutex_unlock(&state->thread_mutex);
             return;
         }
@@ -536,10 +568,10 @@ notify_buffer_ready(MaruCamState *state, uint32_t buf_index)
             qemu_mutex_unlock(&state->thread_mutex);
             return;
         }
-        buf = state->vaddr + state->buf_size * (state->req_frame - 1);
-        memcpy(buf, framebuffer[buf_index].data, state->buf_size);
-        previous_frame_index = buf_index;
-        has_success_frame = 1;
+        buf = state->fb_ptr + state->buf_size * (state->req_frame - 1);
+        memcpy(buf, backend->fbs[buf_index].data, state->buf_size);
+        backend->prev_index = buf_index;
+        backend->has_success = 1;
         state->req_frame = 0; /* clear request */
         state->isr |= 0x01;   /* set a flag of rasing a interrupt */
         qemu_bh_schedule(state->tx_bh);
@@ -549,12 +581,13 @@ notify_buffer_ready(MaruCamState *state, uint32_t buf_index)
 
 static int read_frame(MaruCamState *state)
 {
+    MAKE_BACKEND_V4L2(state);
     struct v4l2_buffer buf;
 
     CLEAR(buf);
     buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     buf.memory = V4L2_MEMORY_MMAP;
-    if (xioctl(v4l2_fd, VIDIOC_DQBUF, &buf) < 0) {
+    if (xioctl(backend->fd, VIDIOC_DQBUF, &buf) < 0) {
         switch (errno) {
         case EAGAIN:
         case EINTR:
@@ -562,7 +595,7 @@ static int read_frame(MaruCamState *state)
             return 0;
         case EIO:
             ERR("The v4l2_read() met the EIO\n");
-            if (convert_trial-- == -1) {
+            if (backend->convert_trial-- == -1) {
                 ERR("Try count for v4l2_read is exceeded: %s\n",
                     strerror(errno));
                 return -1;
@@ -576,7 +609,7 @@ static int read_frame(MaruCamState *state)
 
     notify_buffer_ready(state, buf.index);
 
-    if (xioctl(v4l2_fd, VIDIOC_QBUF, &buf) < 0) {
+    if (xioctl(backend->fd, VIDIOC_QBUF, &buf) < 0) {
         ERR("QBUF error: %s\n", strerror(errno));
         return -1;
     }
@@ -585,17 +618,18 @@ static int read_frame(MaruCamState *state)
 
 static int __v4l2_streaming(MaruCamState *state)
 {
+    MAKE_BACKEND_V4L2(state);
     fd_set fds;
     struct timeval tv;
     int ret;
 
     FD_ZERO(&fds);
-    FD_SET(v4l2_fd, &fds);
+    FD_SET(backend->fd, &fds);
 
     tv.tv_sec = 1;
     tv.tv_usec = 0;
 
-    ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv);
+    ret = select(backend->fd + 1, &fds, NULL, NULL, &tv);
     if (ret < 0) {
         if (errno == EAGAIN || errno == EINTR) {
             ERR("Select again: %s\n", strerror(errno));
@@ -605,10 +639,10 @@ static int __v4l2_streaming(MaruCamState *state)
         __raise_err_intr(state);
         return -1;
     } else if (!ret) {
-        timeout_n++;
-        ERR("Select timed out: count(%u)\n", timeout_n);
-        if (ready_count <= MARUCAM_SKIPFRAMES) {
-            switch (timeout_n) {
+        backend->timeout++;
+        ERR("Select timed out: count(%u)\n", backend->timeout);
+        if (backend->ready_count <= MARUCAM_SKIPFRAMES) {
+            switch (backend->timeout) {
             case 1:
                 ERR("Waiting for reading a frame data\n");
                 return 0;
@@ -625,19 +659,19 @@ static int __v4l2_streaming(MaruCamState *state)
                 return -1;
             }
         }
-        if (timeout_n >= 5) {
+        if (backend->timeout >= 5) {
             ERR("Webcam is busy, failed to a read frame. Raises an error\n");
             __raise_err_intr(state);
             return -1;
         }
-        if (previous_frame_index != -1) {
+        if (backend->prev_index != -1) {
             ERR("Sends previous frame data\n");
-            notify_buffer_ready(state, previous_frame_index);
+            notify_buffer_ready(state, backend->prev_index);
         }
         return 0;
     }
 
-    if (!v4l2_fd || (v4l2_fd == -1)) {
+    if (!backend->fd || (backend->fd == -1)) {
         ERR("The file descriptor is closed or not opened\n");
         __raise_err_intr(state);
         return -1;
@@ -651,8 +685,8 @@ static int __v4l2_streaming(MaruCamState *state)
     }
 
     /* clear the skip count for select time-out */
-    if (timeout_n > 0) {
-        timeout_n = 0;
+    if (backend->timeout > 0) {
+        backend->timeout = 0;
     }
 
     return 0;
@@ -662,6 +696,7 @@ static int __v4l2_streaming(MaruCamState *state)
 static void *marucam_worker_thread(void *thread_param)
 {
     MaruCamState *state = (MaruCamState *)thread_param;
+    MAKE_BACKEND_V4L2(state);
 
     while (1) {
         qemu_mutex_lock(&state->thread_mutex);
@@ -673,10 +708,10 @@ static void *marucam_worker_thread(void *thread_param)
             break;
         }
 
-        convert_trial = 10;
-        ready_count = 0;
-        timeout_n = 0;
-        has_success_frame = 0;
+        backend->convert_trial = 10;
+        backend->ready_count = 0;
+        backend->timeout = 0;
+        backend->has_success = 0;
         qemu_mutex_lock(&state->thread_mutex);
         state->streamon = _MC_THREAD_STREAMON;
         qemu_mutex_unlock(&state->thread_mutex);
@@ -698,7 +733,7 @@ static void *marucam_worker_thread(void *thread_param)
     return NULL;
 }
 
-int marucam_device_check(int log_flag)
+int marucam_device_check(void)
 {
     int tmp_fd;
     struct timeval t1, t2;
@@ -707,15 +742,14 @@ int marucam_device_check(int log_flag)
     struct v4l2_frmsizeenum size;
     struct v4l2_capability cap;
     int ret = 0;
+    const char *dev_name = "/dev/video0";
 
     gettimeofday(&t1, NULL);
     if (stat(dev_name, &st) < 0) {
-        INFO("<WARNING> Cannot identify '%s': %s\n",
-                dev_name, strerror(errno));
+        INFO("<WARNING> Cannot identify '%s': %s\n", dev_name, strerror(errno));
     } else {
         if (!S_ISCHR(st.st_mode)) {
-            INFO("<WARNING>%s is no character device\n",
-                    dev_name);
+            INFO("<WARNING>%s is no character device\n", dev_name);
         }
     }
 
@@ -724,7 +758,7 @@ int marucam_device_check(int log_flag)
         ERR("Camera device open failed: %s\n", dev_name);
         gettimeofday(&t2, NULL);
         ERR("Elapsed time: %lu:%06lu\n",
-                t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+            t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
         return ret;
     }
     if (ioctl(tmp_fd, VIDIOC_QUERYCAP, &cap) < 0) {
@@ -732,7 +766,7 @@ int marucam_device_check(int log_flag)
         close(tmp_fd);
         gettimeofday(&t2, NULL);
         ERR("Elapsed time: %lu:%06lu\n",
-                t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+            t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
         return ret;
     }
     if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ||
@@ -741,81 +775,79 @@ int marucam_device_check(int log_flag)
         close(tmp_fd);
         gettimeofday(&t2, NULL);
         ERR("Elapsed time: %lu:%06lu\n",
-                t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+            t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
         return ret;
     }
     ret = 1;
 
-    if (log_flag) {
-        INFO("Driver: %s\n", cap.driver);
-        INFO("Card:  %s\n", cap.card);
-        INFO("Bus info: %s\n", cap.bus_info);
+    INFO("Driver: %s\n", cap.driver);
+    INFO("Card:  %s\n", cap.card);
+    INFO("Bus info: %s\n", cap.bus_info);
+
+    CLEAR(format);
+    format.index = 0;
+    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+    if (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) < 0) {
+    close(tmp_fd);
+        gettimeofday(&t2, NULL);
+        ERR("Elapsed time: %lu:%06lu\n",
+            t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+        return ret;
+    }
+
+    do {
+        CLEAR(size);
+        size.index = 0;
+        size.pixel_format = format.pixelformat;
 
-        CLEAR(format);
-        format.index = 0;
-        format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+        INFO("PixelFormat: %c%c%c%c\n",
+             (char)(format.pixelformat),
+             (char)(format.pixelformat >> 8),
+             (char)(format.pixelformat >> 16),
+             (char)(format.pixelformat >> 24));
 
-        if (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) < 0) {
+        if (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0) {
             close(tmp_fd);
             gettimeofday(&t2, NULL);
             ERR("Elapsed time: %lu:%06lu\n",
-                    t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+                t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
             return ret;
         }
 
-        do {
-            CLEAR(size);
-            size.index = 0;
-            size.pixel_format = format.pixelformat;
-
-            INFO("PixelFormat: %c%c%c%c\n",
-                             (char)(format.pixelformat),
-                             (char)(format.pixelformat >> 8),
-                             (char)(format.pixelformat >> 16),
-                             (char)(format.pixelformat >> 24));
-
-            if (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) < 0) {
-                close(tmp_fd);
-                gettimeofday(&t2, NULL);
-                ERR("Elapsed time: %lu:%06lu\n",
-                        t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
-                return ret;
-            }
+        if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
+            do {
+                INFO("\tGot a discrete frame size %dx%d\n",
+                     size.discrete.width, size.discrete.height);
+                     size.index++;
+            } while (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
+        } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
+            INFO("We have stepwise frame sizes:\n");
+            INFO("\tmin width: %d, min height: %d\n",
+                 size.stepwise.min_width, size.stepwise.min_height);
+            INFO("\tmax width: %d, max height: %d\n",
+                 size.stepwise.max_width, size.stepwise.max_height);
+            INFO("\tstep width: %d, step height: %d\n",
+                 size.stepwise.step_width, size.stepwise.step_height);
+        } else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
+            INFO("We have continuous frame sizes:\n");
+            INFO("\tmin width: %d, min height: %d\n",
+                 size.stepwise.min_width, size.stepwise.min_height);
+            INFO("\tmax width: %d, max height: %d\n",
+                 size.stepwise.max_width, size.stepwise.max_height);
 
-            if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
-                do {
-                    INFO("\tGot a discrete frame size %dx%d\n",
-                                    size.discrete.width, size.discrete.height);
-                    size.index++;
-                } while (yioctl(tmp_fd, VIDIOC_ENUM_FRAMESIZES, &size) >= 0);
-            } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
-                INFO("We have stepwise frame sizes:\n");
-                INFO("\tmin width: %d, min height: %d\n",
-                        size.stepwise.min_width, size.stepwise.min_height);
-                INFO("\tmax width: %d, max height: %d\n",
-                        size.stepwise.max_width, size.stepwise.max_height);
-                INFO("\tstep width: %d, step height: %d\n",
-                        size.stepwise.step_width, size.stepwise.step_height);
-            } else if (size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
-                INFO("We have continuous frame sizes:\n");
-                INFO("\tmin width: %d, min height: %d\n",
-                        size.stepwise.min_width, size.stepwise.min_height);
-                INFO("\tmax width: %d, max height: %d\n",
-                        size.stepwise.max_width, size.stepwise.max_height);
-
-            }
-            format.index++;
-        } while (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) >= 0);
-    }
+        }
+        format.index++;
+    } while (yioctl(tmp_fd, VIDIOC_ENUM_FMT, &format) >= 0);
 
     close(tmp_fd);
     gettimeofday(&t2, NULL);
     INFO("Elapsed time: %lu:%06lu\n",
-                    t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
+         t2.tv_sec-t1.tv_sec, t2.tv_usec-t1.tv_usec);
     return ret;
 }
 
-void marucam_device_init(MaruCamState *state)
+static void backend_v4l2_init(MaruCamState *state)
 {
     state->destroying = false;
     qemu_thread_create(&state->thread_id,
@@ -825,7 +857,11 @@ void marucam_device_init(MaruCamState *state)
                        QEMU_THREAD_JOINABLE);
 }
 
-void marucam_device_exit(MaruCamState *state)
+static void backend_v4l2_reset(MaruCamState *state)
+{
+}
+
+static void backend_v4l2_release(MaruCamState *state)
 {
     state->destroying = true;
     qemu_mutex_lock(&state->thread_mutex);
@@ -834,20 +870,20 @@ void marucam_device_exit(MaruCamState *state)
     qemu_thread_join(&state->thread_id);
 }
 
-void marucam_device_open(MaruCamState *state)
+static void backend_v4l2_open(MaruCamState *state)
 {
-    MaruCamParam *param = state->param;
+    MAKE_BACKEND_V4L2(state);
 
-    param->top = 0;
-    v4l2_fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);
-    if (v4l2_fd < 0) {
-        ERR("The v4l2 device open failed: %s\n", dev_name);
-        param->errCode = EINVAL;
+    backend->fd = v4l2_open(backend->dev_name, O_RDWR | O_NONBLOCK, 0);
+    if (backend->fd < 0) {
+        ERR("The v4l2 device open failed: %s\n", backend->dev_name);
+        state->io_ptr->err_code = EINVAL;
+        state->io_ptr->ret_val = -1;
         return;
     }
     INFO("Opened\n");
 
-    /* FIXME : Do not use fixed values */
+    /* FIXME : Do not use fixed values
     CLEAR(dst_fmt);
     dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     dst_fmt.fmt.pix.width = 640;
@@ -869,50 +905,63 @@ void marucam_device_open(MaruCamState *state)
          dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height,
          dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage,
          dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field);
+  */
+}
+
+static void backend_v4l2_close(MaruCamState *state)
+{
+    MAKE_BACKEND_V4L2(state);
+
+    if (!is_stream_paused(state)) {
+        state->backend->stream_off(state);
+    }
+
+    backend_v4l2_reset_controls(backend);
+    backend_v4l2_storedframe_clear(backend);
+
+    v4l2_close(backend->fd);
+    backend->fd = 0;
+    INFO("Closed\n");
 }
 
-void marucam_device_start_preview(MaruCamState *state)
+static void backend_v4l2_stream_on(MaruCamState *state)
 {
+    MAKE_BACKEND_V4L2(state);
+
     struct timespec req;
-    MaruCamParam *param = state->param;
-    param->top = 0;
     req.tv_sec = 0;
     req.tv_nsec = 10000000;
 
     INFO("Pixfmt(%c%c%c%C), W:H(%d:%d), buf size(%u)\n",
-         (char)(dst_fmt.fmt.pix.pixelformat),
-         (char)(dst_fmt.fmt.pix.pixelformat >> 8),
-         (char)(dst_fmt.fmt.pix.pixelformat >> 16),
-         (char)(dst_fmt.fmt.pix.pixelformat >> 24),
-         dst_fmt.fmt.pix.width,
-         dst_fmt.fmt.pix.height,
-         dst_fmt.fmt.pix.sizeimage);
-
-    param->errCode = mmap_framebuffers(&framebuffer, &n_framebuffer);
-    if (param->errCode) {
+         (char)(backend->dst_fmt.fmt.pix.pixelformat),
+         (char)(backend->dst_fmt.fmt.pix.pixelformat >> 8),
+         (char)(backend->dst_fmt.fmt.pix.pixelformat >> 16),
+         (char)(backend->dst_fmt.fmt.pix.pixelformat >> 24),
+         backend->dst_fmt.fmt.pix.width,
+         backend->dst_fmt.fmt.pix.height,
+         backend->dst_fmt.fmt.pix.sizeimage);
+
+    state->io_ptr->err_code = mmap_framebuffers(backend);
+    if (state->io_ptr->err_code) {
         ERR("Failed to mmap framebuffers\n");
-        if (framebuffer != NULL) {
-            free_framebuffers(framebuffer, n_framebuffer);
-            g_free(framebuffer);
-            framebuffer = NULL;
-            n_framebuffer = 0;
+        if (backend->fbs != NULL) {
+            free_framebuffers(backend);
         }
+        state->io_ptr->ret_val = -1;
         return;
     }
 
-    param->errCode = start_capturing();
-    if (param->errCode) {
-        if (framebuffer != NULL) {
-            free_framebuffers(framebuffer, n_framebuffer);
-            g_free(framebuffer);
-            framebuffer = NULL;
-            n_framebuffer = 0;
+    state->io_ptr->err_code = start_capturing(backend);
+    if (state->io_ptr->err_code) {
+        if (backend->fbs != NULL) {
+            free_framebuffers(backend);
         }
+        state->io_ptr->ret_val = -1;
         return;
     }
 
     INFO("Starting preview\n");
-    state->buf_size = dst_fmt.fmt.pix.sizeimage;
+    state->buf_size = backend->dst_fmt.fmt.pix.sizeimage;
     qemu_mutex_lock(&state->thread_mutex);
     qemu_cond_signal(&state->thread_cond);
     qemu_mutex_unlock(&state->thread_mutex);
@@ -923,12 +972,11 @@ void marucam_device_start_preview(MaruCamState *state)
     }
 }
 
-void marucam_device_stop_preview(MaruCamState *state)
+static void backend_v4l2_stream_off(MaruCamState *state)
 {
+    MAKE_BACKEND_V4L2(state);
     struct timespec req;
     struct v4l2_requestbuffers reqbuf;
-    MaruCamParam *param = state->param;
-    param->top = 0;
     req.tv_sec = 0;
     req.tv_nsec = 50000000;
 
@@ -943,355 +991,295 @@ void marucam_device_stop_preview(MaruCamState *state)
         }
     }
 
-    if (has_success_frame) {
-        saved_frame.width = dst_fmt.fmt.pix.width;
-        saved_frame.height = dst_fmt.fmt.pix.height;
-        saved_frame.size = dst_fmt.fmt.pix.sizeimage;
-        if (saved_frame.data) {
-            g_free(saved_frame.data);
-            saved_frame.data = NULL;
-        }
-        saved_frame.data = (void *)g_malloc0(saved_frame.size);
-        memcpy(saved_frame.data,
-               framebuffer[previous_frame_index].data,
-               saved_frame.size);
-        TRACE("Saves a frame data\n");
+    if (backend->has_success) {
+        backend_v4l2_storedframe_set(backend);
     }
 
-    param->errCode = stop_capturing();
-    if (framebuffer != NULL) {
-        free_framebuffers(framebuffer, n_framebuffer);
-        g_free(framebuffer);
-        framebuffer = NULL;
-        n_framebuffer = 0;
+    state->io_ptr->err_code = stop_capturing(backend);
+    if (state->io_ptr->err_code) {
+        ERR("Try again to turn off streaming\n");
+        state->io_ptr->err_code = stop_capturing(backend);
+    }
+    if (backend->fbs != NULL) {
+        free_framebuffers(backend);
     }
     state->buf_size = 0;
 
     reqbuf.count = 0;
     reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     reqbuf.memory = V4L2_MEMORY_MMAP;
-    if (xioctl(v4l2_fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
+    if (xioctl(backend->fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
         ERR("Failed to ioctl() with VIDIOC_REQBUF in stop_preview: %s\n",
             strerror(errno));
     }
+
+    if (state->io_ptr->err_code) {
+        state->io_ptr->ret_val = -1;
+    }
+
     INFO("Stopping preview\n");
 }
 
-void marucam_device_s_param(MaruCamState *state)
-{
-    MaruCamParam *param = state->param;
 
-    param->top = 0;
+static void backend_v4l2_s_parm(MaruCamState *state)
+{
+    MAKE_BACKEND_V4L2(state);
 
     /* If KVM enabled, We use default FPS of the webcam.
      * If KVM disabled, we use mininum FPS of the webcam */
     if (!kvm_enabled()) {
-        set_maxframeinterval(state, dst_fmt.fmt.pix.pixelformat,
-                     dst_fmt.fmt.pix.width,
-                     dst_fmt.fmt.pix.height);
+        set_maxframeinterval(backend->fd,
+                             backend->dst_fmt.fmt.pix.pixelformat,
+                             backend->dst_fmt.fmt.pix.width,
+                             backend->dst_fmt.fmt.pix.height);
     }
 }
 
-void marucam_device_g_param(MaruCamState *state)
+static void backend_v4l2_g_parm(MaruCamState *state)
 {
-    MaruCamParam *param = state->param;
-
+    struct v4l2_captureparm *cp = (struct v4l2_captureparm *)state->io_ptr->data;
     /* We use default FPS of the webcam
      * return a fixed value on guest ini file (1/30).
      */
-    param->top = 0;
-    param->stack[0] = 0x1000; /* V4L2_CAP_TIMEPERFRAME */
-    param->stack[1] = 1; /* numerator */
-    param->stack[2] = 30; /* denominator */
+    cp->capability = V4L2_CAP_TIMEPERFRAME;
+    cp->timeperframe.numerator = 1;
+    cp->timeperframe.denominator = 30;
 }
 
-void marucam_device_s_fmt(MaruCamState *state)
+static void backend_v4l2_s_fmt(MaruCamState *state)
 {
-    struct v4l2_format format;
-    MaruCamParam *param = state->param;
+    MAKE_BACKEND_V4L2(state);
+    struct v4l2_format *format = (struct v4l2_format *)state->io_ptr->data;
 
-    param->top = 0;
-    CLEAR(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 = V4L2_FIELD_ANY;
-
-    if (xioctl(v4l2_fd, VIDIOC_S_FMT, &format) < 0) {
+    if (xioctl(backend->fd, VIDIOC_S_FMT, format) < 0) {
         ERR("Failed to set video format: format(0x%x), width:height(%d:%d), "
-          "errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width,
-          format.fmt.pix.height, strerror(errno));
-        param->errCode = errno;
+          "errstr(%s)\n", format->fmt.pix.pixelformat, format->fmt.pix.width,
+          format->fmt.pix.height, strerror(errno));
+        state->io_ptr->err_code = errno;
+        state->io_ptr->ret_val = -1;
         return;
     }
 
-    memcpy(&dst_fmt, &format, sizeof(format));
-    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;
+    memcpy(&backend->dst_fmt, format, sizeof(struct v4l2_format));
     TRACE("Set the format: w:h(%dx%d), fmt(0x%x), size(%d), "
          "color(%d), field(%d)\n",
-         dst_fmt.fmt.pix.width, dst_fmt.fmt.pix.height,
-         dst_fmt.fmt.pix.pixelformat, dst_fmt.fmt.pix.sizeimage,
-         dst_fmt.fmt.pix.colorspace, dst_fmt.fmt.pix.field);
+         format->fmt.pix.width, format->fmt.pix.height,
+         format->fmt.pix.pixelformat, format->fmt.pix.sizeimage,
+         format->fmt.pix.colorspace, format->fmt.pix.field);
 }
 
-void marucam_device_g_fmt(MaruCamState *state)
+static void backend_v4l2_g_fmt(MaruCamState *state)
 {
-    struct v4l2_format format;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    CLEAR(format);
-    format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    MAKE_BACKEND_V4L2(state);
+    struct v4l2_format *format = (struct v4l2_format *)state->io_ptr->data;
 
-    if (xioctl(v4l2_fd, VIDIOC_G_FMT, &format) < 0) {
+    if (xioctl(backend->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;
-        TRACE("Get the format: w:h(%dx%d), fmt(0x%x), size(%d), "
-             "color(%d), field(%d)\n",
-             format.fmt.pix.width, format.fmt.pix.height,
-             format.fmt.pix.pixelformat, format.fmt.pix.sizeimage,
-             format.fmt.pix.colorspace, format.fmt.pix.field);
+        state->io_ptr->err_code = errno;
+        state->io_ptr->ret_val = -1;
+        return;
     }
+    TRACE("Get the format: w:h(%dx%d), fmt(0x%x), size(%d), "
+          "color(%d), field(%d)\n",
+          format->fmt.pix.width, format->fmt.pix.height,
+          format->fmt.pix.pixelformat, format->fmt.pix.sizeimage,
+          format->fmt.pix.colorspace, format->fmt.pix.field);
 }
 
-void marucam_device_try_fmt(MaruCamState *state)
+static void backend_v4l2_try_fmt(MaruCamState *state)
 {
-    struct v4l2_format format;
-    MaruCamParam *param = state->param;
+    MAKE_BACKEND_V4L2(state);
+    struct v4l2_format *format = (struct v4l2_format *)state->io_ptr->data;
 
-    param->top = 0;
-    CLEAR(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 = V4L2_FIELD_ANY;
-
-    if (xioctl(v4l2_fd, VIDIOC_TRY_FMT, &format) < 0) {
+    if (xioctl(backend->fd, VIDIOC_TRY_FMT, format) < 0) {
         ERR("Failed to check video format: format(0x%x), width:height(%d:%d),"
-            " errstr(%s)\n", format.fmt.pix.pixelformat, format.fmt.pix.width,
-            format.fmt.pix.height, strerror(errno));
-        param->errCode = errno;
+            " errstr(%s)\n", format->fmt.pix.pixelformat, format->fmt.pix.width,
+            format->fmt.pix.height, strerror(errno));
+        state->io_ptr->err_code = errno;
+        state->io_ptr->ret_val = -1;
         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;
     TRACE("Check the format: w:h(%dx%d), fmt(0x%x), size(%d), "
          "color(%d), field(%d)\n",
-         format.fmt.pix.width, format.fmt.pix.height,
-         format.fmt.pix.pixelformat, format.fmt.pix.sizeimage,
-         format.fmt.pix.colorspace, format.fmt.pix.field);
+         format->fmt.pix.width, format->fmt.pix.height,
+         format->fmt.pix.pixelformat, format->fmt.pix.sizeimage,
+         format->fmt.pix.colorspace, format->fmt.pix.field);
 }
 
-void marucam_device_enum_fmt(MaruCamState *state)
+static void backend_v4l2_enum_fmt(MaruCamState *state)
 {
-    uint32_t index;
-    MaruCamParam *param = state->param;
+    struct v4l2_fmtdesc *f = (struct v4l2_fmtdesc *)state->io_ptr->data;
 
-    param->top = 0;
-    index = param->stack[0];
-
-    if (index >= ARRAY_SIZE(supported_dst_pixfmts)) {
-        param->errCode = EINVAL;
+    if (f->index >= ARRAY_SIZE(support_fmts)) {
+        state->io_ptr->err_code = errno;
+        state->io_ptr->ret_val = -1;
         return;
     }
-    param->stack[1] = 0; /* flags = NONE */
-    param->stack[2] = supported_dst_pixfmts[index].fmt; /* pixelformat */
+
+    f->flags = 0; /* flags = NONE */
+    f->pixelformat = support_fmts[f->index].fmt; /* pixelformat */
+
     /* set description */
-    switch (supported_dst_pixfmts[index].fmt) {
+    switch (support_fmts[f->index].fmt) {
     case V4L2_PIX_FMT_YUYV:
-        strcpy((char *)&param->stack[3], "YUYV");
+        pstrcpy((char *)f->description, sizeof(f->description), "YUYV");
         break;
     case V4L2_PIX_FMT_YUV420:
-        strcpy((char *)&param->stack[3], "YU12");
+        pstrcpy((char *)f->description, sizeof(f->description), "YU12");
         break;
     case V4L2_PIX_FMT_YVU420:
-        strcpy((char *)&param->stack[3], "YV12");
+        pstrcpy((char *)f->description, sizeof(f->description), "YV12");
         break;
     default:
         ERR("Invalid fixel format\n");
-        param->errCode = EINVAL;
+        state->io_ptr->err_code = EINVAL;
+        state->io_ptr->ret_val = -1;
         break;
     }
 }
 
-void marucam_device_qctrl(MaruCamState *state)
+static void backend_v4l2_query_ctrl(MaruCamState *state)
 {
+    MAKE_BACKEND_V4L2(state);
+    struct v4l2_queryctrl *qc = (struct v4l2_queryctrl *)state->io_ptr->data;
     uint32_t i;
-    char name[32] = {0,};
-    struct v4l2_queryctrl ctrl;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    CLEAR(ctrl);
-    ctrl.id = param->stack[0];
 
     /* NOTICE: Tizen MMFW hardcoded for control name
                Do Not Modified the name
     */
-    switch (ctrl.id) {
+    switch (qc->id) {
     case V4L2_CID_BRIGHTNESS:
         TRACE("Query : BRIGHTNESS\n");
-        strcpy(name, "brightness");
+        pstrcpy((char *)qc->name, sizeof(qc->name), "brightness");
         i = 0;
         break;
     case V4L2_CID_CONTRAST:
         TRACE("Query : CONTRAST\n");
-        strcpy(name, "contrast");
+        pstrcpy((char *)qc->name, sizeof(qc->name), "contrast");
         i = 1;
         break;
     case V4L2_CID_SATURATION:
         TRACE("Query : SATURATION\n");
-        strcpy(name, "saturation");
+        pstrcpy((char *)qc->name, sizeof(qc->name), "saturation");
         i = 2;
         break;
     case V4L2_CID_SHARPNESS:
         TRACE("Query : SHARPNESS\n");
-        strcpy(name, "sharpness");
+        pstrcpy((char *)qc->name, sizeof(qc->name), "sharpness");
         i = 3;
         break;
     default:
         ERR("Invalid control ID\n");
-        param->errCode = EINVAL;
+        state->io_ptr->err_code = EINVAL;
+        state->io_ptr->ret_val = -1;
         return;
     }
 
-    if (xioctl(v4l2_fd, VIDIOC_QUERYCTRL, &ctrl) < 0) {
+    if (xioctl(backend->fd, VIDIOC_QUERYCTRL, qc) < 0) {
         if (errno != EINVAL) {
             ERR("Failed to query video controls: %s\n", strerror(errno));
         }
-        param->errCode = errno;
+        state->io_ptr->err_code = errno;
+        state->io_ptr->ret_val = -1;
         return;
     } else {
         struct v4l2_control sctrl, gctrl;
         CLEAR(sctrl);
         CLEAR(gctrl);
-        sctrl.id = gctrl.id = ctrl.id;
-        if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &gctrl) < 0) {
+        sctrl.id = gctrl.id = qc->id;
+        if (xioctl(backend->fd, VIDIOC_G_CTRL, &gctrl) < 0) {
             ERR("[%s] Failed to get video control value: id(0x%x), "
                 "errstr(%s)\n",
                 __func__, gctrl.id, strerror(errno));
-            param->errCode = errno;
+            state->io_ptr->err_code = errno;
+            state->io_ptr->ret_val = -1;
             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 = gctrl.value;
+        ctrl_tbl[i].hit = 1;
+        ctrl_tbl[i].min = qc->minimum;
+        ctrl_tbl[i].max = qc->maximum;
+        ctrl_tbl[i].step = qc->step;
+        ctrl_tbl[i].init_val = gctrl.value;
 
-        if ((ctrl.maximum + ctrl.minimum) == 0) {
+        if ((qc->maximum + qc->minimum) == 0) {
             sctrl.value = 0;
         } else {
-            sctrl.value = (ctrl.maximum + ctrl.minimum) / 2;
+            sctrl.value = (qc->maximum + qc->minimum) / 2;
         }
 
-        if (xioctl(v4l2_fd, VIDIOC_S_CTRL, &sctrl) < 0) {
+        if (xioctl(backend->fd, VIDIOC_S_CTRL, &sctrl) < 0) {
             ERR("[%s] Failed to set control value: id(0x%x), value(%d), "
                 "errstr(%s)\n",
                 __func__, sctrl.id, sctrl.value, strerror(errno));
-            param->errCode = errno;
+            state->io_ptr->err_code = errno;
+            state->io_ptr->ret_val = -1;
             return;
         }
 
         INFO("Query Control: id(0x%x), name(%s), min(%d), max(%d), "
              "step(%d), def_value(%d)\n"
              "flags(0x%x), get_value(%d), set_value(%d)\n",
-             ctrl.id, ctrl.name, ctrl.minimum, ctrl.maximum,
-             ctrl.step, ctrl.default_value, ctrl.flags,
+             qc->id, qc->name, qc->minimum, qc->maximum,
+             qc->step, qc->default_value, qc->flags,
              gctrl.value, sctrl.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));
+    qc->minimum = MARUCAM_CTRL_VALUE_MIN;    /* minimum */
+    qc->maximum = MARUCAM_CTRL_VALUE_MAX;    /* maximum */
+    qc->step = MARUCAM_CTRL_VALUE_STEP;   /* step */
+    qc->default_value = MARUCAM_CTRL_VALUE_MID;    /* default_value */
 }
 
-void marucam_device_s_ctrl(MaruCamState *state)
+static void backend_v4l2_s_ctrl(MaruCamState *state)
 {
+    MAKE_BACKEND_V4L2(state);
+    struct v4l2_control *ctrl = (struct v4l2_control *)state->io_ptr->data;
     uint32_t i;
-    struct v4l2_control ctrl;
-    MaruCamParam *param = state->param;
 
-    param->top = 0;
-    CLEAR(ctrl);
-    ctrl.id = param->stack[0];
-
-    switch (ctrl.id) {
+    switch (ctrl->id) {
     case V4L2_CID_BRIGHTNESS:
         i = 0;
-        TRACE("%d is set to the value of the BRIGHTNESS\n", param->stack[1]);
+        TRACE("%d is set to the value of the BRIGHTNESS\n", ctrl->value);
         break;
     case V4L2_CID_CONTRAST:
         i = 1;
-        TRACE("%d is set to the value of the CONTRAST\n", param->stack[1]);
+        TRACE("%d is set to the value of the CONTRAST\n", ctrl->value);
         break;
     case V4L2_CID_SATURATION:
         i = 2;
-        TRACE("%d is set to the value of the SATURATION\n", param->stack[1]);
+        TRACE("%d is set to the value of the SATURATION\n", ctrl->value);
         break;
     case V4L2_CID_SHARPNESS:
         i = 3;
-        TRACE("%d is set to the value of the SHARPNESS\n", param->stack[1]);
+        TRACE("%d is set to the value of the SHARPNESS\n", ctrl->value);
         break;
     default:
-        ERR("Our emulator does not support this control: 0x%x\n", ctrl.id);
-        param->errCode = EINVAL;
+        ERR("Our emulator does not support this control: 0x%x\n", ctrl->id);
+        state->io_ptr->err_code= EINVAL;
+        state->io_ptr->ret_val = -1;
         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 control value: id(0x%x), value(r:%d, c:%d), "
-            "errstr(%s)\n", ctrl.id, param->stack[1], ctrl.value,
-            strerror(errno));
-        param->errCode = errno;
+    ctrl->value = value_convert_from_guest(ctrl_tbl[i].min,
+            ctrl_tbl[i].max, ctrl->value);
+    if (xioctl(backend->fd, VIDIOC_S_CTRL, ctrl) < 0) {
+        ERR("Failed to set control value: id(0x%x), value(%d), errstr(%s)\n",
+            ctrl->id, ctrl->value, strerror(errno));
+        state->io_ptr->err_code = errno;
+        state->io_ptr->ret_val = -1;
         return;
     }
 }
 
-void marucam_device_g_ctrl(MaruCamState *state)
+static void backend_v4l2_g_ctrl(MaruCamState *state)
 {
+    MAKE_BACKEND_V4L2(state);
+    struct v4l2_control *ctrl = (struct v4l2_control *)state->io_ptr->data;
     uint32_t i;
-    struct v4l2_control ctrl;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    CLEAR(ctrl);
-    ctrl.id = param->stack[0];
 
-    switch (ctrl.id) {
+    switch (ctrl->id) {
     case V4L2_CID_BRIGHTNESS:
         TRACE("Gets the value of the BRIGHTNESS\n");
         i = 0;
@@ -1309,83 +1297,93 @@ void marucam_device_g_ctrl(MaruCamState *state)
         i = 3;
         break;
     default:
-        ERR("Our emulator does not support this control: 0x%x\n", ctrl.id);
-        param->errCode = EINVAL;
+        ERR("Our emulator does not support this control: 0x%x\n", ctrl->id);
+        state->io_ptr->err_code = EINVAL;
+        state->io_ptr->ret_val = -1;
         return;
     }
 
-    if (xioctl(v4l2_fd, VIDIOC_G_CTRL, &ctrl) < 0) {
+    if (xioctl(backend->fd, VIDIOC_G_CTRL, ctrl) < 0) {
         ERR("Failed to get video control value: %s\n", strerror(errno));
-        param->errCode = errno;
+        state->io_ptr->err_code = errno;
+        state->io_ptr->ret_val = -1;
         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]);
+    ctrl->value = value_convert_to_guest(ctrl_tbl[i].min,
+            ctrl_tbl[i].max, ctrl->value);
+    TRACE("Value: %d\n", ctrl->value);
 }
 
-void marucam_device_enum_fsizes(MaruCamState *state)
+static void backend_v4l2_enum_fsizes(MaruCamState *state)
 {
-    uint32_t index, pixfmt, i;
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
-    index = param->stack[0];
-    pixfmt = param->stack[1];
+    struct v4l2_frmsizeenum *fsize = (struct v4l2_frmsizeenum *)state->io_ptr->data;
+    uint32_t i;
 
-    if (index >= ARRAY_SIZE(supported_dst_frames)) {
-        param->errCode = EINVAL;
+    if (fsize->index >= ARRAY_SIZE(support_frames)) {
+        state->io_ptr->err_code = EINVAL;
+        state->io_ptr->ret_val = -1;
         return;
     }
-    for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) {
-        if (supported_dst_pixfmts[i].fmt == pixfmt) {
+    for (i = 0; i < ARRAY_SIZE(support_fmts); i++) {
+        if (support_fmts[i].fmt == fsize->pixel_format) {
             break;
         }
     }
 
-    if (i == ARRAY_SIZE(supported_dst_pixfmts)) {
-        param->errCode = EINVAL;
+    if (i == ARRAY_SIZE(support_fmts)) {
+        state->io_ptr->err_code = EINVAL;
+        state->io_ptr->ret_val = -1;
         return;
     }
 
-    param->stack[0] = supported_dst_frames[index].width;
-    param->stack[1] = supported_dst_frames[index].height;
+    fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+    fsize->discrete.width = support_frames[fsize->index].width;
+    fsize->discrete.height = support_frames[fsize->index].height;
 }
 
-void marucam_device_enum_fintv(MaruCamState *state)
+static void backend_v4l2_enum_fintv(MaruCamState *state)
 {
-    MaruCamParam *param = state->param;
-
-    param->top = 0;
+    struct v4l2_frmivalenum *fival = (struct v4l2_frmivalenum *)state->io_ptr->data;
 
-    /* switch by index(param->stack[0]) */
-    switch (param->stack[0]) {
+    /* switch by index) */
+    switch (fival->index) {
     case 0:
         /* we only use 1/30 frame interval */
-        param->stack[1] = 30;   /* denominator */
+        fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+        fival->discrete.numerator = 1;
+        fival->discrete.denominator = 30;
         break;
     default:
-        param->errCode = EINVAL;
+        state->io_ptr->err_code = EINVAL;
+        state->io_ptr->ret_val = -1;
         return;
     }
-    param->stack[0] = 1;    /* numerator */
 }
 
-void marucam_device_close(MaruCamState *state)
+MaruCamBackend *marucam_backend_create(MaruCamState *state)
 {
-    if (!is_stream_paused(state)) {
-        marucam_device_stop_preview(state);
-    }
-
-    marucam_reset_controls();
-
-    if (saved_frame.data) {
-        g_free(saved_frame.data);
-        saved_frame.data = NULL;
-    }
-    memset(&saved_frame, 0x00, sizeof(saved_frame));
-
-    v4l2_close(v4l2_fd);
-    v4l2_fd = 0;
-    INFO("Closed\n");
+    MCBackendV4l2 *backend_v4l2;
+
+    backend_v4l2 = g_new0(MCBackendV4l2, 1);
+
+    backend_v4l2->base.init                = backend_v4l2_init;
+    backend_v4l2->base.reset               = backend_v4l2_reset;
+    backend_v4l2->base.release             = backend_v4l2_release;
+    backend_v4l2->base.open                = backend_v4l2_open;
+    backend_v4l2->base.close               = backend_v4l2_close;
+    backend_v4l2->base.stream_on           = backend_v4l2_stream_on;
+    backend_v4l2->base.stream_off          = backend_v4l2_stream_off;
+    backend_v4l2->base.enum_fmt            = backend_v4l2_enum_fmt;
+    backend_v4l2->base.try_fmt             = backend_v4l2_try_fmt;
+    backend_v4l2->base.s_fmt               = backend_v4l2_s_fmt;
+    backend_v4l2->base.g_fmt               = backend_v4l2_g_fmt;
+    backend_v4l2->base.s_parm              = backend_v4l2_s_parm;
+    backend_v4l2->base.g_parm              = backend_v4l2_g_parm;
+    backend_v4l2->base.query_ctrl          = backend_v4l2_query_ctrl;
+    backend_v4l2->base.s_ctrl              = backend_v4l2_s_ctrl;
+    backend_v4l2->base.g_ctrl              = backend_v4l2_g_ctrl;
+    backend_v4l2->base.enum_framesizes     = backend_v4l2_enum_fsizes;
+    backend_v4l2->base.enum_frameintervals = backend_v4l2_enum_fintv;
+
+    return &backend_v4l2->base;
 }