Overview of the V4L2 driver framework(二)

来源:互联网 发布:windows文件夹清理 编辑:程序博客网 时间:2024/04/19 23:46

 

struct v4l2_device

------------------

 

Each device instanceis represented by a struct v4l2_device (v4l2-device.h). Very simple devices canjust allocate this struct, but most of the time you would embed this structinside a larger struct.

 

You must registerthe device instance:

每个设备实例由structv4l2_devicev4l2-device.h)表示。非常简单的设备可以只分配这个结构,但大多数时候你会把这个结构体嵌入一个更大的结构体。

 

您必须注册设备实例:

 

v4l2_device_register(structdevice *dev, struct v4l2_device *v4l2_dev);

 

Registration willinitialize the v4l2_device struct. If the dev->driver_data field is NULL, itwill be linked to v4l2_dev.

 

Drivers that wantintegration with the media device framework need to set dev->driver_datamanually to point to the driver-specific device structure that embed the structv4l2_device instance. This is achieved by a dev_set_drvdata() call beforeregistering the V4L2 device instance. They must also set the struct v4l2_devicemdev field to point to a properly initialized and registered media_deviceinstance.

 

If v4l2_dev->nameis empty then it will be set to a value derived from dev (driver name followedby the bus_id, to be precise). If you set it up before callingv4l2_device_register then it will be untouched. If dev is NULL, then you *must*setup v4l2_dev->name before calling v4l2_device_register.

 

You can usev4l2_device_set_name() to set the name based on a driver name and adriver-global atomic_t instance. This will generate names like ivtv0, ivtv1,etc. If the name ends with a digit, then it will insert a dash: cx18-0, cx18-1,etc. This function returns the instance number.

 

The first 'dev'argument is normally the struct device pointer of a pci_dev, usb_interface orplatform_device. It is rare for dev to be NULL, but it happens with ISA devicesor when one device creates multiple PCI devices, thus making it impossible toassociate v4l2_dev with a particular parent.

 

You can also supplya notify() callback that can be called by sub-devices to notify you of events.Whether you need to set this depends on the sub-device. Any notifications asub-device supports must be defined in a header in include/media/<subdevice>.h.

注册将初始化v4l2_device结构。如果dev-> driver_data字段为NULL,它将链接到v4l2_dev

 

需要与媒体设备框架集成的驱动程序需要手动设置dev-> driver_data,以指向嵌入structv4l2_device实例的驱动程序特定的设备结构。这是通过在注册V4L2设备实例之前调用dev_set_drvdata()实现的。它们还必须将struct v4l2_device mdev字段设置为指向正确初始化和注册的media_device实例。

 

如果v4l2_dev->name为空,那么它将被设置为从dev(驱动程序名称,后跟bus_id,精确地)派生的值。如果你在调用v4l2_device_register之前设置它,它将是不变的。如果devNULL,那么你必须在调用v4l2_device_register之前设置v4l2_dev->name

 

您可以使用v4l2_device_set_name()根据驱动程序名称和驱动程序全局atomic_t实例设置名称。这将生成名称,如ivtv0ivtv1等。如果名称以一个数字结尾,则它将插入一个破折号:cx18-0cx18-1等。此函数返回实例号。

 

第一个“dev”参数通常是pci_devusb_interfaceplatform_devicestruct设备指针。 dev很少为NULL,但它发生在ISA设备或一个设备创建多个PCI设备时,因此不可能将v4l2_dev与特定的父进程关联。

 

您还可以提供一个notify()回调,可以由子设备调用以通知您事件。是否需要设置这取决于子设备。子设备支持的任何通知必须在include / media / <subdevice> .h中的标题中定义。

 

 

You unregister with:

您注销:

 

v4l2_device_unregister(structv4l2_device *v4l2_dev);

 

If thedev->driver_data field points to v4l2_dev, it will be reset to NULL.Unregistering will also automatically unregister all subdevs from the device.

If you have ahotpluggable device (e.g. a USB device), then when a disconnect happens theparent device becomes invalid. Since v4l2_device has a pointer to that parentdevice it has to be cleared as well to mark that the parent is gone. To do thiscall:

 

