前面分析了handler的创建以及添加ctrl的过程,对于ctrl来说,ctrl的类型有很多,这里仅仅分析了一个而已,其他的基本也是这个套路。既然handler创建了,ctrl添加了,那么如何通过ioctl去操作呢?
这里贴一个ctrl实例
h_flip = v4l2_ctrl_new_std(handler, &xxx_ctrl_ops,
V4L2_CID_HFLIP, 0, 1, 1, 0);
通过id V4L2_CID_HFLIP可以知道,这是一个操作水平镜像的ctrl
我们可以通过v4l2-ctl查看
# v4l2-ctl -l -d /dev/v4l-subdev3
User Controls
...
horizontal_flip 0x00980914 (bool) : default=0 value=0
vertical_flip 0x00980915 (bool) : default=0 value=0
...
可以看出当前值为0
下面写个程序通过ioctl操作
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <linux/videodev2.h>
#include <sys/mman.h>
#include <errno.h>
int main(int argc, char **argv)
{
int fd;
int ret;
struct v4l2_control ctrl;
struct v4l2_queryctrl qctrl;
if (argc != 3) {
printf("Usage: v4l2_ctrl_test <device> <value>\n");
printf("example: v4l2_ctrl_test /dev/video0 1\n");
goto err1;
}
fd = open(argv[1], O_RDWR);
if (fd < 0) {
printf("open device: %s fail\n", argv[1]);
goto err1;
}
ctrl.id = V4L2_CID_HFLIP;
if (ioctl(fd, VIDIOC_G_CTRL, &ctrl) < 0) {
printf("ioctl G V4L2_CID_HFLIP error!\n");
goto err;
}
printf("value = %d\n", ctrl.value);
ctrl.value = atoi(argv[2]);
if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) < 0) {
printf("ioctl S V4L2_CID_HFLIP error!\n");
goto err;
}
err:
close(fd);
err1:
return -1;
}
首次通过VIDIOC_G_CTRL,获取ctrl到值,然后通过VIDIOC_S_CTRL设置ctrl的值
# v4l2_ctrl_test /dev/v4l-subdev3 1
value = 0
# v4l2-ctl -l -d /dev/v4l-subdev3
User Controls
...
horizontal_flip 0x00980914 (bool) : default=0 value=1
vertical_flip 0x00980915 (bool) : default=0 value=0
...
操作后可以看到值从0变成了1
对于一个ctrl,如果不知道其最大最小这些信息,可以通过下面的ioctl去获取
qctrl.id = V4L2_CID_HFLIP;
if (ioctl(fd, VIDIOC_QUERYCTRL, &qctrl) < 0) {
printf("ioctl Q V4L2_CID_HFLIP error!\n");
goto err;
}
printf("name : %s\n", qctrl.name);
printf("type : 0x%08x\n", qctrl.type);
printf("minimum : %d\n", qctrl.minimum);
printf("maximum : %d\n", qctrl.maximum);
printf("step : %d\n", qctrl.step);
printf("default_value : %d\n", qctrl.default_value);
得到如下的 打印信息:
name : Horizontal Flip
type : 0x00000002
minimum : 0
maximum : 1
step : 1
default_value : 0
对于ioctl的调用过程这里不再去跟进分析,内核对应下面的这3个函数
v4l_g_ctrl
v4l_s_ctrl
v4l_queryctrl