对于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.\n"); //输出调试信息
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.\n");
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文件中