HAL层中文名称又叫硬件抽象层,可以理解我Linux驱动的应用层。本文实现了一个简单的hello HAL的代码,衔接hello驱动和hello JNI:
http://blog.csdn.net/eliot_shao/article/details/51860229
Android标准架构实例分析之编写最简单的hello驱动
HAL层的代码会使用open read write等系统调用操作驱动层的文件系统(dev、sysfs、proc),同时它也有自己的数据结构,为上层提供接口,并导出和本体模块相关ID号。上层可以使用hw_get_module获得HAL中写的方法。其实如果不是为了避开Linux的GPL开源协议,HAL层可以不用,直接使用JNI层或者在Java代码中访问操作驱动层的文件系统(dev、sysfs、proc)也是可行的。
详细原理可以参考:
http://blog.csdn.net/eliot_shao/article/details/50461738
1、编写HAL层头文件
2、填充相关的结构体
首先我们要知道关于HAL的三点要求:
1、 每一个hardware硬件模块都有一个ID;
2、 每一个hardware模块必须有一个继承struct hw_module_t common;的结构体;
3、 每一个hardware模块必须有一个继承struct hw_device_t common;的结构体;
struct hw_module_t的继承者担负了“联络员”的任务,在/system/lib/hw下面有若干hardware module,本地框架层通过ID找到对应的模块。
struct hw_device_t的继承者承担了对驱动操作方法的包装的任务。
struct hw_module_t和struct hw_device_t的内容定义在:
hardware\libhardware\include\hardware\hardware.h
所以我们的hello.h内容如下:
#ifndef ANDROID_HELLO_INTERFACE_H
#define ANDROID_HELLO_INTERFACE_H
#include
__BEGIN_DECLS
#define HELLO_HARDWARE_MODULE_ID "hello"//ID
struct hello_module_t {
struct hw_module_t common;
};//hw_module_t的继承者
struct hello_device_t {
struct hw_device_t common;
int fd;
int (*set_val)(struct hello_device_t* dev, int val);
int (*get_val)(struct hello_device_t* dev, int* val);
};//hw_device_t的继承者
__END_DECLS
#endif
我们总结一下硬件具体的调用流程,也是hardware层的工作流程:
1、 通过ID找到硬件模块,struct hw_module_t common的结构体的继承者;
2、 通过硬件模块找到hw_module_methods_t,打开操作,获得设备的hw_device_t;
3、 调用hw_device_t中的各种操作硬件的方法;
4、 调用完成,通过hw_device_t的close关闭设备。
HAL规定了需要创一个名为HAL_MODULE_INFO_SYM结构体,如下:
struct hello_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag= HARDWARE_MODULE_TAG,
//.module_api_version = FINGERPRINT_MODULE_API_VERSION_2_0,
.hal_api_version= HARDWARE_HAL_API_VERSION,
.id = HELLO_HARDWARE_MODULE_ID,
.name = "Demo shaomingliang hello HAL",
.author = "The Android Open Source Project",
.methods= &hello_module_methods,
},
};
填充struct hw_module_t common 并对其成员 methods进行赋值:
.methods= &hello_module_methods,
hello_module_methods的定义如下:
static struct hw_module_methods_t hello_module_methods = {
.open = hello_device_open,
};
在 hello_device_open
对 struct hello_device_t
进行填充。
下面是抽象层hello.c的详细代码:
#define LOG_TAG "HelloStub"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MODULE_NAME "Hello"
char const * const device_name = "/dev/hello" ;
static int hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);
static int hello_device_close(struct hw_device_t* device);
static int hello_set_val(struct hello_device_t* dev, int val);
static int hello_get_val(struct hello_device_t* dev, int* val);
static struct hw_module_methods_t hello_module_methods = {
.open = hello_device_open,
};
static int hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device)
{
struct hello_device_t* dev;
char name_[64];
//pthread_mutex_t lock;
dev = (struct hello_device_t*)malloc(sizeof(struct hello_device_t));
if(!dev) {
ALOGE("Hello Stub: failed to alloc space");
return -EFAULT;
}
ALOGE("Hello Stub: hello_device_open eliot_shao");
memset(dev, 0, sizeof(struct hello_device_t));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (hw_module_t*)module;
dev->common.close = hello_device_close;
dev->set_val = hello_set_val;
dev->get_val = hello_get_val;
//pthread_mutex_lock(&lock);
dev->fd = -1 ;
snprintf(name_, 64, device_name, 0);
dev->fd = open(name_, O_RDWR);
if(dev->fd == -1) {
ALOGE("Hello Stub:eliot failed to open %s !-- %s.", name_,strerror(errno));
free(dev);
return -EFAULT;
}
//pthread_mutex_unlock(&lock);
*device = &(dev->common);
ALOGI("Hello Stub: open HAL hello successfully.");
return 0;
}
static int hello_device_close(struct hw_device_t* device) {
struct hello_device_t* hello_device = (struct hello_device_t*)device;
if(hello_device) {
close(hello_device->fd);
free(hello_device);
}
return 0;
}
static int hello_set_val(struct hello_device_t* dev, int val) {
ALOGI("Hello Stub: set value to device.");
write(dev->fd, &val, sizeof(val));
return 0;
}
static int hello_get_val(struct hello_device_t* dev, int* val) {
if(!val) {
ALOGE("Hello Stub: error val pointer");
return -EFAULT;
}
read(dev->fd, val, sizeof(*val));
ALOGI("Hello Stub: get value from device");
return 0;
}
struct hello_module_t HAL_MODULE_INFO_SYM = {
.common = {
.tag = HARDWARE_MODULE_TAG,
//.module_api_version = FINGERPRINT_MODULE_API_VERSION_2_0,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = HELLO_HARDWARE_MODULE_ID,
.name = "Demo shaomingliang hello HAL",
.author = "The Android Open Source Project",
.methods = &hello_module_methods,
},
};
Android.mk 的详细代码如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello.default
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SRC_FILES := hello.c
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
将hal的代码放到如下位置:
hardware\libhardware\modules\hello\hello.c
hardware\libhardware\modules\hello\Android.mk
hardware\libhardware\include\hardware\hello.h
执行:mmm hardware\libhardware\modules\hello\
将会在system/lib/hw/下生成一个hello.default.so!