本部分的核心是系统移植,学习驱动开发离不开移植,移植技术和LInux 内核技术是Android 驱动开发最核心的基础。在本节内容中,将对Android 移植的基本只是进行简要介绍:
1、移植各个Android 部件的方式
在Android 系统中,不同子系统的移植方式不同,不同部件的移植方式如下所示:
- 显示系统:使用Framebuffer 标准或其他驱动,对应的硬件抽象层是Gralloc.
- 用户输入系统:使用Event 设备的驱动程序,对应的硬件抽象层是 EventHub
- 3D 加速系统:使用非标准的驱动程序,对应的硬件抽象层是 OpenGL
- 音频系统:使用非标准的驱动程序,对应的C++ 继承的硬件抽象层。
- 视频输出系统:使用非标准的驱动程序,对应的硬件抽象层是 overlay模块
- 摄像头系统: 使用非标准的驱动程序,对应的是 C++ 继承的硬件抽象层。
- 多媒体解码系统: 使用非标准的驱动程序,对应的硬件抽象层是 Skia 和 openMax 插件。
- 电话系统: 使用非标准的驱动程序,对应的硬件抽象层是动态开发插件库。
- GPS 定位系统: 使用非标准的驱动程序,对应的硬件抽象层通常直接接口。
- 无线局域网:使用WLAN 驱动程序,对应的硬件抽象层分别是 Linux 下的WPA 和Android 下的 Wifi
- 蓝牙系统: 使用 Bluetooh 驱动程序,对应的硬件抽象层分别是 Linux 下的BlueZ 和Android 下的 Bluedroid
- 传感器系统: 使用非标准的驱动程序,对应的硬件抽象层是 Sensor 硬件模块。
- 振动器系统:使用SYS 文件系统中固定位置的驱动程序,对应的硬件抽象层 Android 标准的直接接口。
- 背光和指示灯系统:使用非标准的驱动程序,对应的硬件抽象层是 Light 硬件模块。
- 警告器系统:使用 Misc 驱动程序,对应的硬件抽象层是 Android 标准的JNI 层。
- 电池管理系统: 使用SYS 文件系统中固定位置的驱动程序,对应的硬件抽象层是 Android 标准的直接接口。
2、移植技巧之辅助工作
在 Android 移植过程中,除了移植驱动程序和硬件抽象层之外,还需要实现一些辅助工作。在本节的内容中,就讲解这些辅助性工作。
1)、设置设备权限
当Android 系统启动时,在内核引导参数上一般都会设置 "init=/init", 此时如果内核成功挂载了这个文件系统后,首先运行的就是这个根目录下的 init 程序。这个 init 程序是 Android 系统运行后的第一个用户空间的程序,它以守护进程的方式运行。
当我们需要增加驱动程序的设备节点时,我们需要随之更改这些设备节点的属性,这些更改内容被保存在 文件 "system/core/init/devices.c" ,我们摘一些权限相关进行讲解:
(1)定义perms_表示设备的类型,具体代码如下所示:
(2) 定义数组 devperms 表示系统中的设备,具体代码按如下所示:
上述数组中,分别设置了设备的权限、所属用户和所属组。具体权限值得含义和Linux 中的完全一致,其中3个数组分别表示所属用户、所属组和其他人的权限,4 表示可读,2表示可写,1表示可执行。例如数组内的如下首行代码:
{"/dev/null",0666,AID_ROOT,AID_ROOT,0},
"/dev/null" 是一个标准的设备,赋予他的权限是 0666,表示任何用户可以对其进行读/写操作。
如果需要增加一个新的设备节点文件,需要在数组devperms 中新增一行内容。
(3)两个函数,在文件中有两个比较重要的函数,分别是 handle_device_event() 和 make_device(), 具体实现代码如下。
函数 get_device_perm() 会比较 path 路径是否和 devperms[] 数组中的inode 路径相同,如果相同则返回 devperms[] 数组中指定的 uid 、 gid 和mode 数值。这样 make_device 就会向 “/dev” 创建 inode 结点,并同时改变该 inode 的 uid 和 gid .
(4) 和用户名相关的名称,和用户名相关的名称被定义在文件 "system/core/include/private/android_filesystem_config.h" 中,其中用 android_id_info 来表示用户名 id的属性,定义代码如下所示。
2.init.rc 实现初始化操作
文件 "system/core/rootdir/init.rc" 可以实现一些简单的初始化操作,Android 中的 init.rc 是启动脚本。init.rc 脚本被直接安装到目标系统的根目录下,并被 init 可执行的程序解析。
init.rc 是init 启动后被执行的启动脚本,其语法主要包含了下面的内容。
- Commands : 命令
- Actions : 动作
- Triggers : 触发条件
- Services : 服务
- Options : 选项
- Propertise : 属性
- Commands 是一些基本的操作命令,例如 :
这些命令在iinit 可执行过程中被解析,然后可以调用相关的函数来实现:
on init
export PATH /sbin:/system/sbin:/system/bin:/system/xbin
mkdir /system
init 表示一个触发条件,当这个触发条件发生后会设置变量并建立一个目录,上述操作就称作一个 “动作”。
- Service (服务): 通常表示启动一个可执行程序,用Options(选项) 来表示服务的附加内容以配合服务使用,具体代码如下所示:
service vold /system/bin/vold
socket vold stream 0660 root mount
service bootsound /system/bin/playmp3
user media
group audio
oneshot
其中 vold 和 bootsound 分别表好似两个服务的名称,“/system/bin/vold” 和 “/system/bin/playmp3” 分别是他们所对应的可执行程序。
socket 、user 、group 和 oneshot 是配合服务使用的选项,其中 oneshot 选项表示该服务只启动一次,如果没有 oneshot 选项,则这个可执行程序会一直存在,如果可执行程序被杀死,则会重新启动。
3、更改配置文件
在Android 硬件抽象层的移植过程中,经常需要向系统中加入运行时的配置文件以配置系统的 功能。etc 文件 即运行时的配置文件,例如配置信息通常被保存在如下文件中。
4、文件系统的属性
在文件 "system/core/include/private/android_filesystem_config.h" 中定义了各个文件的属性,其中 fs_path_config 表示文件系统的属性,定义代码如下所示:
在数组 android_dirs[] 中定义了子目录的属性,定义代码如下所示:
然后再数组 android_files[] 中定义了默认文件的属性,定义代码如下所示。
文章摘自:
《Android 底层接口与驱动开发技术详解》