第一个Android驱动添加

网上的东西有好有坏,网上的东西容易过时,这个时候,就需要我来做一个更新和整理
Android驱动开发全过程(有图有真相)
附上为我领路的 文件,表示感谢

做一下总结:

我将从从下往上的步骤进行描述:

硬件驱动层程序:

  1. kernel/driver/hello hello.h hello. c 真正与硬件交互的代码
  2. Kconfig Makefile 显示到内核编译选项中(只是显示)
  3. driver/Makefile 在这儿添加我们的Makefile 之后,编译时才会编译我们的硬件驱动程序
  4. 本层程序成功的标志,在hello目录下生成 hello.o

硬件抽象层 :

  1. hardware/libhardware/include/hardware hello.h
  2. hardware/libhardware/modules/hello hello.c Android.mk
  3. 成功的标志 在 out/target/product/generic/system/lib/hw 目录下看到 hello.default.so

jni 层:

  1. framework/base/services/jni com_android_server_HelloService.cpp (c++ 文件)
  2. onload.cpp Android.mk
  3. framework/base/services/java/com/android/server/hello hello.c
  4. frameworks/base/core/java/android/os目录,新增IHelloService.aidl接口定义文件。
  5. frameworks/base 目录,修改 Android.mk 添加 新加的 aidl ,使其被编译。
  6. frameworks/base/services/java/com/Android/server 添加 HelloService.java
  7. 在SystemServer.java 中添加 HelloService 以便于开机就可以把该服务运行起来。
  8. 成功的标志: 编译并烧写成功之后在 adb 中执行 adb shell service list ,查看自己的服务是否启动起来。如果有启动起来,那恭喜,成功了。

一、驱动的加载

  1. 在 driver 下边创建一个自己的目录
  2. 创建 .h 和 .c 文件
  3. 创建 Makeconfig 和 Kconfig 文件
    作用: 在 menuconfig 中添加我们自己的选项(选项中的名字是我们在 Kconfig 中指定的)
    但此时我们还无法把我们自己的驱动编译进去
  4. 在 drivers/Makefile 文件中添加 obj-$(注意不是s)……
    此时,我们再执行编译内核的命令就可以把自己的代码编译进去了
    (当然,编译的方式有多种,具体怎样视硬件而定,查对应的文档就可以了)
  5. 烧写完成之后,文档中说会在 adb shell /dev 下边看到对应的文件夹,我没有,但是后来又有了。晕。。。
    我们也可以用另外一种方式,在 log 中看打的log,判断 驱动是否有加载
    (附上 看log 方法)
    adb shell
    su
    dmesg | grep “你打印的内容”
    在这儿,我搜索的是 init 中的 “Initializing hello device.”

重点:在编译过程中遇到了好几个问题,导致编译不过。具体问题和解决方法如下:

1> implicit declaration of function ‘create_proc_entry’

解决方法:
1. 把 create_proc_entry 方法 换为 proc_create 。
2. 然后将下边的if 语句注释掉
3. 给proc_create 最后添加一个参数 &hello_fops。
修改后的样子:(注意下边的if 语句要使用图中方式注释掉)
第一个Android驱动添加_第1张图片

2> error: implicit declaration of function ‘init_MUTEX’

解决方法:
1. 将 init_MUTEX 换为 sema_init
2. 给 sema_init 添加一个参数
修改后的样子:
第一个Android驱动添加_第2张图片

3> error: implicit declaration of function ‘kmalloc’

error: implicit declaration of function ‘kfree’

解决方法:
1. 添加头文件
修改后的样子:
第一个Android驱动添加_第3张图片
到这儿,恭喜大家,驱动已经加载成功了!!!!!!!!

二、在Android 系统中增加C 可执行程序来访问硬件驱动程序

这一步只是用可执行程序来验证硬件驱动程序是否可用,用命令行就可以实现,这一步不是必须的。

三、在Ubuntu 上为Android 增加硬件抽象层(HAL)模块访问Linux内核

这一部分,文档中写的很详细,也没有遇到什么问题。但需要注意的就是,Android.mk 文件中的每一行的末尾尽量不要出现空格,不然也许会编译不过。所以直接复制过去的童鞋们需要注意一下。

四、为Android 硬件抽象层(HAL)模块编写JNI 方法提供Java 访问硬件服务接口

如果以前使用过 aidl (进程间通信)的话,会好理解一些,如果没有的话,建议先去看一下aidl 的相关知识。
在这一层遇到过一个问题,解了好久。
Native registration unable to find class ‘com/android/server/HelloService’, aborting
现象:无法开机,看log, HelloService 找不到。
解决步骤:
首先看一下 com_android_server_HelloService.cpp 中的register_android_server_HelloService 方法

int register_android_server_HelloService(JNIEnv *env) {  
    return jniRegisterNativeMethods(env, "com/android/server/HelloService", method_table, 
NELEM(method_table)); 

这个路径是 我们 HelloService 的路径,必须一丝不差。
2、该文档中有很多处把 android 写成 Android 地方,编译时会出现很多找不到类,方法等的错误,需要注意一下。
3、如果以上都没有错误,但还是无法开机,建议把 out 目录删掉,重新进行编译。

五、上层 App 进行访问测试

在这一块可能出现的问题:

1. 因为权限问题,无法读取也无法修改值。这个问题再文档中有提到。

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 目录,里面有一个名为uevent.rc
文件,往里面添加一行:/dev/hello 0666 root root
在这儿,需要说的就是,修改完之后不要去编译 system/core ,我在本地一直无法编译通过。并且报出和很多问题,导致无法开机。所以,直接去全部编译就好了。

2. App无法 获取到 module

I/SystemServer( 461): Hello Service
I/HelloService( 461): Hello JNI: initializing……
E/HelloService( 461): Hello JNI: failed to get hello stub module.

最后报错,出现这样一个问题,是因为在全编的时候没有编译生成 hello.default.so ,所以无法找到。
解决方法:
自己编译 mmm hardware/libhardware/modules/hello/
然后 打包烧写,就可以解决这个问题了。
至于在全编的时候编译到自己添加的东西,后续再研究。

在整个流程中,遇到了许多问题,在这儿无法完全叙述出来,如果有童鞋遇到了不同的问题,可以在评论区留言,一起交流。

你可能感兴趣的:(Android,android系统开发)