android访问应用程序第2步:实现hal层

android访问应用程序第2步:实现hal层,第1张

概述文章目录1.hardware层概述1.1主要数据结构1.2上层访问驱动流程1.3Hal伪代码示例2.实现hal对于驱动的访问2.1hellotest.c2.2Android.mk2.3hellotest.h2.4编译hal模块3.编写测试代码3.1hellotest.c3.2测试代码调用流程3.3Android.mk4.测试在android系统中

文章目录1.hardware层概述1.1 主要数据结构1.2 上层访问驱动流程1.3 Hal伪代码示例2.实现hal对于驱动的访问2.1 hellotest.c2.2 Android.mk2.3 hellotest.h2.4 编译hal模块3.编写测试代码3.1 hellotest.c3.2 测试代码调用流程3.3 Android.mk4.测试
在androID系统中会提供hal层,即harDWare层来封装对linux的驱动访问,同时会为上层提供一个统一的硬件接口

1.harDWare层概述1.1 主要数据结构

在hal层,会有以下三个结构体

struct hw_module_tstruct hw_module_methods_tstruct hw_device_t1.2 上层访问驱动流程

原文:参考Android应用程序访问linux驱动第二步:实现并测试hardware层
使用hw_get_module()方法获取hal层对应的module,函数通过给定模块的ID来寻找硬件模块的动态链接库,找到后使用load()函数打开这个库,并通过一个固定的符号-HAL_MODulE_INFO_SYM寻找hw_module_t结构体,我们会在hw_module_t结构体中会有一个methods属性,指向hw_module_methods_t结构体,这个结构体中会提供一个open方法用来打开模块,在open的参数中会传入一个hw_device_t**的数据结构,这样我们就可以把对模块的 *** 作函数等数据保存在这个hw_device_t结构中,这样,这样用户可以通过hw_device_t来和模块交互。

1.3 Hal伪代码示例

具体的说,我们在上层可以这样调用HAL层的module:

xxx_module_t *module;hw_get_module(XXXID,(struct hw_module_t **)&module);以上两步我们就获得了对应ID的 hw_module_t结构体。struct xxx_device_t *device;module->methods->open(module,XXXID,(struct hw_device_t **)&device);这样我们就获得了hw_device_t结构体,通过hw_device_t结构体我们就可以访问HAL层对应的module了。

整个过程可用一张图展示:

2.实现hal对于驱动的访问

在asop源码目录下harDWare/libharDWare/modules新建hellotest目录,添加两个文件:hellotest.c 和 AndroID.mk

