为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序
在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 <hardware/hardware.h>
- __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 <hardware/hardware.h>
- #include <hardware/hello.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <cutils/log.h>
- #include <cutils/atomic.h>
- #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权限,这时候就导致打开设备文件失败:
- 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;
- }
虽然我们在Android系统为我们自己的硬件增加了一个硬件抽象层模块,但是现在Java应用程序还不能访问到我们的硬件。我们还必须编写JNI方法 和在Android的Application Frameworks层增加API接口,才能让上层Application访问我们的硬件。在接下来的文章中,我们还将完成这一系统过程,使得我们能够在 Java应用程序中访问我们自己定制的硬件
为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序的更多相关文章
- 在Ubuntu上为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序(老罗学习笔记3)
简单来说,硬件驱动程序一方面分布在Linux内核中,另一方面分布在用户空间的硬件抽象层中.接着,在Ubuntu上为Android系统编写Linux内核驱动程序(老罗学习笔记1)一文中举例子说明了如何在 ...
- 在Ubuntu上为Android系统内置C可执行程序测试Linux内核驱动程序(老罗学习笔记2)
在前一篇文章中,我们介绍了如何在Ubuntu上为Android系统编写Linux内核驱动程序.在这个名为hello的Linux内核驱动程序中,创建三个不同的文件节点来供用户空间访问,分别是传统的设备文 ...
- 为Android系统内置C可执行程序测试Linux内核驱动程序
在前一篇文章中,我们介绍了如何在Ubuntu上为Android系统编写Linux内核驱动程序.在这个名为hello的Linux内核驱动程序中, 创建三个不同的文件节点来供用户空间访问,分别是传统的设备 ...
- Android架构分析之使用自定义硬件抽象层(HAL)模块
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android版本:2.3.7_r1 Linux内核版本:android-goldfish-2.6.29 在上一篇博 ...
- 在Ubuntu上为Android系统编写Linux内核驱动程序(老罗学习笔记1)
这里,我们不会为真实的硬件设备编写内核驱动程序.为了方便描述为Android系统编写内核驱动程序的过程,我们使用一个虚拟的硬件设备,这个设备只有一个4字节的寄存器,它可读可写.想起我们第一次学习程序语 ...
- 在Ubuntu上为Android系统编写Linux内核驱动程序
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6568411 在智能手机时代,每个品牌的手机都有 ...
- 转: 使用 /sys 文件系统访问 Linux 内核
转一个挺不错的文章 使用 /sys 文件系统访问 Linux 内核 https://www.ibm.com/developerworks/cn/linux/l-cn-sysfs/ 如果你正在开发的设备 ...
- 转:使用 /proc 文件系统来访问 Linux 内核的内容
使用 /proc 文件系统来访问 Linux 内核的内容 https://www.ibm.com/developerworks/cn/linux/l-proc.html /proc 文件系统并不是 G ...
- 使用 /sys 文件系统访问 Linux 内核
sysfs 与 /sys sysfs 文件系统总是被挂载在 /sys 挂载点上.虽然在较早期的2.6内核系统上并没有规定 sysfs 的标准挂载位置,可以把 sysfs 挂载在任何位置,但较近的2.6 ...
随机推荐
- flex安装debug
1.解决 不是最新版本的问题: cmd-->regedit-->HKEY_LOCAL_MATCHING-->SOFTWARE-->MACROMEDIA -->FLASHP ...
- MVC3+EF4.1学习系列(三)-----排序 刷选 以及分页
上篇文章 已经做出了基本的增删改查 但这远远不足以应付实际的项目 今天讲下实际项目中 肯定会有的 排序 刷选 以及分页. 重点想多写点分页的 毕竟这个是任何时候都要有的 而且 我会尽量把这个 ...
- Scala Tuple类型
Tuple可以作为集合存储不同类型的数据,初始化实例如下: val tuple = (1,3,3.14,"aa") val third = tuple._3 Tuple 下标访问从 ...
- genymotion模拟器配置Genymotion-ARM-Translation 兼容包
前提是你的adb的环境已经配置正确,不知道怎么配置的可参考http://jingyan.baidu.com/article/17bd8e52f514d985ab2bb800.html 如果还不成功的话 ...
- mongoDB3--mongoDB的基本操作。
[MongoDb探究]03-mongodb基本操作语句 标签: mongodbdb.createCollectiondb.collectionName.indb.dropDatabasedb.coll ...
- HDU2202--最大三角形(凸包,枚举)
Problem Description 老师在计算几何这门课上给Eddy布置了一道题目,题目是这样的:给定二维的平面上n个不同的点,要求在这些点里寻找三个点,使他们构成的三角形拥有的面积最大.Eddy ...
- linux中将程序加入到开机自动启动
如果将在linux中将命令或者程序设置为开机自动启动,只需要进入到将对应命令加入到/etc/rc.d/rc.local文件里即可,如下 打开文件,vi /etc/rc.d/rc.local #!/bi ...
- Eclipse的WorkingSet使用(转载)
Eclipse作为一款流行的JavaIDE开发工具,其有很多好用的功能为我们的开发提供帮助.但我们的工作空间中有很多项目时,管理起来就很头疼了. 但是我们又不想更换工作区间,所以我们需要一个更加有效的 ...
- git(创建,提交,回退)
创建版本库 2334次阅读 什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改.删除,Git都能跟踪,以 ...
- time_t
所在的头文件为 time.h 定义为: #ifndef __TIME_T #define __TIME_T /* 避免重复定义 time_t */ typedef long time_ ...