如果dev->driver_data字段指向v4l2_dev,它将被重置为NULL注销动作也会自动从设备中注销所有子设备。

如果您有热插拔设备(例如USB设备),则当发生断开连接时,父设备将无效。因为v4l2_device有一个指向该父设备的指针,它必须被清除以标记父设备已经走了。要执行此调用:

 

v4l2_device_disconnect(structv4l2_device *v4l2_dev);

 

This does *not*unregister the subdevs, so you still need to call the v4l2_device_unregister()function for that. If your driver is not hotpluggable, then there is no need tocall v4l2_device_disconnect().

 

Sometimes you needto iterate over all devices registered by a specific driver. This is usuallythe case if multiple device drivers use the same hardware. E.g. the ivtvfbdriver is a framebuffer driver that uses the ivtv hardware. The same is truefor alsa drivers for example.

 

You can iterate overall registered devices as follows:

 

**注销子变量,所以你仍然需要调用v4l2_device_unregister()函数。如果您的驱动程序不可热插拔,则无需调用v4l2_device_disconnect()。

 

有时,您需要遍历由特定驱动程序注册的所有设备。如果多个设备驱动程序使用相同的硬件,通常是这种情况。例如。 ivtvfb驱动程序是使用ivtv硬件的framebuffer驱动程序。例如,alsa驱动程序也是如此。

 

您可以遍历所有注册的设备,如下所示:

 

static intcallback(struct device *dev, void *p)

{

structv4l2_device *v4l2_dev = dev_get_drvdata(dev);

 

/*test if this device was inited */

if(v4l2_dev == NULL)

return0;

...

return0;

}

 

int iterate(void *p)

{

structdevice_driver *drv;

interr;

 

/*Find driver 'ivtv' on the PCI bus.

   pci_bus_type is a global. For USB busses useusb_bus_type. */

drv= driver_find("ivtv", &pci_bus_type);

/*iterate over all ivtv device instances */

err= driver_for_each_device(drv, NULL, p, callback);

put_driver(drv);

returnerr;

}

 

Sometimes you needto keep a running counter of the device instance. This is commonly used to mapa device instance to an index of a module option array.

 

The recommendedapproach is as follows:

有时您需要保留设备实例的运行计数器。这通常用于将设备实例映射到模块选项数组的索引。

 

推荐方法如下:

 

static atomic_tdrv_instance = ATOMIC_INIT(0);

 

static intdrv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)

{

...

state->instance= atomic_inc_return(&drv_instance) - 1;

}

 

If you have multipledevice nodes then it can be difficult to know when it is safe to unregisterv4l2_device for hotpluggable devices. For this purpose v4l2_device hasrefcounting support. The refcount is increased whenever video_register_deviceis called and it is decreased whenever that device node is released. When therefcount reaches zero, then the v4l2_device release() callback is called. Youcan do your final cleanup there.

 

If other devicenodes (e.g. ALSA) are created, then you can increase and decrease the refcountmanually as well by calling:

如果您有多个设备节点,那么可能很难知道何时安全地注销可热插拔设备的v4l2_device。 为此,v4l2_device具有引用计数支持。 每当调用video_register_device时,引用计数都会增加,并且只要设备节点被释放,引用计数就会减少。当引用计数达到零时,则调用v4l2_devicerelease()回调。 你可以在那里做最后的清理。

 

如果创建了其他设备节点(例如ALSA),则可以通过调用以手动方式增加和减少引用计数:

 

 

voidv4l2_device_get(struct v4l2_device *v4l2_dev);

 

or:

 

intv4l2_device_put(struct v4l2_device *v4l2_dev);

 

Since the initialrefcount is 1 you also need to call v4l2_device_put in the disconnect()callback (for USB devices) or in the remove() callback (for e.g. PCI devices),otherwise the refcount will never reach 0.

由于初始引用计数为1,还需要在disconnect()回调(对于USB设备)或remove()回调(例如PCI设备)中调用v4l2_device_put,否则引用计数永远不会达到0

1 0