结合老罗的博客,我自己分析总结一下:::
1. 在~/Android_4.2.2_SourceCode/hardware/libhardware/include/hardware下新建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对上提供的函数接口。
2. 新建~/Android_4.2.2_SourceCode/hardware/libhardware/modules/hello目录,并添加
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 "huangh0624@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
};
/*模块实例变量*/
/* 实例变量名必须为HAL_MODULE_INFO_SYM,
* tag也必须为HARDWARE_MODULE_TAG,这是Android硬件抽象层规范规定的*/
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,
}
};
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) {
ALOGE("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) {
ALOGE("Hello Stub: failed to open /dev/hello -- %s.", strerror(errno));free(dev);
return -EFAULT;
}
*device = &(dev->common);
ALOGI("Hello Stub: open /dev/hello successfully.");
return 0;
}
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) {
ALOGI("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) {
ALOGE("Hello Stub: error val pointer");
return -EFAULT;
}
read(dev->fd, val, sizeof(*val));
ALOGI("Hello Stub: get value %d from device", *val);
return 0;
}
注意:老罗博客里面全是LOGI, LOGE,被我改为ALOGI, ALOGE。因为
#include <cutils/log.h>引用的文件地址为:~/Android_4.2.2_SourceCode/system/core/include/cutils/log.h
这里我发现没有LOGI,只有ALOGI。应该是android版本更新改变了一些宏定义而已。。。。
3. 该目录下新建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)
4. 编译
编译前需要初始化相关工具:
$ cd ~/Android_4.2.2_SourceCode
$ source ./build/envsetup.sh
然后就可以使用mmm工具了
继续
~/Android_4.2.2_SourceCode$ mmm hardware/libhardware/modules/hello
下面是截取的编译过程 :
make:进入目录'/home/hwh/Android_4.2.2_SourceCode'然后我们去
target thumb C: hello <= hardware/libhardware/modules/hello/hello.c
target SharedLib: hello (out/target/product/generic/obj/SHARED_LIBRARIES/hello_intermediates/LINKED/hello.so)
target Symbolic: hello (out/target/product/generic/symbols/system/lib/hw/hello.so)
target Strip: hello (out/target/product/generic/obj/lib/hello.so)
Install: out/target/product/generic/system/lib/hw/hello.so
make:离开目录“/home/hwh/Android_4.2.2_SourceCode”
~/Android_4.2.2_SourceCode/out/target/product/generic/system/lib/hw/hello.so发现了hello.so文件,说明编译成功。
5. 重新打包Android系统镜像system.img
~/Android_4.2.2_SourceCode $ make snod重新打包后,system.img就包含我们定义的硬件抽象层模块hello.default了。
写道这里,其实遗漏一个部分,就是老罗说的,除非root的系统,才能访问我们的hello.so文件。但是是否真的不能访问,我需要验证。
待我验证完毕后,再添加老罗说的那部分。。
// 下面是老罗写的文章
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
地址:http://blog.csdn.net/luoshengyang/article/details/6573809
在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权限,这时候就导致打开设备文件失败:
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应用程序中访问我们自己定制的硬件。 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!
- 顶
- 39
- 踩
- 0
- 41楼 only09030301112013-05-24 15:19发表 [回复]
- *device = &(dev->common); 这个不对吧,应该是这样吧*device = dev
- 40楼 jay07252013-04-07 13:49发表 [回复]
-
罗老师,想问下。我在HAL里调用system和mkfifo等系统函数,由APK来调用。但是没有执行system和mkfifo函数的权限。请问在哪个位置修改权限?
谢谢!
- 39楼 all80232013-04-06 15:43发表 [回复]
- 楼主你好,我编译的友善之臂提供的android源码,在out/target/product/smdk210/system/lib/hw下没有生成led.default.so。我找了一下在out/target/product/smdk210/obj路径下生成了led.default.so。请问这个库算是编译成功了吗?我在写android应用程序时把这个库导入了工程里,APK程序运行的时候提示找不到这个库,能帮忙啊分析一下吗?
- 38楼 binglansong2013-03-13 17:56发表 [回复]
- 罗老师你好,我在编译的时候,出现过这两种情况,第一次是提示:没有什么可以做的为“all_modules”。我查看了xbin那个目录,发现里面已经有一个我想要生成ledapp(可能是开发板中源码自带了一个),所以想是不是因为已经生成了app所以没有可以做的,我剪切出来,再mmm,进入目录后的提示只有一行:Istall:out/target/product/tq210/system/xbin/ledapp 。这个没有其他的生成过程的提示。又一次编译的时候提示:进入目录“/。/。/。/device/embedsky/tq210/device.mk:41:”*** commands commence before first target. 停止。因为这个生成的.so文件要复制到另一个文件夹下,我去查看那个文件夹,发现本来就有将要生成的.so文件,但是这次剪掉后还是出现同样的提示。请问是什么问题呢。谢谢罗老师
- 37楼 longyi01072013-01-10 23:43发表 [回复]
-
老罗,你好,看到这里我有一个疑问:
android HAL层设计是用来让厂商不用公布驱动程序的源码的?
但目前看到好像驱动程序的源码还是在添加在内核里,所以还是要公布出来,是吗?- Re: 罗升阳2013-01-11 09:28发表 [回复]
-
回复longyi0107:前面有介绍:http://blog.csdn.net/luoshengyang/article/details/6567257
- Re: longyi01072013-01-11 21:02发表 [回复]
-
回复Luoshengyang:仔细体会了下,有点感觉了。呵呵~
内核驱动层只提供简单的访问硬件逻辑,例如读写硬件寄存器的通道,至于从硬件中读到了什么值或者写了什么值到硬件中的逻辑,都放在硬件抽象层中去了,这样就可以把商业秘密隐藏起来了。也正是由于这个分层的原因,Android被踢出了Linux内核主线代码树中。大家想想,Android放在内核空间的驱动程序对硬件的支持是不完整的,把Linux内核移植到别的机器上去时,由于缺乏硬件抽象层的支持,硬件就完全不能用了
- 36楼 longkg2012-11-21 17:34发表 [回复]
- 罗老师你好,我现在想将framebuffer里面的数据直接拷贝出来,那么本地层如何通过jni接口直接往java层传递一连串的字符串呢?
- 34楼 百無一用是書生2012-10-23 21:52发表 [回复]
-
这几天把这一系列的实做给练习了一便,感觉不错,遇到的问题就是/dev/hello权限的问题。下边主要是对/dev/hello权限的修改提供一下自己的笨方法。仅供参考。
方法1。devices.h这个文件修改还是不能解决的可以去改/system/core/rootdir/init.rc ,加上chmod 777 /dev 和chmod 777 /dev/hello.注意有的时候你可能要改提供商的init.rc,一股可能在/device/厂商/板子平台/ 实在不行全局搜索。
方法2。直接再系统启动后,在主机用命令adb shell mount -o remount rw /dev, 然后adb shell进入板子,再chmod 777 /dev 和chmod 777 /dev/hello. 接下来再stop命令和start命令重启android.记住不是重启板子!!!
另外adb shell mount -o remount rw 目标 非常好用,有的时候要push一些东西但又没有权限时可以用这条指令。。
- 32楼 suifeng2012-08-09 14:47发表 [回复]
-
我把自己奇怪的错误,贴在这里,希望其他人不要再犯类似的错误:
build/core/base_rules.mk:73: unusual tags optinal on hello.default at hardware/libhardware/modules/hello
target C: hello.default <= hardware/libhardware/modules/hello/hello.c
target SharedLib: hello.default (out/target/product/adv_x86/obj/SHARED_LIBRARIES/hello.default_intermediates/LINKED/hello.default.so)
out/target/product/adv_x86/obj/lib/crtbegin_so.o: In function `__do_global_dtors_aux':
(.text+0x25): undefined reference to `__cxa_finalize'
out/target/product/adv_x86/obj/lib/crtbegin_so.o: In function `atexit':
(.text+0xcb): undefined reference to `__cxa_atexit'
out/target/product/adv_x86/obj/lib/crtbegin_so.o: In function `__stack_chk_fail_local':
。。。
make: *** [out/target/product/adv_x86/obj/SHARED_LIBRARIES/hello.default_intermediates/LINKED/hello.default.so] Error 1
make: Leaving directory `/home/txf/ANDROID'
解决方法:
从modules下的其他目录里面,拷贝一个Android.mk 文件放在hello 目录中间,然后将需要的项修改即可!
- 31楼 qinyun1882012-04-11 15:28发表 [回复]
-
你好,我想问一下,我按你的步骤编译下来,但是我的out/target/product/这个目录下没有生成generic文件,只有ideal6410这个目录,在这个目录下就有/system/lib/hw,但是里面没有生成hello.default.so 呢?
- Re: lqxandroid20122012-08-02 11:52发表 [回复]
-
回复qinyun188:也许不在这个路径
/system/lib/hw 这个是有的。
O(∩_∩)O哈哈~,搜索一下,总会有的。
我照着博主的做,搞完整个流程了。
蛮好玩的。
- 30楼 manshq163com2012-04-09 17:26发表 [回复]
- 正在做android 的产品,搜索到了楼主的博客,太好了写的,必须要顶一下.另外楼主能否写一下关于android 内核驱动调试的方法可以吗 ,对我们这种初学者来说,很有帮助
- 29楼 kongji1232012-04-08 10:41发表 [回复]
-
LZ,怎么我编译
mmm hardware/libhardware/moudles/hello报错,
make:进入目录'/home/yzh/android2.3_lau'
make: *** 没有规则可以创建“out/target/product/generic/obj/SHARED_LIBRARIES/hello.default_intermediates/hello.o”需要的目标“/hello.c”。 停止。
make:离开目录“/home/yzh/android2.3_lau”
我在hello目录下有hello.c 和Android.mk,怎么报需要目标“/hello.c”
这个问題到底怎么解决啊,这个哥们只是说知道了,但并没有说怎么解决的
- 28楼 oucsunjie2012-03-28 16:47发表 [回复]
-
博主,您好!我仿照你的程序正在写led的HAL模块,我在编译时遇到这样的问题:
[root@OUC-B103 modules]# mmm led/
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.3.4
TARGET_PRODUCT=generic
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=GRJ22
============================================
make: 进入目录“/opt/FriendlyARM/tiny6410/android/Android-2.3.4”
make: *** 没有规则可以创建“out/target/product/generic/obj/SHARED_LIBRARIES/led.default_intermediates/LINKED/led.default.so”需要的目标“out/target/product/generic/obj/lib/liblog.so”。 停止。
make: 离开目录“/opt/FriendlyARM/tiny6410/android/Android-2.3.4”
麻烦您给一些建议,谢谢了!- Re: qinyun1882012-04-11 15:44发表 [回复]
- 回复oucsunjie:你好,我现在也遇到了跟你一样的问题,请问你的解决了吗?是怎么解决的呢?谢谢
- 27楼 luxingshun2012-03-02 16:54发表 [回复]
-
楼主。。为什么我按你的弄。打开设备时失败
16. if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {
17. LOGE("Hello Stub: failed to open /dev/hello -- %s.", strerror(errno));free(dev);
18. return -EFAULT;
19. }
老是返回-1,,能告诉我是怎么回事不?2.3.3的系统
- 26楼 thrill0072012-02-13 14:40发表 [回复]
-
尊敬的博主:
我编译的时候出现下面情况:
。。。
prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/../lib/gcc/arm-eabi/4.4.3/../../../../arm-eabi/bin/ld: out/target/product/tcc9300st/obj/lib/crtbegin_so.o:(.text+0x8): error: undefined reference to '__cxa_finalize'
collect2: ld returned 1 exit status
make: *** [out/target/product/tcc9300st/obj/SHARED_LIBRARIES/hello.default_intermediates/LINKED/hello.default.so] Error 1
make: Leaving directory `/home/lifeng/android-0812'
请指教,多谢!
- 25楼 flydream02011-12-19 15:53发表 [回复]
-
博主,提个问题,HAL是怎么向上提供接口的呢?
是通过这个模块实例变量吗?
/*模块实例变量*/
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,HARDWARE_MODULE_TAG.
从上面可以看到一个方法列表:methods: &hello_module_methods,但是这个方法列表只定义了一个打开函数:
/*模块方法表*/
static struct hw_module_methods_t hello_module_methods = {
open: hello_device_open
};
接下来看这个打开函数:在函数hello_device_open内动态分配了一个(struct hello_device_t*)空间,也给其赋了值,打开,关闭,获取,设置四个函数都有,接下来在返回之前*device = &(dev->common);
可见返回前只给*device赋了值&(dev->common),而这个common只包含两个信息:
dev->common.module = (hw_module_t*)module;
dev->common.close = hello_device_close;
我的疑问是,从HAL上层来说,设置和获取的接口可见吗?从这里的代码如何设置的?- Re: flydream02011-12-19 18:31发表 [回复]
-
回复flydream0:我找到答案了:下篇文章中有这么一行代码:
/*通过硬件抽象层定义的硬件模块打开接口打开硬件设备*/
static inline int hello_device_open(const hw_module_t* module, struct hello_device_t** device) {
return module->methods->open(module, HELLO_HARDWARE_MODULE_ID, (struct hw_device_t**)device);
}
由此可见*device=&(dev->common)返回的是(struct hw_device_t*),然后又传给了(struct hello_device_t*)...,问题是何不支持返回*device =dev?
后来查看了一下hardware.h,得到以下原型:
typedef struct hw_module_methods_t {
/** Open a specific device */
int (*open)(const struct hw_module_t* module, const char* id,
struct hw_device_t** device);
} hw_module_methods_t;
原来Open函数的原型中,第三个参数的类型明确指出是: struct hw_device_t** device,而不能随便是我们定义的(struct hello_device_t**).
- 24楼 dinglbo2011-12-12 01:09发表 [回复]
-
LZb你好。按你的这一系列教程,我做到后面发现最后卡在了这里。
Hello Stub: failed to open /dev/hello -- Permission denied.
我用的是2.2版本的。里面没有uevent.rc这个,但是在init下找到了device.c这个文件,于是我在文件中加了如下代码:- static struct perms_ devperms[] = {
- { "/dev/null", 0666, AID_ROOT, AID_ROOT, 0 },
- ……………………
- { "/dev/binder", 0666, AID_ROOT, AID_ROOT, 0 },
- { "/dev/hello", 0666, AID_ROOT, AID_ROOT, 0 }, /*这是我加的*/
- /* logger should be world writable (for logging) but not readable */
- { "/dev/log/", 0662, AID_ROOT, AID_LOG, 1 },
但编译过后还是会产生之前的错误!
我不知道怎么办了,求帮助~
- 23楼 ZFZF2949900512011-11-29 21:21发表 [回复]
- 还要请问下楼主用的画图软件是什么?呵呵。有没有在ubuntu下好的画图软件推荐啊?谢谢
- 21楼 ZFZF2949900512011-11-28 22:25发表 [回复]
- 请问dev->common.close = hello_device_close; 这个close函数在什么情况下会调用? 打开设备后如果没有出现错误,程序也没有显示的调用,难道是android系统自己调用吗?
- 20楼 ZFZF2949900512011-11-24 23:04发表 [回复]
-
你好。我在2.3.4源码上编译居然出来个这么错误,真不知道哪里原因?
target thumb C: hello.default <= hardware/libhardware/modules/hello/hello.c
In file included from hardware/libhardware/modules/hello/hello.c:5:
bionic/libc/include/errno.h:45: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'extern'
make: *** [out/target/product/omap3evm/obj/SHARED_LIBRARIES/hello.default_intermediates/hello.o] 错误 1- Re: 罗升阳2011-11-26 16:46发表 [回复]
-
回复ZFZF294990051:试了一下把hello.c文件名改成hello.cpp看看
- Re: ZFZF2949900512011-11-28 22:26发表 [回复]
-
回复Luoshengyang:试了还是不行,同样错误。埃...
- Re: 罗升阳2011-11-29 17:38发表 [回复]
-
回复ZFZF294990051:如果实在是解决不了,我建议还是不要include头文件errno.h吧,这个不是必须的,相应引用的地方改改就行了。如果你解决了这个问题,也欢迎你在这里分享一下:)
- Re: ZFZF2949900512011-11-30 10:02发表 [回复]
- 回复Luoshengyang:这个部分我找到错误了。原来是我在hello.h中的__END_DECLS写成了__EDN_DECLS. 我先include<hello.h> 所以不论在它下面再Include其他头文件,都会报错。原理我还以为是编译器的问题,以为是c语言的问题,原来最大问题还是我自己。太粗心了。希望别人不要犯同样的错误。这种问题太折磨人。
- 18楼 floweriswho2011-11-17 23:40发表 [回复]
- java...好期待阿!
- 17楼 ccstuoshu12011-11-15 16:18发表 [回复]
- 博主你好,我想写个USB驱动加到内核中,然后我只需要在应用程序中调用这个usb设备的读写操作,这个读写操作就是很一般的字符设备里面都有的read,write,现在的问题是我必须要重新在android框架下把你这个写hello的例子流程重新走一遍还是可以套用里面已经有的我只需要把这个设备名称加到某个位置就行了。因为是菜鸟所以问题可能没表达清楚,希望博主读懂了,谢谢。
- 16楼 ccstuoshu12011-11-15 16:05发表 [回复]
-
android上的/dev下的设备文件权限 可以在init程序中控制,一般在
android/system/core/init/devices.c中有个变量:
static struct perms_ devperms[]={
...
{ "/dev/hello", 0666, AID_ROOT, AID_ROOT, 0 },
}
就好了,然后重新编译一遍就好了,我是重新编译的整个内核,用mmm单独编译好像不行,我不知道为什么
- 15楼 ytllei2011-11-13 15:21发表 [回复]
- 博主你好,有没有办法在在上层应用层调用自己增加的系统调用?
- 13楼 jxgtalent2011-10-26 15:15发表 [回复]
-
我按照你的方法一步一步操作,怎么报告以下错误啊?网上也没找到满意的答复,求教了
CC drivers/video/goldfishfb.o
LD drivers/video/built-in.o
LD drivers/built-in.o
arm-eabi-ld: error: cannot open drivers/hello/built-in.o: No such file or directory
make[1]: *** [drivers/built-in.o] Error 1
make: *** [drivers] Error 2
- 12楼 guidian1032011-09-28 18:07发表 [回复]
-
问一下,
/*模块方法表*/
23.static struct hw_module_methods_t hello_module_methods = {
24. open: hello_device_open
25.};
这个有什么用?我不用可不可以?
还有,为什么一定是hw_module_methods_t 这个结构,不能用其他结构吗?- Re: 罗升阳2011-09-28 23:15发表 [回复]
-
回复guidian103:这个问题就好比是问为什么C语言要用int来表示整数,为什么不能用其它的关键字来表示。
这是HAL的规范,换句话说,就是Google定的游戏规则,你要在这个平台上做东西,就必须遵守这个游戏规则,具体为什么,就要看一下HAL的实现了(libhardware/include/hardware/hardware.h和hardware/libhardware/hardware.c两个文件)。- Re: guidian1032011-10-16 13:56发表 [回复]
- 回复Luoshengyang:明白,谢谢
- 11楼 xyzxyzxz2011-09-21 12:04发表 [回复]
-
博主您好!仔细看了下这段代码,有两处疑问,由于是新手可能问题很基础,勿见笑,
1. LOGI("Hello Stub: set value %d to device.", val);是什么函数?
为什么不是printf("Hello Stub: set value %d to device.", val)?
2. write(dev->fd, &val, sizeof(val)); read(dev->fd, val, sizeof(*val));这两个函数为什么目标地址都是dev->fd,dev->fd不是设备号吗?这样就能写入设备的val了吗?- Re: 罗升阳2011-09-22 01:35发表 [回复]
-
回复xyzxyzxz:1. Android在内核提供了日志系统的功能,LOGI就是用来敲日志的,具体可以参考一下《浅谈Android系统开发中LOG的使用》、《Android日志系统驱动程序Logger源代码分析》、《Android应用程序框架层和系统运行库层日志系统源代码分析》和《Android日志系统Logcat源代码简要分析》这一系列文件。printf是C运行时库提供的一个函数,一般它是输出到终端上的。两者不是同一样概念。
2. dev->fd不是设备号,是打开文件描述符,具体来说,就/dev/hello设备文件的打开文件描述符。这里的write和read是系统调用函数,是用来读写文件的,这两个函数先通过文件系统层,然后进入到我们的设备驱动模块去调用相应的读写函数,这个就涉及到Linux设备驱动的相关知识了,可以参考前面一篇文章《Android学习启动篇》一文提到的一本书《Linux Device Drivers》。
- 10楼 kevinacc2011-09-21 09:55发表 [回复]
-
博主的教程很好啊。学习中。。。
这里应该是一个笔误:
解决办法是类似于Linux的udev规则,打开Android源代码工程目录下,进入到system/core/rootdir目录,里面有一个名为uevent.rc文件,往里面添加一行:
其中的uevent.rc应该是ueventd.rc。我验证过了。
- 8楼 wantianpei2011-09-07 23:49发表 [回复]
-
楼主:
USER-NAME@MACHINE-NAME:~/Android$ mmm hardware/libhardware/moudles/hello
modules
应该改成:
USER-NAME@MACHINE-NAME:~/Android$ mmm hardware/libhardware/modules/hello
- 7楼 atxtu2011-09-01 15:03发表 [回复]
- 用mmm hardware/libhardware/moudles/hello单个编译模块成功,而make clean后重新make怎么在system/lib/hw中没有生成hello.default呢?怎么让这个新加的模块一起编译呢
- 6楼 jhluroom2011-08-24 20:46发表 [回复]
-
您好:我编译出现这样的提示是什么原因造成的?谢谢!!
make:进入目录'/home/jhlu/android/src'
make: *** 没有规则可以创建“out/target/product/generic/obj/SHARED_LIBRARIES/hello.default_intermediates/hello.o”需要的目标“:”。 停止。
make:离开目录“/home/jhlu/android/src”- Re: 罗升阳2011-08-24 21:05发表 [回复]
-
回复jhluroom:参考一下这两位哥们的碰到的问题:
-------------------------------
@bychen_19851208:
1.
LZ,怎么我编译
mmm hardware/libhardware/moudles/hello报错,
make:进入目录'/home/yzh/android2.3_lau'
make: *** 没有规则可以创建“out/target/product/generic/obj/SHARED_LIBRARIES/hello.default_intermediates/hello.o”需要的目标“/hello.c”。 停止。
make:离开目录“/home/yzh/android2.3_lau”
我在hello目录下有hello.c 和Android.mk,怎么报需要目标“/hello.c”
2.
知道了
----------------------------------
@hui05504
1.
楼主,按照你上面的教程,出现了以下错误,
No rule to make target `out/target/product/generic/obj/lib/libhardware.so', needed by `out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so'. Stop.
,麻烦指导下,谢谢
2.
不好意思,这个错误的出错原因估计是在out/target/product/generic/这个目录下,因为我编译源码的时候不是在generic里生成的,而是在新建的目录底下生成,但是这个命令确默认是在generic的路径,所以出错了
-------------------------------------
- 5楼 bychen_198512082011-08-03 14:48发表 [回复]
- 知道了
- 4楼 bychen_198512082011-08-03 14:44发表 [回复]
-
LZ,怎么我编译
mmm hardware/libhardware/moudles/hello报错,
make:进入目录'/home/yzh/android2.3_lau'
make: *** 没有规则可以创建“out/target/product/generic/obj/SHARED_LIBRARIES/hello.default_intermediates/hello.o”需要的目标“/hello.c”。 停止。
make:离开目录“/home/yzh/android2.3_lau”
我在hello目录下有hello.c 和Android.mk,怎么报需要目标“/hello.c”
- 3楼 hui055042011-07-31 14:13发表 [回复]
-
解决办法是类似于Linux的udev规则,打开Android源代码工程目录下,进入到system/core/rootdir目录,里面有一个名为uevent.rc文件,往里面添加一行
楼主,system/core/rootdir目录下没有uevent.rc文件,只有init.rc这个文件,怎么添加root权限呢?- Re: qinyun1882012-04-11 15:51发表 [回复]
-
回复hui05504:@hui05504
1.
楼主,按照你上面的教程,出现了以下错误,
No rule to make target `out/target/product/generic/obj/lib/libhardware.so', needed by `out/target/product/generic/obj/SHARED_LIBRARIES/libandroid_servers_intermediates/LINKED/libandroid_servers.so'. Stop.
,麻烦指导下,谢谢
2.
不好意思,这个错误的出错原因估计是在out/target/product/generic/这个目录下,因为我编译源码的时候不是在generic里生成的,而是在新建的目录底下生成,但是这个命令确默认是在generic的路径,所以出错了
-------------------------------------
我现在也出现了这个情况,那要怎么解决呢?
- Re: hui055042011-07-31 17:29发表 [回复]
-
回复hui05504:不好意思,楼主,那个不能联系评论三次,只有在这里说了。
首先谢谢楼主的回复,问题找到了,out/target/product/generic/system/lib/hw目录,是有hello.xxxxx.so文件。错误的原因是没有添加root的权限,按照你这篇文章所提到的解决方法:
(解决办法是类似于Linux的udev规则,打开Android源代码工程目录下,进入到system/core/rootdir目录,里面有一个名为uevent.rc文件,往里面添加一行)
但是在我的system/core/rootdir目录下没有uevent.rc文件,只有init.rc这个文件,怎么添加root权限呢?- Re: 罗升阳2011-07-31 18:44发表 [回复]
-
回复hui05504:参考一个这个:
回复gunglaw:你下载的是最新版本的源代码么?旧一点的版本可能不是这种机制,你可以看一下system/core/init目录下,有没有ueventd.c这个文件,uevent.rc这个文件的内容是在ueventd_main这个函数里面进行解析的,如果没有,就要分析一下同目录下的init.c这个文件了,里面可以修改设备文件的访问模式。- Re: hui055042011-07-31 18:53发表 [回复]
-
回复Luoshengyang:没有这个目录,我的代码是android 2.2的源码,:( 怎么分析呢,楼主,这个问题困惑我一天了,杯具!
- Re: 罗升阳2011-07-31 19:15发表 [回复]
-
回复hui05504:你在init.c文件里面,搜索一下,看看有没有找到"/dev/binder"这个字符串,如果能找到的话,它就是处理/dev/binder设备文件访问权限的地方,/dev/hello设备文件的处理方式和/dev/binder的是一样的,你参考一下加点代码就可以了。
- Re: mutex_js2012-03-25 19:32发表 [回复]
-
回复Luoshengyang:楼主,init.c文件引入了devices.h文件,我在devices.c文件中找到如下代码,添加了最后一句,但是还是不生效,求助啊。
static struct perms_ devperms[] = {
{ "/dev/null", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/zero", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/full", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/ptmx", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/tty", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/random", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/urandom", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/ashmem", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/binder", 0666, AID_ROOT, AID_ROOT, 0 },
{ "/dev/hello", 0666, AID_ROOT, AID_ROOT, 0 },- Re: cofspring20122012-08-12 15:08发表 [回复]
-
回复mutex_js:你好,我也是在devices.c里面加了{ "/dev/hello", 0666, AID_ROOT, AID_ROOT, 0 },这么一行,还是无效。。。请问你后来是怎么解决的呐?
- Re: 罗升阳2012-08-12 15:16发表 [回复]
-
回复cofspring2012:你用adb工具连上设备,用ls -l /dev/hello文件确认一下它的权限位。devices.c文件是包含在init模块中的,如果init是打包在ramdisk.img镜像中的,所以,你修改了devices.c文件,并且重新编译了init模块之后,还要确保新编译出来的init模块已经打包在ramdisk.img镜像里面。
- Re: cofspring20122012-08-13 21:59发表 [回复]
-
回复Luoshengyang:谢谢楼主热心回复哦,我之前是有重新编译init模块的,不过,ramdisk.img没有重新打包,刚才我重新打包了,进入out/..../root目录,使用这个命令find . | cpio -o -H newc | gzip > ../ramdisk-new.img进行重新打包,可是hello.apk还是写不了。。。。adb之后,是这样的
# ls -l /dev/hello
crw------- root root 252, 0 2012-08-13 13:49 hello
正确的权限显示应该是怎么样的?
我对底层很不熟,刚刚开始学习,非常感谢楼主的文章,也请楼主多多指导。- Re: 罗升阳2012-08-13 23:26发表 [回复]
-
回复cofspring2012:这个权限没能设置好,只有root用户有读写权限。
- Re: cofspring20122012-08-14 08:40发表 [回复]
- 回复Luoshengyang:谢谢楼主这么及时回复哦,之前不知道为什么重新打包之后还是不对,刚才又重新检查了一边device.c,重新把{ "/dev/hello", 0666, AID_ROOT, AID_ROOT, 0 },这行改到了binder那行的下面,原本是放在最后一行的,不知道是不是这个原因,总之现在重新编译init并打包ramdisk以后,可以正确写上了,别的用户也有rw权限了。谢谢楼主啦
- 1楼 gunglaw2011-07-12 10:24发表 [回复]
-
帅哥,我在system/core/rootdir目录里没有发现uevent.rc这个文件啊,自己创建一个? 需要在Android.mk文件中做什么修改呢?
- Re: ZFZF2949900512011-11-30 16:29发表 [回复]
- 回复gunglaw:请问你这个权限问题是怎么解决的?可以共享一下么?