我对linux理解之v4l2

我们先看具体sensor slave怎么注册到v4l2的:
static struct v4l2_int_ioctl_desc ov5642_ioctl_desc[] = {//ioctl与对应的序号联系在一起,在v4l2层将被转换成固定的名字
    {vidioc_int_dev_init_num, (v4l2_int_ioctl_func *)ioctl_dev_init},
    {vidioc_int_dev_exit_num, ioctl_dev_exit},
    {vidioc_int_s_power_num, (v4l2_int_ioctl_func *)ioctl_s_power},
    {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func *)ioctl_g_ifparm},
/*    {vidioc_int_g_needs_reset_num,
                (v4l2_int_ioctl_func *)ioctl_g_needs_reset}, */
/*    {vidioc_int_reset_num, (v4l2_int_ioctl_func *)ioctl_reset}, */
    {vidioc_int_init_num, (v4l2_int_ioctl_func *)ioctl_init},
/*    {vidioc_int_enum_fmt_cap_num,
                (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap}, */
/*    {vidioc_int_try_fmt_cap_num,
                (v4l2_int_ioctl_func *)ioctl_try_fmt_cap}, */
    {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_g_fmt_cap},
/*    {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_s_fmt_cap}, */
    {vidioc_int_g_parm_num, (v4l2_int_ioctl_func *)ioctl_g_parm},
    {vidioc_int_s_parm_num, (v4l2_int_ioctl_func *)ioctl_s_parm},
/*    {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func *)ioctl_queryctrl}, */
    {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *)ioctl_g_ctrl},
    {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *)ioctl_s_ctrl},
};
static struct v4l2_int_slave ov5642_slave = {//slave
    .ioctls = ov5642_ioctl_desc,
    .num_ioctls = ARRAY_SIZE(ov5642_ioctl_desc),
};

