title: Setting ctrl with V4L2 on ov5640
body: <p>I would like to control various <code>ov5640</code> camera parameters by using <code>ioctl</code> and <code>VIDIOC_S_CTRL</code> from V4L2 in the following manner:</p>
  
  <pre><code>#include &lt;string&gt;
  #include &lt;iostream&gt;
  
  #include &lt;fcntl.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;malloc.h&gt;
  #include &lt;cstring&gt;
  #include &lt;sys/mman.h&gt;
  #include &lt;sys/ioctl.h&gt;
  #include &lt;linux/videodev2.h&gt;
  
  #define IOCTL_TRIES 3
  #define CLEAR(x) memset (&amp;(x), 0, sizeof (x))
  
  static int xioctl(int fd, int request, void *arg)
  {
      int r;
      int tries = IOCTL_TRIES;
  
      do {
          r = ioctl(fd, request, arg);
      } while (--tries &gt; 0 &amp;&amp; r == -1 &amp;&amp; EINTR == errno);
  
      return r;
  }
  
  bool v4l2_ctrl_set(int fd, uint32_t id, int val)
  {
      struct v4l2_control ctrl;
      CLEAR(ctrl);
  
      ctrl.id = id;
      ctrl.value = val;
      if (xioctl(fd, VIDIOC_S_CTRL, &amp;ctrl) == -1) {
          std::cout &lt;&lt; "Failed to set ctrl with id " 
                    &lt;&lt; id &lt;&lt; " to value " &lt;&lt; val
                    &lt;&lt; "\nerror (" &lt;&lt; errno &lt;&lt; "): " &lt;&lt; strerror(errno) &lt;&lt; std::endl;
  
          return false;
      }
  
      return true;
  }
  
  int main()
  {
  
      int fd = open("/dev/video0", O_RDWR | O_NONBLOCK);
      if (fd == -1) {
          std::cout &lt;&lt; "Failed to open the camera" &lt;&lt; std::endl;
          return -1;
      }
  
      v4l2_ctrl_set(fd, V4L2_CID_SATURATION, 100);
  
      return 0;
  }
  </code></pre>
  
  <p>Unfortunately <code>ioctl</code> fails and I get <code>error (25): Inappropriate ioctl for device</code>. I'm using <a href="https://www.intrinsyc.com/computing-platforms/open-q-820-usom/" rel="nofollow noreferrer">Intrinsyc Open-Q 820 µSOM</a> with <a href="https://git.linaro.org/landing-teams/working/qualcomm/kernel.git/tree/?h=release%2Fqcomlt-4.14" rel="nofollow noreferrer">linaro 4.14</a>. I've managed to add some debugs prints to ov5640 driver file in <a href="https://git.linaro.org/landing-teams/working/qualcomm/kernel.git/tree/drivers/media/i2c/ov5640.c?h=release/qcomlt-4.14#n1923" rel="nofollow noreferrer">ov5640_s_ctrl function</a> before <code>if (sensor-&gt;power_count == 0) {</code> (in case there were problems with power save mode) and recompile the kernel. I ran the code, but looking through <code>dmesg</code> my <code>printk</code> message doesn't get printed, so that means that <code>ov5640_s_ctrl</code> doesn't get called even though the callback is set:</p>
  
  <pre><code>static const struct v4l2_ctrl_ops ov5640_ctrl_ops = {
      .g_volatile_ctrl = ov5640_g_volatile_ctrl,
      .s_ctrl = ov5640_s_ctrl,
  };
  </code></pre>
  
  <p>Am I using V4L2 wrong? Should I enable something before setting the controls? It's even more confusing since I manage to get an image from the camera with v4l2, but I can't set/get any controls.</p>