準(zhǔn)備在QT210的android系統(tǒng)中實(shí)現(xiàn)GPS功能,程序已經(jīng)寫好了,也可以編譯出gps.s5pc110.so的庫(kù),但是不知道上層怎么調(diào)用這個(gè)庫(kù),在GPS相關(guān)的Android.mk中也沒有找到,很是納悶。通過分析hardware module才知道是怎么回事,之前并沒有詳細(xì)的了解hardware module,現(xiàn)在簡(jiǎn)單的分析一下。
HAL層的hardware module主要實(shí)現(xiàn)文件為:
hardware/libhardware/hareware.c
hardware/libhardware/include/hardware/hardware.h
重要的結(jié)構(gòu)體:
- typedef struct hw_device_t {   
 
- 
    uint32_t tag;  /** tag must be initialized to HARDWARE_DEVICE_TAG */   標(biāo)識(shí)符 
 
- 
    uint32_t version;  /** version number for hw_device_t */             版本號(hào)
 
- 
    struct hw_module_t* module;  /** reference to the module this device belongs to */   該硬件屬于哪個(gè)module
 
- 
    uint32_t reserved[12];  /** padding reserved for future use */  
 
- 
    int (*close)(struct hw_device_t* device);  /** Close this device */  關(guān)閉設(shè)備操作
 
- 
} hw_device_t;
表示一個(gè)硬件設(shè)備,存儲(chǔ)了各種硬件設(shè)備的公共屬性和方法
- typedef struct hw_module_t {   
 
- 
    uint32_t tag;   /** tag must be initialized to HARDWARE_MODULE_TAG */   標(biāo)識(shí)符
 
- 
    uint16_t version_major;  /** major version number for the module */     主版本號(hào)
 
- 
    uint16_t version_minor;  /** minor version number of the module */      次版本號(hào)
 
- 
    const char *id;   /** Identifier of module */                    id,決定了庫(kù)的文件名
 
- 
    const char *name;   /** Name of this module */                    模塊的名字
 
- 
    const char *author;  /** Author/owner/implementor of the module */   模塊作者
 
- 
    struct hw_module_methods_t* methods;  /** Modules methods */         模塊的操作方法
 
- 
    void* dso; /** module's dso */ 
 
- 
    uint32_t reserved[32-7];  /** padding to 128 bytes, reserved for future use */
 
- 
} hw_module_t;
描述一個(gè)硬件模塊
- typedef struct hw_module_methods_t {
 
- 
    int (*open)(const struct hw_module_t* module, const char* id,
 
- 
            struct hw_device_t** device);
 
- 
} hw_module_methods_t;
定義了操作設(shè)備的方法,只有一個(gè)open函數(shù)
hareware.c分析:
- /** Base path of the hal modules */   指定硬件模塊庫(kù)存放的路徑
 
- 
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
 
- 
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
下面這個(gè)用于搜索不同的庫(kù)文件名:
- /**
 
- 
 * 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",
 
- 
    "ro.product.board",
 
- 
    "ro.board.platform",
 
- 
    "ro.arch"
 
- 
};
庫(kù)的名稱要根據(jù)實(shí)際的product或board指定
在210平臺(tái)GPS模塊庫(kù)的文件名可以為:
gps.s5pc110.so
gps.ARMV7.so
gps.default.so
hw_get_module函數(shù)作用是在系統(tǒng)中查找模塊的庫(kù)文件
根據(jù)硬件模塊的id參數(shù)和指定的查找路徑,配合product,board等變量,最終指定到一個(gè)so庫(kù)文件
- int hw_get_module(const char *id, const struct hw_module_t **module) 
 
---------------------------------------------------------------------------------
- 
    /* Loop through the configuration variants looking for a module */
 
