V4L2驱动程序整体框架
学习资料:
韦东山第三期
应用程序调用open/read/write会调用到v4l2_fops的相应函数:
![0](https://img2024.cnblogs.com/blog/3261801/202403/3261801-20240326185322188-218026378.png)
接口层再调用到硬件相关的代码,根据打开的文件得到一个video_device(根据此设备号),调用这个video_device里面的vdev->fops->open函数
![0](https://img2024.cnblogs.com/blog/3261801/202403/3261801-20240326185323069-94040178.png)
可以看到read和ioctl也是类似的:
![0](https://img2024.cnblogs.com/blog/3261801/202403/3261801-20240326185321713-91959812.png)
![0](https://img2024.cnblogs.com/blog/3261801/202403/3261801-20240326185322350-1619981172.png)
应用程序进入到驱动之后,v4l2_ops都是中转作用,再根据设备的此设备号找到video_device,video_device里面有v4l2_file_operations硬件相关结构体
![0](https://img2024.cnblogs.com/blog/3261801/202403/3261801-20240326185323097-503683358.png)
如何编写摄像头驱动程序:
分配/设置/注册一个video_device
从上往下分析:
1、分配一个video_device
s->dev = airspy_template; static struct video_device airspy_template = { .name = "AirSpy SDR", .release = video_device_release_empty, .fops = &airspy_fops, .ioctl_ops = &airspy_ioctl_ops, };
2、注册一个v4l2_device结构体
v4l2_device没有跟硬件相关的接口函数,其辅助作用,比如说里面有各种锁,并不是注册,称为初始化更好
s->v4l2_dev.release = airspy_video_release;
ret = v4l2_device_register(&intf->dev, &s->v4l2_dev);
3、v4l2_device和video_device建立联系,注册一个video_device
s->vdev.v4l2_dev = &s->v4l2_dev; ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1); VFL_TYPE_SDR VFL_TYPE_GRABBER vdev->cdev->ops = &v4l2_fops; // 也就是接口层,此处关联,重要*** ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1); // 次设备号注册字符设备