static struct v4l2_int_device ov5642_int_device = {
    .module = THIS_MODULE,
    .name = "ov5642",
    .type = v4l2_int_type_slave,
    .u = {
        .slave = &ov5642_slave,
    },
};
v4l2_int_device_register(&ov5642_int_device);//注册v4l2_int_device:
int v4l2_int_device_register(struct v4l2_int_device *d)
{
    if (d->type == v4l2_int_type_slave)
        sort(d->u.slave->ioctls, d->u.slave->num_ioctls,//按照序号存储,加快访问速度
             sizeof(struct v4l2_int_ioctl_desc),
             &ioctl_sort_cmp, NULL);
    mutex_lock(&mutex);
    list_add(&d->head, &int_list);//无论是slave还是master都会添加到int_list中
    v4l2_int_device_try_attach_all();//都会做匹配动作
    mutex_unlock(&mutex);

    return 0;
}
我们看下v4l2匹配函数v4l2_int_device_try_attach_all():
void v4l2_int_device_try_attach_all(void)
{
    struct v4l2_int_device *m, *s;

    list_for_each_entry(m, &int_list, head) {//对int_list中每个master
        if (m->type != v4l2_int_type_master)
            continue;

        list_for_each_entry(s, &int_list, head) {//对int_list中的每个salve
            if (s->type != v4l2_int_type_slave)
                continue;

            /* Slave is connected? */
            if (s->u.slave->master)//slave中master已经被赋值说明已经连接起来
                continue;

            /* Slave wants to attach to master? */
            if (s->u.slave->attach_to[0] != 0
                && strncmp(m->name, s->u.slave->attach_to,
                       V4L2NAMESIZE))
                continue;

            if (!try_module_get(m->module))
                continue;

            s->u.slave->master = m;//说明slave找到了master
            if (m->u.master->attach(s)) {//执行master的匹配函数
                s->u.slave->master = NULL;
                module_put(m->module);
                continue;
            }
        }
    }
}
上面即是slave注册到v4l2的过程,也许你会比较的奇怪,开始那些ioctl哪去呢?系统怎么访问呢?下面我们就分析这个过程。
我们在v4l2-int-device.h中有这样的定义:
/* IOCTL command numbers. */
enum v4l2_int_ioctl_num {
    /*
     *
     * "Proper" V4L ioctls, as in struct video_device.
     *
     */
    vidioc_int_enum_fmt_cap_num = 1,
    vidioc_int_g_fmt_cap_num,
    vidioc_int_s_fmt_cap_num,
    vidioc_int_try_fmt_cap_num,
    vidioc_int_queryctrl_num,
    vidioc_int_g_ctrl_num,
    vidioc_int_s_ctrl_num,
    vidioc_int_cropcap_num,
    vidioc_int_g_crop_num,
    vidioc_int_s_crop_num,
    vidioc_int_g_parm_num,
    vidioc_int_s_parm_num,
    vidioc_int_querystd_num,
    vidioc_int_s_std_num,
    vidioc_int_s_video_routing_num,
......
};
V4L2_INT_WRAPPER_1(enum_fmt_cap, struct v4l2_fmtdesc, *);
V4L2_INT_WRAPPER_1(g_fmt_cap, struct v4l2_format, *);
V4L2_INT_WRAPPER_1(s_fmt_cap, struct v4l2_format, *);
V4L2_INT_WRAPPER_1(try_fmt_cap, struct v4l2_format, *);
V4L2_INT_WRAPPER_1(queryctrl, struct v4l2_queryctrl, *);
V4L2_INT_WRAPPER_1(g_ctrl, struct v4l2_control, *);
V4L2_INT_WRAPPER_1(s_ctrl, struct v4l2_control, *);
V4L2_INT_WRAPPER_1(cropcap, struct v4l2_cropcap, *);
V4L2_INT_WRAPPER_1(g_crop, struct v4l2_crop, *);
V4L2_INT_WRAPPER_1(s_crop, struct v4l2_crop, *);
V4L2_INT_WRAPPER_1(g_parm, struct v4l2_streamparm, *);
V4L2_INT_WRAPPER_1(s_parm, struct v4l2_streamparm, *);
V4L2_INT_WRAPPER_1(querystd, v4l2_std_id, *);
V4L2_INT_WRAPPER_1(s_std, v4l2_std_id, *);
V4L2_INT_WRAPPER_1(s_video_routing, struct v4l2_routing, *);
我们看下V4L2_INT_WRAPPER_1这个宏定义:
#define V4L2_INT_WRAPPER_1(name, arg_type, asterisk)            \
    static inline int vidioc_int_##name(struct v4l2_int_device *d,    \
                        arg_type asterisk arg)    \
    {                                \
        return v4l2_int_ioctl_1(d, vidioc_int_##name##_num,    \
                    (void *)(unsigned long)arg);    \
    }                                \
                                    \
    static inline struct v4l2_int_ioctl_desc            \
    vidioc_int_##name##_cb(int (*func)                \
                   (struct v4l2_int_device *,        \
                arg_type asterisk))            \
    {                                \
        struct v4l2_int_ioctl_desc desc;            \
                                    \
        desc.num = vidioc_int_##name##_num;            \
        desc.func = (v4l2_int_ioctl_func *)func;        \
                                    \
        return desc;                        \
    }
我们举例来说,V4L2_INT_WRAPPER_1(s_ctrl, struct v4l2_control, *),那也就是有了这样的定义:
    static inline int vidioc_int_s_ctrl(struct v4l2_int_device *d,   
                        arg_type asterisk arg)   
    {                              
        return v4l2_int_ioctl_1(d, vidioc_int_s_ctrl_num,   
                    (void *)(unsigned long)arg);   
    }                              
                                   
    static inline struct v4l2_int_ioctl_desc           
    vidioc_int_s_ctrl_cb(int (*func)               
                   (struct v4l2_int_device *,      
                arg_type asterisk))           
    {                              
        struct v4l2_int_ioctl_desc desc;           
                                   
        desc.num = vidioc_int_s_ctrl_num;           
        desc.func = (v4l2_int_ioctl_func *)func;      
                                   
        return desc;
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值