Video4Linux框架简介(2) - v4l2_device

V4L2 PCI基础驱动程序实例


struct v4l2_device (1)

(译注: 第一步,先基于你的桥接驱动(譬如这里就是PCI设备),添加一个v4l2设备对象,通常v4l2设备都不是独立存在的。)

#include      // 每个V4L2驱动都需要添加这两个头文件
#include 
MODULE_DESCRIPTION("V4L2 PCI Skeleton Driver");
MODULE_AUTHOR("Hans Verkuil");
MODULE_LICENSE("GPL v2");
MODULE_DEVICE_TABLE(pci, skeleton_pci_tbl);
struct skeleton {
struct pci_dev *pdev;
struct v4l2_device v4l2_dev;    //v4l2设备对象,实际上,它不像是一个设备,
                                 //而是一系列v4l2设备以及控制的顶层结构,这一点在后续
                                 //提到框架时会再说明
};
static const struct pci_device_id skeleton_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR) },
{ 0, }
};
    // 待添加
   // 待添加

static struct pci_driver skeleton_driver = {
.name = KBUILD_MODNAME,
.probe = skeleton_probe,
.remove = skeleton_remove,
.id_table = skeleton_pci_tbl,
};
module_pci_driver(skeleton_driver); 


struct v4l2_device (2)

(译注: 第二步,添加注册和注销函数)


static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct skeleton *skel;
int ret;
pci_enable_device(pdev);
pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
skel = devm_kzalloc(&pdev->dev, sizeof(struct skeleton), GFP_KERNEL);
if (!skel)
return -ENOMEM;
skel->pdev = pdev;
ret = v4l2_device_register(&pdev->dev, &skel->v4l2_dev); //诸如设置名字,锁等资源的初始化
if (ret)
goto disable_pci;
dev_info(&pdev->dev, "V4L2 PCI Skeleton Driver loaded\n");
return 0;
disable_pci:
pci_disable_device(pdev);
return ret;
}
static void skeleton_remove(struct pci_dev *pdev)
{
struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev);
struct skeleton *skel = container_of(v4l2_dev, struct skeleton, v4l2_dev);
v4l2_device_unregister(&skel->v4l2_dev);  //与register相对应,注销所用到的资源
pci_disable_device(skel->pdev);
}


总结一下 struct v4l2_device:


●首先,它是V4L2驱动的顶级结构。
●Misnomer:更好的名称应该是v4l2_root(译注:关于这一点 Verkuil本人和内核社区提交过修改,不过由于涉及的修改实在太多,被reject了)。
●v4l2_device_(un)register应已调用v4l2_root_init / exit。
●维护子设备(v4l2_subdev)列表。
●具有对子设备的notify()回调。
●当最后一个设备引用释放时调用release()回调。



你可能感兴趣的:(Open,Source,Linux,Kernel,V4L2,Camera)