On 20/01/14 13:46, Hans Verkuil wrote:
> From: Hans Verkuil <hans.verk...@cisco.com>
> 
> Document the support for complex types in controls.
> 
> Signed-off-by: Hans Verkuil <hans.verk...@cisco.com>
> ---
>  Documentation/DocBook/media/v4l/controls.xml | 185 
> +++++++++++++++++----------
>  1 file changed, 118 insertions(+), 67 deletions(-)
> 
> diff --git a/Documentation/DocBook/media/v4l/controls.xml 
> b/Documentation/DocBook/media/v4l/controls.xml
> index a5a3188..85d78d4 100644
> --- a/Documentation/DocBook/media/v4l/controls.xml
> +++ b/Documentation/DocBook/media/v4l/controls.xml
> @@ -13,6 +13,19 @@ correctly with any device.</para>
>      <para>All controls are accessed using an ID value. V4L2 defines
>  several IDs for specific purposes. Drivers can also implement their
>  own custom controls using <constant>V4L2_CID_PRIVATE_BASE</constant>
> +<footnote><para>The use of <constant>V4L2_CID_PRIVATE_BASE</constant>
> +is problematic because different drivers may use the same
> +<constant>V4L2_CID_PRIVATE_BASE</constant> ID for different controls.
> +This makes it hard to programatically set such controls since the meaning
> +of the control with that ID is driver dependent. In order to resolve this
> +drivers use unique IDs and the <constant>V4L2_CID_PRIVATE_BASE</constant>
> +IDs are mapped to those unique IDs by the kernel. Consider these
> +<constant>V4L2_CID_PRIVATE_BASE</constant> IDs as aliases to the real
> +IDs.</para>
> +<para>Many applications today still use the 
> <constant>V4L2_CID_PRIVATE_BASE</constant>
> +IDs instead of using &VIDIOC-QUERYCTRL; with the 
> <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>
> +flag to enumerate all IDs, so support for 
> <constant>V4L2_CID_PRIVATE_BASE</constant>
> +is still around.</para></footnote>
>  and higher values. The pre-defined control IDs have the prefix
>  <constant>V4L2_CID_</constant>, and are listed in <xref
>  linkend="control-id" />. The ID is used when querying the attributes of
> @@ -31,25 +44,22 @@ the current video input or output, tuner or modulator, or 
> audio input
>  or output. Different in the sense of other bounds, another default and
>  current value, step size or other menu items. A control with a certain
>  <emphasis>custom</emphasis> ID can also change name and
> -type.<footnote>
> -     <para>It will be more convenient for applications if drivers
> -make use of the <constant>V4L2_CTRL_FLAG_DISABLED</constant> flag, but
> -that was never required.</para>
> -      </footnote> Control values are stored globally, they do not
> +type.</para>
> +
> +    <para>If a control is not applicable to the current configuration
> +of the device (for example, it doesn't apply to the current video input)
> +drivers set the <constant>V4L2_CTRL_FLAG_INACTIVE</constant> flag.</para>
> +
> +    <para>Control values are stored globally, they do not
>  change when switching except to stay within the reported bounds. They
>  also do not change &eg; when the device is opened or closed, when the
>  tuner radio frequency is changed or generally never without
> -application request. Since V4L2 specifies no event mechanism, panel
> -applications intended to cooperate with other panel applications (be
> -they built into a larger application, as a TV viewer) may need to
> -regularly poll control values to update their user
> -interface.<footnote>
> -     <para>Applications could call an ioctl to request events.
> -After another process called &VIDIOC-S-CTRL; or another ioctl changing
> -shared properties the &func-select; function would indicate
> -readability until any ioctl (querying the properties) is
> -called.</para>
> -      </footnote></para>
> +application request.</para>
> +
> +    <para>V4L2 specifies an event mechanism to notify applications
> +when controls change value (see &VIDIOC-SUBSCRIBE-EVENT;, event
> +<constant>V4L2_EVENT_CTRL</constant>), panel applications might want to make
> +use of that in order to always reflect the correct control value.</para>
>  
>      <para>
>        All controls use machine endianness.
> @@ -434,127 +444,152 @@ Drivers must implement 
> <constant>VIDIOC_QUERYCTRL</constant>,
>  controls, <constant>VIDIOC_QUERYMENU</constant> when it has one or
>  more menu type controls.</para>
>  
> -    <example>
> -      <title>Enumerating all controls</title>
> +    <example id="enum_all_controls">
> +      <title>Enumerating all user controls</title>
>  
>        <programlisting>
>  &v4l2-queryctrl; queryctrl;
>  &v4l2-querymenu; querymenu;
>  
> -static void
> -enumerate_menu (void)
> +static void enumerate_menu(void)
>  {
> -     printf ("  Menu items:\n");
> +     printf("  Menu items:\n");
>  
> -     memset (&amp;querymenu, 0, sizeof (querymenu));
> +     memset(&amp;querymenu, 0, sizeof(querymenu));
>       querymenu.id = queryctrl.id;
>  
>       for (querymenu.index = queryctrl.minimum;
>            querymenu.index &lt;= queryctrl.maximum;
> -           querymenu.index++) {
> -             if (0 == ioctl (fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
> -                     printf ("  %s\n", querymenu.name);
> +          querymenu.index++) {
> +             if (0 == ioctl(fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
> +                     printf("  %s\n", querymenu.name);
>               }
>       }
>  }
>  
> -memset (&amp;queryctrl, 0, sizeof (queryctrl));
> +memset(&amp;queryctrl, 0, sizeof(queryctrl));
>  
>  for (queryctrl.id = V4L2_CID_BASE;
>       queryctrl.id &lt; V4L2_CID_LASTP1;
>       queryctrl.id++) {
> -     if (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
> +     if (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
>               if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
>                       continue;
>  
> -             printf ("Control %s\n", queryctrl.name);
> +             printf("Control %s\n", queryctrl.name);
>  
>               if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
> -                     enumerate_menu ();
> +                     enumerate_menu();
>       } else {
>               if (errno == EINVAL)
>                       continue;
>  
> -             perror ("VIDIOC_QUERYCTRL");
> -             exit (EXIT_FAILURE);
> +             perror("VIDIOC_QUERYCTRL");
> +             exit(EXIT_FAILURE);
>       }
>  }
>  
>  for (queryctrl.id = V4L2_CID_PRIVATE_BASE;;
>       queryctrl.id++) {
> -     if (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
> +     if (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
>               if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
>                       continue;
>  
> -             printf ("Control %s\n", queryctrl.name);
> +             printf("Control %s\n", queryctrl.name);
>  
>               if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
> -                     enumerate_menu ();
> +                     enumerate_menu();
>       } else {
>               if (errno == EINVAL)
>                       break;
>  
> -             perror ("VIDIOC_QUERYCTRL");
> -             exit (EXIT_FAILURE);
> +             perror("VIDIOC_QUERYCTRL");
> +             exit(EXIT_FAILURE);
>       }
>  }
>  </programlisting>
>      </example>
>  
>      <example>
> +      <title>Enumerating all user controls (alternative)</title>
> +     <programlisting>
> +memset(&amp;queryctrl, 0, sizeof(queryctrl));
> +
> +queryctrl.id = V4L2_CTRL_CLASS_USER | V4L2_CTRL_FLAG_NEXT_CTRL;
> +while (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
> +     if (V4L2_CTRL_ID2CLASS(queryctrl.id) != V4L2_CTRL_CLASS_USER)
> +             break;
> +     if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
> +             continue;
> +
> +     printf("Control %s\n", queryctrl.name);
> +
> +     if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
> +             enumerate_menu();
> +
> +     queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
> +}
> +if (errno != EINVAL) {
> +     perror("VIDIOC_QUERYCTRL");
> +     exit(EXIT_FAILURE);
> +}
> +</programlisting>
> +    </example>
> +
> +    <example>
>        <title>Changing controls</title>
>  
>        <programlisting>
>  &v4l2-queryctrl; queryctrl;
>  &v4l2-control; control;
>  
> -memset (&amp;queryctrl, 0, sizeof (queryctrl));
> +memset(&amp;queryctrl, 0, sizeof(queryctrl));
>  queryctrl.id = V4L2_CID_BRIGHTNESS;
>  
> -if (-1 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
> +if (-1 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
>       if (errno != EINVAL) {
> -             perror ("VIDIOC_QUERYCTRL");
> -             exit (EXIT_FAILURE);
> +             perror("VIDIOC_QUERYCTRL");
> +             exit(EXIT_FAILURE);
>       } else {
> -             printf ("V4L2_CID_BRIGHTNESS is not supported\n");
> +             printf("V4L2_CID_BRIGHTNESS is not supported\n");
>       }
>  } else if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED) {
> -     printf ("V4L2_CID_BRIGHTNESS is not supported\n");
> +     printf("V4L2_CID_BRIGHTNESS is not supported\n");
>  } else {
> -     memset (&amp;control, 0, sizeof (control));
> +     memset(&amp;control, 0, sizeof (control));
>       control.id = V4L2_CID_BRIGHTNESS;
>       control.value = queryctrl.default_value;
>  
> -     if (-1 == ioctl (fd, &VIDIOC-S-CTRL;, &amp;control)) {
> -             perror ("VIDIOC_S_CTRL");
> -             exit (EXIT_FAILURE);
> +     if (-1 == ioctl(fd, &VIDIOC-S-CTRL;, &amp;control)) {
> +             perror("VIDIOC_S_CTRL");
> +             exit(EXIT_FAILURE);
>       }
>  }
>  
> -memset (&amp;control, 0, sizeof (control));
> +memset(&amp;control, 0, sizeof(control));
>  control.id = V4L2_CID_CONTRAST;
>  
> -if (0 == ioctl (fd, &VIDIOC-G-CTRL;, &amp;control)) {
> +if (0 == ioctl(fd, &VIDIOC-G-CTRL;, &amp;control)) {
>       control.value += 1;
>  
>       /* The driver may clamp the value or return ERANGE, ignored here */
>  
> -     if (-1 == ioctl (fd, &VIDIOC-S-CTRL;, &amp;control)
> +     if (-1 == ioctl(fd, &VIDIOC-S-CTRL;, &amp;control)
>           &amp;&amp; errno != ERANGE) {
> -             perror ("VIDIOC_S_CTRL");
> -             exit (EXIT_FAILURE);
> +             perror("VIDIOC_S_CTRL");
> +             exit(EXIT_FAILURE);
>       }
>  /* Ignore if V4L2_CID_CONTRAST is unsupported */
>  } else if (errno != EINVAL) {
> -     perror ("VIDIOC_G_CTRL");
> -     exit (EXIT_FAILURE);
> +     perror("VIDIOC_G_CTRL");
> +     exit(EXIT_FAILURE);
>  }
>  
>  control.id = V4L2_CID_AUDIO_MUTE;
> -control.value = TRUE; /* silence */
> +control.value = 1; /* silence */
>  
>  /* Errors ignored */
> -ioctl (fd, VIDIOC_S_CTRL, &amp;control);
> +ioctl(fd, VIDIOC_S_CTRL, &amp;control);
>  </programlisting>
>      </example>
>    </section>
> @@ -625,16 +660,32 @@ supported.</para>
>  &v4l2-control;, except for the fact that it also allows for 64-bit
>  values and pointers to be passed.</para>
>  
> +      <para>Since the &v4l2-ext-control; supports pointers it is now
> +also possible to have controls with complex types such as arrays/matrices
> +and/or structures. All such complex controls will have the
> +<constant>V4L2_CTRL_FLAG_HIDDEN</constant> set since such controls cannot
> +be displayed in control panel applications. Nor can they be used in the
> +user class (for backwards compatibility reasons), and you need to specify
> +the <constant>V4L2_CTRL_FLAG_NEXT_HIDDEN</constant> when enumerating controls
> +to actually be able to see such hidden controls. In other words, these
> +controls with complex types should only be used programmatically.</para>
> +
> +      <para>Since such complex controls need to expose more information
> +about themselves than is possible with &VIDIOC-QUERYCTRL; the
> +&VIDIOC-QUERY-EXT-CTRL; ioctl was added. In particular, this ioctl gives
> +the size of the matrix if this control consists of more than
> +one element.</para>
> +
>        <para>It is important to realize that due to the flexibility of
>  controls it is necessary to check whether the control you want to set
>  actually is supported in the driver and what the valid range of values
> -is. So use the &VIDIOC-QUERYCTRL; and &VIDIOC-QUERYMENU; ioctls to
> -check this. Also note that it is possible that some of the menu
> -indices in a control of type <constant>V4L2_CTRL_TYPE_MENU</constant>
> -may not be supported (<constant>VIDIOC_QUERYMENU</constant> will
> -return an error). A good example is the list of supported MPEG audio
> -bitrates. Some drivers only support one or two bitrates, others
> -support a wider range.</para>
> +is. So use the &VIDIOC-QUERYCTRL; (or &VIDIOC-QUERY-EXT-CTRL;) and
> +&VIDIOC-QUERYMENU; ioctls to check this. Also note that it is possible
> +that some of the menu indices in a control of type
> +<constant>V4L2_CTRL_TYPE_MENU</constant> may not be supported
> +(<constant>VIDIOC_QUERYMENU</constant> will return an error). A good
> +example is the list of supported MPEG audio bitrates. Some drivers only
> +support one or two bitrates, others support a wider range.</para>
>  
>        <para>
>       All controls use machine endianness.
> @@ -675,12 +726,12 @@ control class is found:</para>
>        <informalexample>
>       <programlisting>
>  qctrl.id = V4L2_CTRL_CLASS_MPEG | V4L2_CTRL_FLAG_NEXT_CTRL;
> -while (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;qctrl)) {
> -     if (V4L2_CTRL_ID2CLASS (qctrl.id) != V4L2_CTRL_CLASS_MPEG)
> +while (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;qctrl)) {
> +     if (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_MPEG)
>               break;
>               /* ... */
> -             qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
> -     }
> +     qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
> +}
>  </programlisting>
>        </informalexample>
>  
> @@ -700,7 +751,7 @@ ID based on a control ID.</para>
>  <constant>VIDIOC_QUERYCTRL</constant> will fail when used in
>  combination with <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>. In
>  that case the old method of enumerating control should be used (see
> -1.8). But if it is supported, then it is guaranteed to enumerate over
> +<xref linkend="enum_all_controls" />). But if it is supported, then it is 
> guaranteed to enumerate over
>  all controls, including driver-private controls.</para>
>      </section>

It would have been easier to review if the whitespace changes were in
a separate patch.

Reviewed-by: Sylwester Nawrocki <s.nawro...@samsung.com>


I guess we want a note somewhere the V4L2_CTRL_FLAG_DISABLED flag
is deprecated ? It seems to be used in very few drivers.

--
Regards,
Sylwester
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to