Android的硬體抽象層模組編寫規範

陳洪波發表於2015-08-24
版權宣告:您好,轉載請留下本人部落格的地址,謝謝 https://blog.csdn.net/hongbochen1223/article/details/47950221

硬體抽象層模組編寫規範

Android系統的硬體抽象層以模組的形式來管理各個硬體訪問介面.每一個硬體模組都對應有一個動態連結庫檔案.這些動態連結庫檔案的命令需要符合一定的規範.同時,在系統內部,每一個硬體抽象層模組都使用結構體hw_module_t來描述,而硬體裝置則使用結構體hw_device_t來描述.下面我們跟著老羅來學習描述硬體抽象層模組檔案的命名規範以及結構體hw_module_t和hw_device_t的定義.

1:硬體抽象層模組檔案命名規範
硬體抽象層模組檔案的命名規範定義在hardware/libhardware/hardware.c檔案中.

/**
 * There are a set of variant filename for modules. The form of the filename
 * is "<MODULE_ID>.variant.so" so for the led module the Dream variants 
 * of base "ro.product.board", "ro.board.platform" and "ro.arch" would be:
 *
 * led.trout.so
 * led.msm7k.so
 * led.ARMV6.so
 * led.default.so
 */
static const char *variant_keys[] = {
    "ro.hardware",  /* This goes first so that it can pick up a different
                       file on the emulator. */
    "ro.product.board",
    "ro.board.platform",
    "ro.arch"
};

這段程式碼和註釋的意思是,硬體抽象層模組檔案的命名規範為".variant.so",其中,MODULE_ID表示模組的ID,variant表示四個系統屬性ro.hardware,ro.product.board,ro.board.platform,ro.arch 之一.系統在載入硬體抽象層模組的時候,以此按照ro.hardware,ro.product.board,ro.board.platform,ro.arch的順序來取他們的屬性值.如果其中的一個屬性存在,那麼就把他的值作為variant的值,然後在檢查對應的檔案是否存在,如果存在,那麼就找到要載入的硬體抽象層模組檔案了.否則,就繼續找下一個系統屬性.如果這四個系統屬性都不存在,或者對應這四個系統屬性的硬體抽象層模組檔案不存在,那麼就使用”MODULE_ID.default.so”來作為要載入的硬體抽象層模組檔案的名稱.

系統屬性ro.hardware是在系統啟動時,由init程式負責設定.它首先會讀取/proc/cmdline檔案,檢查裡面有沒有一個名稱為androidboot.hardware的屬性,如果有,就把他的值作為屬性ro.hardware的值,否則,就將/proc/cpuinfo檔案的內容讀取出來,並且將裡面的硬體資訊解析出來,即將Hardware欄位的內容作為屬性ro.hardware的值.例如,在Android模擬器中,從/proc/cpuinfo檔案讀取出來的Hardware欄位內容為goldfish,於是,init程式會將屬性ro.hardware的值設定為”goldfish”.系統屬性ro.product.board,ro.board.platform,ro.arch是從/system/build.prop檔案讀取出來的.檔案/system/build.prop是由編譯系統中的編譯指令碼build/core/Makefile和Shell指令碼build/tools/buildinfo.sh生成的.

2:硬體抽象層模組結構體定義規範

結構體hw_module_t和hw_device_t以及其相關的其他結構體定義在檔案hardware/libhardware/include/hardware/hardware.h中.

/**
 * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
 * and the fields of this data structure must begin with hw_module_t
 * followed by module specific information.
 *
 * 每一個硬體模組肯定會有一個名為HAL_MODULE_INFO_SYM的資料結構,並且
 * 這個資料結構的域一定是以hw_module_t開始,後面跟著模組特殊的資訊.
 *
 */
typedef struct hw_module_t {
    /** tag must be initialized to HARDWARE_MODULE_TAG */
    /** tag一定要被初始化為HARDWARE_MODULE_TAG  */
    uint32_t tag;
    /** major version number for the module */
    /** 這個模組的主版本號碼  */  
    uint16_t version_major;
    /** minor version number of the module */
    /** 這個模組的小版本號 */
    uint16_t version_minor;
    /** Identifier of module */
    /** 模組的識別符號 */
    const char *id;
    /** Name of this module */
    /** 這個模組的名稱 */
    const char *name;
    /** Author/owner/implementor of the module */
    /** 這個模組的作者/擁有者/實現者 */
    const char *author;
    /** Modules methods */
    /** 模組方法 */
    struct hw_module_methods_t* methods;
    /** module`s dso */
    /** 模組的dso */
    void* dso;
    /** padding to 128 bytes, reserved for future use */
    /** 填充到128位元組,為以後的使用所保留 */
    uint32_t reserved[32-7];
} hw_module_t;

