?? key_struct_driver_waitq.c
字號:
/************************************************************************
* 創建日期:2007/12/21
* 文件名稱:key_irq.c
* 文件作者:teacher liang
* 文件功能描述:MATRIX4開發板上一共有16個按鍵,分別影射到GPF0、GPF2、
* GPG3、GPG11, * 當按下按鍵時分別產生0、2、11、19號
* 外部中斷。這個驅動十分簡單,它僅僅是在按下了按鍵后打
* 印出一串消息。如果希望按下按鍵后做一些更有意義的事,
* 需要改寫中斷處理程序key_handler。
* **********************************************************************/
#include <linux/init.h> // 模塊初始化、清除函數的宏定義;
#include <linux/sched.h> // 大部分內核API的定義;
#include <linux/module.h> // 必須,
#include <linux/version.h> // 內核版本
#include <linux/moduleparam.h> // 模塊參數
#include <linux/kernel.h> // printk
#include <linux/types.h> // dev_t定義;
#include <linux/fs.h> // 文件系統頭文件,必需;
#include <linux/cdev.h> //struct cdev定義
#include <linux/interrupt.h> //注冊和注銷函數等
#include <asm/signal.h> //request_irq函數的標識
#include <asm/arch/irqs.h> //中斷號
#include <asm/hardware.h> //GPIO口操作函數
#include <asm/irq.h> //disable_irq, set_irq_type等函數的聲明
#include <asm/arch/regs-gpio.h> //GPIO口定義
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <linux/poll.h>
//#include "led_struct_driver.h"#define MATRIX4_KEYBOARD_NAME "matrix4_key"
void LedDisp(int led); /* function symbol from led driver(led_struct_driver.c)*/
static unsigned int key_major=0;
static unsigned int key_minor=0;
static unsigned int key_irq_munber[4]={IRQ_EINT19, IRQ_EINT11, IRQ_EINT2, IRQ_EINT0};
//static int eint[4] = {IRQ_EINT19, IRQ_EINT11, IRQ_EINT2, IRQ_EINT0};
static unsigned int ioport[4] = {S3C2410_GPG11, S3C2410_GPG3, S3C2410_GPF2, S3C2410_GPF0};
static unsigned int kscan[4] = {S3C2410_GPE11, S3C2410_GPG6, S3C2410_GPE13, S3C2410_GPG2};
static int ready = 0;static int key_value = 0;
static struct s3c2410_key {
int irq_no; unsigned int gpio_port; unsigned int gpio_port_kscan; int key_no;} s3c2410_key_tab[16] = {
/*鍵盤第1列 k10 k7 k4 k1*/ { IRQ_EINT19, S3C2410_GPG11, S3C2410_GPE11, 1 },
{ IRQ_EINT11, S3C2410_GPG3, S3C2410_GPE11, 4 },
{ IRQ_EINT2, S3C2410_GPF2, S3C2410_GPE11, 7 },
{ IRQ_EINT0, S3C2410_GPF0, S3C2410_GPE11, 10 },
/*鍵盤第2列 k11 k8 k5 k2*/ { IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG6, 2 },
{ IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG6, 5 },
{ IRQ_EINT2, S3C2410_GPF2, S3C2410_GPG6, 8 },
{ IRQ_EINT0, S3C2410_GPF0, S3C2410_GPG6, 11 },
/*鍵盤第3列 k12 k9 k5 k3*/ { IRQ_EINT19, S3C2410_GPG11, S3C2410_GPE13, 3 },
{ IRQ_EINT11, S3C2410_GPG3, S3C2410_GPE13, 6 },
{ IRQ_EINT2, S3C2410_GPF2, S3C2410_GPE13, 9 },
{ IRQ_EINT0, S3C2410_GPF0, S3C2410_GPE13, 12 },
/*鍵盤第4列 k16 k15 k14 k13*/ { IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG2, 13 },
{ IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG2, 14 },
{ IRQ_EINT2, S3C2410_GPF2, S3C2410_GPG2, 15 },
{ IRQ_EINT0, S3C2410_GPF0, S3C2410_GPG2, 16 },
};
//定義與綁定tasklet函數void key_tasklet_action(unsigned long t);
DECLARE_TASKLET(key_tasklet, key_tasklet_action, 0);
void key_tasklet_action(unsigned long t)
{ printk("<1>led action\n");
LedDisp((int)t); printk("<1> the key value is : %d \n",key_value);
}
/*初始化按鍵的等待隊列*/static DECLARE_WAIT_QUEUE_HEAD(buttons_wait);
static int matrix4_gpio_setup(void)
{ s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_EINT0);
s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_EINT2);
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_EINT11);
s3c2410_gpio_cfgpin(S3C2410_GPG11,S3C2410_GPG11_EINT19);
s3c2410_gpio_cfgpin(S3C2410_GPE11,S3C2410_GPE11_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPE13,S3C2410_GPE13_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPG2,S3C2410_GPG2_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPG6,S3C2410_GPG6_OUTP);
}/* 設置GPIO口為輸入狀態 */static void buttons_port_reset(void){ //int i; s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_INP);
s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_INP);
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_INP);
s3c2410_gpio_cfgpin(S3C2410_GPG11,S3C2410_GPG11_INP);
//s3c2410_gpio_setpin(S3C2410_GPF0,1);
}
/* 設置單個kscan口為輸出0 */static void buttons_kscan_reset(int column){ int i; for(i=0; i < sizeof kscan / sizeof kscan[1]; i++) { if(i == column) s3c2410_gpio_setpin(kscan[i], 0);
else s3c2410_gpio_setpin(kscan[i], 1);
}}
/* 初始化kscan口為輸出0 */static void buttons_io_port_init(void){ int i; s3c2410_gpio_cfgpin(S3C2410_GPE11,S3C2410_GPE11_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPE13,S3C2410_GPE13_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPG2,S3C2410_GPG2_OUTP);
s3c2410_gpio_cfgpin(S3C2410_GPG6,S3C2410_GPG6_OUTP);
for(i=0; i < sizeof kscan / sizeof kscan[1]; i++) { //set_gpio_ctrl(kscan[i] | GPIO_PULLUP_DIS | GPIO_MODE_OUT);
//write_gpio_bit(, 0);
//s3c2410_gpio_cfgpin(kscan[i], );
s3c2410_gpio_setpin(kscan[i],0); }}/* 重新設置中斷 */static void buttons_int_reset(void){/*
int i;
for(i=0; i < sizeof eint / sizeof eint[1]; i++) { set_external_irq(eint[i], EXT_FALLING_EDGE, GPIO_PULLUP_DIS); }
*/
s3c2410_gpio_cfgpin(S3C2410_GPF0,S3C2410_GPF0_EINT0);
s3c2410_gpio_cfgpin(S3C2410_GPF2,S3C2410_GPF2_EINT2);
s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_EINT11);
s3c2410_gpio_cfgpin(S3C2410_GPG11,S3C2410_GPG11_EINT19);
}
static irqreturn_t buttons_irq(int irq, void *dev_id, struct pt_regs *reg)
{ struct s3c2410_key *k; int i, j; int found = 0; int up = -1; int column = 0; int row = 0; buttons_port_reset(); /* 設置GPIO為輸入狀態 */ mdelay(10); /*延時10000us*/
/* 鍵盤掃描 */ for ( j = 0; j < sizeof kscan / sizeof kscan[1]; j++) { buttons_kscan_reset(j); column = j; for ( i = 0; i < sizeof key_irq_munber / sizeof key_irq_munber[1]; i++) {
if(key_irq_munber[i] == irq) {
row = i; // up = read_gpio_bit(ioport[i]);
up = s3c2410_gpio_getpin(ioport[i]);
break; } } if(up == 0) { found = 1; break; } } mdelay(10); /* 延時去抖 */
if (found) { k = s3c2410_key_tab + column * 4 + row;
if (up) { key_value = k->key_no + 0x80;// } else { key_value = k->key_no; } } ready = 1; wake_up_interruptible(&buttons_wait);
//調度tasklet執行
key_tasklet.data = row+1;
tasklet_schedule(&key_tasklet);
buttons_io_port_init(); /* 重新設置GPIO為輸出 */ buttons_int_reset(); /* 重新設置中斷 */
return 0;
}
/*static void key_handler(int irq,void *dev_id,struct pt_regs *regs)
{
disable_irq(irq);
printk("<1>the irq is %d \n",(irq-16));
enable_irq(irq);
return 0;
}*/static int matrix4_buttons_open(struct inode *inode,struct file *filp)
{
printk("<1>matrix4_keyboard_open \n");
return 0;
}
static int matrix4_buttons_release(struct inode *inode,struct file *filp)
{
return 0;
}
static int matrix4_buttons_read(struct file * file, char * buffer, size_t count, loff_t *ppos){ static int key;// int flags; int repeat; if (!ready) return -EAGAIN; if (count != sizeof key_value) return -EINVAL; //save_flags(flags); if (key != key_value) { key = key_value; repeat = 0; } else { repeat = 1; } //restore_flags(flags); /*if (repeat) { return -EAGAIN; }*/ copy_to_user(buffer, &key, sizeof key); ready = 0; return sizeof key_value;}static unsigned int matrix4_buttons_select(struct file *filp, struct poll_table_struct *wait)
{ if (ready) return 1; poll_wait(filp, &buttons_wait, wait);
//通過調用函數 poll_wait,增加buttons_wait等待隊列到poll_table 結構。 return 0;}static int matrix4_buttons_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ switch(cmd) { default: return -EINVAL; }}static struct file_operations matrix4_buttons_fops = { .owner = THIS_MODULE,
.open = matrix4_buttons_open,
.release = matrix4_buttons_release,
.ioctl = matrix4_buttons_ioctl,
.poll = matrix4_buttons_select,
.read = matrix4_buttons_read,
};
/*
static struct file_operations key_fops={
.owner = THIS_MODULE,
.open = matrix4_keyboard_open,
.release = matrix4_keyboard_release,
};
*/
static dev_t dev;
static struct cdev *key_cdev;
static int matrix4_buttons_init(void)
{
int i;
int result; if(key_major)
{
dev=MKDEV(key_major,key_minor);
result=register_chrdev_region(dev,1,MATRIX4_KEYBOARD_NAME);
}
else
{
result=alloc_chrdev_region(&dev,key_minor,1,MATRIX4_KEYBOARD_NAME);
key_major=MAJOR(dev);
}
if(result<0)
{
printk("<1>MATRIX4 keyboard device cannot get key_major!\n");
return -1;
}
key_cdev=cdev_alloc();
cdev_init(key_cdev,&matrix4_buttons_fops);
key_cdev->owner=THIS_MODULE;
// key_cdev->ops=&key_fops;
/* 注冊中斷 */
matrix4_gpio_setup();
for(i=0;i<4;i++)
{
if(request_irq(key_irq_munber[i],buttons_irq,SA_INTERRUPT,MATRIX4_KEYBOARD_NAME,NULL)){
printk("<1>Error : cannot register irq %d \n",key_irq_munber[i]);
return -1;
}
set_irq_type(key_irq_munber[i],IRQT_FALLING);
}
result=cdev_add(key_cdev,dev,1);
if(result){
printk("<1>Error: while register keyboard device !\n");
return -1;
} return 0;}
static void matrix4_buttons_exit(void)
{
int i;
unregister_chrdev_region(dev,1);
cdev_del(key_cdev);
for(i=0;i<4;i++)
free_irq(key_irq_munber[i],buttons_irq);
}
module_init(matrix4_buttons_init);
module_exit(matrix4_buttons_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("");
MODULE_DESCRIPTION("MATRIX4 keyboard driver!");
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -