以前在瑞芯微的平台上调试过adckey,也修改过adckey对应的功能,当时在瑞芯微平台上的需求是将recovery按键修改成back按键,修改方法也很简单,在dts设备树里面只要修改对应的key值为back的key值就行。现在全志A33平台的需求是将vol+按键修改成back按键,调查后发现全志平台的修改就没有像瑞芯微平台这么简单了,在A33的sys_config.fex的配置文件里面,没有对adc key的配置操作,这样子的话只能自己去驱动里面去修改对应内容,修改过程如下:
1.一开始并不清楚如何下手,那么先看下按键的原理图是从哪个引脚上引出的。
如下图所示的按键电路,adckey就是通过串联电阻的方式,检测不同的电压来判断按下的是哪个按键。
2.上图的按键是从lradc0引脚引出,现在要做的是把VOL+按键修改成BACK按键,但是目前还不知道要修改哪个驱动,那么索性直接在driver目录下搜索lradc关键字,看看哪些驱动里面有这个关键字。
搜索完目录发现./drivers/input/keyboard/sunxi-keyboard.c文件里面含有lradc字符,而且sunxi-keyboard.c文件就是对按键的处理,所以我们进入到该驱动文件下查看对应的内容。
直接看驱动的初始化函数,发现初始化函数里面的有一个函数,跟我们现在有做的工作有很大的关系:
if (request_irq(SW_INT_IRQNO_LRADC, sunxi_isr_key, 0, "sunxikbd", NULL)) {
err = -EBUSY;
printk(KERN_DEBUG "request irq failure. \n");
goto fail2;
}
该函数的参数有一个SW_INT_IRQNO_LRADC的宏,而且是一个按键的中断申请函数,我们直接进入到中断函数里面查看对应的操作。
接下来我就直接在中断函数源码里面,以注解的方式对函数的功能进行说明:
static irqreturn_t sunxi_isr_key(int irq, void *dummy)
{
u32 reg_val = 0;
int judge_flag = 0;
dprintk(DEBUG_INT, "Key Interrupt\n");
reg_val = sunxi_keyboard_read_ints(); //louhn:读取按键按下的数据
//writel(reg_val,KEY_BASSADDRESS + LRADC_INT_STA);
if (reg_val & LRADC_ADC0_DOWNPEND) { //louhn:分析按键数据是否为按键按下
dprintk(DEBUG_INT, "key down\n");
}
if (reg_val & LRADC_ADC0_DATAPEND) { //louhn:分析按键数据
key_val = sunxi_keyboard_read_data(KEY_BASSADDRESS+LRADC_DATA0);
if (key_val < 0x3f) {
compare_buffer[key_cnt] = key_val&0x3f;
}
if ((key_cnt + 1) < REPORT_START_NUM) {
key_cnt++;
/* do not report key message */
} else {
if(compare_buffer[0] == compare_buffer[1])
{
key_val = compare_buffer[1];
scancode = keypad_mapindex[key_val&0x3f]; //louhn:scancode即为提取的按键的值
judge_flag = 1;
key_cnt = 0;
} else {
key_cnt = 0;
judge_flag = 0;
}
if (1 == judge_flag) {
dprintk(DEBUG_INT, "report data: key_val :%8d transfer_code: %8d , scancode: %8d\n", \
key_val, transfer_code, scancode);
if (transfer_code == scancode) {
/* report repeat key value */
#ifdef REPORT_REPEAT_KEY_FROM_HW
input_report_key(sunxikbd_dev, sunxi_scankeycodes[scancode], 0);
input_sync(sunxikbd_dev);
input_report_key(sunxikbd_dev, sunxi_scankeycodes[scancode], 1);
input_sync(sunxikbd_dev);
#else
/* do not report key value */
#endif
} else if (INITIAL_VALUE != transfer_code) {
/* report previous key value up signal + report current key value down */
input_report_key(sunxikbd_dev, sunxi_scankeycodes[transfer_code], 0);
input_sync(sunxikbd_dev);
input_report_key(sunxikbd_dev, sunxi_scankeycodes[scancode], 1);
input_sync(sunxikbd_dev);
transfer_code = scancode;
} else {
/* INITIAL_VALUE == transfer_code, first time to report key event */
input_report_key(sunxikbd_dev, sunxi_scankeycodes[scancode], 1);
input_sync(sunxikbd_dev);
transfer_code = scancode;
}
}
}
}
if (reg_val & LRADC_ADC0_UPPEND) { //louhn:按键抬起
if(INITIAL_VALUE != transfer_code) {
dprintk(DEBUG_INT, "report data: key_val :%8d transfer_code: %8d \n",key_val, transfer_code);
input_report_key(sunxikbd_dev, sunxi_scankeycodes[transfer_code], 0);
input_sync(sunxikbd_dev);
}
dprintk(DEBUG_INT, "key up \n");
key_cnt = 0;
judge_flag = 0;
transfer_code = INITIAL_VALUE;
}
sunxi_keyboard_clr_ints(reg_val);
return IRQ_HANDLED;
}
3.之后只要我们修改scancode的值就可以了,通过测试了解到vol+键的scancode 为0,而back按键的scancode为3,所以这里只要加个判断就可以将vol+按键的功能改为back功能。
} else {
if(compare_buffer[0] == compare_buffer[1])
{
key_val = compare_buffer[1];
scancode = keypad_mapindex[key_val&0x3f];
if(scancode == 0){ // louhn:如果scancode == 0,就将scancode替换成3
scancode = 3;
}
judge_flag = 1;
key_cnt = 0;
} else {
key_cnt = 0;
judge_flag = 0;
}
... ...