现在继续在该系列第一篇的基础上,开发对应的HAL程序,
参照:
http://www.cnblogs.com/MMLoveMeMM/articles/3687640.html
http://blog.csdn.net/zfzf294990051/article/details/7343877
步骤如下:
<1> 设备文件名还是callleds,callleds.h头文件放在Android系统源代码hardware/libhardware/include/hardware目录下,内容如下:
#ifndef ANDROID_CALLLEDS_INTERFACE_H__ #define ANDROID_CALLLEDS_INTERFACE_H__ #include<hardware/hardware.h> __BEGIN_DECLS #define CALLLEDS_HARDWARE_MODULE_ID "callleds" struct callleds_module_t{ struct hw_module_t common; }; struct callleds_device_t{ struct hw_device_t common; int fd; int (*set_led)(struct callleds_device_t* dev,int val); }; __END_DECLS #endif
<2> : 上面callleds.h具体实现的callleds.c文件放在hardware/libhardware/modules下,一般需要根据不同设备在这个目录下先见一个自己对应的文件夹,这里再新建一个callleds文件夹,将callleds.c文件放入这个文件夹中,callleds.c的内容如下:
#include<hardware/hardware.h> #include<hardware/callleds.h> #include<fcntl.h> #include<errno.h> #include<cutils/log.h> #include<cutils/atomic.h> #define TAG "callledsStub" #define DEVICE_NAME "/sys/class..." #define MODULE_NAME "callleds" #define MODULE_AUTHOR "zhibao.liu" static int callleds_device_open(const struct hw_module_t* module,const char* name,struct hw_device_t** device); static int callleds_device_close(struct hw_device_t* device); static int callleds_set_led(struct callleds_device_t* dev,int val); static struct hw_module_methods_t callleds_module_methods={ open: callleds_device_open }; struct callleds_module_t HAL_MODULE_INFO_SYM={ common:{ tag: HARDWARE_MODULE_TAG, version_major: 1, version_minor: 0, id: CALLLEDS_HARDWARE_MODULE_ID, name: MODULE_NAME, author: MODULE_AUTHOR, methods: &callleds_module_methods, } }; static int callleds_device_open(const struct hw_module_t* module,const char* name,struct hw_device_t** device){ struct callleds_device_t* dev; dev=(struct callleds_device_t*)malloc(sizeof(struct callleds_device_t)); if(!dev){ //LOGE("callleds STUD: faile to alloc space !"); return -1; } memset(dev,0,sizeof(struct callleds_device_t)); dev->common.tag=HARDWARE_DEVICE_TAG; dev->common.version=0; dev->common.module=(hw_module_t*)module; dev->common.close=callleds_device_close; dev->set_led=callleds_set_led; if((dev->fd=open(DEVICE_NAME,O_RDWR))==-1){ //LOGE("callleds STUD: failed to open /sys/class... %s .",strerror(errno)); free(dev); return -1; } *device=&(dev->common); //LOGI("callled STUD : open /sys/class successfully ."); return 0; } static int callleds_device_close(struct hw_device_t* device){ struct callleds_device_t* callleds_device=(struct callleds_device_t*)device; if(callleds_device){ close(callleds_device->fd); free(callleds_device); } return 0; } static int callleds_set_led(struct callleds_device_t* dev,int val){ //LOGI("call STUB : set value %d to device .",val); write(dev->fd,&val,sizeof(val)); return 0; }
<3> : 要编译上面的程序,就需要在callleds.c同目录下新建一个Android.mk的文件,内容如下:
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 :=callleds.c LOCAL_MODULE := callleds.default include $(BUILD_SHARED_LIBRARY)
<4> 修改权限,只有修改权限以后,上层的应用才能够调用这些接口.
解决办法是类似于Linux的udev规则,打开Android源代码工程目录下,进入到system/core/rootdir目录,里面有一个名为ueventd.rc文件,往里面添加一行:
/dev/callleds 0666 root root
添加到同类型最后一行,上面可以直接复制一下,改一下名字就可以了.
<5> 完成上面的,基本上就就绪了,在android源代码根目录下执行:
. build/envsetup.sh
由于我不常用mmm,一般用mm,所以切换目录到callleds.c的目录下,执行 : mm
<6> : 执行后的结果的文件目录:
编译成功后,就可以在out/target/product/generic/system/lib/hw目录下看到callleds.default.so文件了.参见下图:
<7> : 由于前面修改了权限,如果把这个so文件直接用在后面的service的cpp程序,到后面的应用层的APP还是会出错,所以这里必须要build一次整个系统,让后让机器重新在安装build后的系统才行,这个操作只需要一次就可以了,以后再改这个so文件就不需要更改了,似乎有点坑爹.当然只需要build出system.img就可以了.