?? w90p710_keypad.c
字號:
#include <linux/init.h>
#include <linux/slab.h>
#include <asm/errno.h>
#include <asm/delay.h>
#include <asm/arch/irqs.h>
#include <linux/mm.h>
#include <linux/poll.h>
#include <linux/module.h>
//#include <linux/jiffies.h>
#include <linux/timer.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm-arm/irq.h>
#include "w90p710_keypad.h"
MODULE_LICENSE("GPL");
//#undef DEBUG
#define DEBUG
#ifdef DEBUG
#define PDEBUG(fmt, args...) printk( KERN_ALERT "KEY: " fmt, ## args)
#else
#define PDEBUG(fmt, args...)
#endif
#undef DEBUG
#define MAJOR_NUM 192
#define MAX_BUTTON_BUF 16
#define BUTTON_TIMER_DELAY200MS (HZ/5)
#define BUTTON_TIMER_DELAY100MS (HZ/10)
#define BUTTON_TIMER_DELAY20MS (HZ/100)
static void (*buttonEvent)(void);
static unsigned char DEV_NAME[10] = "Keyboard";
static unsigned char KEYBOARD_ARRAY[5][4]={
{20,19,18,17},
{16,15,14,13},
{12,11,10, 9},
{ 8, 7, 6, 5},
{ 4, 3, 2, 1}
};
typedef struct{
unsigned char row;
unsigned char col;
}_KEYBOARD_INDEX;
static _KEYBOARD_INDEX keyboard_index;
typedef struct {
// unsigned int buttonIRQ;
unsigned char buf[MAX_BUTTON_BUF];
unsigned int head,tail;
wait_queue_head_t wq;
}_BUTTON_DEV;
static _BUTTON_DEV buttondev;
#define BUF_HEAD (buttondev.buf[buttondev.head])
#define BUF_TAIL (buttondev.buf[buttondev.tail])
#define INCBUF(x,mod) ((++(x)) & ((mod)-1))
static unsigned char buttonRead(void);
static unsigned char wakeup_flag=0;
static unsigned char timer_counter=0;
static unsigned char counter=0;
static unsigned char key_16=0;
//static int button_irq = 0;
static struct timer_list timer;
static unsigned char buttonRead(void)
{
unsigned char button_ret;
button_ret = BUF_TAIL;
buttondev.tail = INCBUF(buttondev.tail,MAX_BUTTON_BUF);
return button_ret;
}
static void buttonEvent_dummy(void) {}
static void buttonEvent_1(void)
{
unsigned char k=9;
unsigned int temp;
while(k!=4)
{
writel(readl(REG_GPIO_DATAOUT2)|0x3E0,REG_GPIO_DATAOUT2);
writel(readl(REG_GPIO_DATAOUT2)&(~(0x1<<(k--))),REG_GPIO_DATAOUT2);
temp = readl(REG_GPIO_DATAIN2) & 0x1E;
if(temp != 0x1E)
{
keyboard_index.row = k-4;
// PDEBUG("keyboard_index.row =%d,keyboard_index.col = %d\n",keyboard_index.row,keyboard_index.col);
if(keyboard_index.row>4)
keyboard_index.row = 0;
if(keyboard_index.col>3)
keyboard_index.col = 0;
if(KEYBOARD_ARRAY[keyboard_index.row][keyboard_index.col] != 19)
{
// PDEBUG("other key!\n");
BUF_HEAD = KEYBOARD_ARRAY[keyboard_index.row][keyboard_index.col];
buttondev.head = INCBUF(buttondev.head,MAX_BUTTON_BUF);
wakeup_flag=1;
wake_up_interruptible(&(buttondev.wq));
// del_timer(&timer);
}
else
{
PDEBUG("counter = %d,key_16=%d\n",counter,key_16);
key_16 = 1;
counter++;
if( !timer_counter )
{
timer_counter = 1;
timer.expires = jiffies + BUTTON_TIMER_DELAY200MS;
// PDEBUG("button_Event1 :add_timer timer_counter=%d\n",++timer_counter);
add_timer(&timer);
}
if(counter>5)
{
key_16 = 0;
counter = 0;
BUF_HEAD = 20;
buttondev.head = INCBUF(buttondev.head,MAX_BUTTON_BUF);
wakeup_flag=1;
wake_up_interruptible(&(buttondev.wq));
// PDEBUG("button_Event1 :del_timer timer_counter=%d\n",--timer_counter);
if( timer_counter )
{
timer_counter = 0;
del_timer(&timer);
}
}
}
break;
}
}
writel(readl(REG_GPIO_DATAOUT2) & 0xFFFFFC1F,REG_GPIO_DATAOUT2); //H0~H4 output Low
}
static int button_down(void)
{
unsigned int temp;
temp = readl(REG_GPIO_DATAIN2) & 0x1E;
if(temp != 0x1E)
{
//keyboard_index.col = (~(temp>>1) & 0xf);
switch(temp)
{
case 0x1C: keyboard_index.col = 0; break;
case 0x1A: keyboard_index.col = 1; break;
case 0x16: keyboard_index.col = 2; break;
case 0x0E: keyboard_index.col = 3; break;
default : break;
}
return 1;
}
return 0;
}
static void timer_handler(unsigned long data)
{
PDEBUG("timer_handler()\n");
// PDEBUG("timer_handler :del timer timer_counter=%d\n",--timer_counter);
if( timer_counter )
{
timer_counter = 0;
del_timer(&timer);
}
if(button_down())
{
PDEBUG(" timer_handler : button down\n");
buttonEvent();
}
else if(key_16)
{
// PDEBUG("timer_handler in else :del timer timer_counter=%d\n",--timer_counter);
// del_timer(&timer);
counter = 0;
key_16 =0;
BUF_HEAD = 19;
buttondev.head = INCBUF(buttondev.head,MAX_BUTTON_BUF);
wakeup_flag=1;
wake_up_interruptible(&(buttondev.wq));
}
// del_timer(&timer);
enable_irq(INT_nIRQ2);
}
static void keyboard_irq(int irq, void *dev_id, struct pt_regs *regs)
{
int i;
disable_irq_nosync(INT_nIRQ2);
// printk("In keyboard_irq!\n");
if((readl(0xFFF09000) & 0x1) == 0){
counter = 0;
if( !timer_counter )
{
timer_counter = 1;
timer.expires = jiffies + BUTTON_TIMER_DELAY100MS;
//printk("clear irq when in keyboard irq 1 = 0x%x\n",readl(0xFFF8212C));
writel(readl(0xFFF8212C) | (1<<4),0xFFF8212C);
add_timer(&timer);
}
}
else
{
PDEBUG("clear the isr sorce!\n");
for(i=0;i<50000;i++) ;
*(unsigned int volatile *)(0xfff00024) = 0;
}
enable_irq(INT_nIRQ2);
return;
}
static int keyboard_open(struct inode* i,struct file* f)
{
int result;
MOD_INC_USE_COUNT;
buttondev.head=buttondev.tail=0;
buttonEvent = buttonEvent_1;
writel( (readl(REG_AIC_SCR4) & 0xFFFFFF3F) | 0x80 ,REG_AIC_SCR4); //negative edge
// writel( (readl(REG_AIC_SCR4) & 0xFFFFFF3F) ,REG_AIC_SCR4); //low
// writel((readl(REG_AIC_IMR) | 0x10) ,REG_AIC_IMR); //mask bit
enable_irq(INT_nIRQ2);
result = request_irq(INT_nIRQ2,keyboard_irq,0,DEV_NAME,NULL);
if(result)
printk("register the keyboard_irq failed!\n");
// else
// printk("register the keyboard_irq successfull!\n");
return 0;
}
static int keyboard_close(struct inode *inode,struct file *filp)
{
MOD_DEC_USE_COUNT;
buttonEvent=buttonEvent_dummy;
free_irq(INT_nIRQ2,NULL);
return 0;
}
static ssize_t keyboard_read(struct file *filp, char *buff, size_t read_mode, loff_t *offp)
{
static unsigned char button_ret;
retry:
PDEBUG("keyboard_read: retry start\n");
if(buttondev.head!=buttondev.tail) {
button_ret = buttonRead();
copy_to_user(buff,(char *)&button_ret,sizeof(unsigned char));
PDEBUG("keyboard_read: the button_ret is 0x%x\n",button_ret);
// timer_counter = 0;
return sizeof(unsigned char);
}
else
{
if(filp->f_flags & O_NONBLOCK)
return -EAGAIN;
PDEBUG("keyboard_read: sleep\n");
//interruptible_sleep_on(&(buttondev.wq));//為安全起見,
wait_event_interruptible(buttondev.wq,wakeup_flag);
wakeup_flag=0;
PDEBUG("keyboard_read: sleep_after\n");
if(signal_pending(current))
{
printk("rturn -ERESTARTSYS\n");
return -ERESTARTSYS;
}
goto retry;
}
return sizeof(unsigned char);
}
static struct file_operations keyboard_fops =
{
owner: THIS_MODULE,
open: keyboard_open,
read: keyboard_read,
release: keyboard_close,
};
static int __init keyboard_710_reg(void)
{
int result;
buttonEvent=buttonEvent_dummy;
result = register_chrdev(MAJOR_NUM,DEV_NAME,&keyboard_fops);
if(result<0)
{
printk("initial the device error!\n");
return (result);
}
writel(readl(REG_GPIO_CFG2) & 0x00000001,REG_GPIO_CFG2); //GP43~GP51 in I/O mode
writel((readl(REG_GPIO_DIR2) & 0xFFFFFFE1) | 0x3E0,REG_GPIO_DIR2); //GP51~GP47 OUTPUT,GP46~GP43 INPUT
writel(readl(REG_GPIO_DATAOUT2) & 0xFFFFFC1F,REG_GPIO_DATAOUT2); //H0~H4 output Low
writel((readl(REG_GPIO_CFG5) & 0xF3FFFFFF) | 0x04000000 ,REG_GPIO_CFG5); //nIRQ2
init_waitqueue_head(&(buttondev.wq));
init_timer(&timer);
timer.function = timer_handler;
printk("W90P710 POS Keyboard initialized successful\n");
return (result);
}
static void keyboard_710_exit(void)
{
unregister_chrdev(MAJOR_NUM,DEV_NAME);
return;
}
module_init(keyboard_710_reg);
module_exit(keyboard_710_exit);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -