[转] Linux下编写GT911触摸驱动
源码在最下面
问题一:资源获取Gt911数据手册
在韦老师给的资料里,路径为\06_Datasheet\Extend_modules\7寸LCD模块\电容触控芯片GT911 Datasheet_121120(海威思.pdf
问题二:需要准备哪些知识
- 能够修改设备树
- 能够编写字符设备驱动
- 能够在linux下编写中断程序
- 能够在linux下编写IIC收发程序
- 了解input子系统
- 移植tslib(用于校准,测试触摸屏)
源码在最下面
在韦老师给的资料里,路径为\06_Datasheet\Extend_modules\7寸LCD模块\电容触控芯片GT911 Datasheet_121120(海威思.pdf
在对应的 Makefile 中增加:
EXTRA_CFLAGS +=-Wno-date-time
EXTRA_CFLAGS +=-Wno-error=date-time
android 生成的 kernel config 在 out/target/product/msm8937_32/obj/KERNEL_OBJ/.config
。要想找出到底哪个 config 决定了最后的 config,我们可以选择 CONFIG_TOUCHSCREEN_FT5X06=y
这一项进行测试。
直接在 kernel
目录下面搜索所有的 CONFIG_TOUCHSCREEN_FT5X06=y
, 然后修改CONFIG_TOUCHSCREEN_FT5X06=n
,再使用 make kernel
,然后查看最终的输出 config,查看变化。
最终确定是 msm-4.9/arch/arm/configs/msm8937_defconfig
决定了 out/target/product/msm8937_32/obj/KERNEL_OBJ/.config
参考: https://blog.csdn.net/u013377887/article/details/81328491
-nostdlib
选项,并在后面附上指定的库即可。类似于arm-linux-gcc -fPIC -shared hardcontrol.c -o libhardcontrol.so -I /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -nostdlib /work/android-5.0.2/prebuilts/ndk/9/platform/android-19/arch-arm/usr/lib/libc.so
arm-linux-gcc -fPIC -shared hardcontrol.c -o libhardcontrol.so -I /usr/lib/jvm/java-1.7.0-openjdk-amd64/include/ -nostdlib /work/android-5.0.2/prebuilts/ndk/9/platform/android-19/arch-arm/usr/lib/libc.so -I /work/android-5.0.2/prebuilts/ndk/9/platform/android-19/arch-arm/usr/include /work/android-5.0.2/prebuilts/ndk/9/platform/android-19/arch-arm/usr/lib/liblog.so
如 com_android_server_LedService.cpp
这样的文件是 jni 源码,主要做的是向系统注册的事情。hal_led.c
这样的是实际的对硬件进行操作的源码,比如说 read, write, ioctrl 等等。
之所以分开来主要考虑两个原因。
com_android_server_LedService.cpp
这样的文件如果有变更,那么需要系统重新编译。hal_led.c
这样的正常时编译为 so 库,所以可以不用系统重新编译。hal_led.c
这样的源码,只是提供一个 so 的库文件。onload.cpp
调用 com_android_server_LedService.cpp
中实现的函数SystemServer.java
需要 new LedService
然后再 addService
LedService.java
里面调用 native 方法ILedService.java
给 app 来使用。ILedService.java
ILedService.aidl
,然后修改一下接口。Android.mk
,如果没有,就向上一层继续查找,知道找到为止。Android.mk
中仿照 vibr aidl,把ILedService.aidl
加入进去。mmm .
进行编译。ILedService.java
生成ILedService iLedService;
iLedService = ILedService.stub.asInterface(ServiceManager.getService("led"));
iLedService.ledCtrl(0, 1);
VibratorService.java
来写 LedService.java
.ILedService.java
找 Stub
申明实现的接口 android.os.ILedService
, android.os.ILedService
这个里面自动生成的需要实现的只有 ledCtrl
这个函数。LedService.java
中实现 ledCtrl
,这个函数中直接调用 native 方法即可。别忘了申明 native 方法LedService.java
中的构造函数中也需要调用 open 的 native 方法。别忘了申明 native 方法SystemServer.java
中,找到 vibr 使用 ServiceManager.addService
的地方,仿照写个 led 的添加服务的调用。com_android_server_LedService.cpp
参考 com_android_server_VibratorService.cpp
来写。
Onload.cpp
找到 register_android_server_VibratorService(env)
这个注册的地方,复制一份,改为 register_android_server_LedService(env)
. 别忘了添加这个函数相应的申明。
mmm
编译时的指令mmm frameworks/base show commands >log.txt 2>&1
import android.os.ILedService
会找不到out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
这个复制出来,并改个名字。led_hal.c
参考 hardware/libhardware/modules/vibrator/vibrator.c
和 hardware.h
来写 led_hal.c
上面这些修改好了之后,可以使用命令进行编译。
mmm frameworks/base/services
mmm hardware/libhardware/modules/led
make snod
logcat 在命令行中可以使用类似 logcat LedHal:I *:S
这样的方法来进行过滤。
转自: http://gityuan.com/2016/03/19/android-build/
工欲善其事,必先利其器,对于想要深入学习Android源码,必须先掌握Android编译命令.
关于Android Build系统,这个话题很早就打算整理下,迟迟没有下笔,决定跟大家分享下。先看下面几条指令,相信编译过Android源码的人都再熟悉不过的。
source setenv.sh
lunch
make -j12
记得最初刚接触Android时,同事告诉我用上面的指令就可以编译Android源码,指令虽短但过几天就记不全或者忘记顺序,每次编译时还需要看看自己的云笔记,冰冷的指令总是难以让我记忆。后来我决定认真研究下这个指令的含义。知其然还需知其所以然,这样能更深层次的理解并记忆,才能与自身的知识体系建立强连接,或许还有意外收获,果然如此,接下来跟大家分享一下在研究上述几条指令含义的过程中,深入了解到的Android Build(编译)系统。
准备好编译环境后,编译Android源码的第一步是 source build/envsetup.sh
,其中source命令就是用于运行shell脚本命令,功能等价于”.”,因此该命令也等价于. build/envsetup.sh
。在文件envsetup.sh
声明了当前会话终端可用的命令,这里需要注意的是当前会话终端,也就意味着每次新打开一个终端都必须再一次执行这些指令。起初并不理解为什么新开的终端不能直接执行make指令,到这里总算明白了。
接下来,解释一下本文开头的引用的命令:
source setenv.sh //初始化编译环境,包括后面的lunch和make指令
lunch //指定此次编译的目标设备以及编译类型
make -j12 //开始编译,默认为编译整个系统,其中-j12代表的是编译的job数量为12。
所有的编译命令都在envsetup.sh
文件能找到相对应的function,比如上述的命令lunch,make,在文件一定能找到
function lunch(){
...
}
function make(){
...
}
source envsetup.sh
,需要cd到setenv.sh
文件所在路径执行,路径可能在build/envsetup.sh
,或者integrate/envsetup.sh
,再或者不排除有些厂商会封装自己的.sh脚本,但核心思路是一致的。
具体实现这里就不展开说明,下面精炼地总结了一下各个指令用法和功效。
编译指令 | 解释 |
---|---|
m | 在源码树的根目录执行编译 |
mm | 编译当前路径下所有模块,但不包含依赖 |
mmm [module_path] | 编译指定路径下所有模块,但不包含依赖 |
mma | 编译当前路径下所有模块,且包含依赖 |
mmma [module_path] | 编译指定路径下所有模块,且包含依赖 |
make [module_name] | 无参数,则表示编译整个Android代码 |
下面列举部分模块的编译指令:
模块 | make命令 | mmm命令 |
---|---|---|
init | make init | mmm system/core/init |
zygote | make app_process | mmm frameworks/base/cmds/app_process |
system_server | make services | mmm frameworks/base/services |
java framework | make framework | mmm frameworks/base |
framework资源 | make framework-res | mmm frameworks/base/core/res |
jni framework | make libandroid_runtime | mmm frameworks/base/core/jni |
binder | make libbinder | mmm frameworks/native/libs/binder |
上述mmm命令同样适用于mm/mma/mmma,编译系统采用的是增量编译,只会编译发生变化的目标文件。当需要重新编译所有的相关模块,则需要编译命令后增加参数-B
,比如make -B [module_name]
,或者 mm -B [module_path]
。
Tips:
搜索指令 | 解释 |
---|---|
cgrep | 所有C/C++文件执行搜索操作 |
jgrep | 所有Java文件执行搜索操作 |
ggrep | 所有Gradle文件执行搜索操作 |
mangrep [keyword] | 所有AndroidManifest.xml文件执行搜索操作 |
mgrep [keyword] | 所有Android.mk文件执行搜索操作 |
sepgrep [keyword] | 所有sepolicy文件执行搜索操作 |
resgrep [keyword] | 所有本地res/*.xml文件执行搜索操作 |
sgrep [keyword] | 所有资源文件执行搜索操作 |
上述指令用法最终实现方式都是基于grep
指令,各个指令用法格式:
xgrep [keyword] //x代表的是上表的搜索指令
例如,搜索所有AndroidManifest.xml文件中的launcher
关键字所在文件的具体位置,指令
mangrep launcher
再如,搜索所有Java代码中包含zygote所在文件
jgrep zygote
又如,搜索所有system_app的selinux权限信息
sepgrep system_app
Tips: Android源码非常庞大,直接采用grep来搜索代码,不仅方法笨拙、浪费时间,而且搜索出很多无意义的混淆结果。根据具体需求,来选择合适的代码搜索指令,能节省代码搜索时间,提高搜索结果的精准度,方便定位目标代码。
导航指令 | 解释 |
---|---|
croot | 切换至Android根目录 |
cproj | 切换至工程的根目录 |
godir [filename] | 跳转到包含某个文件的目录 |
Tips: 当每次修改完某个文件后需要编译时,执行cproj
后会跳转到当前模块的根目录,也就是Android.mk文件所在目录,然后再执行mm指令,即可编译目标模块;当进入源码层级很深后,需要返回到根目录,使用croot
一条指令完成;另外cd -
指令可用于快速切换至上次目录。
查询指令 | 解释 |
---|---|
hmm | 查询所有的指令help信息 |
findmakefile | 查询当前目录所在工程的Android.mk文件路径 |
print_lunch_menu | 查询lunch可选的product |
printconfig | 查询各项编译变量值 |
gettop | 查询Android源码的根目录 |
gettargetarch | 获取TARGET_ARCH值 |
上述只是列举比较常用的指令,还有其他指令,而且不同的build编译系统,支持的指令可能会存在一些差异,当忘记这些编译指令,可以通过执行hmm
,查询指令的帮助信息。
最后再列举两个比较常用的指令:
rm -rf out/
frameworks/base/api
;Android 编译系统是Android源码的一部分,用于编译Android系统,Android SDK以及相关文档。该编译系统是由Make文件、Shell以及Python脚本共同组成,其中最为重要的便是Make文件。关于编译系统可参考 理解 Android Build 系统。 www.ibm.com/developerworks/cn/opensource/os-cn-android-build/
整个Build系统的Make文件分为三大类:
/build/core
,其他Make文件都是基于该框架编写的;/device
,该目录下往往又以公司名和产品名划分两个子级目录,比如/device/qcom/msm8916
;经过make编译后的产物,都位于/out
目录,该目录下主要关注下面几个目录:
在/out/target/product/[product_name]目录下,有几个重量级的镜像文件:
当然还有boot.img,reocovery.img等镜像文件,这里就不介绍了。
在源码树中每一个模块的所有文件通常都相应有一个自己的文件夹,在该模块的根目录下有一个名称为“Android.mk” 的文件。编译系统正是以模块为单位进行编译,每个模块都有唯一的模块名,一个模块可以有依赖多个其他模块,模块间的依赖关系就是通过模块名来引用的。也就是说当模块需要依赖一个jar包或者apk时,必须先将jar包或apk定义为一个模块,然后再依赖相应的模块。
对于Android.mk文件,通常都是以下面两行
LOCAL_PATH := $(call my-dir) //设置当编译路径为当前文件夹所在路径
include $(CLEAR_VARS) //清空编译环境的变量(由其他模块设置过的变量)
为方便模块编译,编译系统设置了很多的编译环境变量,如下:
针对这些环境变量,编译系统还定义了一些便捷函数,如下:
$(call my-dir)
:获取当前文件夹路径;$(call all-java-files-under, )
:获取指定目录下的所有Java文件;$(call all-c-files-under, )
:获取指定目录下的所有C文件;$(call all-Iaidl-files-under, )
:获取指定目录下的所有AIDL文件;$(call all-makefiles-under, )
:获取指定目录下的所有Make文件;示例:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 获取所有子目录中的Java文件
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# 当前模块依赖的动态Java库名称
LOCAL_JAVA_LIBRARIES := com.gityuan.lib
# 当前模块的名称
LOCAL_MODULE := demo
# 将当前模块编译成一个静态的Java库
include $(BUILD_STATIC_JAVA_LIBRARY)
转自: https://segmentfault.com/a/1190000021742841
基于 Android 9.0。
许多命令时间一长就记不清了,记录一下。
在shell中执行"source build/envsetup.sh"后,Android将增加一些命令到当前环境中。
lunch <product_name>-<build_variant>
tapas [<App1> <App2> ...] [arm|x86|mips|arm64|x86_64|mips64] [eng|userdebug|user]
mm:编译当前目录中的所有模块,但不包含依赖的模块。
mmm dir/:target1,target2.
make 或 m 后面可以跟随不同的参数来指定编译目标。
dump-products:显示产品的编译信息。
make runtime
device/[company]/[device]
[device]
is your PCBA name. product is your software.
mkdir -p device/qiushao/pure
lunch
--> COMMON_LUNCH_CHOICES := pure-eng
(AndroidProducts.mk)
--> PRODUCT_MAKEFILES := $(LOCAL_DIR)/pure.mk
(AndroidProducts.mk)
--> PRODUCT_DEVICE := pure
(pure.mk)
--> device/[company]/pure/BoardConfig.mk
==> out directory: PRODUCT_NAME := pure
(pure.mk)
vim AndroidProducts.mk
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/pure.mk
COMMON_LUNCH_CHOICES := \
pure-eng
vim pure.mk
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_x86_64.mk)
PRODUCT_NAME := pure
PRODUCT_DEVICE := pure
vim BoardConfig.mk
include $(SRC_TARGET_DIR)/board/generic_x86_64/BoardConfig.mk
tree
.
└── pure
├── AndroidProducts.mk
├── BoardConfig.mk
└── pure.mk