老罗android之旅补丁版之三HAL层

kernel层往上就是HAL层了

先把原网址贴上来
 三. 在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就是啦~


Thanks~~待续~~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值