Linux v4l2架构学习总链接
应用测试代码如下:
vivi驱动分析如下:
step 2 : 查询设备功能
struct v4l2_capability cap;
ioctl(fd, VIDIOC_QUERYCAP, &cap)
video注册的时候fops是v4l2_fops,所以会调用到v4l2_fops.unlocked_ioctl 也就是 v4l2_ioctl
v4l2_ioctl中 调用到 vdev->fops->unlocked_ioctl,vdev->fops对于vivi驱动的vivi_fops,所以unlocked_ioctl就是video_ioctl2
其中VIDIOC_QUERYCAP对应 v4l_querycap
static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct v4l2_capability *cap = (struct v4l2_capability *)arg;
struct video_device *vfd = video_devdata(file);
int ret;
cap->version = LINUX_VERSION_CODE;
cap->device_caps = vfd->device_caps;
cap->capabilities = vfd->device_caps | V4L2_CAP_DEVICE_CAPS;
/*
* 对应vivi驱动的 vidioc_querycap
*/
ret = ops->vidioc_querycap(file, fh, cap);
cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT;
/*
* Drivers MUST fill in device_caps, so check for this and
* warn if it was forgotten.
*/
WARN(!(cap->capabilities & V4L2_CAP_DEVICE_CAPS) ||
!cap->device_caps, "Bad caps for driver %s, %x %x",
cap->driver, cap->capabilities, cap->device_caps);
cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT;
return ret;
}
vivi驱动vidioc_querycap源码如下
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
struct vivi_dev *dev = video_drvdata(file);
strcpy(cap->driver, "vivi");
strcpy(cap->card, "vivi");
/*
* 这里加深一下理解
* dev->v4l2_dev.name 是什么?
* vivi驱动中有这样一句代码
* snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
"%s-%03d", VIVI_MODULE_NAME, inst);
* "vivi-000" "vivi-001" 这种名字
*/
strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
cap->version = VIVI_VERSION;
/*
* 驱动表示支持capture,streaming及read write
*/
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \
V4L2_CAP_READWRITE;
return 0;
}
VIDIOC_QUERYCAP的过程比较简单
这里要注意,linux4.9.11中 struct v4l2_capability 中不仅仅有capabilities还新增了 device_caps。
物理设备 整体功能
* @capabilities: capabilities of the physical device as a whole
通过此特定设备(节点)访问的功能
* @device_caps: capabilities accessed via this particular device (node)
通俗的解释是:比如有个设备支持audio和capture,但是硬件上音频相关的线路没有连接,从当前的驱动上只支持capture,而无法支持audio。
这里我也写了一个测试程序v4l2_test测试vivi注册的video节点
int main(int argc, char **argv)
{
int fd;
struct v4l2_capability cap;
if (argc != 2) {
printf("Usage: v4l2_test <device>\n");
printf("example: v4l2_test /dev/video0\n");
return -1;
}
fd = open(argv[1], O_RDWR);
if (fd < 0) {
printf("open video device fail\n");
return -1;
}
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {
printf("Get video capability error!\n");
return -1;
}
if (!(cap.device_caps & V4L2_CAP_VIDEO_CAPTURE)) {
printf("Video device not support capture!\n");
close(fd);
return -1;
}
printf("Support capture!\n");
close(fd);
return 0;
}
通常在v4l2应用开发中,VIDIOC_QUERYCAP主要目的就是判断当前设备是否支持我们想要的功能,仅此而已。
代码放在了码云上