基于安卓的非標(biāo)準(zhǔn)驅(qū)動(dòng)程序設(shè)計(jì)
從LED控制功能的架構(gòu)來(lái)分,整個(gè)功能可以分成五個(gè)模塊:LED驅(qū)動(dòng)模塊、LED Stub模塊、LED本地服務(wù)模塊、LED服務(wù)管理模塊和LED應(yīng)用模塊。
2.2 HAL中的Stub的設(shè)計(jì)與實(shí)現(xiàn)
圖4是LED Stub的實(shí)現(xiàn)過(guò)程。LED Stub是硬件抽象層中LED控制的代理,當(dāng)LED控制的本地服務(wù)需要調(diào)用LED Stub時(shí),通過(guò)函數(shù)hw_get_module( )結(jié)合LED Stub的模塊ID向HAL申請(qǐng)LED Stub,本地服務(wù)獲得Stub對(duì)象后,可以把Stub看作一個(gè)抽象硬件進(jìn)行操作。
下面是定義LED Stub的HAL結(jié)構(gòu)體:
struct led_module_t {
struct hw_module_t common;
}
struct led_module_t {
struct hw_module_t common;
int fd;
int(*ns_set_on)(struct led_control_device_t*dev,int32_t led);
int(*ns_set_off)(struct led_control_device_t*dev,int32_t led);
}
將結(jié)構(gòu)體led_module_t初始化一個(gè)實(shí)例名為HAL_MODULE_INFO_SYM,這個(gè)名稱不能修改,實(shí)例里包含了Stub的模塊信息,主要包括:
tag:標(biāo)記了結(jié)構(gòu)體的類型,這里的值為HARDWARE_MODULE_TAG;
id:LED Stub的模塊ID,在本地服務(wù)向HAL獲取Stub時(shí)調(diào)用的函數(shù)hw_get_module()中,通過(guò)這里的id查找LED Stub;
methods:是結(jié)構(gòu)體hw_module_methods_t的實(shí)例,為HAL定義回調(diào)函數(shù)open()。
這里的open()函數(shù)是一個(gè)必須實(shí)現(xiàn)的回調(diào)函數(shù)接口,在本地服務(wù)獲得Stub對(duì)象后調(diào)用,它負(fù)責(zé)申請(qǐng)結(jié)構(gòu)體led_control_device_t的空間,填充信息,注冊(cè)具體操作的回調(diào)函數(shù)接口并打開(kāi)LED驅(qū)動(dòng)。
結(jié)構(gòu)體led_control_device_t繼承了hw_device_t,在open()函數(shù)調(diào)用時(shí)填充的主要信息包括:
tag:結(jié)構(gòu)體的類型,這里的值為HARDWARE_DEVICE_TAG;
module:Stub的模塊,也就是實(shí)例HAL_MODULE_INFO_SYM中的hw_module_t部分;
close:釋放LED Stub的回調(diào)函數(shù);
fd:打開(kāi)設(shè)備驅(qū)動(dòng)文件返回的文件描述符;
ns_set_on:打開(kāi)LED燈的回調(diào)函數(shù)指針;
ns_set_off:關(guān)閉LED燈的回調(diào)函數(shù)指針。
回調(diào)函數(shù)指針“*ns_set_on”和“*ns_set_off”分別指向?qū)崿F(xiàn)函數(shù)hal_ led_on()和hal_led_off(),在實(shí)現(xiàn)函數(shù)中通過(guò)系統(tǒng)調(diào)用ioctl()對(duì)LED燈進(jìn)行開(kāi)關(guān)控制。
2.3 硬件控制服務(wù)的JNI實(shí)現(xiàn)
LED控制本地庫(kù)編譯后為“l(fā)ibled.so”保存在Android文件系統(tǒng)的“/sysem/lib/”目錄下面,LED控制服務(wù)的Android進(jìn)程運(yùn)行后由虛擬機(jī)實(shí)例裝入本地庫(kù),具體實(shí)現(xiàn)過(guò)程如圖5所示。
LED控制服務(wù)調(diào)用System.load()函數(shù),它的虛擬機(jī)實(shí)例就會(huì)裝入LED控制本地庫(kù),虛擬機(jī)會(huì)首先調(diào)用 JNI_OnLoad()函數(shù)完成:
(1) 把虛擬機(jī)環(huán)境信息保存到本地庫(kù)的一個(gè)結(jié)構(gòu)體“JNIEnv”的實(shí)例中;
(2) 建立一個(gè)應(yīng)用層中的LED控制服務(wù)與本地庫(kù)的JNI函數(shù)表;
(3) 返回虛擬機(jī)本地庫(kù)使用的JNI版本。
加載完后,應(yīng)用層中的LED控制服務(wù)就可以通過(guò)虛擬機(jī)中的JNI函數(shù)表把運(yùn)行的Java函數(shù)轉(zhuǎn)換為本地函數(shù)執(zhí)行。在LED控制服務(wù)類中定義有JNI函數(shù)的方式,例如下面的代碼段:
public final class LedService extends IledService.Stub {
…….
static {
System.load(“/system/lib/libled.so”);
}
……
private static native boolean as_init();
private static native boolean as_set_on(int led);
private static native boolean as_set_off(int led);
}
本文的研究工作是在S3C2440開(kāi)發(fā)板上進(jìn)行的,以給開(kāi)發(fā)板上的LED燈增加驅(qū)動(dòng)程序?yàn)槔?,展示了一種為Android平臺(tái)非標(biāo)準(zhǔn)硬件增加驅(qū)動(dòng)程序的設(shè)計(jì)方案,對(duì)于實(shí)現(xiàn)其他設(shè)備的驅(qū)動(dòng)具有一定的借鑒意義。由于各種硬件設(shè)備及其接口差異較大,本文著重于驅(qū)動(dòng)程序的設(shè)計(jì)方案,沒(méi)有討論相關(guān)的硬件接口驅(qū)動(dòng)細(xì)節(jié)。隨著Android平臺(tái)日漸成熟以及應(yīng)用數(shù)量的增加,它在嵌入式領(lǐng)域的應(yīng)用范圍將會(huì)更加廣泛。為Android設(shè)備編寫不同于標(biāo)準(zhǔn)Linux系統(tǒng)的設(shè)備驅(qū)動(dòng)程序會(huì)變得越來(lái)越多。
評(píng)論