对于BEEP的HAL层函数与LED的HAL层的函数很相似,就不多说了。
头文件放在/hardware/libhardware/include/hardware/目录下
beep_under_hal.h
#ifndef ANDROID_BEEP_UNDER_H #define ANDROID_BEEP_UNDER_H #include <hardware/hardware.h> #include <stdint.h> #include <sys/cdefs.h> __BEGIN_DECLS //以C语言的方式编译和连接函数与变量 #define BEEP_UNDER_MODULE_ID "beep_unders" //MODULE id struct beep_under_module_t //蜂鸣器模块文件 { struct hw_module_t common; }; struct beep_under_device_t //蜂鸣器设备文件 { struct hw_device_t common; int (*beep_on)(struct beep_under_device_t *dev,int cmd); int (*beep_off)(struct beep_under_device_t *dev,int cmd); }; __END_DECLS #endif
beep_under_hal.c
#include <hardware/beep_under_hal.h> #include <hardware/hardware.h> #include <fcntl.h> #include <android/log.h> #include <stdlib.h> #include <stdio.h> #define BEEP_ON 1 //开蜂鸣器 #define BEEP_OFF 0 //关蜂鸣器 #define DEVICE_NAME "/dev/beep_unders" //蜂鸣器对应于驱动中生成的设备文件 static int fd=-1; //文件操作描述符 int beep_open() //打开蜂鸣器 设备文件 { fd=open(DEVICE_NAME,O_RDWR); //以可读可写的方式打开设备文件 if(fd<0) //判断是否成功打开 { __android_log_print(ANDROID_LOG_DEBUG,"msg","can not open fd. "); //输出调试信息 return -1; } __android_log_print(ANDROID_LOG_DEBUG,"msg","beep open success ,fd=%d",fd); //输出成功打开调试信息 return 0; } int beep_close(struct hw_device_t *dev) //关闭蜂鸣器设备文件 { if(fd!=-1) { close(fd); //关闭文件 if(dev) free(dev); //释放设备占有的内存空间 } return 0; } int beep_on(struct beep_under_device_t *dev,int cmd) //操作蜂鸣器发声 { if(fd==-1) return -1; return ioctl(fd,BEEP_ON,1); } int beep_off(struct beep_under_device_t *dev,int cmd) //操作蜂鸣器不发声 { if(fd==-1) return -1; return ioctl(fd,BEEP_OFF,1); } int beep_init(const struct hw_module_t *module,const char *id,struct hw_device_t **device) //蜂鸣器的初始化函数 { struct beep_under_device_t *dev; dev=(struct beep_under_device_t *)malloc(sizeof(struct beep_under_device_t)); //分配内存空间 if(dev==NULL) //判断是否成功分配内存 { __android_log_print(ANDROID_LOG_DEBUG,"msg","can not alloc mem. "); return -1; } memset(dev,0,sizeof(*dev)); //将内存清零 dev->common.tag=HARDWARE_DEVICE_TAG; //设置设备的相关信息 dev->common.version=1; dev->common.close=(int (*)(struct hw_device_t *))beep_close; dev->common.module=module; *device=(struct hw_device_t *)&dev->common; //将设备带回 dev->beep_on=beep_on; dev->beep_off=beep_off; if(beep_open()==-1) //打开蜂鸣器文件 { free(dev); dev=NULL; return -1; } return 0; } struct hw_module_methods_t beep_under_methods_t= //模块方法 { open:beep_init }; const struct beep_under_module_t HAL_MODULE_INFO_SYM= //找到模块的导出符号,HMI { common: { tag:HARDWARE_MODULE_TAG, version_major:1, version_minor:0, id:BEEP_UNDER_MODULE_ID, //用于组成模块名称的ID name:"beep stub", author:"undergrowth", methods:&beep_under_methods_t, } };
编译文件:Android.mk
LOCAL_PATH :=$(call my-dir) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE :=false LOCAL_SHARED_LIBRARIES :=libutils LOCAL_SRC_FILES :=beep_under_hal.c LOCAL_MODULE :=beep_unders.$(TARGET_BOARD_PLATFORM) LOCAL_MODULE_PATH :=$(LOCAL_PATH) LOCAL_MODULE_TAGS :=optional include $(BUILD_SHARED_LIBRARY)
出现的错误
1.load:couldn't find symbol beep_unders
原因:将static改为const
static struct beep_under_module_t HAL_MODULE_INFO_SYM=
改为
const struct beep_under_module_t HAL_MODULE_INFO_SYM=
附:生成的beep_unders.tq210.so放在/system/lib/hw/目录下
hal流程:上层的JNI通过hw_get_module函数传递的ID在/system/lib/hw/目录下查找与由ID组成的相符的文件名(比如beep_unders.tq210.so或者是beep_unders.default.so,而beep_unders即是ID名),然后使用load函数打开动态链接库(实际上是dlopen函数),获得HMI,然后传递给调用的JNI层的module.
至于hw_get_module函数,load函数,dlopen函数都在/hardware/libhardware/hardware.c文件中