1、开发Android硬件抽象层代码
~/android-2.3_r1/hardware/libhardware
----include
----hardware
----freg.h
----hareware.h
-----modules
----freg
----freg.cpp
----Android.mk
hareware.h
.........
#ifndef ANDROID_INCLUDE_HARDWARE_HARDWARE_H
#define ANDROID_INCLUDE_HARDWARE_HARDWARE_H
#include <stdint.h>
#include <sys/cdefs.h>
#include <cutils/native_handle.h>
__BEGIN_DECLS
/*
* Value for the hw_module_t.tag field
*/
#define MAKE_TAG_CONSTANT(A,B,C,D) (((A) << 24) | ((B) << 16) | ((C) << 8) | (D))
#define HARDWARE_MODULE_TAG MAKE_TAG_CONSTANT('H', 'W', 'M', 'T')
#define HARDWARE_DEVICE_TAG MAKE_TAG_CONSTANT('H', 'W', 'D', 'T')
struct hw_module_t;
struct hw_module_methods_t;
struct hw_device_t;
/**
* 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.
*/
typedef struct hw_module_t {
/** tag must be initialized to HARDWARE_MODULE_TAG */
uint32_t tag;
/** major version number for the module */
uint16_t version_major;
/** minor version number of the module */
uint16_t version_minor;
/** Identifier of module */
const char *id;
/** Name of this module */
const char *name;
/** Author/owner/implementor of the module */
const char *author;
/** Modules methods */
struct hw_module_methods_t* methods;
/** module's dso */
void* dso;
/** padding to 128 bytes, reserved for future use */
uint32_t reserved[32-7];
} hw_module_t;
typedef struct hw_module_methods_t {
/** Open a specific device */
int (*open)(const struct hw_module_t* module, const char* id,
struct hw_device_t** device);
} hw_module_methods_t;
/**
* Every device data structure must begin with hw_device_t
* followed by module specific public methods and attributes.
*/
typedef struct hw_device_t {
/** tag must be initialized to HARDWARE_DEVICE_TAG */
uint32_t tag;
/** version number for hw_device_t */
uint32_t version;
/** reference to the module this device belongs to */
struct hw_module_t* module;
/** padding reserved for future use */
uint32_t reserved[12];
/** Close this device */
int (*close)(struct hw_device_t* device);
} hw_device_t;
/**
* Name of the hal_module_info
*/
#define HAL_MODULE_INFO_SYM HMI
/**
* Name of the hal_module_info as a string
*/
#define HAL_MODULE_INFO_SYM_AS_STR "HMI"
/**
* Get the module info associated with a module by id.
* @return: 0 == success, <0 == error and *pHmi == NULL
*/
int hw_get_module(const char *id, const struct hw_module_t **module);
........
__END_DECLS
#endif /* ANDROID_INCLUDE_HARDWARE_HARDWARE_H */
hw_module_t结构体:
(1)在结构体hw_module_t的定义前面有一段注释,意思是硬件抽象层中的每一个模块都必须自定义一个硬件抽象层模块结构体,而且它的第一个成员变量的类型必须为hw_module_t。
(2)硬件抽象层中的每一个模块都必须存在一个导出符号HAL_MODULE_IFNO_SYM,即“HMI”,它指向一个自定义的硬件抽象层模块结构体。
(3)结构体hw_module_t的成员变量tag的值必须设置为HARWARE_MODULE_TAG,即设置为一个常量值('H'<<24|'W'<<16|'M'<<8|'T'),用来标志这是一个硬件抽象层模块结构体。
(4)结构体hw_module_t的成员变量dso用来保存加载硬件抽象层模块后得到的句柄值。
(5)结构体hw_module_t的成员变量methods定义了一个硬件抽象层模块的操作方法列表,它的类型为hw_module_methods_t,接下来我们就介绍它的定义。
hw_module_methods_t结构体:
(1)只有一个成员变量,它是一个函数指针,用来打开硬件抽象层模块中的硬件设备。其中,参数module表示要打开的硬件设备所在的模块;参数id表示要打开的硬件设备的ID;参数device是一个输出参数,用来描述一个已经打开的硬件设备。由于一个硬件抽象层模块可能会包含多个硬件设备。因此,在调用结构体hw_module_methods_t的成员变量open来打开一个硬件设备时,我们需要指定它的ID。
hw_device_t结构体:
(1)硬件抽象层模块中的每一个硬件设备都必须自定义一个硬件设备结构体,而且它的第一个成员变量的类型必须为hw_device_t。
(2)结构体hw_device_t的成员变量tag的值必须设置为HARDWARE_DEVICE_TAG,即设置为一个常量值('H'<<24|'W'<<16|'D'<<8|'T'),用来标志这是一个硬件抽象层中的硬件设备结构体。
(3)结构体hw_device_t的成员变量close是一个函数指针,它用来关闭一个硬件设备。
至此,硬件抽象层模块接口的编写规范就介绍完了。
freg.h
#ifndef ANDROID_FREG_INTERFACE_H
#define ANDROID_FREG_INTERFACE_H
#include <hardware/hardware.h>
__BEGIN_DECLS
/**
* The id of this module
*/
#define FREG_HARDWARE_MODULE_ID "freg"
/**
* The id of this device
*/
#define FREG_HARDWARE_DEVICE_ID "freg"
struct freg_module_t {
struct hw_module_t common;
};
struct freg_device_t {
struct hw_device_t common;
int fd;
int (*set_val)(struct freg_device_t* dev, int val);
int (*get_val)(struct freg_device_t* dev, int* val);
};
__END_DECLS
#endif
宏FREG_HARDWARE_MODULE_ID和FREG_HARDWARE_DEVICE_ID分别用来描述模块ID和设备ID。结构体freg_module_t用来描述自定义的模块结构体,它的第一个成员变量的类型为hw_module_t。结构体freg_device_t用来描述虚拟硬件设备freg,它的第一个成员变量的类型为freg_device_t。此外,结构体freg_device_t还定义了其他三个成员变量,其中,成员变量fd是一个文件描述符,用来描述打开的设备文件/dev/freg,成员变量set_val和get_val是函数指针,它们分别用来写和读虚拟硬件设备freg的寄存器val的内容。
freg.cpp
#define LOG_TAG "FregHALStub"
#include <hardware/hardware.h>
#include <hardware/freg.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
#define DEVICE_NAME "/dev/freg"
#define MODULE_NAME "Freg"
#define MODULE_AUTHOR "shyluo@gmail.com"
//因为在实现前,要用到这些函数,所以先定义
static int freg_device_open(const struct hw_module_t* module, const char* id, struct hw_device_t** device);
static int freg_device_close(struct hw_device_t* device);
static int freg_set_val(struct freg_device_t* dev, int val);
static int freg_get_val(struct freg_device_t* dev, int* val);
static struct hw_module_methods_t freg_module_methods = {
open: freg_device_open
};
struct freg_module_t HAL_MODULE_INFO_SYM = {//一个硬件抽象层模块必须导出一个名称为HAL_MODULE_INFO_SYM的符号
common: {
tag: HARDWARE_MODULE_TAG,//tag值必须设置为HARDWARE_MODULE_TAG
version_major: 1,
version_minor: 0,
id: FREG_HARDWARE_MODULE_ID,
name: MODULE_NAME,
author: MODULE_AUTHOR,
methods: &freg_module_methods,
}
};
static int freg_device_open(const struct hw_module_t* module, const char* id, struct hw_device_t** device) {
if(!strcmp(id, FREG_HARDWARE_DEVICE_ID)) {//首先要匹配ID
struct freg_device_t* dev;
dev = (struct freg_device_t*)malloc(sizeof(struct freg_device_t));//分配freg_device_t结构体
if(!dev) {
LOGE("Failed to alloc space for freg_device_t.");
return -EFAULT;
}
memset(dev, 0, sizeof(struct freg_device_t));
dev->common.tag = HARDWARE_DEVICE_TAG;//必须初始化为HARDWARE_DEVICE_TAG
dev->common.version = 0;
dev->common.module = (hw_module_t*)module;
dev->common.close = freg_device_close;//关闭函数
dev->set_val = freg_set_val;
dev->get_val = freg_get_val;
if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {
LOGE("Failed to open device file /dev/freg -- %s.", strerror(errno));
free(dev);
return -EFAULT;
}
*device = &(dev->common);
LOGI("Open device file /dev/freg successfully.");
return 0;
}
return -EFAULT;
}
static int freg_device_close(struct hw_device_t* device) {
struct freg_device_t* freg_device = (struct freg_device_t*)device;
if(freg_device) {
close(freg_device->fd);
free(freg_device);
}
return 0;
}
static int freg_set_val(struct freg_device_t* dev, int val) {
if(!dev) {
LOGE("Null dev pointer.");
return -EFAULT;
}
LOGI("Set value %d to device file /dev/freg.", val);
write(dev->fd, &val, sizeof(val));
return 0;
}
static int freg_get_val(struct freg_device_t* dev, int* val) {
if(!dev) {
LOGE("Null dev pointer.");
return -EFAULT;
}
if(!val) {
LOGE("Null val pointer.");
return -EFAULT;
}
read(dev->fd, val, sizeof(*val));
LOGI("Get value %d from device file /dev/freg.", *val);
return 0;
}
在这段代码中,最值得关注的就是模块变量HAL_MODULE_INFO_SYM的定义。按照硬件抽象层模块编写规范,每一个硬件抽象层模块必须导出一个名称为HAL_MODULE_INFO_SYM的符号,它指向一个自定义的硬件抽象层模块结构体,而且它的第一个类型为hw_module_t的成员变量tag值必须设置为HARDWARE_MODULE_TAG。除此之外,还初始化了这个硬件抽象层模块结构体的版本号、ID、名称、作者和操作方法列表等。
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_SRC_FILES := freg.cpp
LOCAL_MODULE := freg.default
include $(BUILD_SHARED_LIBRARY)
include $(BUILD_SHARED_LIBRARY),表示要将硬件抽象层模块编译成一个动态链接库文件,名称为freg.default。
2、编译
编译硬件抽象层:
生成的动态链接库文件,名称为freg.default.so,保存在out/target/product/generic/system/lib/hw目录下。
打包:
在out/target/product/gerneri目录下会生成Android系统镜像文件system.img。