7f27219
From a8ed8c04c119e5a323a2c79fcd0d28b4d29fc28a Mon Sep 17 00:00:00 2001
7f27219
From: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
7f27219
Date: Thu, 23 Apr 2015 22:56:09 -0300
7f27219
Subject: [PATCH] v4l2: use REQBUFS properly
7f27219
7f27219
There are two issues on this driver with regards to buffer
7f27219
request:
7f27219
7f27219
1) it is not calling VIDIOC_REQBUFS for USERPTR;
7f27219
7f27219
2) It is calling VIDIOC_REQBUFS at probe, to check the max
7f27219
   number of supported buffers, but it doesn't deallocate
7f27219
   the buffers at the end of the probe function.
7f27219
7f27219
Fix those issues. Also, improve the error/warning messages
7f27219
associated with possible problems.
7f27219
7f27219
This is based on the issues detected by the patch proposed
7f27219
to fix this bug:
7f27219
	https://bugs.archlinux.org/task/44091
7f27219
7f27219
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
7f27219
7f27219
diff --git a/zbar/video/v4l2.c b/zbar/video/v4l2.c
7f27219
index aabd16643ddc..f6662d3707f9 100644
7f27219
--- a/zbar/video/v4l2.c
7f27219
+++ b/zbar/video/v4l2.c
7f27219
@@ -201,21 +201,6 @@ static int v4l2_cleanup (zbar_video_t *vdo)
7f27219
 
7f27219
 static int v4l2_mmap_buffers (zbar_video_t *vdo)
7f27219
 {
7f27219
-    struct v4l2_requestbuffers rb;
7f27219
-    memset(&rb, 0, sizeof(rb));
7f27219
-    rb.count = vdo->num_images;
7f27219
-    rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
7f27219
-    rb.memory = V4L2_MEMORY_MMAP;
7f27219
-    if(v4l2_ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0)
7f27219
-        return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__,
7f27219
-                           "requesting video frame buffers (VIDIOC_REQBUFS)"));
7f27219
-    zprintf(1, "mapping %u buffers (of %d requested)\n",
7f27219
-            rb.count, vdo->num_images);
7f27219
-    if(!rb.count)
7f27219
-        return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
7f27219
-                           "driver returned 0 buffers"));
7f27219
-    if(vdo->num_images > rb.count)
7f27219
-        vdo->num_images = rb.count;
7f27219
 
7f27219
     struct v4l2_buffer vbuf;
7f27219
     memset(&vbuf, 0, sizeof(vbuf));
7f27219
@@ -313,8 +298,32 @@ static int v4l2_set_format (zbar_video_t *vdo,
7f27219
 static int v4l2_init (zbar_video_t *vdo,
7f27219
                       uint32_t fmt)
7f27219
 {
7f27219
+    struct v4l2_requestbuffers rb;
7f27219
     if(v4l2_set_format(vdo, fmt))
7f27219
         return(-1);
7f27219
+
7f27219
+    memset(&rb, 0, sizeof(rb));
7f27219
+    rb.count = vdo->num_images;
7f27219
+    rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
7f27219
+    if(vdo->iomode == VIDEO_MMAP)
7f27219
+        rb.memory = V4L2_MEMORY_MMAP;
7f27219
+    else
7f27219
+        rb.memory = V4L2_MEMORY_USERPTR;
7f27219
+
7f27219
+    if(v4l2_ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0)
7f27219
+        return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__,
7f27219
+                           "requesting video frame buffers (VIDIOC_REQBUFS)"));
7f27219
+
7f27219
+    if(!rb.count)
7f27219
+        return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_INVALID, __func__,
7f27219
+                           "driver returned 0 buffers"));
7f27219
+
7f27219
+    if(vdo->num_images > rb.count)
7f27219
+        vdo->num_images = rb.count;
7f27219
+
7f27219
+    zprintf(1, "using %u buffers (of %d requested)\n",
7f27219
+            rb.count, vdo->num_images);
7f27219
+
7f27219
     if(vdo->iomode == VIDEO_MMAP)
7f27219
         return(v4l2_mmap_buffers(vdo));
7f27219
     return(0);
7f27219
@@ -324,7 +333,7 @@ static int v4l2_probe_iomode (zbar_video_t *vdo)
7f27219
 {
7f27219
     struct v4l2_requestbuffers rb;
7f27219
     memset(&rb, 0, sizeof(rb));
7f27219
-    rb.count = vdo->num_images; /* FIXME workaround broken drivers */
7f27219
+    rb.count = vdo->num_images;
7f27219
     rb.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
7f27219
     if(vdo->iomode == VIDEO_MMAP)
7f27219
         rb.memory = V4L2_MEMORY_MMAP;
7f27219
@@ -340,14 +349,31 @@ static int v4l2_probe_iomode (zbar_video_t *vdo)
7f27219
             return(err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__,
7f27219
                                "querying streaming mode (VIDIOC_REQBUFS)"));
7f27219
 #ifdef HAVE_SYS_MMAN_H
7f27219
+	err_capture(vdo, SEV_WARNING, ZBAR_ERR_SYSTEM, __func__,
7f27219
+                               "USERPTR failed. Falling back to mmap");
7f27219
         vdo->iomode = VIDEO_MMAP;
7f27219
+#else
7f27219
+	return err_capture(vdo, SEV_ERROR, ZBAR_ERR_SYSTEM, __func__,
7f27219
+                           "Userptr not supported, and zbar was compiled without mmap support"));
7f27219
 #endif
7f27219
     }
7f27219
     else {
7f27219
         if(!vdo->iomode)
7f27219
-            vdo->iomode = VIDEO_USERPTR;
7f27219
+            rb.memory = V4L2_MEMORY_USERPTR;
7f27219
+	/* Update the num_images with the max supported by the driver */
7f27219
         if(rb.count)
7f27219
             vdo->num_images = rb.count;
7f27219
+	else
7f27219
+            err_capture(vdo, SEV_WARNING, ZBAR_ERR_SYSTEM, __func__,
7f27219
+                        "Something is wrong: number of buffers returned by REQBUF is zero!");
7f27219
+
7f27219
+        /* requesting 0 buffers
7f27219
+         * This cleans up the buffers allocated previously on probe
7f27219
+         */
7f27219
+	rb.count = 0;
7f27219
+        if(v4l2_ioctl(vdo->fd, VIDIOC_REQBUFS, &rb) < 0)
7f27219
+            err_capture(vdo, SEV_WARNING, ZBAR_ERR_SYSTEM, __func__,
7f27219
+                        "releasing video frame buffers (VIDIOC_REQBUFS)");
7f27219
     }
7f27219
     return(0);
7f27219
 }