HAL接口层 --- hardware模块接口
Posted Achillisjack
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HAL接口层 --- hardware模块接口相关的知识,希望对你有一定的参考价值。
下面分析一个文件hardware/libhardware/hardware.c,这个文件提供了一些函数,上层通过这些函数可以用来查找加载HAL库,
以及获取指定HAL库的模块变量;
load方法如下,
static int load(const char *id, const char *path,const struct hw_module_t **pHmi)
int status;
void *handle;
struct hw_module_t *hmi;
handle = dlopen(path, RTLD_NOW);
•••
这个接口是一个内部函数,逻辑如下:
1,首先先加载path指定的HAL动态库
2,然后通过下面的代码
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
hmi = (struct hw_module_t *)dlsym(handle, sym);
从动态库中获取模块名为HMI的模块, 在hardware/libhardware/include/hardware.h中有如下宏定义:
#define HAL_MODULE_INFO_SYM HMI
#define HAL_MODULE_INFO_SYM_AS_STR "HMI"
因此HAL模块变量必须定义成HAL_MODULE_INFO_SYM才能被正确获取;
3, 检测模块id是否匹配,匹配才能成功获取到模块变量
hw_module_exists方法如下,
static int hw_module_exists(char *path, size_t path_len,const char *name, const char *subname)
snprintf(path, path_len, "%s/%s.%s.so",HAL_LIBRARY_PATH2, name, subname);
if (access(path, R_OK) == 0)
return 0;
snprintf(path, path_len, "%s/%s.%s.so",HAL_LIBRARY_PATH1, name, subname);
if (access(path, R_OK) == 0)
return 0;
return -ENOENT;
该函数会填充path字符串,填充后path描述的路径为HAL_LIBRARY_PATHX/name.subname.so,先后判断HAL_LIBRARY_PATH2和HAL_LIBRARY_PATH1中的模块是否存在,只要有一个存在就返回0.
其中的HAL_LIBRARY_PATHX定义如下
#if defined(__LP64__)
#define HAL_LIBRARY_PATH1 "/system/lib64/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"
#else
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
#endif
hw_get_module_by_class方法如下,
int hw_get_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
int i;
char prop[PATH_MAX];
char path[PATH_MAX];
char name[PATH_MAX];
char prop_name[PATH_MAX];
•••
这个函数通过模块ID class_id获取到对应的模块变量,以上面的sensor模块为例,逻辑如下:
1, 这里的inst 为NULL,因此name 就是class_id ,sensor 模块就是SENSORS_HARDWARE_MODULE_ID(sensors)
2, 设置prop_name为ro.hardware. sensors,如果该属性存在,则用prop存储属性值,并判断HAL_LIBRARY_PATH2或HAL_LIBRARY_PATH1中是否存在模块sensors.prop.so;存在对应的模块,则跳到found;
3, 如果ro.hardware. sensors不存在,或者属性存在,但模块sensors.prop.so 不存在,则依次扫描variant_keys 这个数组中的属性是否存在,如果存在,则判断模块sensors.prop.so是否存在,一旦存在,则立马退出循环,跳到found; 这里variant_keys 数组,有4 个成员, “ro.hardware”、“ ro.product.board”、“ ro.board.platform”、“ ro.arch”。系统会通过适当的方法,根据平台、架构等给这些属性赋值,“ro.hardware”属性的属性值是在系统启动时由init 进程负责设置的。它首先会读取/proc/cmdline文件,检查里面有没有一个名为androidboot.hardware的属性,该属性在BoardConfig.mk 文件中有定义,如果有,就把它的值赋值给“ro.hardware”,高通平台即为qcom;“ ro.product.board”、“ ro.board.platform”、“ ro.arch” 属性是从/system/build.prop 文件读取出来的, 这里ro.product.board=msm8916(BoardConfig.mk 中定义了TARGET_BOARD_PLATFORM=
msm8916);/system/build.prop文件是由编译系统中的编译脚本build/core/Makefile和shell脚本build/tools/buildinfo.sh生成的,这里不再详细分析。
4, 本例中ro.product.board的属性为8916,hw_module_exists函数判断sensors.msm8916.so存在,并把模块完整路径赋值给path,然后跳到found执行中加载模块库的函数load,load 会加载path指定的模块,并从模块中获取名为HMI的变量
hw_get_module方法如下,
int hw_get_module(const char *id, const struct hw_module_t **module)
return hw_get_module_by_class(id, NULL, module);
这是标准的Android HAL接口,所有HAL模块的加载和模块变量的获取都是调用这个函数,通过指定的模块id 来指定模块.
以上是关于HAL接口层 --- hardware模块接口的主要内容,如果未能解决你的问题,请参考以下文章
实现自己的HAL-10 控制led(内核驱动的hal),从app 到 hal 到底层内核kernel层的驱动 的实现