Linux下USB摄像头驱动开发

时间:2023-02-14 17:27:13


今年上半年我对市场常见的vimicro 摄像头移植了Linux下的驱动至在研的一款嵌入式开发板,开发环境为:
            OS:Linux2.6.9

Compile:cross 3.3.2

CPU:Intel PXA270

Camera Type :Vimicro ZC301P +HV7131R

使用的驱动源码基于*软件spca5xx。基于源码作了些小改动。记录一下。

Linux下的USB驱动架构
 

Linux下完整的USB驱动程序必须包括3个模块:USB core,USB 主控制器驱动,USB设备驱动。三者的关系如下:

Linux下USB摄像头驱动开发

其中:

Linux Core封装了支持USB主控制器和USB设备驱动的API,通过一系列的数据结构、宏、函数来抽象化设备硬件并掩蔽硬件具体细节,使得Linux系统对USB设备的访问采用如同一般文件访问类似的接口函数,如此实现了硬件无关。“设备即是文件”。

USB HC(Host Controller)全面负责主机端对USB的信息传输分工,对下注册功能和相关数据结构;对上提供了设备驱动与USB Core数据传输的桥梁。USB上的实时流数据传输通常通过URB(USB Request Block)的数据结构实现,每一次数据传输中,设备驱动建立URB,提交给USB HC,USB HC负责完成此次与设备端的URB交互。

USB驱动程序的结构
 

struct usb_driver spca5xx_driver

struct video_device spca50x_template

struct file_operations spca5xx_fops

模块初始化与卸载
 

spca5xx_init()模块初始化;spca5xx_disconnect()模块卸载;spca5xx_probe() 物理设备查找、匹配、配置,并向内核注册video设备。

系统调用接口
 

spca5xx_open()完成设备的打开和初始化,并初始化解码器模块,spca5xx_close()完成设备的关闭;

spca5xx_read()完成数据的读取,其主要的工作就是将数据由内核空间传送到进程用户空间;

spca5xx_mmap()实现将设备内存映射到用户进程的地址空间的功能;

spca5xx_ioctl()实现文件信息的获取功能。

数据传输
 

spca50x_reg_write

摄像头数据传输过程
 

USB总线上信息传输类型可分成控制、中断、等时、成块四种:其中控制型主要用于设备的“配置”与控制;中断型主要用于主机对USB设备的周期性查询;实时性使用与实时的音视频信号传输;成块型用于信息量大,没有很强的时间要求,但要求可靠传递的应用。对摄像头而言,通常采用的是实时传输。USB设备端提供若干通信端口(port),主机与端口间建立起逻辑上的通信管道,进行数据传输。在摄像头的设备初始化阶段,主机与0号端口通信,驱动程序检测摄像头型号和所有端口信息;进入数据传输阶段,主机与探测到的实时输入端口建立通信管道,实时回传摄像头拍摄到的图像数据。

USB主机控制器把每秒总线时间分成1024个固定大小的frame,每个frame占据1ms的时间带宽并以此为时间单位递增,同时对应一个等时交互队列。主机负责把USB总线上回传的等时图像数据流量分配给各frame,USB主机控制器每一秒钟扫描一遍所有frame,依次读入各frame携带的等时数据包至内核缓冲区中。应用程序通过内存映射,在用户空间直接读取内核缓冲区内容,存入Linux显存帧缓冲(framebuffer)中,从而在显示屏中出现图像数据。

笔者的实验摄像头为Vimicro ZC301P,sensor是HV7131R,驱动程序中每秒钟进行2次URB传输,每个URB携带16个1023字节的数据包,这样每秒钟所能得到的图像数据大小为32Kbyte。对RGB565、大小320×240、16位颜色深度的图像格式,在PXA270处理器的嵌入式开发板上测试,帧速达到每秒17帧,完全满足嵌入式网络实时视频会议的需要。

Linux下USB摄像头驱动开发

提高摄像头工作质量的几种方法
双URB
双帧缓冲
V4L协议改进