周頂輝,王艷秋
(遼寧工業(yè)大學(xué)通信與信息系統(tǒng),遼寧 錦州 121000)
隨著多媒體、網(wǎng)絡(luò)技術(shù)的迅猛發(fā)展和后PC機(jī)時(shí)代的到來(lái),USB攝像頭的應(yīng)用越來(lái)越廣泛,例如遠(yuǎn)程監(jiān)控、視頻電話和視頻會(huì)議等。攝像頭由主控芯片和傳感芯片組成,主控芯片負(fù)責(zé)圖像采集、壓縮以及和主機(jī)的通信。我們使用的是市面上常見(jiàn)的一款CMOS攝像頭,主控芯片為臺(tái)灣松翰科技(Sonix)公司的SN9C288CF6-1,傳感芯片是ov7620。本文主要介紹USB協(xié)議驅(qū)動(dòng)模塊的分層結(jié)構(gòu)、驅(qū)動(dòng)程序的實(shí)現(xiàn)過(guò)程及設(shè)備的硬件初始化。
USB設(shè)備驅(qū)動(dòng)程序,主要由USB內(nèi)核控制模塊和設(shè)備驅(qū)動(dòng)模塊兩部分構(gòu)成。USB內(nèi)核控制模塊封裝了支持USB主控制器及USB設(shè)備驅(qū)動(dòng)的特定API,通過(guò)定義一系列的數(shù)據(jù)結(jié)構(gòu)、宏和函數(shù),來(lái)抽象化硬件,使得系統(tǒng)對(duì)各種設(shè)備的訪問(wèn)都采用統(tǒng)一的形式,做到了硬件無(wú)關(guān)。設(shè)備驅(qū)動(dòng)模塊,主要完成USB設(shè)備的注冊(cè)注銷、硬件初始化和為上層應(yīng)用程序提供接口等工作。由于在Linux系統(tǒng)中,已經(jīng)內(nèi)置了USB內(nèi)核控制模塊,我們只需要編寫(xiě)設(shè)備驅(qū)動(dòng)程序。
Linux USB驅(qū)動(dòng)程序首先要做的,就是把包含設(shè)備信息和相關(guān)操作的結(jié)構(gòu)體ov7620_driver注冊(cè)到USB子系統(tǒng)里,該過(guò)程是調(diào)用usb_register函數(shù)來(lái)完成的,具體過(guò)程如下:
usb_ov7620_init(void)
{......
proc_ov7620_create();//建立PROC設(shè)備文件
if(usb_register(&ov7620_driver)<0)//調(diào)用usb_register函數(shù)完成注冊(cè)
return-1;
info("ov7620 driver%s registered",version);
return 0;
};
其中ov7620_driver包含了USB攝像頭的相關(guān)信息,并提供了當(dāng)攝像頭插入拔出時(shí)所對(duì)應(yīng)的操作,結(jié)構(gòu)如下:
static struct usb_driver ov7620_driver={
.name="ov7620",
.id_table=device_table,
.probe=ov7620_probe,
.disconnect=ov7620_disconnect
};
probe和disconnect是函數(shù)指針。當(dāng)插入U(xiǎn)SB攝像頭時(shí),調(diào)用ov7620_probe()函數(shù),主要用來(lái)檢測(cè)VID和PID,看USB內(nèi)核控制模塊里有沒(méi)有匹配的驅(qū)動(dòng),如果有向Linux的視頻子系統(tǒng)注冊(cè),并將驅(qū)動(dòng)實(shí)現(xiàn)的系統(tǒng)調(diào)用,掛到內(nèi)核中:
ov7620_probe(struct usb_interface*intf,const struct usb_device_id*id)
{......
if((err_probe=spcaDetectCamera(ov7620))<0)//具體物理設(shè)備查找,匹配廠商號(hào),設(shè)備號(hào)
{err("Devices not found!!");goto error;}
……
memcpy(ov7620->vdev,&ov7620_template,sizeof(ov7620_template));
//系統(tǒng)調(diào)用的掛接,在此將驅(qū)動(dòng)實(shí)現(xiàn)的系統(tǒng)調(diào)用,掛到內(nèi)核中
};
當(dāng)攝像頭從USB總線拔掉,設(shè)備指針會(huì)調(diào)用ov7620_disconnect()函數(shù):
static void ov7620_disconnect(struct usb_interface*intf)
{……
if(ov7620->vdev)
video_unregister_device(ov7620->vdev);//注銷video設(shè)備
};
當(dāng)設(shè)備插入U(xiǎn)SB總線時(shí),系統(tǒng)會(huì)調(diào)用probe函數(shù)探測(cè)設(shè)備并把系統(tǒng)調(diào)用掛接到內(nèi)核。上層應(yīng)用程序在獲取設(shè)備句柄以后,可以直接通過(guò)系統(tǒng)調(diào)用對(duì)設(shè)備進(jìn)行操作,如read、write等。作為攝像頭驅(qū)動(dòng)不需要輸出功能,因此在程序中沒(méi)有實(shí)現(xiàn)write系統(tǒng)調(diào)用。數(shù)據(jù)結(jié)構(gòu)如下:
static struct file_operations ov7620_fops={
.owner=THIS_MODULE,
.open=ov7620_open,//open功能
.release=ov7620_close,//close功能
.read=ov7620_read,//read功能
.mmap=ov7620_mmap,//內(nèi)存映射功能
.ioctl=ov7620_ioctl,//文件信息獲取
};
ov7620_open完成設(shè)備的打開(kāi)和初始化,并初始化解碼器模塊。其具體實(shí)現(xiàn)如下:
static int ov7620_open(struct video_device*vdev,int flags)
{……
err=ov7620_init_source(ov7620);//初始化控制器和傳感器芯片
err=ov7620_init_transfert(ov7620);//初始化URB(usb request block)包,啟動(dòng)攝像頭,采用同步傳輸?shù)姆绞絺魉蛿?shù)據(jù)
};
ov7620_close函數(shù)主要完成設(shè)備的關(guān)閉,ov7620_mmap和ov7620_read是應(yīng)用程序讀取數(shù)據(jù)的兩個(gè)接口函數(shù)。ov7620_mmap通過(guò)remap_page_range函數(shù)實(shí)現(xiàn)內(nèi)存映射,ov7620_read通過(guò)copy_to_user實(shí)現(xiàn)用戶空間和內(nèi)核空間的數(shù)據(jù)拷貝,只讀取其中一幀大小的數(shù)據(jù)。
在打開(kāi)設(shè)備時(shí),需要對(duì)硬件進(jìn)行初始化。攝像頭由兩個(gè)主要的芯片組成,圖像傳感器芯片ov7620和橋接芯片SN9C102P。攝像頭的結(jié)構(gòu)框圖如圖1。橋接芯片提供了開(kāi)放的源代碼,里面提供了對(duì)傳感器控制的接口函數(shù),如sn9c102_i2c_write,sn9c102_i2c_read等。利用提供的接口函數(shù)我們就可以對(duì)ov7620的寄存器寫(xiě)值,完成傳感器的初始化工作和圖像采集控制,過(guò)程如下:
sn9c102_i2c_write (ov7620->dev,ov7620_sensor_init [i],8)//ov7630_sensor_init是傳感器ov7620寄存器結(jié)構(gòu)。
圖1 攝像頭的結(jié)構(gòu)框圖
在PC機(jī)上搭建交叉編譯環(huán)境,系統(tǒng)配置為fedora 7,內(nèi)核2.6.19,安裝的交叉編譯工具為arm-linux-gcc-3.4.1。編譯環(huán)境建立以后,還需要配置Makefile文件,完成后只要在終端里執(zhí)行make命令就可以生成驅(qū)動(dòng)模塊文件。然后通過(guò)超級(jí)終端下載到Te2440開(kāi)發(fā)板上,用insmod命令加載驅(qū)動(dòng)。在開(kāi)發(fā)板上運(yùn)行servfox,在PC機(jī)上通過(guò)spcaview就可以看到圖像了。
本文對(duì)USB攝像頭驅(qū)動(dòng)程序的開(kāi)發(fā)過(guò)程,進(jìn)行了簡(jiǎn)單的介紹,并介紹了Makefile文件的內(nèi)容。本文程序結(jié)構(gòu)功能相對(duì)簡(jiǎn)單,在此基礎(chǔ)上可以擴(kuò)展出一個(gè)視頻監(jiān)控系統(tǒng),或者進(jìn)行圖像處理方面的研究。
[1]Alessandro Rubini,Jonathan Corbet.Linux設(shè)備驅(qū)動(dòng)程序[M].魏永明,駱 鋼,姜 君譯.北京:中國(guó)電力出版社,2002.
[2]劉春成.基于嵌入式Linux的USB攝像頭驅(qū)動(dòng)開(kāi)發(fā)[J].計(jì)算機(jī)工程與設(shè)計(jì),2007,(8):2-3.
[3]魏 武,楊堅(jiān)銳.嵌入式Linux下USB攝像頭驅(qū)動(dòng)程序的開(kāi)發(fā)[J].現(xiàn)代電子技術(shù),2006,(11):3-4.
[4]孫天澤,袁文菊,張海峰.嵌入式設(shè)計(jì)及Linux驅(qū)動(dòng)開(kāi)發(fā)指南—基于ARM9處理器[M].北京:電子工業(yè)出版社,2005.