牟躍,周淵平
(四川大學(xué) 電子信息學(xué)院, 四川 成都 610065)
摘要:由于Android操作系統(tǒng)開(kāi)放源碼,在近幾年被廣泛用于各個(gè)領(lǐng)域,可以利用Android系統(tǒng)的開(kāi)放性,開(kāi)發(fā)該系統(tǒng)在有線電話方面的應(yīng)用。將Android平臺(tái)與撥號(hào)芯片MT8880結(jié)合起來(lái)研究。因?yàn)锳ndroid原生代碼具有很大局限性,支持的設(shè)備太少,所以為了識(shí)別MT8880這個(gè)特定設(shè)備,并控制MT8880的邏輯輸出,需要在Linux內(nèi)核中添加驅(qū)動(dòng)模塊,并在HAL層和JNI層生成動(dòng)態(tài)鏈接庫(kù),使得頂層應(yīng)用程序可以控制撥號(hào)芯片MT8880。MT8880芯片主要用于發(fā)送雙音多頻信號(hào)(Dual Tone Multi Frequency),在加載了撥號(hào)驅(qū)動(dòng)和應(yīng)用程序后,可以實(shí)現(xiàn)Android系統(tǒng)的撥號(hào)功能。經(jīng)測(cè)試,設(shè)計(jì)的撥號(hào)驅(qū)動(dòng)能實(shí)現(xiàn)對(duì)新增設(shè)備的控制,電話應(yīng)用能成功撥號(hào)。
關(guān)鍵詞:Android;Linux內(nèi)核; HAL; JNI;MT8880芯片
中圖分類(lèi)號(hào):TP399文獻(xiàn)標(biāo)識(shí)碼:ADOI: 10.19358/j.issn.1674-7720.2017.09.026
引用格式:牟躍,周淵平.基于Android電話撥號(hào)功能的驅(qū)動(dòng)設(shè)計(jì)[J].微型機(jī)與應(yīng)用,2017,36(9):88-91,99.
0引言
Android是由Google公司和開(kāi)放手機(jī)聯(lián)盟領(lǐng)導(dǎo)及開(kāi)發(fā)、基于Linux內(nèi)核的開(kāi)放源代碼的操作系統(tǒng)[1]。Android最近幾年發(fā)展迅猛,被用于各種場(chǎng)合。TQ210開(kāi)發(fā)板搭載的是Android4.0系統(tǒng),使用的是三星公司生產(chǎn)的S5PV210處理器,能夠滿足大多數(shù)應(yīng)用場(chǎng)合的需求。而采用的撥號(hào)芯片MT8880能夠發(fā)送經(jīng)過(guò)濾波處理過(guò)的雙音多頻(Dual Tone Multi Frequency,DTMF)信號(hào)。
電話由于其信號(hào)穩(wěn)定、抗干擾能力強(qiáng)、輻射小等優(yōu)點(diǎn)被廣泛用于企業(yè)、事業(yè)機(jī)構(gòu)和個(gè)人。在如今移動(dòng)設(shè)備被各個(gè)行業(yè)廣泛應(yīng)用的大環(huán)境下,可以通過(guò)底層驅(qū)動(dòng)的開(kāi)發(fā)[2],使得Android可以識(shí)別外部新增設(shè)備。將Android平臺(tái)與撥號(hào)芯片MT8880結(jié)合研究,可以實(shí)現(xiàn)Android電話撥號(hào)功能。
1硬件系統(tǒng)
1.1硬件框架
Android開(kāi)發(fā)平臺(tái)(TQ210開(kāi)發(fā)板)和MT8880撥號(hào)芯片構(gòu)成了硬件系統(tǒng)的主要部分[3],如圖1所示。Android平臺(tái)采用 TQ210 開(kāi)發(fā)板, TQ210開(kāi)發(fā)板的核心板為63 mm×53 mm×7 mm的10層板,共有280根引腳。核心板引出了兩路攝像頭接口CAMERA_A和CAMERA_B,其中CAMERA_B主要是開(kāi)發(fā)板為滿足不同開(kāi)發(fā)需求預(yù)留的應(yīng)用接口,可GPIO口復(fù)用,當(dāng)不用攝像頭功能時(shí),可作為GPIO擴(kuò)展口。Android的 GPIO接口連接MT8880撥號(hào)芯片,使用CAMERA_B的GPIO口與芯片的相應(yīng)管腳相連接,并通過(guò)GPIO口輸出高低邏輯電平,對(duì)芯片進(jìn)行控制,實(shí)現(xiàn)發(fā)送DTMF信號(hào)的功能。
1.2語(yǔ)音撥號(hào)芯片MT8880
MT8880芯片采用ISOCMOS技術(shù)制造,具有功耗低和穩(wěn)定性高等特點(diǎn),能夠比較準(zhǔn)確地發(fā)送DTMF信號(hào)。MT8880的發(fā)送部分的內(nèi)部邏輯如圖2所示。從結(jié)構(gòu)上看,在發(fā)送與電話號(hào)碼對(duì)應(yīng)的DTMF信號(hào)之前,必須對(duì)寄存器進(jìn)行相應(yīng)操作,首先選擇對(duì)狀態(tài)寄存器SR和控制寄存器CRA進(jìn)行操作,打開(kāi)信號(hào)音突發(fā)選通電路,使芯片能夠輸出信號(hào),然后通過(guò)控制寄存器CRB和發(fā)送數(shù)據(jù)寄存器TDR,使得電話號(hào)碼能夠通過(guò)D1~D4數(shù)據(jù)線輸入,最后經(jīng)過(guò)行、列計(jì)數(shù)器和D/A轉(zhuǎn)換器,輸出DTMF信號(hào)。通過(guò)RSO及WR和RD口線可對(duì)相關(guān)寄存器進(jìn)行選擇和控制,具體控制功能的實(shí)現(xiàn)如表1。 從外部看,可以通過(guò)外部微處理器訪問(wèn)其內(nèi)部的寄存器,以實(shí)現(xiàn)DTMF信號(hào)的發(fā)送功能。
2軟件系統(tǒng)設(shè)計(jì)
2.1Android源碼編譯環(huán)境的搭建
首先在64位的Ubuntu12.04操作系統(tǒng)中,完成Android源碼的編譯操作,并在系統(tǒng)中安裝和配置JDK,而為了順利編譯Android源碼,在系統(tǒng)中還需要安裝GCC編譯器、相關(guān)的庫(kù)和交叉編譯器arm-linux-gcc。在完成編譯環(huán)境的搭建后,目標(biāo)代碼便能在其他平臺(tái)上運(yùn)行。
2.2撥號(hào)功能的軟件框架
Android的系統(tǒng)架構(gòu)與其操作系統(tǒng)一樣,采用了分層架構(gòu),主要包括應(yīng)用程序?qū)印?yīng)用程序框架層、系統(tǒng)運(yùn)行庫(kù)和核心層[4],如圖3所示。為使Android可以識(shí)別撥號(hào)芯片MT8880這個(gè)特定的新增設(shè)備,即通過(guò)頂層代碼實(shí)現(xiàn)對(duì)硬件設(shè)備的控制,首先在Linux內(nèi)核實(shí)現(xiàn)了名為tel.c的內(nèi)核驅(qū)動(dòng),為系統(tǒng)上層提供了操作底層硬件的接口;然后在HAL層封裝控制邏輯,在JNI層將本地代碼封裝成上層應(yīng)用可以調(diào)用的Java代碼,并生成相應(yīng)的動(dòng)態(tài)鏈接庫(kù)文件即.so文件;最后頂層便可通過(guò)調(diào)用動(dòng)態(tài)鏈接庫(kù),實(shí)現(xiàn)撥號(hào)功能。
2.2.1底層驅(qū)動(dòng)設(shè)計(jì)
底層驅(qū)動(dòng)模塊主要是控制CAMERA_B上的GPIO管腳,提供控制MT8880撥號(hào)芯片硬件設(shè)備接口的邏輯電平,使得系統(tǒng)能夠控制外部芯片MT8880實(shí)現(xiàn)撥號(hào)。撥號(hào)驅(qū)動(dòng)程序tel.c采用的混雜型驅(qū)動(dòng)設(shè)備miscdevice,主要由設(shè)備的注冊(cè)misc_register、注銷(xiāo)misc_deregister、打開(kāi)open、關(guān)閉close等部分組成。驅(qū)動(dòng)程序tel.c通過(guò)宏S3C_GPIO_SFN(x)對(duì)管腳功能進(jìn)行定義,當(dāng)x為0時(shí),管腳為輸入,x為1時(shí),管腳為輸出;通過(guò)函數(shù)int s3c_gpio_setpull(unsigned int pin, amsung_gpio_pull_t pull)為指定的GPIO管腳配置上下位狀態(tài);通過(guò)函數(shù)int gpio_request(unsigned gpio, const char *label)向內(nèi)核申請(qǐng)管腳,并用label去描述它;通過(guò)函數(shù)void gpio_free(unsigned gpio)釋放一個(gè)已經(jīng)申請(qǐng)的引腳,此函數(shù)與gpio_request對(duì)應(yīng);通過(guò)函數(shù)int gpio_direction_output(unsigned gpio, int value )在管腳處輸出一個(gè)電平value(0或者1);通過(guò)函數(shù)int gpio_direction_input(unsigned gpio)讀取;通過(guò)函數(shù)static unsigned int gpio_cfg_table[]定義了gpio_table數(shù)組,這個(gè)數(shù)組用來(lái)定義電話驅(qū)動(dòng)所用的GPIO引腳,總共需要7個(gè)引腳,分別為GPI0的0~6口。
2.2.2驅(qū)動(dòng)的編譯與安裝
將底層驅(qū)動(dòng)程序tel.c文件編寫(xiě)好后放入到/driver/char/mydrivers目錄下,并修改該目錄下的Kconfig和Makefile文件。由于使用動(dòng)態(tài)加載驅(qū)動(dòng)程序,所以必須先通過(guò)make menuconfig和make modules命令生成.ko文件,運(yùn)行以上兩個(gè)命令后其編譯結(jié)果如圖4所示。 然后使用adb devices和adb push命令將tel.ko文件傳送到開(kāi)發(fā)板上,并通過(guò)adb shell 命令進(jìn)入到Android Shell命令模式,即切換到開(kāi)發(fā)板,最后使用insmod 命令將tel.ko模塊加載到開(kāi)發(fā)板上。使用以上命令后,其編譯結(jié)果如圖5所示。
2.3HAL層軟件
硬件抽象層(Hardware Abstraction Layer,HAL)位于Linux內(nèi)核上面一層[5],其具體位置如圖6所示。HAL層主要用于隱藏底層驅(qū)動(dòng)的業(yè)務(wù)邏輯,即頂層調(diào)用底層驅(qū)動(dòng)的具體細(xì)節(jié),這樣就能夠擺脫Linux開(kāi)源束縛,使關(guān)于驅(qū)動(dòng)開(kāi)發(fā)的具體細(xì)節(jié)不用公開(kāi),得到保護(hù)。
編譯 HAL 層庫(kù)文件方法如下:
?。?)首先在 hardware/libhardware/include 目錄下創(chuàng)建tel.h 頭文件。tel.h頭文件主要用于定義hw_module_t、hw_device和hw_module_methods這三個(gè)重要的關(guān)系緊密的結(jié)構(gòu)體。tel.h也為HAL模塊定義了一個(gè)ID,通過(guò)這個(gè)ID來(lái)查找tel的HAL模塊。
?。?)然后需要在device/embedsky/tq21目錄下創(chuàng)建名為libwiretelephone的文件夾,在該文件夾中添加tel.c、Android.mk 兩個(gè)文件。在HAl層實(shí)現(xiàn)了所有撥號(hào)驅(qū)動(dòng)的業(yè)務(wù)邏輯, 在HAL層通過(guò)對(duì)GPIO口的控制實(shí)現(xiàn)對(duì)MT8880撥號(hào)芯片發(fā)送部分的控制,使芯片能夠發(fā)出雙音多頻(DTMF)信號(hào)。
?。?)運(yùn)行mmm device/embedsky/tq210/libtel命令生成tel.tq210.so文件,然后將文件復(fù)制到開(kāi)發(fā)板上的/system/lib/hw目錄。最后通過(guò)adb device命令和adb push命令將tel.tq210.so文件加載到開(kāi)發(fā)板上[6],運(yùn)行以上命令后,編譯結(jié)果如圖7所示。
2.4JNI層軟件
JNI(Java Native Interface)層指的是本地編程接口[7],其工作原理圖如圖8所示。主要使Java編寫(xiě)的應(yīng)用程序和用C、C++編寫(xiě)的底層驅(qū)動(dòng)及一些本地鏈接庫(kù)能夠?qū)崿F(xiàn)信息的交互。
編譯 JNI 層庫(kù)文件的方法如下:
?。?)在Android 文件系統(tǒng)下的 packages /apps 下創(chuàng)建一個(gè)名為libtel的文件夾, 再在該文件夾中創(chuàng)建 jni 文件夾,在jni文件夾中創(chuàng)建tel.cpp 和Androi d.mk 文件。在tel.cpp文件中,通過(guò)JNINativeMethod定義了JNI函數(shù)的映射。通過(guò) registe_android_server_telService(JNIEnv *env)函數(shù)將JNI程序庫(kù)與Java類(lèi)綁定,系統(tǒng)在成功裝載JNI共享庫(kù)后會(huì)自動(dòng)調(diào)用JNI_Onload函數(shù),用于初始化JNI模塊。
?。?)在packages/apps/ Wiretelephone/jni/ 目錄下運(yùn)行mmm,生成libtel.so動(dòng)態(tài)共享庫(kù)[8],然后使用cp命令將生成的文件復(fù)制到開(kāi)發(fā)板對(duì)應(yīng)的out/target/product/tq210/rootfs_dir/system/lib目錄下。最后通過(guò)adb device命令和adb push命令將tel.tq210.so文件加載到開(kāi)發(fā)板上,運(yùn)行以上命令,其編譯成功后,結(jié)果如圖9所示。
3驅(qū)動(dòng)程序測(cè)試
在TQ210開(kāi)發(fā)板中加載電話撥號(hào)程序的APP層程序后,測(cè)試驅(qū)動(dòng)能否正常運(yùn)行,實(shí)現(xiàn)其相關(guān)功能,有如下幾步:
(1)將TQ210開(kāi)發(fā)板的相關(guān)GPIO接口與示波器相連接,打開(kāi)開(kāi)發(fā)板和示波器電源,通過(guò)撥號(hào)界面撥號(hào)時(shí),示波器上出現(xiàn)對(duì)應(yīng)的電平波形,即相關(guān)GPIO接口能夠?qū)崿F(xiàn)輸出功能,內(nèi)核驅(qū)動(dòng)實(shí)現(xiàn)了對(duì)通用接口的控制。
(2)將TQ210開(kāi)發(fā)板、MT8880芯片和電話連接起來(lái),在撥號(hào)界面進(jìn)行撥號(hào), 經(jīng)測(cè)試能順利撥通,即可以控制MT8880芯片產(chǎn)生DTMF信號(hào)。
經(jīng)過(guò)以上測(cè)試,該驅(qū)動(dòng)程序?qū)崿F(xiàn)了對(duì)MT8880芯片的控制,使整個(gè)系統(tǒng)在加載了APP程序后能夠?qū)崿F(xiàn)撥號(hào)功能,如圖10所示。
4結(jié)束語(yǔ)
通過(guò)以上測(cè)試,說(shuō)明該驅(qū)動(dòng)程序能夠?qū)崿F(xiàn)對(duì)MT8880芯片的控制,即Android可以通過(guò)新增驅(qū)動(dòng)模塊識(shí)別特定設(shè)備,在加載了應(yīng)用層程序后能夠通過(guò)MT8880撥號(hào)芯片實(shí)現(xiàn)完整的DTMF信號(hào)發(fā)送功能。即通過(guò)開(kāi)發(fā)板的通用GPIO口操縱撥號(hào)控制芯片,實(shí)現(xiàn)語(yǔ)音撥號(hào)功能,可以通過(guò)在Linux Kernel中添加新的驅(qū)動(dòng)模塊,使得Android能夠識(shí)別添加的特定硬件設(shè)備。在本文基礎(chǔ)上,如果再添加來(lái)電顯示的驅(qū)動(dòng),控制MT8880的寄存器的設(shè)置,實(shí)現(xiàn)來(lái)電顯示控制,就可以組成一個(gè)完整的電話系統(tǒng)。
參考文獻(xiàn)
?。?] 宋小倩,周東升.基于 Android 平臺(tái)的應(yīng)用開(kāi)發(fā)研究[J].軟件導(dǎo)刊,2011,10(2):104-106.
[2] 宋寶華.Linux 設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解(第2版)[M].北京:人民郵電出版社,2010.
?。?] 杜江,周淵平.基于 Android的電話撥號(hào)功能[J]. 計(jì)算機(jī)系統(tǒng)應(yīng)用, 2014(12):245-248.
?。?] 姚昱旻,劉衛(wèi)國(guó).Android 的架構(gòu)與應(yīng)用開(kāi)發(fā)研究[J].計(jì)算機(jī)系統(tǒng)應(yīng)用,2008,17(11):110-112.
?。?] 李寧.Android深度探索(卷1): HAL與驅(qū)動(dòng)開(kāi)發(fā)[M].北京:人民郵電出版社,2013.
?。?] 付興武,張軍,王洋.基于 SPI 總線協(xié)議的字符設(shè)備驅(qū)動(dòng)程序[J].計(jì)算機(jī)系統(tǒng)應(yīng)用,2013(2):146150.
[7] 李寧.Android開(kāi)發(fā)權(quán)威指南(第2版)[M].北京:人民郵電出版社,2013.
?。?] 明日科技.Android 從入門(mén)到精通[M].北京:清華大學(xué)出版社, 2012.