TQ210搭载Android4.0.3系统构建之BEEP从驱动到HAL到JNI到应用程序(HAL篇)

对于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文件中



原文地址:https://www.cnblogs.com/liangxinzhi/p/4275627.html