新增LED设备--从上层到底层理解安卓架构之HAL篇
扫描二维码
随时随地手机看文章
硬件抽象层介绍
+
1)不是所有的硬件设备都有标准的Linux内核接口,通过HAL层封装了一套固定的向上接口,可以使得上层的开发逻辑更清晰简单。HAL框架是固定的,开发人员只需要按照框架开发即可,无需关注与上层的交互上,将精力放在HAL层本身的实现上即可。
2)从商业角度,硬件厂商可以把一些核心的算法、调试参数、实现逻辑等放在HAL层而不是kenel层,kenel层只是简单与硬件做数据交互。这样的好处是可以不用遵Linux的GPL开源协议,保护自身的商业机密。
Hal架构图
模块类型结构体hw_module_t,设备类型结构体hw_device_t,
两个结构体的详细内容可以参考源码路径:/hardware/libhardware/include/hardware/hardware.h。HAL层开发主要工作是建立好自定义的结构体,并实现hw_device_t的内部的几个关键函数。
头文件hardware/libhardware/include/hardware/testled_hal.h
struct testled_module_t {
struct hw_module_t common;
};
struct testled_device_t {
struct hw_device_t common;
int (*open)(void);
int (*control)(int on);
};
头文件内申明了led的两个关键结构体testled_module_t和testled_device_t,结构体的实现在c文件中。
2)c文件 hardware/libhardware/modules/testled/testled_hal.c
//日志的标签
static int fd;
int testled_hal_dev_close(struct hw_device_t *device)
{
if(device != NULL)
{
struct testled_device_t *temp = (struct testled_device_t *)device;
free(temp);
}
close(fd);
return 0;
}
int testled_hal_open_dev(void)
{
ALOGD("--%s--", __func__);
fd = open("/dev/test-led", O_RDWR);
if(fd < 0)
{
ALOGE("open failed : %s", strerror(errno));
return fd;
}
return 0;
}
int testled_hal_control_dev(int on)
{
ALOGD("--%s--", __func__);
int ret;
switch(on){
case 0:
ret = ioctl(fd, LED1CTRL_ON_CMD,0);
break;
case 1:
ret = ioctl(fd, LED1CTRL_OFF_CMD,0);
break;
case 2:
ret = ioctl(fd, LED2CTRL_ON_CMD,0);
break;
case 3:
ret = ioctl(fd, LED2CTRL_OFF_CMD,0);
break;
default:
break;
}
if(ret < 0){
ALOGE("control failed : %s", strerror(errno));
return ret;
}
return 0;
}
int testled_hal_module_open(const struct hw_module_t *module, const char *id,
struct hw_device_t **device)
{
ALOGD("--%s--", __func__);
struct testled_device_t *led_dev = NULL;
led_dev = (struct testled_device_t *)malloc(sizeof(struct testled_device_t));
if (led_dev == NULL)
{
ALOGE("malloc failed");
return -1;
}
ALOGD("malloc success");
//初始化device对象
led_dev->common.tag = HARDWARE_DEVICE_TAG;
led_dev->common.version = 1;
led_dev->common.module = module;
led_dev->common.close = testled_hal_dev_close;
led_dev->open = testled_hal_open_dev;
led_dev->control = testled_hal_control_dev;
//将当前的led_dev传递给jni层
(struct hw_device_t *)led_dev; =
return 0;
}
struct testled_device_t testled_hal_methods = {
open : testled_hal_module_open,
};
struct testled_module_t HAL_MODULE_INFO_SYM = {
common : {
tag : HARDWARE_MODULE_TAG,
version_major : 1,
version_minor : 0,
id : LED_HAL_MODULE_ID,
name : "testled hal module",
methods : &testled_hal_methods,
},
};
主要实现了hal结构体中的close,open,control函数,并将函数传给结led_dev构体。
common.close = testled_hal_dev_close;
led_dev->open = testled_hal_open_dev;
control = testled_hal_control_dev;
Android.mk hardware/libhardware/modules/testled/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := testled_hal.default
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SRC_FILES := testled_hal.c
LOCAL_SHARED_LIBRARIES := liblog libcutils
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
将c文件编译成模块
hardware/libhardware/modules/Android.mk内加入testled
三、编译
模块编译
mmm hardware/libhardware/modules/ testled
在out/target/product/nanopc-t4/system/lib/hw/ 目录下生生成test_led_hal.default.so
全部编译后,test_led_hal.default.so在设备的/system/lib/hw路径下,android frameworks中的JNI调用led设备时,通过一系列转换就会调用到这个库内部的函数,从而调动掉底层的led驱动。
扫码关注我们
看更多嵌入式案例
喜欢本篇内容请给我们点个再看
免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!