soc camera 子系統(tǒng)為分為soc camera device 和 soc camera host,并且定義了標(biāo)準(zhǔn)的接口或者回調(diào)函數(shù).
流程:
1.獲取傳來(lái)信息,填充soc_camera_link
2.初始化soc_camera_device(iface、device、設(shè)備號(hào)、總線類型)、加入鏈表
3.
一、/linux-3.0.35/drivers/media/video/soc_camera.c主要是用來(lái)管理接口或者回調(diào)函數(shù).
module_init(soc_camera_init);
	static int __init?soc_camera_init(void)
	{
	int ret = bus_register(&soc_camera_bus_type);//注冊(cè)單沒(méi)有關(guān)聯(lián)
	...
	ret = driver_register(&ic_drv);
...
ret = platform_driver_probe(&soc_camera_pdrv,?soc_camera_pdrv_probe);
	...
	}
	static int __devinit?soc_camera_pdrv_probe(struct platform_device *pdev)
	{
	//通過(guò)傳入的參數(shù)pdev獲取platform_data,即struct soc_camera_link
	struct soc_camera_link *icl = pdev->dev.platform_data;
struct soc_camera_device *icd;
/*
* 分配設(shè)備結(jié)構(gòu)及初始化
*/
icd = kzalloc(sizeof(*icd), GFP_KERNEL);
	icd->iface = icl->bus_id;//iface被初始化為bus_id
	icd->pdev = &pdev->dev;
	platform_set_drvdata(pdev, icd);
ret =?soc_camera_device_register(icd);//soc_camera_device加到全局camera device鏈表@devices上,并且為它分配設(shè)備號(hào),做一些必要的初始化
soc_camera_device_init(&icd->dev, icl);//設(shè)置soc_came_device對(duì)應(yīng)device的bus為soc_camera_bus_type,這樣當(dāng)我們注冊(cè)設(shè)備時(shí),就會(huì)調(diào)用soc_camera_probe
	icd->user_width??= DEFAULT_WIDTH;
	icd->user_height?= DEFAULT_HEIGHT;
	}
	struct?soc_camera_link?{
	int bus_id;//匹配soc?camera?host的序號(hào)
	unsigned long flags;
	int i2c_adapter_id;//I2C?適配器號(hào)
	struct i2c_board_info *board_info;
	const char *module_name;
	void *priv;
	struct regulator_bulk_data *regulators;//用于電源的管理
	int num_regulators;
/*
*針對(duì)那些非I2C的平臺(tái)的函數(shù),用于管理sensor設(shè)備的添加或者刪除
	*/
	int (*add_device)(struct soc_camera_link *, struct device *);
	void (*del_device)(struct soc_camera_link *);
	int (*power)(struct device *, int);
	int (*reset)(struct device *);
	int (*set_bus_param)(struct soc_camera_link *, unsigned long flags);
	unsigned long (*query_bus_param)(struct soc_camera_link *);
	void (*free_bus)(struct soc_camera_link *);
	};
	struct?soc_camera_device?{
	struct list_head list;
	struct device dev;
	struct device *pdev;??
	s32 user_width;          ?//圖像的寬度,以像素為單位
	s32 user_height;//圖像的高度,以像素為單位
	u32 bytesperline;??
	u32 sizeimage;          ??//一畫(huà)圖像的大小,也是存儲(chǔ)圖像緩沖區(qū)的大小
	enum v4l2_colorspace colorspace;//色域,指描述色彩時(shí)所使用的坐標(biāo)系
	unsigned char iface;??//于camera?link中的bus_id相對(duì)應(yīng)
	unsigned char devnum;??
	struct soc_camera_sense *sense;?
	struct soc_camera_ops *ops;
	struct video_device *vdev;
	const struct soc_camera_format_xlate *current_fmt;//驅(qū)動(dòng)中當(dāng)前使用的視頻格式
	struct soc_camera_format_xlate *user_formats;    ?//全部支持的視頻格式
	int num_user_formats;
	enum v4l2_field field;??//決定圖像源數(shù)據(jù)交錯(cuò)的方式
	void *host_priv;??
	int use_count;
	struct mutex video_lock;?
	struct file *streamer;??
/*
* 管理幀緩沖區(qū)
	*/
	union {
	struct videobuf_queue vb_vidq;
	struct vb2_queue vb2_vidq;
	};
	};
	static int?soc_camera_device_register(struct soc_camera_device *icd)
	{
	struct soc_camera_device *ix;
	int num = -1, i;
	for (i = 0; i < 256 && num < 0; i++) {//判斷掛接的設(shè)備是否256個(gè)設(shè)備號(hào)都占用
	num = i;
	list_for_each_entry(ix, &devices, list) {
	if (ix->iface == icd->iface && ix->devnum == i) {
	num = -1;
	break;
	}
	}
	?  }
	icd->devnum??= num;//找到空閑的設(shè)備號(hào)
	icd->use_count??= 0;
	icd->host_priv??= NULL;
	mutex_init(&icd->video_lock);
list_add_tail(&icd->list, &devices);//將空閑的設(shè)備結(jié)構(gòu)放入鏈表
}
	static void?soc_camera_device_init(struct device *dev, void *pdata)
	{
	dev->platform_data?= pdata;
	dev->bus??= &soc_camera_bus_type;//設(shè)置總線類型
	dev->release??= dummy_release;
	}
	struct bus_type?soc_camera_bus_type?= {
	?.name??= "soc-camera",
	?.probe??=?soc_camera_probe,
	?.remove??= soc_camera_remove,
	?.suspend?= soc_camera_suspend,
	?.resume??= soc_camera_resume,
	};
	static int?soc_camera_probe(struct device *dev)
	{
	...
	?ret =?video_dev_create(icd);
...
}
	static int?video_dev_create(struct soc_camera_device *icd)
	{
	?struct video_device *vdev = video_device_alloc();
strlcpy(vdev->name, ici->drv_name, sizeof(vdev->name));
	vdev->parent??= &icd->dev;
	?vdev->current_norm?= V4L2_STD_UNKNOWN;
	?vdev->fops??= &soc_camera_fops;
	?vdev->ioctl_ops??= &soc_camera_ioctl_ops;
	?vdev->release??= video_device_release;
	?vdev->tvnorms??= V4L2_STD_UNKNOWN;
icd->vdev = vdev;
	return 0;
	}
	static struct v4l2_file_operations?soc_camera_fops?= {
	?.owner??= THIS_MODULE,
	?.open??=?soc_camera_open,
	?.release?= soc_camera_close,
	?.unlocked_ioctl?=?video_ioctl2,
	?.read??= soc_camera_read,
	?.mmap??= soc_camera_mmap,
	?.poll??= soc_camera_poll,
	};
	static int?soc_camera_open(struct file *file)
	{
	?struct video_device *vdev = video_devdata(file);//獲取video_driver信息
...
}
/linux-3.0.35/drivers/media/video/v4l2-ioctl.c
	long?video_ioctl2(struct file *file,
	??????? unsigned int cmd, unsigned long arg)
	{
	return video_usercopy(file, cmd, arg,?__video_do_ioctl);
	}
	static long?__video_do_ioctl(struct file *file,
	??unsigned int cmd, void *arg)
	{
	struct video_device *vfd = video_devdata(file);
	const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
	void *fh = file->private_data;
...
	case VIDIOC_S_CROP:
	{
	struct v4l2_crop *p = arg;
	ret = ops->vidioc_s_crop(file, fh, p);
	break;
	}
...
}
	
	
	?
 電子發(fā)燒友App
                        電子發(fā)燒友App
                     
                 
                 
           
        
 
        



















 
            
             
             
                 
             工商網(wǎng)監(jiān)
工商網(wǎng)監(jiān)
        
評(píng)論