📄 key_driver.c
字号:
/**
* key driver for usdk130
* liwei@actions, 2006,08
*
* Base on keydriver by houjingkun@actions for lsdk130
*
* module discription:
*
* there are mainly two funs inthis module:
* 1. the key press_down ISR function, buttons_irq()
* 2. the key release_up ISR function, whether_button_up()
* NOTICE:
* in the near future, we may add semaphores for key messgage buffer
*/
/*
* V1.1 For touch key of EKT8120
* Modified by Richard, 2006,12
*/
#include "key_buf_queue.h"
#include "key_driver.h"
#include "irq.h"
#include "Atj213x.h"
#include "elf.h"
#include "drv_manager.h"
#include "includes.h"
#include "WM_Inc.h"
#include "task_key.h"
//#define DEBUG_INFO
#define UART2_INTERRUPT_NUM 19
#define UART2_CTL_ADDR 0xB0160020
#define UART2_RXDAT_ADDR (UART2_CTL_ADDR + 0x4)
#define UART2_TXDAT_ADDR (UART2_CTL_ADDR + 0x8)
#define UART2_STAT_ADDR (UART2_CTL_ADDR + 0xc)
#define UART1_CTL_ADDR 0xB0160000
#define UART1_RXDAT_ADDR (UART1_CTL_ADDR + 0x4)
#define UART1_TXDAT_ADDR (UART1_CTL_ADDR + 0x8)
#define UART1_STAT_ADDR (UART1_CTL_ADDR + 0xc)
//#define CMU_COREPLL 0xB0010000
//#define CMU_BUSCLK (CMU_COREPLL + 0xc)
//#define CMU_UART1CLK (CMU_COREPLL + 0x28)
//#define CMU_UART2CLK (CMU_COREPLL + 0x2c)
static void init_button_reg(void);
static void whether_button_up(void);
static void init_timer_interrupt(void);
static INT32S matrix8_buttons_init(void);
static INT32S matrix8_buttons_release();
static int translateKeyMessage(WM_KEY_INFO *keyInfo);
/**
forward declaration for hold status detecting
*/
void detect_hold_status(void);
void set_bool_holdkey_pressed(void);
void clear_bool_holdkey_pressed(void);
unsigned int is_bool_holdkey_pressed(void);
/*10*18 = 180ms*/
#define TICKS_KEY_DOWN_UP 18 /*INTERVAL between down and up*/
extern INT32U _dstart,_dend;
unsigned int keyapitbl[]={
(unsigned int)matrix8_buttons_read,
(unsigned int)is_bool_holdkey_pressed,
(unsigned int)translateKeyMessage
};
addrInfo addr_info __addrdata=
{
startAddr: (INT32U)&_dstart,
endAddr: (INT32U)&_dend
};/*start/end addr of the drv*/
static drv_Info drvinfo = {
"drv",
matrix8_buttons_init,
matrix8_buttons_release,
(INT32U)keyapitbl
};/*drvinfo required for installing drv*/
extern INT32U key_value[KEY_MESSAGE_BUF_SIZE];
extern unsigned int spos;
extern unsigned int rpos;
/*this two static vars are used to save the value read from the key hardware IOs
*
*/
static INT32U cur_key;
static INT32U save_key;
static INT32U irq_keyValue;
/*the soft timer for key up*/
static INT8U KEY_UP_TIMER;
static INT8U SET_UARTCLK_TIMER;
static unsigned int bool_holdkey_pressed = 0;
static unsigned int tp_reset_packet[4] = {0x54, 0xd8, 0x0, 0x1};
static unsigned int tp_synchronous_packet[4] = {0x00, 0x00, 0x00, 0x00};
static unsigned int tp_reset_flag;
void inline act_set_uart2_clk(void)
{
unsigned int tmp;
tmp = (act_readl(CMU_COREPLL) & 0x3f) * 6 / (((act_readl(CMU_BUSCLK) >> 2) & 0x3) + 1) * 1000000;
tmp = tmp / (9600 * 8) - 1;
if (tmp == (act_readl(CMU_UART2CLK) & 0xffff)) //if equal, no need to change
return;
act_writel(tmp | 0x10000, CMU_UART2CLK);
mdelay(80);
}
void tp_send_reset(void)
{
int i;
act_writel(0xff, UART2_STAT_ADDR);
for (i = 0; i<4 ; i++)
act_writel(tp_reset_packet[i], UART2_TXDAT_ADDR);
}
void tp_send_synchronous(void)
{
int i;
act_writel(0xff, UART2_STAT_ADDR);
for (i = 0; i<4 ; i++)
act_writel(tp_synchronous_packet[i], UART2_TXDAT_ADDR);
}
void init_button_reg(void)
{
INT32U tmp;
tmp = act_readl(DEV_CLK_EN);
tmp |= 0x06400000; //Enable GPIO, key , Uart clk
act_writel(tmp, DEV_CLK_EN);
act_set_uart2_clk();
act_writel(act_readl(MULTI_CON1) | 0x80000110, MULTI_CON1);
act_writel(0x0, UART2_STAT_ADDR);
act_writel(act_readl(UART2_CTL_ADDR) | 0x48003, UART2_CTL_ADDR);
act_writel(0xff, UART2_STAT_ADDR);
#ifdef DEBUG_INFO
printf("\nCMU_COREPLL = %x\n", act_readl(CMU_COREPLL));
printf("\nCMU_BUSCLK = %x\n", act_readl(CMU_BUSCLK));
printf("\nCMU_UART1CLK = %x\n", act_readl(CMU_UART1CLK));
printf("\nCMU_UART2CLK = %x\n", act_readl(CMU_UART2CLK));
printf("\nUART1_CTL_ADDR = %x\n", act_readl(UART1_CTL_ADDR));
printf("\nUART2_CTL_ADDR = %x\n", act_readl(UART2_CTL_ADDR));
#endif
}
/*this func is the ISR for the release_timer
* in this func, we save a new key release_up message by adding a bit in the
* key press_down message in the key_message buffer
*/
void whether_button_up(void)
{
int ind;
unsigned int keyCon;
/*init the key up timer( it is periodical ) at a very large value,
* so that it will not happen until there are a key down irq when the init cnt
* value is modified. */
mod_timer(KEY_UP_TIMER, 0xffffffff);
if (irq_keyValue == 0) {
return;
}
if ( is_full()) {
// printf("key buff full!!\n");
qretrieve();
return;
}
qstore(cur_key | 0x8000);
save_key = 0;
irq_keyValue = 0;
return;
}
void set_uart_clk(void)
{
act_set_uart2_clk();
}
/* should be called by init */
void init_timer_interrupt(void)
{
timer_arg_t arg;
arg.timerHandler = (void *) whether_button_up;
arg.timerValue = 0xffffffff;
arg.type = TIMER_CYCLE;
KEY_UP_TIMER = set_timer(&arg);//INITIAL VALUE
/**
Auto-set uart clk
*/
/*
arg.timerHandler = (void *) set_uart_clk;
arg.timerValue = 100;
arg.type = TIMER_CYCLE;
SET_UARTCLK_TIMER= set_timer(&arg);//INITIAL VALUE
*/
}
static void buttons_irq(unsigned int irq, void *dev_id)
{
INT32U keyCon;
#ifdef DEBUG_INFO
//printf("\n into buttons_irq() level 0 \n");
#endif
if ((act_readl(UART2_STAT_ADDR) & 0x01) == 0)
{
#ifdef DEBUG_INFO
printf("\n UART error! \n");
#endif
act_writel((act_readl(UART2_STAT_ADDR) | 0x01), UART2_STAT_ADDR);
return;
}
irq_keyValue = 0;
while(((act_readl(UART2_STAT_ADDR) >> 5) & 0x01) == 0)
{
irq_keyValue = (irq_keyValue << 8) | (act_readl(UART2_RXDAT_ADDR) & 0xff);
}
#ifdef DEBUG_INFO
printf("\n irq_keyValue = %x \n", irq_keyValue);
#endif
switch (irq_keyValue) {
//welcome
case 0x55555555:
tp_reset_flag = 1;
break;
//touch key
case 0x56000005:
cur_key = BUTTON_F1;
break;
case 0x56000009:
cur_key = BUTTON_F4;
break;
case 0x56000011:
cur_key = BUTTON_ESC;
break;
case 0x56000021:
cur_key = BUTTON_TAB;
break;
case 0x56000041:
cur_key = BUTTON_F3;
break;
case 0x56000081:
cur_key = BUTTON_UP;
break;
//touch scoll
case 0x56080001:
cur_key = BUTTON_F2;
break;
case 0x56040001:
cur_key = BUTTON_F2;
break;
case 0x56020001:
cur_key = BUTTON_F5;
break;
case 0x56010001:
cur_key = BUTTON_F5;
break;
case 0x56008001:
cur_key = BUTTON_TAB;
break;
case 0x56004001:
cur_key = BUTTON_TAB;
break;
case 0x56002001:
cur_key = BUTTON_TAB;
break;
case 0x56001001:
cur_key = BUTTON_TAB;
break;
/* default */
default:
// printf("bad key_data0 %x in button\n", irq_keyValue);
irq_keyValue = 0;
act_writel((act_readl(UART2_STAT_ADDR) | 0x01), UART2_STAT_ADDR);
return ;
}
if (save_key)
{
if (cur_key != save_key) {
qstore(save_key | 0x8000);
}
}
save_key = cur_key;
qstore(cur_key);
/* mod the key_up timer, so that in a TICKS_KEY_DOWN_UP later,
* there will be a key up message; and if there are continous press downs, there would not
* have key up message until there are no press downs*/
mod_timer(KEY_UP_TIMER, TICKS_KEY_DOWN_UP);
act_writel((act_readl(UART2_STAT_ADDR) | 0x01), UART2_STAT_ADDR);
return ;
}
/*
* we simulate a queue in a arrar buffer, since it's small size, we just shift left
* when we read the key messages.
*/
INT32U matrix8_buttons_read( INT32U * buffer, INT32U cnt )
{
INT32U ind;
if ( is_empty() ) {
return 0;
}
if ( cnt > sizeof_key_buf())
cnt = sizeof_key_buf() ;
for ( ind = 0; ind < cnt; ind++ ) {
buffer[ind] = qretrieve();
// printf("read a key %x\n",buffer[ind]);
}
return cnt;
}
INT32S matrix8_buttons_init( )
{
INT32S ret;
save_key = 0;
tp_reset_flag = 0;
init_button_reg();
ret = request_irq(UART2_INTERRUPT_NUM, buttons_irq, 0, DEVICE_NAME, (void *)0);
if (ret) {
#ifdef DEBUG_INFO
printf(" can't request irqs\n");
#endif
return ret;
}
tp_send_reset();
mdelay(500);
while(!tp_reset_flag)
{
#ifdef DEBUG_INFO
printf(" can't reset tp! \n");
#endif
return -1;
}
tp_send_synchronous();
mdelay(500);
act_writel(0xff, UART2_STAT_ADDR);
mdelay(100);
init_timer_interrupt();
return 0;
}
INT32S matrix8_buttons_release()
{
INT32U flags;
free_irq(UART2_INTERRUPT_NUM,(void *)0);
del_timer(KEY_UP_TIMER);
return 0;
}
void set_bool_holdkey_pressed(void)
{
bool_holdkey_pressed = 1;
// printf(" bool_holdkey_pressed set PMU_LRADC = %x\n", act_readl( PMU_LRADC ) );
}
static void clear_bool_holdkey_pressed(void)
{
bool_holdkey_pressed = 0;
}
unsigned int is_bool_holdkey_pressed(void)
{
return bool_holdkey_pressed;
}
/**
* 按键转化: 对于7键方案,以下函数将MENU长按装换为OK短按
* 对于9键方案,直接返回0就可以了
*
* 返回值:如果为1,表示该按键不需要转发,0表示需要继续发出
*
*/
#ifdef KEY_PAD_NUMBER_7
static int keyMenuHacked=0;
static int translateKeyMessage(WM_KEY_INFO *keyInfo)
{
int retVal=0;
switch(keyInfo->Key)
{
case KEY_MENU:
switch(keyInfo->PressedCnt)
{
case GUI_KEY_MODE_LONG: //长按MENU 返回上一级
keyInfo->Key=KEY_MENU;
keyInfo->PressedCnt=GUI_KEY_MODE_DOWN;
keyMenuHacked=1;
//retVal=1;
break;
case GUI_KEY_MODE_DOWN:
retVal=1;
break;
case GUI_KEY_MODE_HOLD:
if(keyMenuHacked)
retVal=1;
break;
case GUI_KEY_MODE_UP:
if(keyMenuHacked)
{
keyInfo->Key=KEY_MENU;
keyInfo->PressedCnt=GUI_KEY_MODE_UP;
}else
{
S_WM_SendKeyMessage(KEY_OK, GUI_KEY_MODE_DOWN);
keyInfo->Key=KEY_OK;
keyInfo->PressedCnt=GUI_KEY_MODE_UP;
}
keyMenuHacked=0;
break;
default:
break;
}
break;
default:
break;
}
return retVal;
}
#else
static int translateKeyMessage(WM_KEY_INFO *keyInfo)
{
return 0;
}
#endif
drv_Info *GetDrvInfo(void)
{
// printf("GetDrvInfo is called !\n");
return &drvinfo;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -