博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
camera驱动(三)
阅读量:3899 次
发布时间:2019-05-23

本文共 4075 字,大约阅读时间需要 13 分钟。

V4L2框架:

        用户空间-->v4l2-->master-->slave

1.slave端(摄像头数据处理芯片)

ak8859_init    -->i2c_add_driver(&ak8859_i2c_driver);    -->ak8859_probe    	-->v4l2_int_device_register(&ak8859_int_device)  #slave和master的注册都使用这个函数    		-->v4l2_int_device_try_attach_all()    			-->m->u.master->attach(s)

详解如下:

drivers/media/platform/mxc/capture/ak8859.c

static int ak8859_probe(struct i2c_client *client,const struct i2c_device_id *id){    ak8859_int_device.priv = &ak8859_data;	/*用户open的时候会通过cam->sensor->priv来访问sensor*/	ret = v4l2_int_device_register(&ak8859_int_device);	/*注册ak8859_data--->*/}

drivers/media/v4l2-core/v4l2-int-device.c

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);	list_add(&d->head, &int_list);	/*无论是slave还是master都会添加到int_list中*/	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中每个slave*/            if (s->type != v4l2_int_type_slave)                continue;            if (s->u.slave->master)/*slave中master已经被赋值说明已经连接起来*/                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;            }        }	}}

2.master端(SOC内置摄像头控制器)

camera_init()    -->mxc_v4l2_probe        -->init_camera_struct(cam, pdev)            -->cam->self->u.master = &mxc_v4l2_master        -->v4l2_int_device_register(cam->self)   #slave和master的注册都使用这个函数            -->v4l2_int_device_try_attach_all()                   -->m->u.master->attach(s)        -->video_register_device(cam-        >video_dev, VFL_TYPE_GRABBER, video_nr)

详解如下:

drivers/media/platform/mxc/capture/mxc_v4l2_capture.c

static __init int camera_init(void){	err = platform_driver_register(&mxc_v4l2_driver);  /*平台注册V4L2驱动*/}static int mxc_v4l2_probe(struct platform_device *pdev){    init_camera_struct(cam, pdev); /*初始化cam_data结构--->*/    /*在很多函数中,形参只是v4l2_int_device类型的self,相要获得更外层的cam_data结构体的话,就可以从self->priv中获取*/	cam->self->priv = cam;	/*注意这里的cam赋值,后面match函数中会用到*/	v4l2_int_device_register(cam->self); /*注册在init_camera_struct函数中填充的self结构体--->*/	video_register_device(cam->video_dev, VFL_TYPE_GRABBER, video_nr)  /*注册video设备-->*/}static int init_camera_struct(cam_data *cam, struct platform_device *pdev){    *(cam->video_dev) = mxc_v4l_template;	/* 注意这里的赋值,包含了ops操作,ops为用户空间提供了操作接口 */    /*在视频采集过程中,如果一个buffer填充满的话,会产生一个中断信号,中断处理函数中最终会调用到这个函数来处理中断*/    cam->enc_callback = camera_callback;	/*设置callback*/    cam->self->u.master = &mxc_v4l2_master;   /*slave或者master注册时会调用master的匹配函数*/}static void camera_callback(u32 mask, void *dev){   #将填满的buffer从working_q链表删除,挂接到done_q链表,然后唤醒等待队列上指定的进程    /* Added to the done queue */	list_del(cam->working_q.next);	list_add_tail(&done_frame->queue, &cam->done_q);	/* Wake up the queue */	cam->enc_counter++;	wake_up_interruptible(&cam->enc_queue);    //唤醒等待队列上的进程cam->enc_queue}

kernel/include/media/v4l2-dev.h

static inline int __must_check video_register_device(struct video_device *vdev,		int type, int nr){	return __video_register_device(vdev, type, nr, 1, vdev->fops->owner);}

drivers/media/v4l2-core/v4l2-dev.c

int __video_register_device(struct video_device *vdev, int type, int nr,int warn_if_nr_in_use, struct module *owner){/* Part 1: 检查设备类型,我们这里是VFL_TYPE_GRABBER*/	switch (type) {	case VFL_TYPE_GRABBER:		name_base = "video";		break;	······	case VFL_TYPE_RADIO:		name_base = "radio";		break;  }  /* Part 2:查找空闲的minor*/  /* Part 3:初始化字符设备*/  vdev->cdev->ops = &v4l2_fops;	/*用户打开设备后的file ops!!!!!*/  ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);    /* Part 4:注册设备到sysfs*/  /* Part 5:注册一个media设备实体*/  /* Part 6:激活设备,设备可以使用 */}

转载地址:http://ghuen.baihongyu.com/

你可能感兴趣的文章
十年生聚,Vim 8.0 发布了!
查看>>
【演歌】加賀の女 歌词翻译
查看>>
東京音頭 (东京音头) 歌词翻译
查看>>
Windows 7 下登录界面里 Ctrl + Alt + Del 无法使用
查看>>
惠山赏菊 & 梅园赏桂
查看>>
[小技巧] cat /proc/modules 显示的地址为 0
查看>>
[游戏] chrome 的小彩蛋
查看>>
napi
查看>>
_GNU_SOURCE和__USE_GNU的差别
查看>>
Linux 有了 “DTrace”
查看>>
Linux 系统中僵尸进程
查看>>
一个 2 年 Android 开发者的 18 条忠告
查看>>
标志性文本编辑器 Vim 迎来其 25 周年纪念日
查看>>
[小技巧] chrome 的 vim 插件
查看>>
在 Linux 中查看你的时区
查看>>
[小技巧] [trac] Fix AttributeError: 'NullTranslations' object has no attribute 'add'
查看>>
[小技巧] Mac OS X上键盘的键位重映射
查看>>
Java对Oracle中Clob类型数据的读取和写入
查看>>
Spring中Quartz的配置
查看>>
MyBatis 防止 % _ sql 注入攻击 解决方法
查看>>