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



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"//ID
struct 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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

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,
    },
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

填充struct hw_module_t common 并对其成员 methods进行赋值:

.methods= &hello_module_methods,
  • 1
  • 2

hello_module_methods的定义如下:

static struct hw_module_methods_t hello_module_methods = {
    .open = hello_device_open,
};
  • 1
  • 2
  • 3
  • 4

在 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,
    },
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99

Android.mk 的详细代码如下:


LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := hello.default
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SRC_FILES := hello.c
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE_TAGS := optional

include $(BUILD_SHARED_LIBRARY)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

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!

猜你喜欢

转载自blog.csdn.net/zhangbijun1230/article/details/80741401
今日推荐