转自 http://www.right.com.cn/forum/thread-146260-1-1.html
 
在Android4.0升级后,突然发现大量平台对Camera的支持均非常不好。要么Camera使用不稳定,要么各类ioctl设置不能使用,更有甚者,连Camera Device都不能创建。
 
而我们的产品,基于Camera的正常工作,必须解决此类问题。选择了其中一款使用CSI接口Camera的平台:全志A20来做研究和解决。
 
0. 基础知识 : 
0.0. 目录结构:
除了常见的,在linux-3.3/drivers/media/video/ 目录下有v4l2一些文件外,全志还在另一个目录下放置了csi以及做支持模组芯片的代码:linux-3.3/drivers/media/video/sunxi_csi/
其中,csi部分在csi0或者csi1中。 模组对应代码在device中。
这些代码,基本组成了全志CSI 接口 Camera的全部驱动代码。
 
0.1. CSI:
COMS Sensor Interface:
CSI接口通常从COMS Sensor,Video Encoder和其它视频输出设备收集数据。
 
0.2. 模组芯片:
手头这块板子上自带GT2005模组。所以需要看linux-3.3/drivers/media/video/sunxi_csi/device/gt2005.c
 
1. 驱动结构:
CSI 模组Driver的基本思路其实挺简单,就是需要创建主设备号为81的device. /dev/videoX。并将其open,close,ioctl 与Driver联系起来,最终反应到Sensor (gt2005)层面。
 
我们首先从linux-3.3/drivers/media/video/sunxi_csi/csi0部分开始着手,这个文件夹内的三个文件:sunxi_csi_reg.c ,sunxi_drv_csi.c, sunxi_csi_reg.h 最终会生成sunxi_csi0.ko。 会被以modules形式insmod 进系统。
 
1.1:CSI0 modules学习:
当sunxi_csi0.ko被insmod时,sunxi_drv_csi.c中的csi_init()被调用。
csi_init() 中注册了一个driver--csi_driver.
platform_driver_register(&csi_driver);
 
csi_driver中有侦测函数:.probe = csi_probe,
Sam的理解是:因为CSI接口一直连接着,所以当此Driver刚被注册时,csi_probe就被调用。
请注意:csi_probe中作了相当多事情,是sunxi_csi0.ko的重点。
 
它做了很多准备工作.并通过video_register_device()创建了Device. /dev/videoX. 并将此device的操作与v4l2_fops联系起来。
所以,对此Device的open,close, ioctl等, 都使用v4l2_fops中提供的函数指证。
 
而我们看v4l2_fops中的ioctl. 它最终是 video_device ->fops->ioctl()。
其实就是:csi_template 中的:.fops       = &csi_fops, 的ioctl. 即:video_ioctl2
 
video_ioctl2,在v4l2-ioctl.c中定义:其实就是:
static long __video_do_ioctl(struct file *file,unsigned int cmd, void *arg)
 
所以,经过CSI程序的链接。最终,对Device /dev/videoX的操作,最终都被归结到__video_do_ioctl
 
同时,csi_ioctl_ops也被链接到ioctl_ops。请注意,未来要用到这里。
 
看到这里,大家都会疑惑。 这怎么和Sensor操作练习起来了。这部分只将CSI和V4L2 连起来了。
这就是下一部要说的gt2005.ko了。
 
 
1.2: GT2005模块学习:
同样道理,insmod gt2005.ko时,gt2005.c中的init_sensor()会被启动。
在init_sensor()中,只执行了:i2c_add_driver(&sensor_driver); 其中,sensor_driver 同样会在驱动安装后立刻启动。
 
static int sensor_probe(struct i2c_client *client,const struct i2c_device_id *id)
v4l2_i2c_subdev_init(sd, client, &sensor_ops);
这一句代码是关键。
它将sensor_ops加入v4l2_subdev->ops中去了。而v4l2_subdev类型的sd被加入list.未来会用。(关键3)
 
分析下:sensor_ops.
static const struct v4l2_subdev_ops sensor_ops = {
.core = &sensor_core_ops,
.video = &sensor_video_ops,
};
也就是有:core和video 两个。一定要注意了,这里和未来很有关系。(关键4)
 
 
 
__video_do_ioctl()最终会通过vfd->ioctl_ops 来做实际动作。而ioctl_ops是谁呢?就是在在sunxi_drv_csi.c中的csi_ioctl_ops
 
 
 
2. ioctl的完整流程:
当用户open /dev/videoX后,使用ioctl()时,
 
