车载系统中倒车的触发逻辑有很多中,其中可通过GPIO来监听倒车信号的变化。mcu通过通过硬线检测电平变化,向GPIO写入电平值,android驱动和应用监听电平变化实现倒车状态监听。
在旧平台中封装了一个方法直接读取/sys/class/misc/mtgpio/pin
节点的内容获取GPIO的电平值。 1为高电平,0为低电平。这种方式虽然简便,但需要赋予应用selinux权限,同时需要应用端开启线程监听变化,存在一定的风险。
private static final int MODE = 0;
private static final int INPUT_VALUE = 2;
private static final int DIRECTION = 5;
private static final int GPIO_HIGH = 1;
private static final int GPIO_LOW = 0;
public static int Backcar_Get_GPIO_Status() {
FileReader reader = null;
BufferedReader br = null;
String line_string;
int gpio_status = -1;
boolean bfind;
try {
reader = new FileReader("/sys/class/misc/mtgpio/pin");
br = new BufferedReader(reader);
line_string = br.readLine();
while(line_string != null) {
bfind = line_string.trim().startsWith("46:");
if(bfind) {
line_string = line_string.replaceAll("46:","");
line_string = line_string.trim();
//the match string([MODE] [PULL_SEL] [DIN] [DOUT] [PULL EN] [DIR] [IES] [SMT]));
/*0 indicate general gpio; 1 indicate output, 0 indicate input*/
if((line_string.charAt(MODE) == '0') && (line_string.charAt(DIRECTION) == '0')) {
if (line_string.charAt(INPUT_VALUE) == '1') {
gpio_status = GPIO_HIGH;
} else {
gpio_status = GPIO_LOW;
}
}
break;
}
line_string = br.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return gpio_status;
}
新平台避免应用层直接操作读取,在framework封装一层sdk供应用调用。framework的代码入下
package com.mediatek.backcar;
import android.os.RemoteException;
import android.util.Log;
import java.util.ArrayList;
import vendor.mediatek.hardware.backcar.V1_0.IBackcar;
import vendor.mediatek.hardware.backcar.V1_0.IBackcarCallback;
import vendor.mediatek.hardware.backcar.V1_0.IBackcarCallback.Stub;
public class BackCar {
private static final String TAG = "[BackCarSDK]";
private BackCar.Listener mListener;
private IBackcar mService;
private IBackcarCallback mCallback;
public BackCar() {
this.mListener = null;
this.mService = null;
this.mCallback = new BackCar.BackcarCallback();
try {
this.mService = IBackcar.getService();
} catch (RemoteException var3) {
var3.printStackTrace();
this.mService = null;
}
}
public boolean setListener(BackCar.Listener listener) {
if (null == this.mService) {
Log.e("[BackCarSDK]", "mService = null");
return false;
} else {
this.mListener = listener;
boolean var3 = true;
int status;
try {
if (null != this.mListener) {
status = this.mService.registerEventCallback(this.mCallback);
} else {
status = this.mService.unregisterEventCallback(this.mCallback);
}
} catch (RemoteException var5) {
var5.printStackTrace();
status = 1;
}
return 0 == status;
}
}
private class BackcarCallback extends Stub {
private BackcarCallback() {
}
public void eventNotify(int evt, int param1, int param2, int param3) {
Log.d("[BackCarSDK]", "eventNotify() enter evt = " + evt + ", param1 = " + param1);
if (BackCar.this.mListener != null) {
BackCar.this.mListener.onEvent(msg.what, msg.arg1, msg.arg2);
}
}
}
public interface Listener {
void onEvent(int var1, int var2, int var3);
}
}
应用层调用backcar framework对上提供的相关接口,framework再通过JNI调用backcar client客户端接口,通过binder通信到backcar server,实现GPIO信号的传递。
Backcar.java对应BackcarImpl.cpp
vendor/mediatek/proprietary/hardware/bcservice Backcar服务代码以及HIDL_SERVER代码
GPIO极性在backcar hal server代码BackcarImpl.cpp的buttonValue方法。
bc_gpio = !!(value & (1 << 0))
其中value为驱动层获取的多个GPIO位值,倒车GPIO为第一位。
Backcar HIDL接口路径
vendor/mediatek/proprietary/hardware/interfaces/backcar
Backcar Service通过打开/dev/backcardrv
节点 向驱动层发送指令进行gpio监测。
驱动层kernel-4.9/drivers/misc/mediatek/backcar/backcar.c
对应/dev/backcardrv
驱动节点,通过gpio_get_value
方法从GPIO表中获取倒车引脚pin电平值。
通过DTS配置gpio num,路径入下:
kernel-4.9/arch/arm/boot/dts/mediatek_android_demo.dts
可通过adb查看gpio表,依次输入如下指令:
adb root
adb shell
cd /sys/devices/soc/1000b000.pinctrl
cat pin
字段1PIN为gpio号,字段2MODE为设置的模式,字段3PULL_SEL为上拉下拉设置,字段4DIN为gpio输入值。