Chinaunix首页 | 论坛 | 博客
  • 博客访问: 311317
  • 博文数量: 101
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 774
  • 用 户 组: 普通用户
  • 注册时间: 2018-10-15 14:13
个人简介

搭建一个和linux开发者知识共享和学习的平台

文章分类

全部博文(101)

文章存档

2024年(15)

2023年(24)

2022年(27)

2019年(8)

2018年(27)

分类: 嵌入式

2024-10-17 10:30:36

V4L2 异步注册

    在异步模式下,子设备探测可以独立于桥接驱动程序的可用性进行。然后,子设备驱动程序必须验证是否满足了成功探测的所有要求。这可能包括检查主时钟的可用性、GPIO 或其他任何内容。如果任何条件不满足,子设备驱动程序可能决定返回-EPROBE_DEFER以请求进一步的重新探测尝试。一旦满足所有条件,子设备将使用v4l2_async_register_subdev()函数在 V4L2 异步核心中注册。取消注册使用v4l2_async_unregister_subdev()调用执行。

    在异步框架中,子设备被称为struct v4l2_async_subdev结构的一个实例。除了这个结构,还有另一个struct v4l2_async_notifier结构。两者都在include/media/v4l2-async.h中定义,并且在 V4L2 异步核心的中心部分。
struct v4l2_async_notifier {
    const struct v4l2_async_notifier_operations *ops;
    unsigned int num_subdevs;
    unsigned int max_subdevs;
    struct v4l2_async_subdev **subdevs;
    struct v4l2_device *v4l2_dev;
    struct v4l2_subdev *sd;
    struct v4l2_async_notifier *parent;
    struct list_head waiting;
    struct list_head done;
    struct list_head list;
};
ops是由此通知器的所有者提供的一组回调,由异步核心在等待在此通知器中的子设备被探测时调用。

v4l2_dev是注册此通知器的桥接驱动程序的 V4L2 父级。

sd,如果此通知器是由子设备注册的,将指向此子设备。我们在这里不讨论这种情况。

subdevs是应该通知此通知器的注册者(桥接驱动程序或另一个子设备驱动程序)的子设备数组。

waiting是此通知器中等待被探测的子设备的列表。

done是实际绑定到此通知器的子设备的列表。

num_subdevs是**subdevs中子设备的数量。

list在注册此通知器时由异步核心使用,以将此通知器链接到通知器的全局列表notifier_list。

子设备注册不再依赖于桥接可用性,只需调用v4l2_async_register_subdev()方法即可。但是,在注册自身之前,桥接驱动程序将不得不执行以下操作:

为以后使用分配一个通知程序。{BANNED}最佳好将此通知程序嵌入较大的设备状态数据结构中。此通知程序对象是struct v4l2_async_notifier类型。

解析其端口节点并为其中指定的每个传感器(或 IP 块)创建一个异步子设备(struct v4l2_async_subdev),并且它需要进行操作:

当桥接驱动程序调用v4l2_async_notifier_register()时,异步核心会迭代notifier->subdevs数组中的异步子设备。对于每个异步子设备,核心会检查asd->match_type值是否为V4L2_ASYNC_MATCH_FWNODE。如果适用,异步核心会通过比较 fwnodes 来确保asd不在notifier->waiting列表或notifier->done列表中。这可以确保asd尚未为fwnode设置,并且它尚不存在于给定的通知器中。如果asd尚未知晓,则将其添加到notifier->waiting中。之后,异步核心将测试notifier->waiting列表中的所有异步子设备,以与subdev_list中存在的所有子设备进行匹配。subdev_list是“类似”孤立子设备的列表,这些子设备是在其桥接驱动程序(因此在其通知器)之前注册的。异步核心使用每个当前asd的asd->match值进行匹配。如果匹配发生(asd->match回调返回 true),则当前异步子设备(来自notifier->waiting)和当前子设备(来自subdev_list)将被绑定,异步子设备将从notifier->waiting列表中移除,子设备将使用v4l2_device_register_subdev()注册到 V4L2 核心,并且子设备将从全局subdev_list列表移动到notifier->done列表中。

{BANNED}最佳后,被注册的实际通知器将被添加到全局通知器列表notifier_list中,以便在以后使用时,可以在异步核心中注册新的子设备时进行匹配尝试。

当子设备驱动程序调用v4l2_async_register_subdev()时,异步核心会尝试将当前子设备notifier_list全局列表中存在的每个通知器中等待的所有异步子设备进行匹配。如果没有匹配发生,这意味着尚未探测到此子设备的桥接,子设备将被添加到全局子设备列表subdev_list中。如果发生匹配,子设备将根本不会添加到此列表中。

还要记住,匹配测试是在struct v4l2_subdev类型的子设备和struct v4l2_async_subdev类型的异步子设备之间严格发生的一些标准的比较。

struct v4l2_async_notifier_operations {
    int (*bound)(struct v4l2_async_notifier *notifier,
                  struct v4l2_subdev *subdev,
                  struct v4l2_async_subdev *asd);
    int (*complete)(struct v4l2_async_notifier *notifier);
    void (*unbind)(struct v4l2_async_notifier *notifier,
                    struct v4l2_subdev *subdev,
                    struct v4l2_async_subdev *asd);
};

bound:如果设置,异步核心将在成功的子设备探测后由其(子设备)驱动程序调用此回调。这也意味着异步子设备已成功匹配此子设备。此回调将以发起匹配的通知器以及匹配的子设备(subdev)和异步子设备(asd)作为参数。大多数驱动程序在这里只是打印调试消息。但是,您可以在这里对子设备进行额外的设置-即v4l2_subdev_call()。如果一切正常,它应该返回一个正值;否则,子设备将被注销。

unbind在从系统中移除子设备时被调用。除了在这里打印调试消息外,桥接驱动程序还必须取消注册视频设备,如果未绑定的子设备对其正常工作是必需的-即video_unregister_device()。

complete在通知器中没有更多的异步子设备等待时被调用。异步核心可以检测到notifier->waiting列表为空(这意味着子设备已经成功探测并全部移动到notifier->done列表中)。完成回调仅对根通知器执行。注册了通知器的子设备不会调用其.complete回调。根通知器通常是由桥接设备注册的。

通常在notifier.complete回调中注册实际的视频设备,因为所有子设备都将被注册,且/dev/videoX的存在意味着它确实可用。.complete回调也适用于注册实际视频设备的子节点,并通过v4l2_device_register_subdev_nodes()和media_device_register()注册媒体设备。

请注意,v4l2_device_register_subdev_nodes()将为每个标有V4L2_SUBDEV_FL_HAS_DEVNODE标志的subdev对象创建一个设备节点(实际上是/dev/v4l2-subdevX)。


阅读(53) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~