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

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

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

$Android/hardware/libhardware/

---Include

---hardware

---helloworld.h

---modules

---helloworld

---helloworld.cpp

---Android.mk

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

头文件helloworld.h实现:

#ifndefANDROID_HELLOWORLD__INTERFACE_H

#defineANDROID_HELLOWORLD_INTERFACE_H

#include<hardware/hardware.h>

___BEGIN_DECLS

//定义模块编号

#defineHELLOWORLD_HARDWARE_MODULE_ID“helloworld”

//定义模块结构体

Structhelloworld_module_t{

Structhw_modult_tcommon;//第一个成员变量必须为 //hw_module_t类型

};

//定义设备编号

#defineHELLOWORLD_HARDWARE_DEVICE_H “helloworld”

//定义设备结构体

Structhelloworld_device_t{

Structhw_module_tcommon;//第一个成员变量必须为该类型

int(*set_val)(structhelloworld_device_t*dev,intval);

Int(*get_val)(structhelloworld_device_t*dev,int*val);

Intfd;

};

__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

#defineLOG_TAG"HelloworldHALStub"

#include<hardware/hardware.h>

#include<fcntl.h>

#include<errno.h>

#include<cutils/log.h>

#include<cutils/atomic.h>

#include<hardware/helloworld.h>

#defineDEVICE_NAME"/dev/helloworld"

#defineMODULE_NAME"helloworld"

#defineMODULE_AUTHOR"xxx@sina.com"

/*

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

*/

staticinthelloworld_device_open(conststructhw_module_t*module,constchar*id,structhw_device_t**device);

staticinthelloworld_set_val(structhelloworld_device_t*dev,intval);

staticinthelloworld_get_val(structhelloworld_device_t*dev,int*val);

staticinthelloworld_device_close(structhw_device_t*device);

staticstructhw_module_methods_thelloworld_module_methods={

open:helloworld_device_open

};

structhelloworld_module_tHAL_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,

}

};

/*

*相关实现部分

*/

/*

*打开设备方法实现

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

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

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

*/

staticinthelloworld_device_open(conststructhw_module_t*module,constchar*id,structhw_device_t**device){

if(!strcmp(id,HELLOWORLD_HARDWARE_DEVICE_ID)){

structhelloworld_device_t*dev;

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

dev=(structhelloworld_device_t*)malloc(sizeof(structhelloworld_device_t));

if(!dev){

LOGE("failedtoallocspaceforhelloworld_device");

return-EFAULT;

}

memset(dev,0,sizeof(structhelloworld_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("failedtoopendevicefile/dev/helloworld-----%s.",strerror(errno));

free(dev);

return-EFAULT;

}

*device=&(dev->common);

LOGI("opendevicefile/dev/helloworldsuccess.");

return0;

}

return-EFAULT;

}

/*

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

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

*/

staticinthelloworld_set_val(structhelloworld_device_t*dev,intval){

if(!dev){

LOGE("nulldevpointer.");

return-EFAULT;

}

LOGI("setvalue%dtodevicefile/dev/helloworld.",val);

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

return0;

}

/*

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

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

*/

staticinthelloworld_get_val(structhelloworld_device_t*dev,int*val){

if(!dev){

LOGE("nulldevpointer.");

return-EFAULT;

}

if(!val){

LOGE("nullvalpointer.");

}

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

LOGI("getvalue%dfromdevicefile/dev/helloworld.",*val);

return0;

}

/*

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

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

*/

staticinthelloworld_device_close(structhw_device_t*device){

structhelloworld_device_t*helloworld_device=(structhelloworld_device_t*)device;

if(helloworld_device){

close(helloworld_device->fd);

free(helloworld_device);

}

return0;

}

编译脚本文件Android.mk

LOCAL_PATH:=$(callmy-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/和makesnod进行编译;最后可以得到一个位于/out/target/product/generic/system/lib目录中的helloworld.default.so文件。这时一个动态的链接库文件。

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

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

群号:179914858

更多相关文章

  1. 海康威视视频监控demo 源码+库文件
  2. Android studio 添加assets文件夹
  3. android R 文件生成不了
  4. 为Android应用程序读取/dev下设备而提权(二)
  5. Android 实现文件上传功能(upload)
  6. Android USB HID设备通信controlTransfer 接口参数
  7. Android清单文件详解(六) ---- 节点的属性
  8. android switch模块 (耳机检测)
  9. 面向 Android* 设备的英特尔® USB 驱动程序

随机推荐

  1. 更改Android应用程序的图标
  2. Android(安卓)4.0 和 Galaxy Nexus 香港
  3. 【Android笔记】Android(安卓)Resourse
  4. 一些好的博客收集(持续更新中)
  5. 第一章:初入Android大门(教程篇)(上)
  6. Android(安卓)自定义View之中国地图热点
  7. Handler机制总结
  8. Android(安卓)中的拿来主义(编译,反编译,AX
  9. android菜单资源
  10. Android之值得开发者(安卓)必备的十八大开