开发Android硬件抽象层模块接口

编写硬件抽象层模块接口分析

在阅读了“编写Android硬件抽象层相关规范说明”之后,我们应该很熟悉如何去定义和编写硬件抽象层模块接口了。下面即为本人实现的相关代码说明。

我们遵循Android源代码的相关习惯和规则,我想是有原因的;因此,我么也把编写的硬件抽象模块接口文件存放在hardware/libhardware/目录中。具体目录结构为(我的源代码放于Android文件夹中):

$Android/hardware/libhardware/

---Include

    ---hardware

        ---helloworld.h

---modules

    ---helloworld

         ---helloworld.cpp

         ---Android.mk

那么下面即为具体的实现代码说明。

头文件helloworld.h实现:

#ifndef ANDROID_HELLOWORLD__INTERFACE_H

#define ANDROID_HELLOWORLD_INTERFACE_H

#include <hardware/hardware.h>

___BEGIN_DECLS

//定义模块编号

#define HELLOWORLD_HARDWARE_MODULE_ID “helloworld”

//定义模块结构体

Struct helloworld_module_t {

Struct hw_modult_t common;//第一个成员变量必须为 //hw_module_t类型

};

//定义设备编号

#define HELLOWORLD_HARDWARE_DEVICE_H “helloworld”

//定义设备结构体

Struct  helloworld_device_t {

Struct hw_module_t common;//第一个成员变量必须为该类型

int (*set_val)(struct helloworld_device_t* dev,int val);

Int(*get_val)(struct helloworld_device_t* dev,int* val);

Int fd;

};

__END_DECLS

#endif

这个头文件中的常量和结构体的定义都是按照Android系统的规范来定义的。宏变量HELLOWORLD_HARDWARE_MODULT_IDHELLOWORLD_HARDWARE_DEVICE_ID分别用来描述欲编写的模块和其对应的设备编号;而结构体变量helloworld_module_thelloworld_device_t则代表着欲编写的模块结构体和对应的设备描述结构体类型,并且这两个结构体的第一个成员变量类型必须为hw_module_t结构体类型。另外,helloworld_device_t中的其他三个变量的含义分别为:函数指针set_valget_val用来对欲访问的设别进行写和读的操作,而fd表示打开的设备文件/dev/helloworld的描述符,借助这个描述符,我们可以知道当前打开的设备的状态。

实现文件helloworld.cpp

#define LOG_TAG "HelloworldHALStub"

#include <hardware/hardware.h>

#include <fcntl.h>

#include <errno.h>

#include <cutils/log.h>

#include <cutils/atomic.h>

#include <hardware/helloworld.h>

#define DEVICE_NAME "/dev/helloworld"

#define MODULE_NAME "helloworld"

#define MODULE_AUTHOR "xxx@sina.com"

/*

*相关函数方法的定义部分

*/

static int helloworld_device_open(const struct hw_module_t* module, const char* id, struct hw_device_t** device);

static int helloworld_set_val(struct helloworld_device_t* dev, int val);

static int helloworld_get_val(struct helloworld_device_t* dev, int* val);

static int helloworld_device_close(struct hw_device_t* device);

static struct hw_module_methods_t helloworld_module_methods = {

open: helloworld_device_open

};

struct helloworld_module_t HAL_MODULE_INFO_SYM = {

common: {

tag: HARDWARE_MODULE_TAG,

version_major: 1,

version_minor: 0,

id: helloworld_HARDWARE_MODULE_ID,

name: MODULE_NAME,

author: MODULE_AUTHOR,

methods: &helloworld_module_methods,

}

};

/*

*相关实现部分

*/

/*

*打开设备方法实现

*第一个参数代表与要打开的设备对应的模块

*第二个参数代表着在抽象层中可能多个的设备的唯一标示,即区分打开那个设备

*第三个参数代表想要打开的目标设备

*/

static int helloworld_device_open(const struct hw_module_t* module, const char* id, struct hw_device_t** device) {

if(!strcmp(id, HELLOWORLD_HARDWARE_DEVICE_ID)) {

struct helloworld_device_t* dev;

//为设备文件分配物理空间大小

dev = (struct helloworld_device_t*)malloc(sizeof(struct helloworld_device_t));

if(!dev) {

LOGE("failed to alloc space for helloworld_device");

return -EFAULT;

}

memset(dev, 0, sizeof(struct helloworld_device_t));//设备驱动信号同步

dev->common.tag = HARDWARE_DEVICE_TAG;//成员变量tag必须为这个值

dev->common.version = 0;

dev->common.module = (hw_module_t*)module;

dev->common.close = helloworld_device_close;//调用设备自身函数关闭设备

//操作设备的两个方法

dev->set_val = helloworld_set_val;

dev->get_val = helloworld_get_val;

//判断当前设备是否打开

if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {

LOGE("failed to open device file /dev/helloworld -----%s.", strerror(errno));

free(dev);

return -EFAULT;

}

*device = &(dev->common);

LOGI("open device file /dev/helloworld success.");

return 0;

}

return -EFAULT;

}

/*

*第一个参数代表欲操作的设备

*第二个参数代表为操作的设备赋予的值

*/

static int helloworld_set_val(struct helloworld_device_t* dev, int val) {

if(!dev) {

LOGE("null dev pointer.");

return -EFAULT;

}

LOGI("set value %d to device file /dev/helloworld.", val);

write(dev->fd, &val, sizeof(val));//调用系统函数,通过对应的设备文件找到欲操作设备,    //并将设定的值写入设备中

return 0;

}

/*

*第一个参数代表操作的设备

*第二个参数表示从设别获取的值

*/

static int helloworld_get_val(struct helloworld_device_t* dev, int* val) {

if(!dev) {

LOGE("null dev pointer.");

return -EFAULT;

}

if(!val) {

LOGE("null val pointer.");

}

read(dev->fd, val, sizeof(*val));//调用系统函数,通过对应的设备文件找到欲操作设备,   //并获取值,留给硬件访问服务读取显示

LOGI("get value %d from device file /dev/helloworld.", *val);

return 0;

}

/*

*关闭设备,这个函数有设备自身提供调用来关闭对应设备

*唯一参数则代表欲关闭的设备

*/

static int helloworld_device_close(struct hw_device_t* device) {

struct helloworld_device_t* helloworld_device = (struct helloworld_device_t*)device;

if(helloworld_device) {

close(helloworld_device->fd);

free(helloworld_device);

}

return 0;

}

编译脚本文件Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_PRELINK_MODULE := false

LOCAL_SHARED_LIBRARIES := liblog

LOCAL_SRC_FILES := helloworld.cpp

LOCAL_MODULE := helloworld.default

LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw

include $(BUILD_SHARED_LIBRARY)//代表将编译的文件编译成为动态链接库文件,名 //称为helloworld.default,并保存在/out/target/product/generic/system/lib目录中。

准备好所有文件之后,使用命令:mmm ./hardware/libhardware/modules/helloworld/和make snod进行编译;最后可以得到一个位于/out/target/product/generic/system/lib目录中的helloworld.default.so文件。这时一个动态的链接库文件。

编写完硬件抽象层模块接口之后,接下来就是为这个模块接口编写一个硬件访问服务,这个硬件访问服务是位于框架层,用来为应用程序提供访问设备硬件的服务接口。敬请期待,硬件访问服务的实现!

本人刚创建了一个QQ群,目的是共同研究学习Android,期待兴趣相投的同学加入!!

群号:179914858

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云水之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值