参考韦东山老师视频:
vivi_init
vivi_create_instance(i);
{
struct vivi_dev *dev;
struct video_device *vfd;
struct v4l2_ctrl_handler *hdl;
// 不是主要, 只是用于初始化一些东西,比如自旋锁、引用计数
v4l2_device_register(NULL, &dev->v4l2_dev);
vfd = video_device_alloc();
*vfd = vivi_template; //设置
1. vfd:
.fops = &vivi_fops,
.ioctl_ops = &vivi_ioctl_ops,
.release = video_device_release,
vfd->v4l2_dev = &dev->v4l2_dev;
//设置"ctrl属性"(用于APP的ioctl):
hdl = &dev->ctrl_handler;
v4l2_ctrl_handler_init(hdl, 11);
dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
V4L2_CID_CONTRAST, 0, 255, 1, 16);
video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
__video_register_device(video_device vdev, type, nr, 1, vdev->fops->owner);
vdev->cdev = cdev_alloc();
vdev->cdev->ops = &v4l2_fops;
cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR:81, vdev->minor), 1);
device_register(&vdev->dev);
video_device[vdev->minor] = vdev;
if (vdev->ctrl_handler == NULL) //设置ctrl_handler;
vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler;
分析vivi.c的open,read,write,ioctl过程
1. open
app: open("/dev/video0",....)
---------------------------------------------------
drv: v4l2_fops.v4l2_open
vdev = video_devdata(filp); // 根据次设备号从数组中得到video_device
ret = vdev->fops->open(filp);
vivi_fops.open
v4l2_fh_open
2. read
app: read ....
---------------------------------------------------
drv: v4l2_fops.v4l2_read
struct video_device *vdev = video_devdata(filp);
ret = vdev->fops->read(filp, buf, sz, off);
3. ioctl
app: ioctl
----------------------------------------------------
drv: v4l2_fops.unlocked_ioctl
v4l2_ioctl
struct video_device *vdev = video_devdata(filp);
ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
video_ioctl2 (v4l2-ioctl.c中)
video_usercopy(file, cmd, arg, __video_do_ioctl);
__video_do_ioctl(*file,cmd, *arg);
struct video_device *vfd = video_devdata(file);
根据APP传入的cmd来获得、设置"某些属性"
v4l2_ctrl_handler的使用过程:
__video_do_ioctl(*file,cmd, *arg);
struct video_device *vfd = video_devdata(file);
case VIDIOC_QUERYCTRL:
{
struct v4l2_queryctrl *p = arg;
if (vfh && vfh->ctrl_handler)
ret = v4l2_queryctrl(vfh->ctrl_handler, p);
else if (vfd->ctrl_handler) // 在哪设置?在video_register_device
ret = v4l2_queryctrl(vfd->ctrl_handler, p);
find_ref(hdl, id);// 根据ID在ctrl_handler里找到v4l2_ctrl,返回它的值