V4L2 document translation

Posted by Jason28 on Sat, 05 Mar 2022 04:01:38 +0100

User control

Devices usually have some user settable controllers, such as brightness and saturation, which will be displayed in the graphical user interface. However, different devices have different available settings, and in addition, their settable value range and default values are different on different devices. Control ioctl provides the information and mechanism to create a good user interface, which will make these controllers work correctly on any device.

All controllers need to be accessed through the ID value. V4L2 defines some IDs for special purposes. The driver can also use V4L2CID_PRIVATE_BASE and greater declare their custom controllers. Predefined ID with prefix V4L2_CID, in Table 1.1 Listed in control IDS http://linuxtv.org/downloads/v4l-dvb-apis/control.html#control-id
These ID s are used to query the properties of a controller and obtain or set the current setting value.

Generally, applications should clearly propose some controllers about their goals. The name of each controller should be easy to understand. If the target is difficult to understand, the driver developer should provide user documents, which can be used by users to get involved in the driver or develop disk control program. The predefined ID should introduce a bit of control programming, such as silencing the device during channel switching.

After switching video input and output, modulator and tuner and sound input and output, the driver may list some different controls. There are different default values, current values, step values and menu items in different scenes. Controls with custom ID S can change their names and types. The control value is saved globally and will not change due to switching, even when the device is turned on or off, such as when the frequency of a tuning radio changes and is no longer requested by external applications. Because V4L2 has no event mechanism, if a panel program wants to cooperate with other panel programs, it needs to regularly obtain control values to update the user interface.

Attached: color temperature meter (from http://en.wikipedia.org/wiki/Color_temperature)

temperaturelight source
1700Kmatch
1850KCandlelight, sunrise, sunset
2700-3300KIncandescent lamp
3000KSoft (warm) light, fluorescent lamp
3200KStudio Lighting
3350KStudio Lighting
4100-4150Kmoonlight
5000KHorizontal daylight, tube lamp, cold light lamp
5500-6000KVertical daylight, electronic flash
6200KXenon flash lamp
6500Kovercast
6500-10500KLCD CRT screen
15000-27000Pure Blue Aurora

Applications can be accessed via VIDIOC_QUERYCTRL and VIDIOC_QUERYMENU ioctl to list effective controls through VIDIOC_G_CTRL and VIDIOC_S_CTRL to get and set control values. When the device has one or more settings, the driver must declare VIDIOC_QUERYCTRL,VIDIOC_G_CTRL,VIDIOC_S_CTRL. When there is one or more menu type control, its corresponding drive must also be declared VIDIOC_QUERYMENU.

Example 1.8 list all controls

struct v4l2_queryctrl queryctrl;
struct v4l2_querymenu querymenu;
 
static void
enumerate_menu (void)
{
    printf ("  Menu items:\n");
 
    memset (&querymenu, 0, sizeof (querymenu));
    querymenu.id = queryctrl.id;
 
    for (querymenu.index = queryctrl.minimum;
         querymenu.index <= queryctrl.maximum;
          querymenu.index++) {
        if (0 == ioctl (fd, VIDIOC_QUERYMENU, &querymenu)) {
            printf ("  %s\n", querymenu.name);
        }
    }
}
 
memset (&queryctrl, 0, sizeof (queryctrl));
 
for (queryctrl.id = V4L2_CID_BASE;
     queryctrl.id < V4L2_CID_LASTP1;
     queryctrl.id++) {
    if (0 == ioctl (fd, VIDIOC_QUERYCTRL, &queryctrl)) {
        if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
            continue;
 
        printf ("Control %s\n", queryctrl.name);
 
        if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
            enumerate_menu ();
    } else {
        if (errno == EINVAL)
            continue;
 
        perror ("VIDIOC_QUERYCTRL");
        exit (EXIT_FAILURE);
    }
}
 
for (queryctrl.id = V4L2_CID_PRIVATE_BASE;;
     queryctrl.id++) {
    if (0 == ioctl (fd, VIDIOC_QUERYCTRL, &queryctrl)) {
        if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED)
            continue;
 
        printf ("Control %s\n", queryctrl.name);
 
        if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
            enumerate_menu ();
    } else {
        if (errno == EINVAL)
            break;
 
        perror ("VIDIOC_QUERYCTRL");
        exit (EXIT_FAILURE);
    }
}

Example 1.9 change control

struct v4l2_queryctrl queryctrl;
struct v4l2_control control;
 
memset (&queryctrl, 0, sizeof (queryctrl));
queryctrl.id = V4L2_CID_BRIGHTNESS;
 
if (-1 == ioctl (fd, VIDIOC_QUERYCTRL, &queryctrl)) {
    if (errno != EINVAL) {
        perror ("VIDIOC_QUERYCTRL");
        exit (EXIT_FAILURE);
    } else {
        printf ("V4L2_CID_BRIGHTNESS is not supported\n");
    }
} else if (queryctrl.flags & V4L2_CTRL_FLAG_DISABLED) {
    printf ("V4L2_CID_BRIGHTNESS is not supported\n");
} else {
    memset (&control, 0, sizeof (control));
    control.id = V4L2_CID_BRIGHTNESS;
    control.value = queryctrl.default_value;
 
    if (-1 == ioctl (fd, VIDIOC_S_CTRL, &control)) {
        perror ("VIDIOC_S_CTRL");
        exit (EXIT_FAILURE);
    }
}
 
memset (&control, 0, sizeof (control));
control.id = V4L2_CID_CONTRAST;
 
if (0 == ioctl (fd, VIDIOC_G_CTRL, &control)) {
    control.value += 1;
 
    /* The driver may clamp the value or return ERANGE, ignored here */
 
    if (-1 == ioctl (fd, VIDIOC_S_CTRL, &control)
        && errno != ERANGE) {
        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);
}
 
control.id = V4L2_CID_AUDIO_MUTE;
control.value = TRUE; /* silence */
 
/* Errors ignored */
ioctl (fd, VIDIOC_S_CTRL, &control);

Topics: C++