結構體hw_module_t中的每一個成員的註釋都已經在上面翻譯了,不過,有幾個點需要注意:

1):在結構體hw_module_t的定義前面有一段註釋,意思是硬體抽象層中的每一個模組都必須自定義一個硬體抽象層模組結構體,而且他的第一個成員變數的型別必須為hw_module_t.

2):硬體抽象層每一個模組都必須存在一個匯出符號HAL_MODULE_INFO_SYM,即HMI,他指向一個自定義的硬體抽象層模組結構體.

3):結構體hw_module_t的成員變數tag的值必須設定為HARDWARE_MODULE_TAG,即設定為一個常量值(‘H’ << 24 | ‘W’ << 16 | ‘M’ << 18 | ‘T’),用來標誌這是一個硬體抽象層結構體.

4):結構體hw_module_t的成員變數dso用來儲存載入硬體抽象層模組後得到的控制程式碼值.前面提到,每一個硬體抽象層都對應一個動態連結庫檔案.載入硬體抽象層模組的過程實際上就是呼叫dlopen函式來載入與其對應的動態連結庫檔案的過程.在呼叫dlclose函式來解除安裝這個硬體抽象層模組的時候,要用到這個控制程式碼值,因此,我們在載入時需要將他儲存起來.

5):結構體hw_module_t的成員變數定義了一個硬體抽象層模組的操作方法列表,他的類悉為hw_module_methods_t.

typedef struct hw_module_methods_t {
    /** Open a specific device */
    /** 開啟一個特定的裝置 */
    int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);
} hw_module_methods_t;

結構體hw_module_methods_t只有一個成員變數,他是一個函式指標,用來開啟硬體抽象層模組中的硬體裝置.其中,引數module表示要開啟的硬體裝置所在的模組,引數id表示要開啟的裝置的ID,引數device是一個輸出引數,用來描述一個已經開啟的硬體裝置.由於一個硬體抽象層模組可能包含多個裝置硬體,因此,在呼叫結構體hw_moduel_methods_t的成員變數open來開啟一個硬體裝置的時候,我們需要指定他的ID.硬體抽象層中的硬體裝置使用結構體hw_device_t來描述.


/**
 * Every device data structure must begin with hw_device_t
 * followed by module specific public methods and attributes.
 *
 * 每一個裝置資料結構都是以hw_device_t開始的,後面跟著模組特定的
 * 公共方法和屬性.
 */
typedef struct hw_device_t {
    /** tag must be initialized to HARDWARE_DEVICE_TAG */
    /** tag一定要被初始化為HARDWARE_DEVICE_TAG */
    uint32_t tag;
    /** version number for hw_device_t */
    /** hw_device_t的版本號 */
    uint32_t version;
    /** reference to the module this device belongs to */
    /** 該裝置所屬模組的引用 */
    struct hw_module_t* module;
    /** padding reserved for future use */
    /** 擴充套件後面使用 */
    uint32_t reserved[12];
    /** Close this device */
    /** 關閉這個裝置 */
    int (*close)(struct hw_device_t* device);
} hw_device_t;

1):硬體抽象層模組中的每一個硬體裝置都必須自定義一個硬體裝置結構體,而且他的第一個成員變數引數為hw_device_t

2):構體hw_device_t的成員變數tag的值必須設定為HARDWARE_DEVICE_TAG,即設定為一個常量值(‘H’ << 24 | ‘W’ << 16 | ‘M’ << 18 | ‘T’),用來標誌這是一個硬體抽象層中的硬體裝置結構體.

3):結構體hw_device_t中的成員變數close是一個函式指標,他用來關閉一個硬體裝置.

注意:硬體抽象層中的硬體裝置是由其所在的模組提供介面來開啟的,而關閉則是由硬體裝置自身提供的介面來完成的.


相關文章