Linux V4L2子系统——v4l2_device

内核版本4.1.15

Linux V4L2子系统——v4l2_device

简介

V4L2主设备实例使用struct v4l2_device结构体表示,v4l2_device是V4L2子系统的入口,管理着V4L2子系统的主设备和从设备。简单设备可以仅分配这个结构体,但在大多数情况下,都会将这个结构体嵌入到一个更大的结构体中。

注册函数

int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)

v4l2的设备注册其实没有注册设备或者设备驱动,只是将v4l2的大结构体与其他设备进行捆绑,并保存v4l2设备对象到当前设备的driverdata中。此函数的作用就是将当前设备驱动和v4l2对象进行捆绑,便于挂接子设备。

函数内容

int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
{
	if (v4l2_dev == NULL)
		return -EINVAL;

	INIT_LIST_HEAD(&v4l2_dev->subdevs);//初始化subdev链表
	spin_lock_init(&v4l2_dev->lock);
	mutex_init(&v4l2_dev->ioctl_lock);
	v4l2_prio_init(&v4l2_dev->prio);
	kref_init(&v4l2_dev->ref);//初始化引用计数
	get_device(dev);
	v4l2_dev->dev = dev;//将当前设备的对象,赋值给v4l2_dev->dev中
	if (dev == NULL) {
		/* If dev == NULL, then name must be filled in by the caller */
		if (WARN_ON(!v4l2_dev->name[0]))
			return -EINVAL;
		return 0;
	}

	/* Set name to driver name + device name if it is empty. */
	if (!v4l2_dev->name[0])//如果v4l2设备的名字为空,则会将当前设备的名字拷贝为v4l2设备中
		snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",
			dev->driver->name, dev_name(dev));
	if (!dev_get_drvdata(dev))
		dev_set_drvdata(dev, v4l2_dev);
	return 0;
}
EXPORT_SYMBOL_GPL(v4l2_device_register);

注销函数

void v4l2_device_unregister(struct v4l2_device *v4l2_dev)

使用v4l2_device_unregister卸载v4l2_device结构体。如果dev->driver_data域指向 v4l2_dev,将会被重置为NULL。主设备注销的同时也会自动注销所有子设备。

void v4l2_device_unregister(struct v4l2_device *v4l2_dev)
{
	struct v4l2_subdev *sd, *next;

	/* Just return if v4l2_dev is NULL or if it was already
	 * unregistered before. */
	if (v4l2_dev == NULL || !v4l2_dev->name[0])
		return;
	v4l2_device_disconnect(v4l2_dev);

	/* Unregister subdevs */
	list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) {
		v4l2_device_unregister_subdev(sd);//注销subdev
#if IS_ENABLED(CONFIG_I2C)
		if (sd->flags & V4L2_SUBDEV_FL_IS_I2C) {
			struct i2c_client *client = v4l2_get_subdevdata(sd);

			/* We need to unregister the i2c client explicitly.
			   We cannot rely on i2c_del_adapter to always
			   unregister clients for us, since if the i2c bus
			   is a platform bus, then it is never deleted. */
			if (client)
				i2c_unregister_device(client);//如果是iic设备也进行注销
			continue;
		}
#endif
#if defined(CONFIG_SPI)
		if (sd->flags & V4L2_SUBDEV_FL_IS_SPI) {
			struct spi_device *spi = v4l2_get_subdevdata(sd);

			if (spi)
				spi_unregister_device(spi);
			continue;
		}
#endif
	}
	/* Mark as unregistered, thus preventing duplicate unregistrations */
	v4l2_dev->name[0] = '\0';
}
EXPORT_SYMBOL_GPL(v4l2_device_unregister);

v4l2_device_disconnect 并不注销主设备,只是将引用计数减下。

void v4l2_device_disconnect(struct v4l2_device *v4l2_dev)
{
	if (v4l2_dev->dev == NULL)
		return;

	if (dev_get_drvdata(v4l2_dev->dev) == v4l2_dev)
		dev_set_drvdata(v4l2_dev->dev, NULL);
	put_device(v4l2_dev->dev);
	v4l2_dev->dev = NULL;
}
EXPORT_SYMBOL_GPL(v4l2_device_disconnect);

参考资料

linux V4L2子系统——v4l2架构(2)之v4l2_device

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值