热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Ubuntu中为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序

本文主要介绍在Ubuntu上为AndroidHAL模块访问Linux内核驱动程序,这里给大家提供方法和一个小的测试程序代码,以及常遇到的问题和解决方法,有需要的小伙伴可以参考下

       在Ubuntu Android简单介绍硬件抽象层(HAL)一文中,我们简要介绍了在Android系统为为硬件编写驱动程序的方法。简单来说,硬件驱动程序一方面分布在Linux内核中,另一方面分布在用户空间的硬件抽象层中。接着Ubuntu Android系统上编写Linux内核驱动程序实现方法一文中举例子说明了如何在Linux内核编写驱动程序。在这一篇文章中,我们将继续介绍Android系统硬件驱动程序的另一方面实现,即如何在硬件抽象层中增加硬件模块来和内核驱动程序交互。在这篇文章中,我们还将学习到如何在Android系统创建设备文件时用类似Linux的udev规则修改设备文件模式的方法。

      一. 参照在Ubuntu Android系统上编写Linux内核驱动程序实现方法一文所示,准备好示例内核驱动序。完成这个内核驱动程序后,便可以在Android系统中得到三个文件,分别是/dev/hello、/sys/class/hello/hello/val和/proc/hello。在本文中,我们将通过设备文件/dev/hello来连接硬件抽象层模块和Linux内核驱动程序模块。

      二. 进入到在hardware/libhardware/include/hardware目录,新建hello.h文件:

      USER-NAME@MACHINE-NAME:~/Android$ cd hardware/libhardware/include/hardware

      USER-NAME@MACHINE-NAME:~/Android/hardware/libhardware/include/hardware$ vi hello.h

      hello.h文件的内容如下:

#ifndef ANDROID_HELLO_INTERFACE_H
#define ANDROID_HELLO_INTERFACE_H
#include 

__BEGIN_DECLS

/*定义模块ID*/
#define HELLO_HARDWARE_MODULE_ID "hello"

/*硬件模块结构体*/
struct hello_module_t {
	struct hw_module_t common;
};

/*硬件接口结构体*/
struct hello_device_t {
	struct hw_device_t common;
	int fd;
	int (*set_val)(struct hello_device_t* dev, int val);
	int (*get_val)(struct hello_device_t* dev, int* val);
};

__END_DECLS

#endif

 这里按照Android硬件抽象层规范的要求,分别定义模块ID、模块结构体以及硬件接口结构体。在硬件接口结构体中,fd表示设备文件描述符,对应我们将要处理的设备文件"/dev/hello",set_val和get_val为该HAL对上提供的函数接口。

      三. 进入到hardware/libhardware/modules目录,新建hello目录,并添加hello.c文件。 hello.c的内容较多,我们分段来看。

      首先是包含相关头文件和定义相关结构:

#define LOG_TAG "HelloStub"

#include 
#include 
#include 
#include 
#include 
#include 

#define DEVICE_NAME "/dev/hello"
#define MODULE_NAME "Hello"
#define MODULE_AUTHOR "shyluo@gmail.com"

/*设备打开和关闭接口*/
static int hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);
static int hello_device_close(struct hw_device_t* device);

/*设备访问接口*/
static int hello_set_val(struct hello_device_t* dev, int val);
static int hello_get_val(struct hello_device_t* dev, int* val);

/*模块方法表*/
static struct hw_module_methods_t hello_module_methods = {
	open: hello_device_open
};

/*模块实例变量*/
struct hello_module_t HAL_MODULE_INFO_SYM = {
	common: {
		tag: HARDWARE_MODULE_TAG,
		version_major: 1,
		version_minor: 0,
		id: HELLO_HARDWARE_MODULE_ID,
		name: MODULE_NAME,
		author: MODULE_AUTHOR,
		methods: &hello_module_methods,
	}
};

  这里,实例变量名必须为HAL_MODULE_INFO_SYM,tag也必须为HARDWARE_MODULE_TAG,这是Android硬件抽象层规范规定的。

      定义hello_device_open函数:

