摘要:介绍了嵌入式Linux系统中USB设备驱动程序开发的基本原理,通过分析USB驱动程序开发的程序框架和重要数据结构,实现了USB摄像头的嵌入式Linux驱动程序,并在S3C2440的平台上实现了图像采集。
关键词:嵌入式Linux;驱动程序;USB摄像头
中图分类号:TP319文献标识码:A文章编号:1672-7800(2013)001-0093-03
0引言
在我们今天的生活中,摄像头广泛应用于视频聊天以及视频实时监控中。世面上摄像头种类繁多,其中USB接口的摄像头价格便宜,性能也很高,因而更适宜推广使用。
主控和传感芯片是摄像头的重要部件。主控芯片负责图像采集、压缩以及与主机进行信息传递。通过摄像头进行图像采集,同时摄像头与嵌入式模块连接,通过嵌入式模块上的无线网卡把采集的图像发送出去。嵌入式模块上使用的是Linux系统,嵌入式Linux系统的源代码方便开发,内核运行稳定并具有可裁减性,对大多数硬件都可以支持,是嵌入式系统领域最重要的操作系统。
本文重点分析了USB摄像头驱动模块的整体结构及驱动程序的实现。
1Linux设备驱动的基本概念
设备驱动程序是一种可以使计算机和设备进行通信的特殊程序,可以说相当于硬件的接口,操作系统只有通过这个接口,才能控制硬件设备的工作,假如某设备的驱动程序未能正确安装,便不能正常工作。应用程序把硬件设备看作是一个设备文件,这样它对硬件设备进行操作就可以像操作普通文件一样。设备驱动程序被看作是内核的构成部分,其完成的功能有:设备的初始化和释放、数据从内核到硬件、从硬件读取数据、接收应用程序传送给设备文件的数据,返回其请求的数据。
Linux内核对外围设备控制操作是通过驱动程序来完成,所以每个设备都需要有驱动程序,否则设备将无法正常工作。
4结语
对中国象棋的文化底蕴进行研究,设计并制作象棋多媒体学习软件,内容涉及象棋文化、口诀、技巧、各棋子基本走法、经典棋局、大师风采等方面,能够丰富人们的精神生活,普及传统文化,发扬中华文明。
象棋多媒体学习软件界面美观,多种媒体效果丰富,交互性强,内容易扩充。适用于不同年龄段、不同就学阶段、不同工作岗位的人群,适用范围广。既可用于象棋自学,也可用于象棋培训。
目前,象棋软件主要为实战型,以博弈为主,面向的对象为精通象棋棋艺的人群,象棋多媒体学习软件面向的对象为普通大众,操作简单,使用者可以通过该软件,熟悉象棋文化,掌握下棋方法和技巧,了解象棋大师和经典棋局,更易于普及和推广中国象棋及其文化,促进象棋竞技的发展。
参考文献:
[1]李松福.象棋史话[M].北京:人民体育出版社,1981.
[2]郭志菊,李树新.象棋文化熟语语义解构[J].汉字文化,2002(2).
[3]丁桂兴.象棋运动好处多[J].教育与管理,2009(12).
[4]刘殿中.象棋实战指南/象棋新编教程[M].北京:北京体育大学出版社,2003.
[5]程明松.中国象棋谱大全[M].成都:蜀蓉棋艺出版社,2003.
[6]李京文.Authorware案例教程[M].北京:中国水利水电出版社,2010.
[7]缪亮.多媒体技术实用教程[M].北京:清华大学出版社,2007.
(责任编辑:孙娟)
2Linux2.6下USB摄像头驱动的实现
2.1USB驱动程序框架
Linux系统里,每一个完备的USB驱动程序都是由USBCore、USB主控制器驱动(HCD)和USB设备驱动3部分组成,其层次关系如图1所示。其中,USBcore完成一些重要的功能,它初始化整个USB系统,申请structbus_typeusb_bus_type结构体,然后扫描USB总线,并为连接的USB设备分配一个structdevice。主机控制器驱动(HCD)必须位于USB软件的最底层,HCD提供主机控制器硬件的抽象,隐藏硬件的细节,在主机控制器之下是物理的USB及所有与之连接的USB设备。而HCD只对USBcore负责。USBcore将用户的请求映射到相关的HCD,用户不能直接访问HCD。
图1USB子系统各模块层次关系
2.2USB摄像头驱动程序编写
驱动程序的编写是要为应用程序提供其可调用的open、read、write、ioctrl。在驱动程序中,依据设备功能的要求对file_operations的函数实现尤为重要,在驱动程序初始化时,file_operations的变量会注册到系统中去,file_operations提供了许多接口,不需要的就初始化为NULL。对设备进行任何操作,file_operations中的函数指针都会被相应地调用。
本USB驱动开发是以LinuxKernel源码中usb_skeleton.c提供的USB驱动程序为原型,编出的一个USB设备的驱动。
在LinuxUSB子系统里注册是USB驱动程序完成的第一个步骤,同时这个驱动程序支持的设备类型在此时确定,支持的设备从系统插入或拔出时的动作也同时规定好。全部这些信息都被传送到USB子系统中。下面举例说明USB摄像头的注册和注销:
structusb_driverabc_driver={
#ifLINUX_VERSION_CODE .owner=THIS_MODULE, #endif .name="abc", .id_table=device_table,
.probe=abc_probe,
.disconnect=abc_disconnect
};
intinitusb_abc_init(void)
{……
abc_create();
……
if(usb_register(&abc_driver)<0)
return-1;
……
}
void__exitusb_abc_exit(void)
{……
abc_destroy();
……}
module_init(usb_abc_init);
module_exit(usb_abc_exit);
在abc_driver结构中,字符串name表明了驱动程序。probe和disconnect是函数指针。
当系统检测到USB摄像头插入时系统会检测它的VendorID和ProductID,如果与驱动模块的注册内容匹配,则调用abc_probe()函数,abc_probe()函数向视频子系统注册,生产厂商号码(VendorID)和产品号(ProductID)在驱动模块加载初始化的时候就向系统注册了。参数dev表明设备信息,参数id则表明USB设备的生产厂商及产品号。如果USB设备通过了probe函数的验证,则usbvideo_RegisterVideoDevice()函数调用向videodev系统注册:
intabc_probe(structusb_interface*intf,conststructusb_device_id*id)
{
……
/*Initvideostuff*/
abc->vdev=video_device_alloc();
if(!abc->vdev)
gotoerror;
memcpy(abc->vdev,&abc_template,sizeof(abc_template));
……}
其中abc_template设备文件操作函数
Staticstructvideo_deviceabc_template={
.name="GSPCAUSBCamera",
.vfl_type=VID_TYPE_CAPTURE,
#ifLINUX_VERSION_CODE<=KERNEL_VERSION(2,6,23)
.hardware=VID_HARDWARE_GSPCA,
#endif
.fops=&abc_fops,
.release=video_device_release,
.minor=-1,};
staticstructv4l2_file_operationsabc_fops={
.owner=THIS_MODULE,
.open=abc_open,
.release=abc_close,
.read=abc_read,
.mmap=abc_mmap,
.ioctl=abc_ioctl,
.unlocked_ioctl=video_ioctl2,
};
其中abc_open()完成设备的打开和初始化。部分代码如下:
staticintabc_open(structvideo_device*vdev,intflags)
{……
abc_alloc(abc);
abc_init_source(abc);
abc_initDecoder(abc);
abc_init_isoc(abc);
……}
abc_read()调用函数copy_to_user(buf,frame->data,count)将数据由内核空间传送到进程的用户空间。代码如下:
staticlongabc_read(structvideo_device*dev,char*buf,unsignedlongcount,intnoblock)
{……
l=copy_to_user(buf,frame->data,count);
……}
当拔掉摄像头,abc_disconnect()函数会调用:
staticvoidabc_disconnect(structusb_device*dev,void*ptr)
{……
video_uegister_device(abc->vdev);
abc->dev=NULL;
up(&abc->lock);
/*Freethememory*/
if(abc&&!abc->user){
spca5xx_dealloc(abc);
kfree(abc);
abc=NULL;
……};
3摄像头驱动的移植与测试
将该驱动移植到友善之臂S3C2440开发板上,该开发板是基于S3C244X处理器的开发平台,同时具有串口、USB接口、网口、JTAG接口等较全面的接口,可以在Linux下工作,便于调试和测试。
本文摄像头的测试程序是基于Video4Linux完成USB摄像头图像和视频获取,其中Video4Linux(简V4L)是Linux中关于视频设备的内核驱动,它为针对视频设备的应用程序编程提供一系列接口函数,这些视频设备包括现今市场上流行的TV卡、视频捕捉卡和USB摄像头等。
编程的思想如下:①打开摄像头;②初始化摄像头状态;③进行视频采集;④对采集的视频进行处理;⑤关闭摄像头。
在主函数main()中,open()函数打开摄像头设备,init_videoIn()函数初始化摄像头设备并且设置图像帧的参数,grab()函数中采用read()系统调用获得图像数据,并把获得的数据以文件形式保存起来,close_v4l()函数关闭USB摄像头设备。下面给出测试程序的基本架构:
intmain(intargc,char**argv){
……
vd->fd=open(vd->videodevice,O_RDWR);
init_videoIn(structvdIn*vd,char*device,intwidth,int
height,intformat,intgrabmethod);
……
grab();
……
close_v4l(&videoIn);
}
4结语
本文全面阐述了嵌入式Linux系统中USB子系统的架构和基本工作原理,详细介绍了USB摄像头驱动程序的开发过程。该摄像头驱动经过测试运行稳定,可用于实际应用。
参考文献:
[1]毛德操,胡希明.Linux内核源代码情景分析[M].杭州:浙江大学出版社,2001.
[2]魏永明,骆刚,姜军.Linux设备驱动程序[M].北京:中国电力出版社,2002.
[3]探矽工作室.嵌入式系统开发圣经[M].北京:中国青年出版社,2002.
[4]杜春雷.ARM体系结构与编程[M].北京:清华大学出版社,2003.
[5]马忠梅,马广云,徐英慧.ARM嵌入式处理器结构与应用基础[M].北京:北京航空航天大学出版社,2002.
[6]倪继利.Linux内核分析及编程[M].北京:电子工业出版社,2005.
[7]万健,冯华,任彧.嵌入式系统中USB块数据传输的设计与实现[J].计算机工程与设计,2005(11).
[8]李光明,姚斌.基于ARM7和嵌入式Linux系统下USB接口的设计[J].计算机工程与设计,2006(6).
[9]孙天泽,袁文菊,张海峰.嵌入式设计及Linux驱动开发指南—基于ARM9处理器[M].北京:电子工业出版社,2005.
[10]Compaq,HewlettPackard,Intel,Lucent,Microsoft,NEC.Philipsuniversalserialbusspecificatioevision2.0[S].2000.
[11]SAMSUNG.S3C2410A200MHzand266MHz32bitRISCmicroprocessoruser"smanualrevision1.0[Z].2004.
(责任编辑:孙娟)