例1:得到能力集:
rel = ioctl(Handle, VIDIOC_QUERYCAP, &cap);
通过上面的分析, 它通过 __video_do_ioctl 最终调用到:vfd->ioctl_ops->vidioc_querycap.
也就是 csi_ioctl_ops 的 .vidioc_querycap          = vidioc_querycap,
 
也就是说: 调用ioctl(VIDIOC_QUERYCAP). 会通过__vidoe_do_ioctl() 最终调用到sunxi_drv_sic.c中的vidioc_querycap()
为什么没有进Sensor呢? 是因为能力集在代码层面维护。不需要去问Sensor。
 
 
例2:得到像素格式
ioctl(Handle, VIDIOC_G_FMT, &Format)
它最终被调用sunxi_drv_csi.c中的vidioc_g_fmt_vid_cap()
因为格式也是由程序维护,所以没有访问Sensor。 
 
例3:设置像素格式
ioctl(Handle, VIDIOC_S_FMT, &Format);
最终被调用sunxi_drv_csi.c中的vidioc_s_fmt_vid_cap()
注意: 设置像素格式,需要通知Sensor。
所以会被调用:
 v4l2_subdev_call(dev->sd,video,s_mbus_fmt,&ccm_fmt);
这里的video. 就是表明调用的是关键4 那个的sensor_video_ops
这里的sd,其实就是关键3 那里的v4l2_subdev类型sd.
所以,又被调用到gt2005.c中的sensor_s_fmt()
此时会向Sensor中写入数据。sensor_write
 
 
例4:
ioctl(Handle, VIDIOC_G_PARM, &Stream_Parm)
会通过__vidoe_do_ioctl()
调用到sunxi_drv_csi.c中vidioc_g_parm() 
这里会:v4l2_subdev_call(dev->sd,video,g_parm,parms);
在gt2005.c中写死的。 如果格式大于 800x600. 则15帧。 小于800x600. 则30帧。
 
 
例5:
ioctl(Handle, VIDIOC_G_PARM, &Stream_Parm)
会通过__vidoe_do_ioctl()
调用到sunxi_drv_csi.c中vidioc_s_parm() 
这里会:v4l2_subdev_call(dev->sd,video,s_parm,parms);
在gt2005.c 中。这里打空。所以其实不能调。
 
例6:
ioctl(Handle, VIDIOC_G_CTRL, &ctrl)
会通过__vidoe_do_ioctl()
调用到sunxi_drv_csi.c中vidioc_g_ctrl() 
这里会:v4l2_subdev_call(dev->sd,core,g_ctrl,ctrl);
注意:这里是core. 所以调用gt2005.c中的sensor_g_ctrl()
 
 
 
例7:
ioctl(Handle, VIDIOC_S_CTRL, &ctrl)
会通过__vidoe_do_ioctl()
调用到sunxi_drv_csi.c中vidioc_s_ctrl() 
这里会:v4l2_subdev_call(dev->sd,core,s_ctrl,ctrl);
注意:这里是core. 所以调用gt2005.c中的sensor_s_ctrl()
 
 
 
但有一点需要注意:在A20平台编程中,大家会发现所有VIDIOC_G_CTRL, VIDIOC_S_CTRL全不可用。Sam查了一下代码。发现是全志修改Kernel时弄错了。
错误如下:
struct v4l2_control {
__u32     id;
__s32     value;
__u32 user_pt;
};
看起来,是全志一位叫Raymon的工程师非常随意的修改了v4l2_control结构体。添加了4个字节的user_pt;
但这会造成严重后果,首先,大量使用v4l2_control的接口会出现未知问题。
更严重的是:ioctl的cmd这一项是计算出来的。v4l2_control的大小会影响到cmd的值。
 
所以,在A20平台上,应用程序使用VIDIOC_G_CTRL, VIDIOC_S_CTRL时,
__video_do_ioctl(struct file *file,unsigned int cmd, void *arg)
参数2:cmd这一项和Kernel中算出的cmd值对不上。所以无法进入:
case VIDIOC_G_CTRL:
case VIDIOC_S_CTRL:
 
 
如果有全志工程师偶尔看到这篇Blog。 请通知Driver部门。修改这个明显错误。