2.1 hellotest.c
/******************************************************************************* @file    	hellotest.c* @brIEf   	测试hellotest驱动* @note    	实现驱动访问相关函数* @author 	无* @version 	1.0.0* @date    	2020-6-05* 修改记录:*******************************************************************************//******************************************************************************								  头文件*******************************************************************************/#include <harDWare/harDWare.h>#include <harDWare/hellotest.h>#include <fcntl.h>#include <errno.h>#include <cutils/log.h>#include <cutils/atomic.h>/******************************************************************************                                宏定义*******************************************************************************/#define DEVICE_name 	"/dev/hello"#define MODulE_name		"HelloTest"#define	MODulE_AUTHOR   "klz"/* 定义LOG */#define LOGV(...) __androID_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) #define LOGD(...) __androID_log_print(ANDROID_LOG_DEBUG , LOG_TAG, __VA_ARGS__)#define LOGI(...) __androID_log_print(ANDROID_LOG_INFO  , LOG_TAG, __VA_ARGS__)#define LOGW(...) __androID_log_print(ANDROID_LOG_WARN  , LOG_TAG, __VA_ARGS__)#define LOGE(...) __androID_log_print(ANDROID_LOG_ERROR  , LOG_TAG, __VA_ARGS__)/******************************************************************************                              变量与数据结构,函数等定义*******************************************************************************/static int hellotest_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);static int hellotest_device_close(struct hw_device_t *device);static int hellotest_write_string(struct hellotest_device_t *dev,char *str);static int hellotest_read_string(struct hellotest_device_t *dev,char **str);//模块方法结构体static struct hw_module_methods_t hellotest_module_methods = {	.open = hellotest_device_open,};//模块实例变量struct hellotest_module_t HAL_MODulE_INFO_SYM = {	  .common = {        .tag                    = HARDWARE_MODulE_TAG,        .module_API_version     = HELLOTEST_HARDWARE_MODulE_API_VERSION_1_0,        .hal_API_version        = HARDWARE_HAL_API_VERSION,        .ID                     = HELLOTEST_HARDWARE_MODulE_ID,        .name                   = "hello test",        .author                 = "The AndroID Open Source Project",        .methods                = &hellotest_module_methods,    }};/******************************************************************************** @name   	hellotest_device_open* @brIEf  	打开驱动* @param  	const struct hw_module_t* module  [IN] 打开的模块* @param  	const char* name     			  [IN] 模块ID* @param  	struct hw_device_t** device       [IN] 从open函数中获取到的hellotest_device_t* @return 	int                               [OUT] 函数的返回值,0:EOK,-1:Error*******************************************************************************/static int hellotest_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device){	struct hellotest_device_t *dev;	dev = (struct hellotest_device_t*)malloc(sizeof(struct hellotest_device_t));		if(!dev)	{		LOGE("%s,Failed to alloc space\n",__FUNCTION__);		return -EFAulT;	}		memset(dev,0,sizeof(struct hellotest_device_t));		dev->common.tag = HARDWARE_DEVICE_TAG;	dev->common.version = 0;	dev->common.module = (hw_module_t*)module;	dev->common.close  = hellotest_device_close;  	dev->write_string  = hellotest_write_string;	dev->read_string   = hellotest_read_string;		if((dev->fd = open(DEVICE_name,O_RDWR)) == -1)	{		LOGE("%s,open %s Failed\n",__func__,DEVICE_name);		return -EFAulT;	}		*device = &(dev->common);	 LOGI("HelloTest: open /dev/hello successfully."); 		return 0;}/******************************************************************************** @name    	hellotest_device_close* @brIEf   	关闭驱动* @param   	struct hw_device_t** device       [IN] 从open函数中获取到的hellotest_device_t* @return  	int                               [OUT] 函数的返回值,0:EOK,-1:Error*******************************************************************************/static int hellotest_device_close(struct hw_device_t *device){	LOGI("%s\n");	struct hellotest_device_t *hello_device = (struct hellotest_device_t *)device;		if(hello_device)	{		close(hello_device->fd);		free(hello_device);	}		return 0;}/******************************************************************************** @name   	 hellotest_write_string* @brIEf  	 向驱动中写入字符串* @param  	 struct hw_device_t* device      [IN] 要写入的hw_device* @param  	 char *str                       [IN] 写入的字符串* @return 	 int                             [OUT] 函数的返回值,0:EOK,-1:Error*******************************************************************************/static int hellotest_write_string(struct hellotest_device_t *dev,char *str){	LOGI("%s\n",__func__);	write(dev->fd,str,sizeof(str));	return 0;}/******************************************************************************** @name   	 hellotest_read_string* @brIEf  	 从驱动中读取字符串* @param  	 struct hw_device_t*device	 [IN] 要读取的hw_device* @param  	 char **str                  [IN] 读取的字符串* @return 	 int                         [OUT] 函数的返回值,0:EOK,-1:Error*******************************************************************************/static int hellotest_read_string(struct hellotest_device_t *dev,char **str){	LOGI("%s\n",__func__);	read(dev->fd,*str,sizeof(*str));	return 0;}

经过上面 *** 作我们可以实现hal层中hw_device_t结构体中的方法 *** 作linux驱动

2.2 AndroID.mk
# copyright (C) 2016 The AndroID Open Source Project## licensed under the Apache license, Version 2.0 (the "license");# you may not use this file except in compliance with the license.# You may obtain a copy of the license at##      http://www.apache.org/licenses/liCENSE-2.0## Unless required by applicable law or agreed to in writing, software# distributed under the license is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implIEd.# See the license for the specific language governing permissions and# limitations under the license.LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODulE := hellotest.defaultLOCAL_MODulE_relative_PATH := hwLOCAL_PROPRIETARY_MODulE := trueLOCAL_SRC_fileS := hellotest.cLOCAL_C_INCLUDES := harDWare/libharDWare/includeLOCAL_header_liBRARIES := libharDWare_headersLOCAL_SHARED_liBRARIES := liblog libcutils libutilsLOCAL_MODulE_Tags := optionalLOCAL_CFLAGS += -Wno-unused-parameter -Wno-implicit-function-declarationinclude $(BUILD_SHARED_liBRARY)

注意:LOCAL_MODulE 的值为hellotest.default,hellotest一定要加上default,不然使用hw_get_module函数找不到我们的HAL模块。

2.3 hellotest.h

