[Title] fixed a bug : failed to set up camera because device is busy
authorjinhyung.jo <jinhyung.jo@samsung.com>
Fri, 24 Aug 2012 13:10:52 +0000 (22:10 +0900)
committerjinhyung.jo <jinhyung.jo@samsung.com>
Fri, 24 Aug 2012 13:10:52 +0000 (22:10 +0900)
[Type] Bugfix
[Module] Emulator / Camera
[Priority] Critical
[CQ#] S1-7702
[Redmine#]
[Problem]
[Cause]
[Solution]
[TestCase]

package/pkginfo.manifest
tizen/src/hw/maru_camera_linux_pci.c

index c21245b65b38c7194fbdbfe66d3556dc69eaeae1..8584d73ca7c9ff5a6bbf885db551dfb27cbacee1 100644 (file)
@@ -1,4 +1,4 @@
-Version: 1.3.25
+Version: 1.3.26
 Maintainer: Yeong-Kyoon Lee<yeongkyoon.lee@samsung.com>
 Source: emulator
 
index e288e7a6226c326a2c039f2ae7239ef26c33f4f2..5575831957aa8525e7f258b4d591b4722fcd1de5 100644 (file)
 \r
 #include <linux/videodev2.h>\r
 \r
+#include <sys/stat.h>\r
+#include <sys/ioctl.h>\r
+\r
 #include <libv4l2.h>\r
 #include <libv4lconvert.h>\r
 \r
 MULTI_DEBUG_CHANNEL(tizen, camera_linux);\r
 \r
+#define MARUCAM_SKIPFRAMES    2\r
+\r
+enum {\r
+    _MC_THREAD_PAUSED,\r
+    _MC_THREAD_STREAMON,\r
+    _MC_THREAD_STREAMOFF,\r
+};\r
+\r
+static const char *dev_name = "/dev/video0";\r
 static int v4l2_fd;\r
 static int convert_trial;\r
 static int ready_count;\r
 \r
 static struct v4l2_format dst_fmt;\r
 \r
+#define CLEAR(x) memset(&(x), 0, sizeof(x))\r
+\r
 static int xioctl(int fd, int req, void *arg)\r
 {\r
     int r;\r
@@ -128,6 +142,24 @@ static int32_t value_convert_to_guest(int32_t min, int32_t max, int32_t value)
     return ret;\r
 }\r
 \r
+static int is_streamon(MaruCamState *state)\r
+{\r
+    int st;\r
+    qemu_mutex_lock(&state->thread_mutex);\r
+    st = state->streamon;\r
+    qemu_mutex_unlock(&state->thread_mutex);\r
+    return (st == _MC_THREAD_STREAMON);\r
+}\r
+\r
+static int is_stream_paused(MaruCamState *state)\r
+{\r
+    int st;\r
+    qemu_mutex_lock(&state->thread_mutex);\r
+    st = state->streamon;\r
+    qemu_mutex_unlock(&state->thread_mutex);\r
+    return (st == _MC_THREAD_PAUSED);\r
+}\r
+\r
 static int __v4l2_grab(MaruCamState *state)\r
 {\r
     fd_set fds;\r
@@ -139,8 +171,8 @@ static int __v4l2_grab(MaruCamState *state)
     FD_ZERO(&fds);\r
     FD_SET(v4l2_fd, &fds);\r
 \r
-    tv.tv_sec = 2;\r
-    tv.tv_usec = 0;\r
+    tv.tv_sec = 0;\r
+    tv.tv_usec = 500000;\r
 \r
     ret = select(v4l2_fd + 1, &fds, NULL, NULL, &tv);\r
     if ( ret < 0) {\r
@@ -159,11 +191,8 @@ static int __v4l2_grab(MaruCamState *state)
         return -1;\r
     }\r
 \r
-       qemu_mutex_lock(&state->thread_mutex);\r
-       ret = state->streamon;\r
-       qemu_mutex_unlock(&state->thread_mutex);\r
-       if (!ret)\r
-              return -1;\r
+    if (!is_streamon(state))\r
+        return -1;\r
 \r
     buf = state->vaddr + (state->buf_size * index);\r
     ret = v4l2_read(v4l2_fd, buf, state->buf_size);\r
@@ -188,8 +217,8 @@ static int __v4l2_grab(MaruCamState *state)
     index = !index;\r
 \r
     qemu_mutex_lock(&state->thread_mutex);\r
-    if (state->streamon) {\r
-        if (ready_count >= 4) {\r
+    if (state->streamon == _MC_THREAD_STREAMON) {\r
+        if (ready_count >= MARUCAM_SKIPFRAMES) {\r
             if (state->req_frame) {\r
                 state->req_frame = 0; // clear request\r
                 state->isr |= 0x01; // set a flag of rasing a interrupt.\r
@@ -208,45 +237,59 @@ static int __v4l2_grab(MaruCamState *state)
     return ret;\r
 }\r
 \r
-// Worker thread\r
+/* Worker thread */\r
 static void *marucam_worker_thread(void *thread_param)\r
 {\r
     MaruCamState *state = (MaruCamState*)thread_param;\r
 \r
 wait_worker_thread:\r
     qemu_mutex_lock(&state->thread_mutex);\r
-    state->streamon = 0;\r
-    convert_trial = 10;\r
+    state->streamon = _MC_THREAD_PAUSED;\r
     qemu_cond_wait(&state->thread_cond, &state->thread_mutex);\r
     qemu_mutex_unlock(&state->thread_mutex);\r
+\r
+    convert_trial = 10;\r
+    ready_count = 0;\r
+    qemu_mutex_lock(&state->thread_mutex);\r
+    state->buf_size = dst_fmt.fmt.pix.sizeimage;\r
+    state->streamon = _MC_THREAD_STREAMON;\r
+    qemu_mutex_unlock(&state->thread_mutex);\r
     INFO("Streaming on ......\n");\r
 \r
     while (1)\r
     {\r
-        qemu_mutex_lock(&state->thread_mutex);\r
-        if (state->streamon) {\r
-            qemu_mutex_unlock(&state->thread_mutex);\r
+        if (is_streamon(state)) {\r
             if (__v4l2_grab(state) < 0) {\r
                 INFO("...... Streaming off\n");\r
                 goto wait_worker_thread;\r
             }\r
         } else {\r
-            qemu_mutex_unlock(&state->thread_mutex);\r
             INFO("...... Streaming off\n");\r
             goto wait_worker_thread;\r
         }\r
     }\r
-    qemu_thread_exit((void*)0);\r
+    return NULL;\r
 }\r
 \r
 int marucam_device_check(void)\r
 {\r
     int tmp_fd;\r
+    struct stat st;\r
     struct v4l2_capability cap;\r
 \r
-    tmp_fd = open("/dev/video0", O_RDWR);\r
+    if (stat(dev_name, &st) < 0) {\r
+        ERR("Cannot identify '%s': %s\n", dev_name, strerror(errno));\r
+        return 0;\r
+    }\r
+\r
+    if (!S_ISCHR(st.st_mode)) {\r
+        ERR("%s is no device.\n", dev_name);\r
+        return 0;\r
+    }\r
+\r
+    tmp_fd = open(dev_name, O_RDWR | O_NONBLOCK, 0);\r
     if (tmp_fd < 0) {\r
-        ERR("camera device open failed.(/dev/video0)\n");\r
+        ERR("camera device open failed.(%s)\n", dev_name);\r
         return 0;\r
     }\r
     if (ioctl(tmp_fd, VIDIOC_QUERYCAP, &cap) < 0) {\r
@@ -270,62 +313,46 @@ void marucam_device_init(MaruCamState* state)
     qemu_thread_create(&state->thread_id, marucam_worker_thread, (void*)state);\r
 }\r
 \r
-// MARUCAM_CMD_OPEN\r
 void marucam_device_open(MaruCamState* state)\r
 {\r
-    struct v4l2_capability cap;\r
     MaruCamParam *param = state->param;\r
 \r
     param->top = 0;\r
-    v4l2_fd = v4l2_open("/dev/video0", O_RDWR);\r
+    v4l2_fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);\r
     if (v4l2_fd < 0) {\r
-        ERR("v4l2 device open failed.(/dev/video0)\n");\r
-        param->errCode = EINVAL;\r
-        return;\r
-    }\r
-    if (xioctl(v4l2_fd, VIDIOC_QUERYCAP, &cap) < 0) {\r
-        ERR("Could not qeury video capabilities\n");\r
-        v4l2_close(v4l2_fd);\r
-        param->errCode = EINVAL;\r
-        return;\r
-    }\r
-    if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ||\r
-            !(cap.capabilities & V4L2_CAP_STREAMING)) {\r
-        ERR("Not supported video driver.\n");\r
-        v4l2_close(v4l2_fd);\r
+        ERR("v4l2 device open failed.(%s)\n", dev_name);\r
         param->errCode = EINVAL;\r
         return;\r
     }\r
 \r
-    memset(&dst_fmt, 0, sizeof(dst_fmt));\r
+    CLEAR(dst_fmt);\r
     INFO("Opened\n");\r
 }\r
 \r
-// MARUCAM_CMD_START_PREVIEW\r
 void marucam_device_start_preview(MaruCamState* state)\r
 {\r
     qemu_mutex_lock(&state->thread_mutex);\r
-    state->streamon = 1;\r
-    ready_count = 0;\r
-    state->buf_size = dst_fmt.fmt.pix.sizeimage;\r
     qemu_cond_signal(&state->thread_cond);\r
     qemu_mutex_unlock(&state->thread_mutex);\r
-       INFO("Starting preview!\n");\r
+    INFO("Starting preview!\n");\r
 }\r
 \r
-// MARUCAM_CMD_STOP_PREVIEW\r
 void marucam_device_stop_preview(MaruCamState* state)\r
 {\r
-       struct timespec req;\r
-       req.tv_sec = 0;\r
-       req.tv_nsec = 333333333;\r
+    struct timespec req;\r
+    req.tv_sec = 0;\r
+    req.tv_nsec = 50000000;\r
 \r
     qemu_mutex_lock(&state->thread_mutex);\r
-    state->streamon = 0;\r
+    state->streamon = _MC_THREAD_STREAMOFF;\r
     state->buf_size = 0;\r
     qemu_mutex_unlock(&state->thread_mutex);\r
-    nanosleep(&req, NULL);\r
-       INFO("Stopping preview!\n");\r
+\r
+    /* nanosleep until thread is paused  */\r
+    while (!is_stream_paused(state))\r
+        nanosleep(&req, NULL);\r
+\r
+    INFO("Stopping preview!\n");\r
 }\r
 \r
 void marucam_device_s_param(MaruCamState* state)\r
@@ -354,7 +381,7 @@ void marucam_device_s_fmt(MaruCamState* state)
     MaruCamParam *param = state->param;\r
 \r
     param->top = 0;\r
-    memset(&dst_fmt, 0, sizeof(struct v4l2_format));\r
+    CLEAR(dst_fmt);\r
     dst_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
     dst_fmt.fmt.pix.width = param->stack[0];\r
     dst_fmt.fmt.pix.height = param->stack[1];\r
@@ -383,7 +410,7 @@ void marucam_device_g_fmt(MaruCamState* state)
     MaruCamParam *param = state->param;\r
 \r
     param->top = 0;\r
-    memset(&format, 0, sizeof(struct v4l2_format));\r
+    CLEAR(format);\r
     format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
 \r
     if (xioctl(v4l2_fd, VIDIOC_G_FMT, &format) < 0) {\r
@@ -408,7 +435,7 @@ void marucam_device_try_fmt(MaruCamState* state)
     MaruCamParam *param = state->param;\r
 \r
     param->top = 0;\r
-    memset(&format, 0, sizeof(struct v4l2_format));\r
+    CLEAR(format);\r
     format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
     format.fmt.pix.width = param->stack[0];\r
     format.fmt.pix.height = param->stack[1];\r
@@ -436,7 +463,7 @@ void marucam_device_enum_fmt(MaruCamState* state)
     MaruCamParam *param = state->param;\r
 \r
     param->top = 0;\r
-    memset(&format, 0, sizeof(struct v4l2_fmtdesc));\r
+    CLEAR(format);\r
     format.index = param->stack[0];\r
     format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\r
 \r
@@ -461,7 +488,7 @@ void marucam_device_qctrl(MaruCamState* state)
     MaruCamParam *param = state->param;\r
 \r
     param->top = 0;\r
-    memset(&ctrl, 0, sizeof(struct v4l2_queryctrl));\r
+    CLEAR(ctrl);\r
     ctrl.id = param->stack[0];\r
 \r
     switch (ctrl.id) {\r
@@ -497,7 +524,7 @@ void marucam_device_qctrl(MaruCamState* state)
         return;\r
     } else {\r
         struct v4l2_control sctrl;\r
-        memset(&sctrl, 0, sizeof(struct v4l2_control));\r
+        CLEAR(sctrl);\r
         sctrl.id = ctrl.id;\r
         if ((ctrl.maximum + ctrl.minimum) == 0) {\r
             sctrl.value = 0;\r
@@ -534,7 +561,7 @@ void marucam_device_s_ctrl(MaruCamState* state)
     MaruCamParam *param = state->param;\r
 \r
     param->top = 0;\r
-    memset(&ctrl, 0, sizeof(struct v4l2_control));\r
+    CLEAR(ctrl);\r
     ctrl.id = param->stack[0];\r
 \r
     switch (ctrl.id) {\r
@@ -576,7 +603,7 @@ void marucam_device_g_ctrl(MaruCamState* state)
     MaruCamParam *param = state->param;\r
 \r
     param->top = 0;\r
-    memset(&ctrl, 0, sizeof(struct v4l2_control));\r
+    CLEAR(ctrl);\r
     ctrl.id = param->stack[0];\r
 \r
     switch (ctrl.id) {\r
@@ -618,7 +645,7 @@ void marucam_device_enum_fsizes(MaruCamState* state)
     MaruCamParam *param = state->param;\r
 \r
     param->top = 0;\r
-    memset(&fsize, 0, sizeof(struct v4l2_frmsizeenum));\r
+    CLEAR(fsize);\r
     fsize.index = param->stack[0];\r
     fsize.pixel_format = param->stack[1];\r
 \r
@@ -644,7 +671,7 @@ void marucam_device_enum_fintv(MaruCamState* state)
     MaruCamParam *param = state->param;\r
 \r
     param->top = 0;\r
-    memset(&ival, 0, sizeof(struct v4l2_frmivalenum));\r
+    CLEAR(ival);\r
     ival.index = param->stack[0];\r
     ival.pixel_format = param->stack[1];\r
     ival.width = param->stack[2];\r
@@ -666,21 +693,14 @@ void marucam_device_enum_fintv(MaruCamState* state)
     }\r
 }\r
 \r
-// MARUCAM_CMD_CLOSE\r
 void marucam_device_close(MaruCamState* state)\r
 {\r
-       uint32_t is_streamon;\r
-\r
-    qemu_mutex_lock(&state->thread_mutex);\r
-    is_streamon = state->streamon;\r
-    qemu_mutex_unlock(&state->thread_mutex);\r
-\r
-       if (is_streamon)\r
-              marucam_device_stop_preview(state);\r
+    if (!is_stream_paused(state))\r
+        marucam_device_stop_preview(state);\r
 \r
     marucam_reset_controls();\r
 \r
     v4l2_close(v4l2_fd);\r
-    v4l2_fd = 0;\r
+    v4l2_fd = -1;\r
     INFO("Closed\n");\r
 }\r