- 
    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {
 
- 
        if (i < HAL_VARIANT_KEYS_COUNT) {
 
- 
            if (property_get(variant_keys[i], prop, NULL) == 0) {
 
- 
                continue;
 
- 
            }
 
- 
            snprintf(path, sizeof(path), "%s/%s.%s.so",       //system/lib/hw/*.*.so
 
- 
                    HAL_LIBRARY_PATH1, id, prop);
 
- 
            if (access(path, R_OK) == 0) break;
 
- 
 
- 
            snprintf(path, sizeof(path), "%s/%s.%s.so",
 
- 
                     HAL_LIBRARY_PATH2, id, prop);
 
- 
            if (access(path, R_OK) == 0) break;
 
- 
        } else {
 
- 
            snprintf(path, sizeof(path), "%s/%s.default.so",    //如果沒查到硬件屬性,使用默認(rèn)的庫(kù)文件名system/lib/hw/*.default.so
 
- 
                     HAL_LIBRARY_PATH1, id);
 
- 
            if (access(path, R_OK) == 0) break;
 
- 
        }
 
- 
    }
創(chuàng)建GPS modules分析:
下面這段話很重要,說明了如何構(gòu)建一個(gè)模塊
- /**
 
- 
 * 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.
 
- 
 */
可以說這是andorid中標(biāo)準(zhǔn)的構(gòu)建模塊的寫法
- const struct hw_module_t HAL_MODULE_INFO_SYM = {
 
- 
    .tag = HARDWARE_MODULE_TAG,
 
- 
    .version_major = 1,
 
- 
    .version_minor = 0,
 
- 
    .id = GPS_HARDWARE_MODULE_ID,
 
- 
    .name = "XC-GPS Module",
 
- 
    .author = "WWW.XCEMBED.COM",
 
- 
    .methods = &hw_module_methods,
 
- 
};
通過分析hw_get_module函數(shù)我們知道,id是用來指定模塊庫(kù)文件名的,給GPS_HARDWARE_MODULE_ID賦值
#define GPS_HARDWARE_MODULE_ID  "gps"
實(shí)際上GPS_HARDWARE_MODULE_ID并不是在代碼中這樣定義的,可能是在某個(gè)編譯腳本里,我暫時(shí)還沒找到
指定methods:
- static struct hw_module_methods_t hw_module_methods = {
 
- 
    .open = open_gps
 
- 
};
只有一個(gè)open_gps函數(shù),當(dāng)模塊加載時(shí)就會(huì)執(zhí)行open_gps:
- static int open_gps(const struct hw_module_t* module, char const* name,
 
- 
                    struct hw_device_t** device)
 
- 
{
 
- 
    struct gps_device_t *gps_device = malloc(sizeof(struct gps_device_t));
 
- 
    if (gps_device)
 
- 
    {
 
- 
        memset(gps_device, 0, sizeof(*gps_device));
 
- 
        gps_device->common.tag        = HARDWARE_DEVICE_TAG;
 
- 
        gps_device->common.version    = 0;
 
- 
        gps_device->common.module     = (struct hw_module_t*)module;
 
- 
        gps_device->get_gps_interface = gps_get_hardware_interface;
 
- 
 
- 
        *device = (struct hw_device_t*)gps_device;
 
- 
 
- 
        return 0;
 
- 
    }
 
- 
 
- 
    return 1; 
 
- 
}
每個(gè)硬件設(shè)備都應(yīng)該有一個(gè)類似xxxx_device_t的結(jié)構(gòu)體,里面包含了hw_device_t
gps的設(shè)備結(jié)構(gòu)體定義如下:
- struct gps_device_t {
 
- 
    struct hw_device_t common;
 
- 
    const GpsInterface* (*get_gps_interface)(struct gps_device_t* dev);
 
- 
};
在open函數(shù)中給這個(gè)模塊所包含的hw_device_t賦值
get_gps_interface函數(shù)用來得到GPS的操作接口
- const GpsInterface* gps_get_hardware_interface(struct gps_device_t* dev)
 
- 
{
 
- 
    return &_GpsInterface;
 
- 
}
接下來,程序的主體部分就是實(shí)現(xiàn)_GpsInterface里面所定義的所有操作
HAL層的模塊是由具體的上一層JNI來調(diào)用,關(guān)于怎么調(diào)用的,下一篇分析GPS module時(shí)再說,我也不是很清楚,再整理一下