在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来和模块交互。
具体的说,我们在上层可以这样调用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了。
整个过程可用一张图展示:
在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模块。
在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.mkLOCAL_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层所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)