前言:指纹调试我们只需要关注kernel、hal、ta就可以将其点亮,高通使用自己的tee环境,MTK则需要使用第三方tee OS,三方tee的集成调试一般会有厂家配合,主要是调试spi ta,在此就不做阐述了,下面重点介绍指纹bring up。
一、驱动调试
驱动调试分为两个方面,dts中配置上电、reset、irq、pinctrl和移植driver代码调试驱动节点。
1.dts配置
一般高通和MTK平台代码中都会有默认集成的一家指纹,只需要copy过来改下gpio,如果有用到pinctrl,也要把pinctrl name改成与驱动中的name 统一。
kernel/msm-4.9/arch/arm64/boot/dts/qcom/(对应自己项目的dts)
-
fpc1020 {
-
compatible = "fpc,fpc1020";
-
interrupt-parent = <&tlmm>;
-
interrupts = <48 0>;
-
fpc,gpio_rst = <&tlmm 124 0x0>;
-
fpc,gpio_irq = <&tlmm 48 0>;
-
vcc_spi-supply = <&pm8953_l5>;
-
vdd_io-supply = <&pm8953_l5>;
-
vdd_ana-supply = <&pm8953_l5>;
-
pinctrl-names = "fpc1020_reset_reset",
-
"fpc1020_reset_active",
-
"fpc1020_irq_active";
-
pinctrl-0 = <&fpc_reset_low>;
-
pinctrl-1 = <&fpc_reset_high>;
-
pinctrl-2 = <&fpc_int_low>;
-
};
以上dts段,我们移植到新项目需要修改:
(1)compatible:驱动代码里的device_id与此处的compatible匹配后,才会走probe函数。
-
static const struct of_device_id fpc1020_of_match[] = {
-
{ .compatible = "fpc,fpc1020", },
-
{}
-
};
(2)GPIO:将reset、irq、中断号等改成自己项目的。
(3)上电:由于指纹即使灭屏休眠状态下也要能够解锁亮屏,所以指纹一般要设置为长供电,例所示为LDO供电,根据原理图,确认好自己用哪路LDO,如果该路供电非长供电,可以在rpm那边修改。
(4)pinctrl:如果厂家驱动driver不使用pinctrl操作gpio则不需要配置,如果厂家驱动driver中要求使用pinctrl,找到对应项目的pinctrl.dtsi,如下图所示.
-
fpc_reset_int {
-
fpc_reset_low: reset_low {
-
mux {
-
pins = "gpio124";
-
function = "fpc_reset_gpio_low";
-
};
-
config {
-
pins = "gpio124";
-
drive-strength = <2>;
-
bias-disable;
-
output-low;
-
};
-
};
-
fpc_reset_high: reset_high {
-
mux {
-
pins = "gpio124";
-
function = "fpc_reset_gpio_high";
-
};
-
config {
-
pins = "gpio124";
-
drive-strength = <2>;
-
bias-disable;
-
output-high;
-
};
-
};
-
fpc_int_low: int_low {
-
mux {
-
pins = "gpio48";
-
};
-
config {
-
pins = "gpio48";
-
drive-strength = <2>;
-
bias-pull-down;
-
input-enable;
-
};
-
};
-
};
(a)要检查gpio是否是自己项目的,下属的label例如fpc_reset_low与dtsi中pinctrl-0 = <&fpc_reset_low>是否匹配。
(b)检查项目dts中,pinctrl-names = "fpc1020_reset_reset",
"fpc1020_reset_active",
"fpc1020_irq_active";
与驱动driver probe函数解析dts时,name是否统一,如不统一很有可能会死机,需要抓串口分析。
-
rc = select_pin_ctl(fpc1020, "fpc1020_reset_reset");
-
rc = select_pin_ctl(fpc1020, "fpc1020_irq_active");
2.驱动driver移植
(1)在kernel/driver/input下,新建fingerprint/fpc文件夹,将厂商提供的驱动代码放到kernel/driver/input/fingerprint/fpc,同时编写Kconfig和Makefile文件。
-
Kconfig:
-
menu "FingerprintCard fingerprint driver"
-
config FINGERPRINT_FPC
-
default n
-
tristate "FPC_BTP fingerprint sensor support"
-
depends on SPI_MASTER
-
endmenu
-
Makefile:
-
obj-$(FINGERPRINT_FPC) += fpc1020.o
(2)Kconfig和Makefile在kernel中是从顶层开始递归调用的,所以还要将新添加的纳入上一层目录的Kconfig和Makefile中,这里就不赘述了,做过驱动的都知道。
(3)在kernel/arch/arm64/configs/ 目录下找到自己项目对应的deconfig和perf-deconfig,加入
CONFIG_FINGERPRINT_FPC=y
注:这里FINGERPRINT_FPC要与(1)中Kconfig和Makefile中保持一致
以上完成后,单编boot和dtbo,单独刷机验证,确认能否开机,以及设备节点是否生成。(此处多数厂家指纹无法通过串口log打印确认dts是否正确被解析,因为这些厂家指纹的dts解析,是由厂家ca发命令解析的,要等ca集成后再看。)
二、hal层移植
1.so库
一般厂家是释放so库的,极少数厂家释放半开源代码给你,这就需要自己调试编译。so一般有fingerprint.default.so和厂家的例如汇顶的gf_hal、gf_ca、工模相关so等。
以so库释放:将so放置在对应目录下,在项目的mk文件里将so纳入版本编译,例如:
PRODUCT_COPY_FILES+= vendor/fingerprint/goodix/fingerprint.default.so:vendor/lib64/hw/fingerprint.default.so
非so库释放:编写Android.mk即可
so只要编译出来是可以单独push的。
2.hal 服务
(1)需要检查下out目录里是否编译出android.hardware.biometrics.fingerprint@2.1-service相关的so和bin文件,一般默认是没有的。没有的话要将这块纳入编译,也可以单独编译push。
(2)需要确认下在hardware/interfaces/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp openhal函数中打开的so库,是否与自己调试的这家name匹配,FINGERPRINT_HARDWARE_MODULE_ID默认是fingerpritn.default.so,如果不一致将FINGERPRINT_HARDWARE_MODULE_ID定义为自己的就行了。
(3)将android.hardware.biometrics.fingerprint@2.1-service.rc 纳入编译,配置该服务开机自启动
(4)hidl修改
Android P以及之后需要修改三处:
device/$product/manifest.xml
hardware/interfaces/compatibility_matrices/...
device/qcom/common/vendor_framework_compatibility_matrix.xml
-
<hal format="hidl" optional="true">
-
<name>android.hardware.biometrics.fingerprint</name>
-
<version>2.1</version>
-
<interface>
-
<name>IBiometricsFingerprint</name>
-
<instance>default</instance>
-
</interface>
-
</hal>
注:语法不一样,device/$product/manifest.xml中添加时是需要去除上述图中optional="true"的。
三、TA移植
这个移植过程按照厂商给的文档一步步移植就可以了,这个在此就不赘述了,最后编译出来的ta在调试阶段也可以单独push 验证。
四、其他配置
(1)在init rc中修改节点权限
-
chown system system dev/goodix_fp
-
chmod 0664 /dev/goodix_fp
(2)打开setting中指纹选项
PRODUCT_COPY_FILES := frameworks/native/data/etc/android.hardware.fingerprint.xml:vendor/etc/permissions/android.hardware.fingerprint.xml
(3)确认spi号,kernel侧检查dts中端口的配置是否正确,在tz侧修改成指纹要用的spi号。
五、模组兼容
一般手机外设器件为了降低风险,模组会有多供料,一般是不同IC的。如果是同一IC,不同模组的,这个不需要我们自己做什么工作了,IC厂家otp中会烧录自己会识别,我们下面重点介绍不同IC的兼容。
方法一:硬件ID兼容
一般硬件会预留ID pin,一个ID pin高低可以兼容两家,两个ID pin可以兼容四家。
1.在lk阶段读取fp_id pin脚value
gpio_get_value(unsigned gpio)//这个是返回寄存器的值 ,需要换算成二进制,再结合数据手册看下gpio哪一位是表示高低电平的
2.利用cmdline,将value值从lk传递至kernel
3.kernel读取saved_command_line值,创建节点并写入值
4.hal中通过读取节点值来加载不同厂商的so
方法二:轮询加载兼容
1.驱动只创建设备结点,不申请配置GPIO和中断
2.在BiometricsFingerprint.cpp的openhal函数中轮询加载各家fingerprint.default.so
3.在ca中去配置GPIO,由供应商在so中完成ID检测,在没有检测到自家指纹模组的时候返回
六、selinux权限
上述是在userdebug版本上关闭selinux权限调试的,需要调试selinux权限保证打开selinux时,指纹仍可用。
调试方法:
adb shell getenforce //查看selinux权限状态,enforcing打开、permissive关闭
adb shell setenforce 0 //关闭selinux权限
adb shell setenforce 1 //打开selniux权限
adb shell stop //上述关闭重启后就会再次打开,可以在关闭selinux权限后执行stop start,这样设备重启后,selinux也不会再次被打开,方便调试
adb shell start
关于selinux权限如何配置,网上资料很多,在此就不赘述了。
七、常见问题
1.死机
常见原因:
(1)dts配置有问题:一般就是前面介绍的name不匹配造成的,抓取串口log,probr=e函数解析dts的代码逐行添加log,确认是哪里出错的,修改即可。
(2)tz内存:移植ta后需要扩大tz内存,不然很有可能会造成死机,每个平台修改的方式不太一样,这个可以问平台方要文档,比对文档修改即可。
Android P高通平台的可以参照:https://blog.csdn.net/dshine_/article/details/85101887
(3)指针异常:找到异常地址处,使用add2line解析出是哪个文件哪一行的代码再分析。
2.无法读取到sensor ID
常见原因:
(1)上电:电压表测量下供电是否符合厂商datasheet要求
(2)spi不通:检查下tz侧的端口号配置是否正确,该spi端口号是否是tz侧用的。(如果是AP侧则需要修改)
3.ta load 不起来
99%是tz内存有问题,如果你坚持认为你按照平台文档已经修改了,那么请你检查你的修改是否生效了
4.setting里没有指纹选项
检查manifest.xml和android.hardware.fingerprint.xml 是否在手机里,要两者都配置了才会出来指纹选项。
八、总结
指纹调试过程中,驱动、so、ta、rc这些都是可以单独刷机或者push的,但是内存和manifest.xml(有的平台能够单独push,在vendor/etc/vintf目录下,但是有的平台push是会死机的,所以不建议单独push)这个是需要全编译生效的,所以在三大件点亮正式开始调试之前一定要先编个已经配置好这些并且能正常开机的版本。
另,指纹其他的如果单独push很可能会乱掉,忘记push 哪一个再回来抓log查看,会非常费时费力,所以建议调试前编译第一个版本的时候,就先把so 、ta、2.1相关、rc等等先全部预置进去,后期哪里有问题,再单独push替换即可。