kernel层往上就是HAL层了
先把原网址贴上来
三. 在Android硬件抽象层增加接口模块访问硬件驱动程序。
硬件抽象层HAL有着及其关键的作用,对下封装kernel,对上提供接口
1>头文件hello.h是要建立在hardware/libhardware/include/hardware目录下的
接口结构体里的set_val和get_val函数就是对下封装,对上提供接口的函数
下面实现他们
但是hello_device_open函数是最初就会被调用到的
3>Makefile
hello目录下新建Makefile文件
照原来的做法是这样的
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 := hello.c
LOCAL_MODULE := hello.default
include $(BUILD_SHARED_LIBRARY)
部分编译是没有错的,64bit编译环境下也确实可以在out/target/product/Z00L/system/lib64/hw/生成我们想要的hello.default.so文件
然后把他push到手机的/system/lib64/hw/下,自认为没有问题了,可是当所有工作都完成后,调用总是不能成功,
去抓取log会发现有一个这样的错误
是Makefile文件的问题,
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
这句话是针对32位编译环境的,应该这样改
LOCAL_MODULE_RELATIVE_PATH := hw
改完发现还是报同样的错,对比同目录其他文件夹下的Makefile文件,于是又改了一句话
把LOCAL_SHARED_LIBRARIES := liblog 后面添加一个词,libcutils
也就是改为
LOCAL_SHARED_LIBRARIES := liblog libcutils
重新push后就可以成功了
先把原网址贴上来
三. 在Android硬件抽象层增加接口模块访问硬件驱动程序。
硬件抽象层HAL有着及其关键的作用,对下封装kernel,对上提供接口
1>头文件hello.h是要建立在hardware/libhardware/include/hardware目录下的
#ifndef ANDROID_HELLO_INTERFACE_H
#define ANDROID_HELLO_INTERFACE_H
#include <hardware/hardware.h>
__BEGIN_DECLS
/*定义模块ID*/
#define HELLO_HARDWARE_MODULE_ID "hello"
/*硬件模块结构体*/
struct hello_module_t
{
struct hw_module_t common;
};
/*硬件接口结构体*/
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);
};
__END_DECLS
#endif
其中定义模块ID,HELLO_HARDWARE_MODULE_ID,定义硬件模块结构结构体hello_module_t,
定义硬件接口结构体hello_device_t,都是有重要意义的接口结构体里的set_val和get_val函数就是对下封装,对上提供接口的函数
下面实现他们
2>在hardware/libhardware/modules目录下添加添加hello文件夹并建立hello.c文件
#define LOG_TAG "HelloStub"
#include <hardware/hardware.h>
#include <hardware/hello.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/log.h>
#include <cutils/atomic.h>
#define DEVICE_NAME "/dev/hello"
#define MODULE_NAME "Hello"
#define MODULE_AUTHOR "shyluo@gmail.com"
/*设备打开和关闭接口*/
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
};
/*模块实例变量*/
struct hello_module_t HAL_MODULE_INFO_SYM =
{
common:
{
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: HELLO_HARDWARE_MODULE_ID,
name: MODULE_NAME,
author: MODULE_AUTHOR,
methods: &hello_module_methods,
}
};
static int hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) {
struct hello_device_t* dev;
dev = (struct hello_device_t*)malloc(sizeof(struct hello_device_t));
ALOGI("jessietest~~~HAL~~init");
if(!dev)
{
ALOGE("jessietest~~~Hello Stub: failed to alloc space");
return -EFAULT;
}
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;
if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1)
{
ALOGE("jessietest~~~Hello Stub: failed to open /dev/hello -- %s.", strerror(errno));
free(dev);
return -EFAULT;
}
*device = &(dev->common);
ALOGI("jessietest~~~Hello Stub: open /dev/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);
}
ALOGI("jessietest~~~Hello Stub: close /dev/hello successfully.");
return 0;
}
static int hello_set_val(struct hello_device_t* dev, int val)
{
ALOGI("jessietest~~~Hello Stub: set value %d to device.", val);
write(dev->fd, &val, sizeof(val));
return 0;
}
static int hello_get_val(struct hello_device_t* dev, int* val)
{
if(!val)
{
ALOGE("jessietest~~~Hello Stub: error val pointer");
return -EFAULT;
}
read(dev->fd, val, sizeof(*val));
ALOGI("jessietest~~~Hello Stub: get value %d from device", *val);
return 0;
}
可以看到,定义硬件接口结构体hello_device_t,以及set_val和get_val实现访问kernel设备,
都是通过在hello_device_open函数中串接起来的这里可以看一下我在完成项目后在phone开机过程中抓取的log,其中关于HAL层的部分
01-10 05:01:53.426 968 968 I HelloStub: jessietest~~~HAL~~init
01-10 05:01:53.427 968 968 I HelloStub: jessietest~~~Hello Stub: open /dev/hello successfully
所以说明在开机过程中,就已经顺利调用到HAL层的hello_device_open函数,其他的读写值因为还没有APP调用,自然没有log但是hello_device_open函数是最初就会被调用到的
3>Makefile
hello目录下新建Makefile文件
照原来的做法是这样的
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 := hello.c
LOCAL_MODULE := hello.default
include $(BUILD_SHARED_LIBRARY)
部分编译是没有错的,64bit编译环境下也确实可以在out/target/product/Z00L/system/lib64/hw/生成我们想要的hello.default.so文件
然后把他push到手机的/system/lib64/hw/下,自认为没有问题了,可是当所有工作都完成后,调用总是不能成功,
去抓取log会发现有一个这样的错误
01-10 04:44:53.473 976 976 E HAL : load: module=/system/lib64/hw/hello.default.so
01-10 04:44:53.473 976 976 E HAL : dlopen failed: "/system/lib64/hw/hello.default.so" is 32-bit instead of 64-bit
意思就是说我们的hello.default.so文件是32bit而不是64bit
可是确实是在lib64下生成的呢,很纠结这是个什么错,于是把这个问题贴到百度,度娘给出了答案是Makefile文件的问题,
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
这句话是针对32位编译环境的,应该这样改
LOCAL_MODULE_RELATIVE_PATH := hw
改完发现还是报同样的错,对比同目录其他文件夹下的Makefile文件,于是又改了一句话
把LOCAL_SHARED_LIBRARIES := liblog 后面添加一个词,libcutils
也就是改为
LOCAL_SHARED_LIBRARIES := liblog libcutils
重新push后就可以成功了
可以看一下so文件
最后的hello.default.so就是啦~