Android HAL 粗解

谨以此文纪念过往的岁月

一.前言

在Android中采用HAL来实现硬件的抽象,在本文中来记录鄙人的一些学习过程,如有不对之处请指教。仅仅是理解HAL的底层,并不去尝试理解JAVA层。

二.HAL的三大结构体

2.1hw_device_t

对于每一个设备数据结构体都必须以该结构体开头,该结构体是所有设备的引导线,在该结构体之后才是每一个设备自己的数据。

typedef structhw_device_t{

uint32_t tag;--必须初始化为HARDWARE_DEVICE_TAG

uint32_t version;--hw_device_t版本号

struct hw_module_t* module; --指向该设备所属的module

uint32_t reserved[12];--保留

int (*close)(struct hw_device_t* device); --关闭设备

} hw_device_t;

2.2 hw_module_methods_t

该结构体仅提供一个打开特殊设备的opne函数的接口。传入参数为hw_module_t,id和hw_device_t,该函数是用于初始化hw_device_t的各成员。

typedef struct hw_module_methods_t {

int (*open)(const structhw_module_t* module, const char* id,

structhw_device_t** device);

} hw_module_methods_t;

2.3 hw_module_t

每一个硬件模块的必须申明一个HAL_MODULE_INFO_SYM的数据结构体,该结构体的第一个成员必须是以hw_module_t为数据的结构体。

typedef structhw_module_t{

uint32_t tag;--必须初始化HARDWARE_MODULE_TAG

uint16_t version_major;

uint16_t version_minor;

const char *id;--模块标示符

const char *name; --该模块的name

const char *author;

struct hw_module_methods_t* methods;--模块的方法

void* dso;

uint32_t reserved[32-7];--保留

} hw_module_t;

我们以网上很有名的led的HAL来看上面的东东。

三.HAL之Led

structled_module_t{
structhw_module_t common;--在此成员之后可以添加该module的其余操作
};
structled_control_device_t{
structhw_device_tcommon;-- hw_device_t必须是为第一个成员。
/* supporting control APIs go here */
int(*set_on)(structled_control_device_t*dev,int32_tled);
int(*set_off)(structled_control_device_t*dev,int32_tled);
};
structled_control_context_t{
structled_control_device_t device;
};

staticintled_device_open(conststructhw_module_t*module,constchar*name,structhw_device_t**device)
{
structled_control_device_t*dev;
dev=(structled_control_device_t*)malloc(sizeof(*dev));
memset(dev,0,sizeof(*dev));
dev->common.tag=HARDWARE_DEVICE_TAG;
dev->common.version=0;
dev->common.module=module;
dev->common.close=led_device_close;
dev->set_on=led_on;
dev->set_off=led_off;
*device=&dev->common;
success:
return0;
}
module操作集仅有一个函数open
staticstructhw_module_methods_t led_module_methods={
open:led_device_open
};

定义一个以HAL_MODULE_INFO_SYM为名的module结构体
conststructled_module_tHAL_MODULE_INFO_SYM={
common:{
tag:HARDWARE_MODULE_TAG,--必须如此初始化,亦如1add1=2
version_major:1,
version_minor:0,
id:LED_HARDWARE_MODULE_ID,
name:"Sample LED Stub",
author:"The Mokoid Open Source Project",
methods:&led_module_methods,--定义该module的操作集
}
/* supporting APIs go here */
};

也许大家会疑惑上面的函数在被制作成.so库后,如何调用。我们并不涉及JAVA层的种种,在此仅讲述如何在C++中调用使用的。

四.Led之C++调用

void led_open(const struct hw_module_t*module,structled_control_device_t**led_device)

{

return module->methods->open(module,NULL,(strcuthw_device_t**)led_device);

}

void led_test(void)

{

Hw_module_t const module;

hw_get_module(LED_HARDWARE_MODULE_ID, &module);

led_control_device _t*led_device;

led_open(module,&led_device);

led_device->set_on();

}

从上面的调用中也应该知道其实led_device仅仅提供了一个指针,其所指向的实体在open中开辟空间。其实这里实现了一个强制类型转换,将具体的设备数据结构体强制转换成hw_device_t结构体,这也可以从此来理解为什么hw_device_t必须定义为具体device结构体的第一个成员。将底层的操作通过该种方式来实现屏蔽。那我们来看动态链接库是如何被加载的。

#define HAL_MODULE_INFO_SYMHMI--还记否所有的设备的module名都必须声明为该值。

#define HAL_MODULE_INFO_SYM_AS_STR"HMI"

hw_get_module->load,其动态库的加载的核心为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); --打开动态库

if (handle == NULL) {

char const *err_str = dlerror();

LOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");

status = -EINVAL;

goto done;

}

const char *sym =HAL_MODULE_INFO_SYM_AS_STR;

hmi = (struct hw_module_t *)dlsym(handle, sym);--获取动态库中HMI的结构体

if (hmi == NULL) {

status = -EINVAL;

goto done;

}

if (strcmp(id, hmi->id) != 0) {

status = -EINVAL;

goto done;

}

hmi->dso = handle;

status = 0;

done:

if (status != 0) {

hmi = NULL;

if (handle != NULL) {

dlclose(handle);

handle = NULL;

}

} else {

}

*pHmi = hmi;

return status;

}

到此各位看官应该明白了在Android hardware中一些不同平台的硬件的HAL流程了吧。通过一个公用的HMI的结构体名来实现了对底层的屏蔽。这里面涉及一个很重要的概念就是所有的硬件设备抽象层都必须要有共同点,那就是hw_module_t和hw_device_t均是不同设备数据结构体的第一个成员,唯有第一个成员才能实现类型的强制转换。

五.总结

Nothing !!!

更多相关文章

  1. Android通过蓝牙HC06与Arduino通信实例
  2. 没错,你可以移动式编码了:4款最好的Android设备HTML编辑器
  3. Android(安卓)2.3 SD卡挂载流程浅析(一)
  4. Android和iPhone及Windows Mobile,Palm Pre
  5. SDK中adb工具用法
  6. android自动安装驱动
  7. 蓝牙实现签到功能(中央与周边)
  8. Google 终于要让 20 亿 Android(安卓)设备能玩上高性能的 AR 了
  9. Android设备使用USB的硬件接口

随机推荐

  1. Android Contacts(一)—— 读取联系人
  2. android 自定义控件全系列导航
  3. Android Studio导入第三方类库的方法
  4. 为什么必须要学flutter
  5. Android 应用开发推荐书单
  6. Android开发之WebView的使用(1)
  7. 更新sdk后,点击sdk管理器报出location of
  8. android动画源码合集、动态主题框架、社
  9. Android Studio安装以及Fetching android
  10. Android 动画标签——translate