static int hello_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) {
	struct hello_device_t* dev;dev = (struct hello_device_t*)malloc(sizeof(struct hello_device_t));
	
	if(!dev) {
		LOGE("Hello Stub: failed to alloc space");
		return -EFAULT;
	}

	memset(dev, 0, sizeof(struct hello_device_t));
	dev->common.tag = HARDWARE_DEVICE_TAG;
	dev->common.version = 0;
	dev->common.module = (hw_module_t*)module;
	dev->common.close = hello_device_close;
	dev->set_val = hello_set_val;dev->get_val = hello_get_val;

	if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {
		LOGE("Hello Stub: failed to open /dev/hello -- %s.", strerror(errno));free(dev);
		return -EFAULT;
	}

	*device = &(dev->common);
	LOGI("Hello Stub: open /dev/hello successfully.");

	return 0;

 DEVICE_NAME定义为"/dev/hello"。由于设备文件是在内核驱动里面通过device_create创建的,而device_create创建的设备文件默认只有root用户可读写,而hello_device_open一般是由上层APP来调用的,这些APP一般不具有root权限,这时候就导致打开设备文件失败:

      Hello Stub: failed to open /dev/hello -- Permission denied.   

       解决办法是类似于Linux的udev规则,打开Android源代码工程目录下,进入到system/core/rootdir目录,里面有一个名为ueventd.rc文件,往里面添加一行:  

           /dev/hello 0666 root root    

         定义hello_device_close、hello_set_val和hello_get_val这三个函数:

static int hello_device_close(struct hw_device_t* device) {
	struct hello_device_t* hello_device = (struct hello_device_t*)device;

	if(hello_device) {
		close(hello_device->fd);
		free(hello_device);
	}
	
	return 0;
}

static int hello_set_val(struct hello_device_t* dev, int val) {
	LOGI("Hello Stub: set value %d to device.", val);

	write(dev->fd, &val, sizeof(val));

	return 0;
}

static int hello_get_val(struct hello_device_t* dev, int* val) {
	if(!val) {
		LOGE("Hello Stub: error val pointer");
		return -EFAULT;
	}

	read(dev->fd, val, sizeof(*val));

	LOGI("Hello Stub: get value %d from device", *val);

	return 0;
}

  四. 继续在hello目录下新建Android.mk文件:

      LOCAL_PATH := $(call my-dir)
      include $(CLEAR_VARS)
      LOCAL_MODULE_TAGS := optional
      LOCAL_PRELINK_MODULE := false
      LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
      LOCAL_SHARED_LIBRARIES := liblog
      LOCAL_SRC_FILES := hello.c
      LOCAL_MODULE := hello.default
      include $(BUILD_SHARED_LIBRARY)

 注意:LOCAL_MODULE的定义规则,hello后面跟有default,hello.default能够保证我们的模块总能被硬象抽象层加载到。

       五. 编译:

      USER-NAME@MACHINE-NAME:~/Android$ mmm hardware/libhardware/modules/hello 

      编译成功后,就可以在out/target/product/generic/system/lib/hw目录下看到hello.default.so文件了。

      六. 重新打包Android系统镜像system.img:

      USER-NAME@MACHINE-NAME:~/Android$ make snod

      重新打包后,system.img就包含我们定义的硬件抽象层模块hello.default了。

      虽然我们在Android系统为我们自己的硬件增加了一个硬件抽象层模块,但是现在Java应用程序还不能访问到我们的硬件。我们还必须编写JNI方法和在Android的Application Frameworks层增加API接口,才能让上层Application访问我们的硬件。在接下来的文章中,我们还将完成这一系统过程,使得我们能够在Java应用程序中访问我们自己定制的硬件。

以上就是Android硬件抽象层(HAL)模块访问Linux内核驱动程序的资料整理,后续继续补充,希望能帮助学习Android源码的朋友。


推荐阅读
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 学习SLAM的女生,很酷
    本文介绍了学习SLAM的女生的故事,她们选择SLAM作为研究方向,面临各种学习挑战,但坚持不懈,最终获得成功。文章鼓励未来想走科研道路的女生勇敢追求自己的梦想,同时提到了一位正在英国攻读硕士学位的女生与SLAM结缘的经历。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • 本文介绍了Linux系统中正则表达式的基础知识,包括正则表达式的简介、字符分类、普通字符和元字符的区别,以及在学习过程中需要注意的事项。同时提醒读者要注意正则表达式与通配符的区别,并给出了使用正则表达式时的一些建议。本文适合初学者了解Linux系统中的正则表达式,并提供了学习的参考资料。 ... [详细]
  • Ubuntu 9.04中安装谷歌Chromium浏览器及使用体验[图文]
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • 成功安装Sabayon Linux在thinkpad X60上的经验分享
    本文分享了作者在国庆期间在thinkpad X60上成功安装Sabayon Linux的经验。通过修改CHOST和执行emerge命令,作者顺利完成了安装过程。Sabayon Linux是一个基于Gentoo Linux的发行版,可以将电脑快速转变为一个功能强大的系统。除了作为一个live DVD使用外,Sabayon Linux还可以被安装在硬盘上,方便用户使用。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • Ubuntu安装常用软件详细步骤
    目录1.GoogleChrome浏览器2.搜狗拼音输入法3.Pycharm4.Clion5.其他软件1.GoogleChrome浏览器通过直接下载安装GoogleChro ... [详细]
  • 本文讨论了在Linux系统中,使用chown命令将django项目目录下的static目录的拥有者从root改为eureka的问题。作者尝试了多种命令,包括chown和sudo chown等,但都没有成功修改拥有者。文章提供了相关目录的权限信息,并补充了项目所在磁盘和操作系统的信息。 ... [详细]
  • Vagrant虚拟化工具的安装和使用教程
    本文介绍了Vagrant虚拟化工具的安装和使用教程。首先介绍了安装virtualBox和Vagrant的步骤。然后详细说明了Vagrant的安装和使用方法,包括如何检查安装是否成功。最后介绍了下载虚拟机镜像的步骤,以及Vagrant镜像网站的相关信息。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • 近年来,大数据成为互联网世界的新宠儿,被列入阿里巴巴、谷歌等公司的战略规划中,也在政府报告中频繁提及。据《大数据人才报告》显示,目前全国大数据人才仅46万,未来3-5年将出现高达150万的人才缺口。根据领英报告,数据剖析人才供应指数最低,且跳槽速度最快。中国商业结合会数据剖析专业委员会统计显示,未来中国基础性数据剖析人才缺口将高达1400万。目前BAT企业中,60%以上的招聘职位都是针对大数据人才的。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
author-avatar
0李延芳0_253
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有