在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文件:

[email protected]:~/Android$ cd hardware/libhardware/include/hardware

[email protected]:~/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 "[email protected]"

/*设备打开和关闭接口*/

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能够保证我们的模块总能被硬象抽象层加载到。

五. 编译:

[email protected]:~/Android$ mmm hardware/libhardware/modules/hello

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

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

[email protected]:~/Android$ make snod

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

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

原文:http://www.cnblogs.com/Ph-one/p/4417666.html

android驱动开发 老罗,在Ubuntu上为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序(老罗学习笔记3)...相关推荐

  1. Android 8.0 linux内核,在Ubuntu上为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序---Android8.0版本实现-对照老罗版本...

    老罗版本参见:https://blog.csdn.net/luoshengyang/article/details/6573809 在Android硬件抽象层(HAL)概要介绍和学习计划一文中,我们简 ...

  2. 在Ubuntu上为Android系统编写Linux内核驱动程序(学习老罗的)

    首先提出2个问题 1. 驱动程序的作用是什么? 答:驱动程序的作用主要是向上层提供访问设备寄存器的一个接口,包括读和写. 2. 访问设备驱动程序的方法? 答:a. 通过proc文件系统来访问:b. 通 ...

  3. 在Ubuntu上为Android系统内置C可执行程序测试Linux内核驱动程序 (学习老罗的)

    不得不说,老罗写的太好了. 按照他的方法,我两次就成功了. 不过有点让人奇怪的地方就是 第一次我make snod是成功的 但是执行如下代码:       root@android:/ # cd sy ...

  4. 在Ubuntu上为Android系统内置C可执行程序测试Linux内核驱动程序

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6571210 在前一篇文章中,我们介绍了如何在U ...

  5. Android驱动开发全过程

    Android驱动开发全过程(有图有真相) 前言 意外在网上发现了这扁文章,看后感觉很有必要分享,所以整理并上传,希望大家喜欢. Android 硬件抽象层(HAL)概要介绍和学习计划 Android ...

  6. 在Ubuntu上为Android系统内置C可执行程序测试Linux内核驱动程序 3

    在前一篇文章中,我们介绍了如何在Ubuntu上为Android系统编写Linux内核驱动程序.在这个名为hello的Linux内核驱动程序中,创建三个不同的文件节点来供用户空间访问,分别是传统的设备文 ...

  7. Android驱动(1)---Ubuntu中为Android系统上编写Linux内核驱动程序实现方法

    Ubuntu中为Android系统上编写Linux内核驱动程序实现方法 本文主要介绍在Ubuntu 上为Android系统编写Linux内核驱动程序, 这里对编写驱动程序做了详细的说明,对研究Andr ...

  8. android驱动之旅-在Ubuntu上为Android系统编写Linux内核驱动程序(3)

    Android的硬件抽象层,简单来说,就是对Linux内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节.也就是说,把对硬件的支持分成了两层,一层放在用户空间(User Space),一层放在内核空 ...

  9. andriod驱动之旅-在Ubuntu上为Android系统内置Java应用程序测试Application Frameworks层的硬件服务(8)

    我们在Android系统增加硬件服务的目的是为了让应用层的APP能够通过Java接口来访问硬件服务.那么, APP如何通过Java接口来访问Application Frameworks层提供的硬件服务 ...

最新文章

  1. Linux Java连接MySQL数据库
  2. SQL 流程控制语句 之四 WAITFOR语句介绍
  3. Bit-Z图解“推荐返佣”那些事儿
  4. 磁盘配额 挂载 和yum源的配置
  5. Apache - No space left on device / Failed to create proxy Mutex
  6. centos6.4下安装配置JDK+TOMCAT+MYSQL笔记
  7. jenkins maven没有使用全局设置文件地址_Jenkins手把手图文教程「基于Jenkins 2.164.1」...
  8. Java线程类核心方法
  9. 第二增长曲线:如何发现击穿破局点的单一要素?
  10. 数据可视化平台由哪些要素组成
  11. c语言erp系统开发,erp系统怎么开发工具
  12. 怎么做到对mac电脑的监控呢?
  13. MentoHUST的使用教程
  14. Invalid bound statement (not found): org.seckill.dao.Suc
  15. 量化交易中N字型技术形态的实现,天勤,mindgo,python版同花顺,okex,huobi,binance等平台都可正常使用
  16. oracle数据透明加密,使用ORACLE 透明数据加密 TDE
  17. 中企海外周报 | 银联业务拓展到171个国家和地区;徐工集团向非洲客户提供定制化设备...
  18. 服务器操作系统查询命令,服务器操作系统查询命令
  19. 2021五一放假几天,如何用桌面日历便签做日程安排
  20. skyfire Sorry. Skyfire Cannot Provide Service In Your Country.解决 天火浏览器不能使用问题。...

热门文章

  1. 1、Django项目设计与搭配开发环境
  2. (最全干货分享)渗透测试全流程归纳总结之二
  3. 北京科技大学,计算机考研情况
  4. opencv 大图中找小图,并点击小图
  5. 金蝶和oracle ebs优缺点,金蝶,用友切换成EBS中存在的差异点
  6. 吊打面试官、分享这份MySQL开发魔典,从入门到通关白皮书
  7. 可能要用心学高并发核心编程,限流原理与实战,分布式令牌桶限流
  8. android颜色透明度百分比
  9. OpenCV Mat类详解和用法
  10. Android 12 快速适配要点