Android架构实例分析之编写hello驱动的HAL层代码

来源:互联网 发布:koala for mac 编辑:程序博客网 时间:2024/06/05 07:38

Android架构实例分析之编写hello驱动的HAL层代码

摘要:

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

HAL代码编写的基本步骤

1、编写HAL层头文件

2、填充相关的结构体

1、编写HAL层头文件

首先我们要知道关于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 <hardware/hardware.h>__BEGIN_DECLS#define HELLO_HARDWARE_MODULE_ID "hello"//IDstruct 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

2、填充相关的结构体

我们总结一下硬件具体的调用流程,也是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 <hardware/hardware.h>#include <hardware/hello.h>#include <sys/mman.h>#include <dlfcn.h>#include <cutils/ashmem.h>#include <cutils/log.h>#include <fcntl.h>#include <errno.h>#include <sys/ioctl.h>#include <string.h>#include <stdlib.h>#include <cutils/log.h>#include <cutils/atomic.h>#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.defaultLOCAL_MODULE_RELATIVE_PATH := hwLOCAL_SRC_FILES := hello.cLOCAL_SHARED_LIBRARIES := liblogLOCAL_MODULE_TAGS := optionalinclude $(BUILD_SHARED_LIBRARY)

hello HAL代码的编译

将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!

2 0
原创粉丝点击