1全志 A20 camera移植的更多相关文章

  1. mtk camera 移植步骤

    mtk camera 移植步骤: 1, Kernel层驱动代码文件添加 /mediatek/custom/doov92_wet_tdd/kernel/imgsensor/下添加imx179_mipi_ ...

  2. 全志a20安卓电视盒子安装可道云kodexplorer服务-编译安装php7.3+nginx

    可道云真的很强大,安装包很小,功能却很齐全,还可以自定义轻应用如果有手机客户端就更好了 研究了一下,可道云根目录放到外置存储设备(移动硬盘)会更合适,改路径的方法下面有提到上传文件时一个文件会在用户目 ...

  3. BPI-M1P(全志A20)刷Android启动卡之后启动的过程

    http://blog.csdn.net/wb4916/article/details/78031511BPI-M1P(全志A20)刷Android启动卡之后启动的过程 BPI-M1P(全志A20)刷 ...

  4. 关于全志A20的Ubuntu12.04 64位系统下环境配置及编译过程笔记【转】

    本文转载自:https://blog.csdn.net/buqingbuyuan/article/details/43370199 在安装Ubuntu系统之后,安装编译所需的GCC等工具,一般选用GC ...

  5. 全志A20芯片用于启动的SD卡的布局

    起始 大小 内容 0 8KB 存放分区表等 8 24KB SPL loader 32 512KB u-boot 544 128KB environment 672 352KB 保留 1024 - 用于 ...

  6. rk3288 ov8858 camera移植

    平台:瑞芯的rk3288 SDK:4.4/5.0/5.1 作者:fulinux *****本文同意转载.只是请注明出处:http://blog.csdn.net/fulinus**** rk3288的 ...

  7. 转:全志A20 GPIO 总结文档

    链接: http://blog.csdn.net/chwenj/article/details/42190745 /* * author:          chwenj@gmail.com. * A ...

  8. 全志A64 QT移植

    1. 把编译工具 gcc-linaro-aarch64.tar.xz 添加到环境.bashrc 中 2. 下载 tslib-1.4.tar.gz ,libiconv-1.15.tar.gz ,qt-e ...

  9. 基于全志a33-vstar开发板的ap6210WiFi模块移植

    可以去链接看更详细的,第一次用博客,这个编辑方式太不友好了. 文档:全志a33--系统移植--ap6210WiFi模块移?..链接:http://note.youdao.com/noteshare?i ...

随机推荐

  1. NSOperationQueue与GCD的使用原则和场景

    首先,我们要明确NSOperationQueue与GCD之间的关系: NSOpertaionQueue用GCD构建封装的,是GCD的高级抽象. 其次,我们要区别两者的不同: GCD仅仅支持FIFO队列 ...

  2. AOP的基本概念

    1)aspect(切面):实现了cross-cutting功能,是针对切面的模块.最常见的是logging模块,这样,程序按功能被分为好几层,如果按传统的继承的话,商业模型继承日志模块的话根本没有什么 ...

  3. PCB设计中的20H原则

    20H原则是指电源层相对地层内缩20H的距离,当然也是为抑制边缘辐射效应.在板的边缘会向外辐射电磁干扰.将电源层内缩,使得电场只在接地层的范围内传导.有效的提高了EMC.若内缩20H则可以将70%的电 ...

  4. git submodule(转载)

    From:http://www.worldhello.net/2010/01/26/425.html 删除 git submodule (git 库子模组) 有两种情况会创建 git submodul ...

  5. POSTMAN发起请求收到乱码 http 406错误

    web前段异常: The resource identified by this request is only capable of generating responses with charac ...

  6. 一次完整的HTTP请求流程

    HTTP通信机制是在一次完整的HTTP通信过程中,Web浏览器与Web服务器之间将完成下列7个步骤: 1. 建立TCP连接: 在HTTP工作开始之前,Web浏览器首先要通过网络与Web服务器建立连接, ...

  7. iOS开发 - OC - 实现本地数据存储的几种方式一

    iOS常用的存储方式介绍 在iOS App开发过程中经常需要操作一些需要持续性保留的数据,比如用户对于App的相关设置.需要在本地缓存的数据等等.本文针对OC中经常使用的一下存储方式做了个整理. 常用 ...

  8. 转 @html.ActionLink的几种参数格式

    一 Html.ActionLink("linkText","actionName") 该重载的第一个参数是该链接要显示的文字,第二个参数是对应的控制器的方法, ...

  9. Java判断Class变量是什么类型

    public static void main(String[] args) { java.util.Date date_u = new java.util.Date(1); java.sql.Dat ...

  10. KMS服务器激活Windows和Office2013EnterprisePlus

    KMS服务器激活Windows和Office2013EnterprisePlus 参考了文档 http://wenku.baidu.com/view/0cb2602358fb770bf68a5501. ...