代码编写
接下来我们就来为我们上上节实现的玩具驱动写一个简单的 HAL 模块。
在 hardware/libhardware/include/hardware
目录下添加 hello_hal.h
:
cpp
#ifndef _HARDWARE_HELLO_HAL_H
#define _HARDWARE_HELLO_HAL_H
#include <hardware/hardware.h>
__BEGIN_DECLS
#define HELLO_HAL_API_VERSION HARDWARE_MODULE_API_VERSION(1,0)
#define HELLO_HAL_HARDWARE_MODULE_ID "hello_hal"
#define HELLO_HAL_DEVICE_ID_MAIN "main_hello_hal"
struct hello_hal_device_t;
typedef struct hello_hal_device_t {
struct hw_device_t common;
int (*hello_hal_open)(struct hello_hal_device_t* hello_hal_dev);
int (*hello_hal_read)(struct hello_hal_device_t* hello_hal_dev, char* str);
int (*hello_hal_write)(struct hello_hal_device_t* hello_hal_dev,const char* str);
} hello_hal_device_t;
static inline int hello_hal_methods_open(const struct hw_module_t* module, hello_hal_device_t** device)
{
return module->methods->open(module, HELLO_HAL_DEVICE_ID_MAIN, (struct hw_device_t**)device);
}
__END_DECLS
#endif // _HARDWARE_VIBRATOR_H
这里的核心是:
- 实现一个 hello_hal_device_t 结构体,这个结构体用于操作具体的硬件
- 实现 hello_hal_methods_open 函数,这个函数用于从 hw_module_t 从找到 hello_hal_device_t 结构体实例
接着在 hardware/libhardware/modules/
目录下添加 hello_hal 目录,并在 hello_hal 目录下添加源码文件 hello_hal.c
:
cpp
#include <hardware/hello_hal.h>
#include <hardware/hardware.h>
#include <cutils/log.h>
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
int fd;
int hello_open (struct hello_hal_device_t* hello_hal_dev) {
fd = open("/dev/hello", O_RDWR);
if (fd == -1)
{
printf("can not open file /dev/hello\n");
return -1;
}
return 0;
}
int hello_close (struct hello_hal_device_t* hello_hal_dev) {
close(fd);
free(hello_hal_dev);
return 0;
}
int hello_read (struct hello_hal_device_t* hello_hal_dev, char* str) {
char buf[1024];
int len = read(fd, buf, 1024);
if (len > 0)
{
buf[1023] = '\0';
str = buf;
return len;
} else {
return -1;
}
}
int hello_write (struct hello_hal_device_t* hello_hal_dev,const char* str) {
int len = strlen(str) + 1;
len = len < 1024 ? len : 1024;
return write(fd, str, len);
}
static int hello_hal_open(const hw_module_t* module, const char* id __unused,
hw_device_t** device __unused) {
hello_hal_device_t *hello_hal_dev = calloc(1, sizeof(hello_hal_device_t));
if (!hello_hal_dev) {
ALOGE("Can not allocate memory for the hello hal device");
return -ENOMEM;
}
hello_hal_dev->common.tag = HARDWARE_DEVICE_TAG;
hello_hal_dev->common.module = (hw_module_t *) module;
hello_hal_dev->common.version = HARDWARE_DEVICE_API_VERSION(1,0);
hello_hal_dev->common.close = hello_close;
hello_hal_dev->hello_hal_open = hello_open;
hello_hal_dev->hello_hal_write = hello_write;
hello_hal_dev->hello_hal_read = hello_read;
*device = (hw_device_t *) hello_hal_dev;
return 0;
}
static struct hw_module_methods_t hello_hal_module_methods = {
.open = hello_hal_open,
};
struct hw_module_t HAL_MODULE_INFO_SYM = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = HELLO_HAL_API_VERSION,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = HELLO_HAL_HARDWARE_MODULE_ID,
.name = "Default Hello HAL",
.author = "ahaoframework",
.methods = &hello_hal_module_methods,
};
- 声明一个 hw_module_t 结构体实例
- 申明一个 hw_module_methods_t 结构体实例,其中 open 函数指针指向 hello_hal_open
- hello_hal_open 会构建一个 hello_hal_device_t 结构体实例,对其成员赋值,核心的成员主要是 hello_hal_open hello_hal_write hello_hal_read 三个函数指针
编译系统配置
接着在 hardware/libhardware/modules/hello_hal
目录下添加 Android.mk
Makefile
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello_hal.default
# HAL module implementation stored in
# hw/<VIBRATOR_HARDWARE_MODULE_ID>.default.so
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_C_INCLUDES := hardware/libhardware
LOCAL_SRC_FILES := hello_hal.c
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
接着在 hardware/libhardware/modules/Android.mk
中添加 hello_hal,这样编译系统才会去编译 hello_hal 模块。
Makefile
hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time \
power usbaudio audio_remote_submix camera usbcamera consumerir sensors vibrator hello_hal \
tv_input fingerprint input vehicle thermal vr
include $(call all-named-subdir-makefiles,$(hardware_modules))
接着在 product 配置文件 build/target/board/generic_x86_64/device.mk
中添加 hello_hal.default 库:
Makefile
PRODUCT_PACKAGES := \
audio.primary.goldfish \
hello_hal.default \
vibrator.goldfish \
至此,完工