[Description]
如何设计GPIO中断模拟普通按键控制静音等功能
[Solution]
参考设计思路:Kernel 底层可以参考kpd.c的POWEY USE EINT 的方式设计:把Key_MUTE送到framework
1.声明中断下半程的tasklet
#if KPD_PWRKEY_USE_EINT
static void kpd_pwrkey_handler(unsigned long data);
static DECLARE_TASKLET(kpd_pwrkey_tasklet, kpd_pwrkey_handler, 0);
static u8 kpd_pwrkey_state = !KPD_PWRKEY_POLARITY;
#endif
2.实现中断服务函数 发送按键消息到framework
#if KPD_PWRKEY_USE_EINT
static void kpd_pwrkey_handler(unsigned long data)
{
bool pressed;
u8 old_state = kpd_pwrkey_state;
kpd_pwrkey_state = !kpd_pwrkey_state;
pressed = (kpd_pwrkey_state == !!KPD_PWRKEY_POLARITY);
if (kpd_show_hw_keycode) {
printk(KPD_SAY "(%s) HW keycode = using EINT\n",
pressed ? "pressed" : "released");
}
input_report_key(kpd_input_dev, KPD_PWRKEY_MAP, pressed);
kpd_print("report Linux keycode = %u\n", KPD_PWRKEY_MAP);
/* for detecting the return to old_state */
mt65xx_eint_set_polarity(KPD_PWRKEY_EINT, old_state);
mt65xx_eint_unmask(KPD_PWRKEY_EINT);
}
3.kpd_pdrv_probe()中加入__set_bit(KPD_PWRKEY_MAP, kpd_input_dev->keybit);
声明中断初始化:
mt_set_gpio_mode(GPIO_KPD_MUTEKEY_EINT_PIN, GPIO_KPD_MUTEKEY_EINT_PIN_M_EINT);
mt_set_gpio_dir(GPIO_KPD_MUTEKEY_EINT_PIN, GPIO_DIR_IN);
//mt_set_gpio_pull_enable(GPIO_KPD_MUTEKEY_EINT_PIN, GPIO_PULL_DISABLE);
mt_set_gpio_pull_enable(GPIO_KPD_MUTEKEY_EINT_PIN, GPIO_PULL_ENABLE);
mt_set_gpio_pull_select(GPIO_KPD_MUTEKEY_EINT_PIN, GPIO_PULL_UP);
#if KPD_PWRKEY_USE_EINT
mt65xx_eint_set_sens(KPD_PWRKEY_EINT, KPD_PWRKEY_SENSITIVE);
mt65xx_eint_set_hw_debounce(KPD_PWRKEY_EINT, KPD_PWRKEY_DEBOUNCE);
mt65xx_eint_registration(KPD_PWRKEY_EINT, true, KPD_PWRKEY_POLARITY,
kpd_pwrkey_eint_handler, false);
#endif
4.dct tool配置GPIO为中断模式
5.注意实现静音按键,拨下开关时间会很长,如果只有一个KEY_MUTE,一直长按(press),没有发release,framework上长按事件会爆掉,建议拔下中断GPIO=0 发KEY_MUTE;拨上中断GPIO=1 发KEY_MUTE1;
如何添加一个按键:请参看MTK online FAQ :MTK on-line > FAQ Home > SW > ALPS > Driver - input system>FAQ04495 [Keypad]How to add a new key on android ICS\ICS2
或者拔下中断GPIO=0 发KEY_MUTE的press,接着马上发送release;在上层通过lastkey静音,newkey释放静音。
framework上在phonewindowmanager收到按键之后,可以拦截KEY_MUTE和KEY_MUTE1 去设置setting 的DB和静音模式
在framework/base/policy/src/com/android/impl/PhoneWindowManager.java
添加调试code 确认按键正常
if (true) {
Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
+ repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
}
//ADD log check the mute key dispatching
if(keyCode == KeyEvent.KEYCODE_MUTE)
Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " MUTE");
6.audio 静音模式接口
静音调用设置setRingerMode状态
RINGER_MODE_SILENT 静音,且无振动
RINGER_MODE_VIBRATE 静音,但有振动
RINGER_MODE_NORMAL 正常声音
铃响模式的设置是通过mAudioManager(音频管理器)来实现的.
mAudioManager所在服务如下:
文件: frameworks/base/media/java/android/media/AudioManager.java
public static final int RINGER_MODE_SILENT = 0;
public static final int RINGER_MODE_VIBRATE = 1;
public static final int RINGER_MODE_NORMAL = 2;
public void setRingerMode(int ringerMode) {
IAudioService service = getService();
try {
service.setRingerMode(ringerMode);
} catch (RemoteException e) {
Log.e(TAG, "Dead object in setRingerMode", e);
}
}
在拦截静音键或者在apk上接收key值添加相应的控制