在harDWare/libharDWare/include/harDWare编写头文件hellotest.h

/******************************************************************************* 文 件 名: hellotest.h  * 功能描述: 测试hello驱动* 作    者: 无* 版 本 号: 1.0.0 * 修改日期: 2021-6-05* 修改记录:*******************************************************************************/#ifndef ANDROID_HELLO_TEST_H#define ANDROID_HELLO_TEST_H#include <harDWare/harDWare.h> __BEGIN_DECLS/******************************************************************************                                宏定义*******************************************************************************/#define HELLOTEST_HARDWARE_MODulE_ID "hellotest" //ID值,必须,用于上层获取该模块#define HELLOTEST_HARDWARE_MODulE_API_VERSION_1_0 HARDWARE_MODulE_API_VERSION(1,0) //API版本/******************************************************************************                              变量与数据结构等定义*******************************************************************************/struct hellotest_module_t {	struct hw_module_t common;};struct hellotest_device_t {//硬件接口结构体	struct hw_device_t common;	int fd;	int (*write_string)(struct hellotest_device_t *dev,char *str);	int (*read_string)(struct hellotest_device_t *dev,char **str);};__END_DECLS#endif
2.4 编译hal模块

直接进入到harDWare/libharDWare/modules/hellotest目录,执行mm命令进行编译

3.编写测试代码

在harDWare/libharDWare/tests/目录下新建一个hellotest目录,新增hellotest.c和AndroID.mk文件:

3.1 hellotest.c
#include <harDWare/harDWare.h>  #include <harDWare/hellotest.h>  #include <fcntl.h>#include <stdio.h>#include <stdlib.h>struct hw_module_t * module;struct hw_device_t * device;int main(){    char *read_str;    char *write_str="hellotest";    read_str = malloc(100);       if(hw_get_module(HELLOTEST_HARDWARE_MODulE_ID,(struct hw_module_t const **)&module)==0)    {        printf("get module sucess\n");    }else{        printf("get module fail\n");        return -1;    }    if(module->methods->open(module,HELLOTEST_HARDWARE_MODulE_ID,(struct hw_device_t const**)&device)==0)    {        printf("open module sucess\n");    }    else    {        printf("open module error\n");        return -1;    }    struct hellotest_device_t* dev = (struct hellotest_device_t *)device;    dev->read_string(dev,&read_str);    if(read_str == NulL)    {        printf("read error");    }    else    {        printf("read data: %s\n",read_str);    }    dev->write_string(dev,write_str);    printf("write data: %s\n",write_str);    dev->read_string(dev,&read_str);    if(read_str == NulL)    {        printf("read error");    }    else    {        printf("read data: %s\n",read_str);    }      return 0;}
3.2 测试代码调用流程

先使用hw_get_module函数获得hw_module_t结构体,再调用hw_module_methods_t结构体中的open方法获得hw_device_t结构体,然后使用hw_device_t结构体中的read_string和write_string方法与linux驱动交互,驱动的打开是在hw_module_methods_t结构体中的open方法中做的。

3.3 AndroID.mk
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODulE_Tags := optionalLOCAL_MODulE := hellotestLOCAL_LDliBS:=  -lharDWareLOCAL_C_INCLUDES := harDWare/libharDWare/include			LOCAL_SRC_fileS := $(call all-subdir-c-files)include $(BUILD_EXECUtable)

然后进入到该目录执行mm命令进行编译

4.测试把生成的hellotest.default.so文件拷贝到androID设备的/system/lib/hw目录下,这需要root权限,没有root权限请自行解决。获得root权限后会提示/system是一个只读文件系统,所以需要重新挂载为可读可写的文件系统,执行mount -o remount,rw /system 即可。修改hellotest.default.so文件的的权限为644,执行chmod 644 /system/lib/DW/hellotest.default.so装载上一节实现的hello.ko驱动:insmod hello.ko
链接Android应用程序访问linux驱动第一步:实现并测试Linux驱动
把生成的my_test可执行文件拷贝的androID设备上,建议push hellotest/data给my_test文件添加可执行权限. chmod +x hellotest执行hellotest。 ./hellotest
打印如下:
get module sucessopen module sucessread data: hellowrite data: hellotestread data: hellotest

可见,测试成功。
如果有问题,可以使用logcat看下HAL层的打印,看看问题出在什么地方。

总结

以上是内存溢出为你收集整理的android访问应用程序第2步:实现hal层全部内容,希望文章能够帮你解决android访问应用程序第2步:实现hal层所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1001559.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存