⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keybutton.c

📁 linux2.6下一个4x4的键盘驱动源码
💻 C
字号:
/*--------------------------------------------------------------  4X4键盘使用中断号IRQ_EINT4, IRQ_EINT5, IRQ_EINT6, IRQ_EINT7  4X4键盘行输入线:S3C2410_GPF4, S3C2410_GPF5,S3C2410_GPF6, S3C2410_GPF7(与中断号分别对应)  4X4键盘列扫描线:S3C2410_GPG0, S3C2410_GPG2, S3C2410_GPG8, S3C2410_GPG9--------------------------------------------------------------*/  #include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/miscdevice.h>#include <asm/uaccess.h> /*copy user*/#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <asm/io.h>#include <asm-arm/arch-s3c2410/irqs.h>#include <asm-arm/irq.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <linux/wait.h>//#include <linux/irq.h>#include <linux/cdev.h>#include <linux/delay.h>#include <linux/devfs_fs.h>#include <linux/devfs_fs_kernel.h>#include <asm/hardware.h>#include <asm/arch/regs-gpio.h>#define DEVICE_NAME	"keybutton"#define BUTTON_MAJOR 234#define BUTTON_MINOR 0#define KBDSTATUS_UP    0#define KBDSTATUS_DOWN  1#define KBDSTATUS_DOWNX  2static int kbd_status; //按键状态static int irq_col_tab[] = { IRQ_EINT4, IRQ_EINT5, IRQ_EINT6, IRQ_EINT7};#define COL_NUM ( (sizeof irq_col_tab) / sizeof (irq_col_tab[0]) )static unsigned gpio_col_tab[] = {S3C2410_GPF4, S3C2410_GPF5,S3C2410_GPF6, S3C2410_GPF7};static unsigned gpio_row_tab[] = {S3C2410_GPG0, S3C2410_GPG2, S3C2410_GPG8, S3C2410_GPG9 };static unsigned gpio_row_out_tab[] = { S3C2410_GPG0_OUTP, S3C2410_GPG2_OUTP, S3C2410_GPG8_OUTP, S3C2410_GPG9_OUTP };static unsigned key_scan_value[] = {0x001,0x004,0x100,0x200};#define ROW_NUM ( sizeof gpio_row_tab / sizeof (gpio_row_tab[0]) )static int ready = 0;static int key_value = 0, last_value = 0;int col_no, row_no,r;unsigned int gpf_con,gpf_dat,gpf_up,gpg_con,gpg_dat,gpg_up,gpf_con1,gpg_con1,gpf_dat1,gpg_dat1;static DECLARE_WAIT_QUEUE_HEAD(buttons_wait);//static int waitting_down_tab[] = {1, 1, 1, 1,};static void __iomem *gpbase;//static void __iomem *addrpenda_map;//static void __iomem *addrpendb_map;static void scan_kbd(void);static void kbd_timer_handler(void);static int ISKBD_DOWN(void);static int ISKBD_DOWN(void){ int c1; gpf_con1=readl(gpbase+0x50) ;  gpf_dat1=readl(gpbase+0x54); gpg_con1=readl(gpbase+0x60) ; gpg_dat1=readl(gpbase+0x64); //printk("ISKBD_DOWN col_no= %d\n",col_no); if(col_no==0){ 	writel(gpf_con1 & 0xfcff,gpbase+0x50); 	c1 = readl(gpbase+0x54) & 0x10; 	writel((gpf_con1 | (2<<8)),gpbase+0x50) ;  } else if(col_no==1){ 	writel(gpf_con1 & 0xf3ff,gpbase+0x50); 	c1 = readl(gpbase+0x54) & 0x20; 	writel((gpf_con1 | (2<<10)),gpbase+0x50) ;  } else if(col_no==2){ 	writel(gpf_con1 & 0xcfff,gpbase+0x50) ; 	c1 = readl(gpbase+0x54) & 0x40; 	writel((gpf_con1 |(2<<12)),gpbase+0x50) ;  } else if(col_no==3){ 	writel(gpf_con1 & 0x3fff,gpbase+0x50) ; 	c1 = readl(gpbase+0x54) & 0x80; 	writel((gpf_con1 |(2<<14)),gpbase+0x50) ;//F端口中F7管脚设为中断模式  } else 	return 0;	 if(!c1)   c1=1; else   c1=0;  return c1;} static void kbd_timer_handler(void){  if(ISKBD_DOWN())   {   	//printk("key  socend test down\n");   if(kbd_status == KBDSTATUS_DOWNX)     	{   		kbd_status = KBDSTATUS_DOWN;   		      scan_kbd();    }     mdelay(100);    kbd_timer_handler();   } else{   kbd_status = KBDSTATUS_UP;    }}static void scan_kbd(void){	   int i;     //spin_lock_irq(&kbd);     gpf_con=readl(gpbase+0x50) ;	       gpf_dat=readl(gpbase+0x54);     gpf_up=readl(gpbase+0x58);     gpg_con=readl(gpbase+0x60) ;     gpg_dat=readl(gpbase+0x64);     gpg_up=readl(gpbase+0x68);     //printk("gpf_con=%x,gpf_up=%x,gpf_dat=%x.gpg_con+%x\n",gpf_con,gpf_up,gpf_dat,gpg_con);     writel(gpf_con & 0x00ff,gpbase+0x50);     writel(gpf_up | 0xf7,gpbase+0x58);     //printk("gpf_con=%x,gpg_con=%x\n",readl(gpbase+0x50),readl(gpbase+0x60));	   for (i = 0; i < 4; i++) 	   {			//unsigned char val = 0x10;			//printk("scan row\n");			writel((gpg_dat | (key_scan_value[i])),gpbase+0x64);			udelay(100);		  r= s3c2410_gpio_getpin(gpio_col_tab[col_no]);			writel((gpg_dat & (~(key_scan_value[i]))),gpbase+0x64);			udelay(100);			if(r)			  { // found				  row_no = i;				  break;			  }		  }		  writel((gpf_con |(2<<2)|(2<<8)|(2<<10)|(2<<12)|(2<<14)),gpbase+0x50) ;      udelay(100);      set_irq_type(IRQ_EINT4,IRQT_LOW);      set_irq_type(IRQ_EINT5,IRQT_LOW);      set_irq_type(IRQ_EINT6,IRQT_LOW);      set_irq_type(IRQ_EINT7,IRQT_LOW);      //printk("gpf_con=%x,gpg_con=%x\n",readl(gpbase+0x50),readl(gpbase+0x60));	  	    //spin_lock_irq(&kbd);	    if (col_no < 0 || row_no < 0) 	    {	    	 mdelay(10);	    	 kbd_timer_handler();	    	 	    }	    key_value = row_no * 4 + col_no + 1;	    //printk("kernel key_value=%d\n",key_value);	    ready = 1;	    wake_up_interruptible(&buttons_wait);}static irqreturn_t  buttons_irq(int irq, void *dev_id, struct pt_regs *reg){	int i;	unsigned long flags;	col_no = -1; row_no = -1;	//printk("interupt=%d\n",irq);	for (i = 0; i < COL_NUM; i++) 	{		if (irq_col_tab[i] == irq) 		{			col_no = i;			//printk("irq col= %d\n",i);			break;		}	}	if (col_no < 0)  {		goto EXIT;	}	//printk("kbd_status 0=%d\n",kbd_status); if(kbd_status == KBDSTATUS_UP)   {  	//printk("key down\n");    local_irq_save(flags);     //printk("ISKBD_DOWN=%d\n",ISKBD_DOWN());   if(ISKBD_DOWN())           {     //printk("key first test down\n");     kbd_status = KBDSTATUS_DOWNX;          mdelay(10);         kbd_timer_handler();    }    else    	local_irq_restore(flags);	   }  EXIT:		  return IRQ_HANDLED;}static void free_irqs(void){	int i;	for (i = 0; i < COL_NUM; i++) {		int irq = irq_col_tab[i];		free_irq(irq, buttons_irq);	}}static void buttons_io_port_init(void){	int i;	for (i = 0; i < ROW_NUM; i ++) {		unsigned gpio = gpio_row_tab[i];		s3c2410_gpio_cfgpin(gpio, gpio_row_out_tab[i]);		s3c2410_gpio_pullup(gpio,1);		s3c2410_gpio_setpin(gpio,0);	}}static int buttons4x4_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos){	     //static int key;	     //int repeat = key == key_value;	    // key == key_value;        if (!ready)                return -EAGAIN;        if (count != sizeof key_value)                return -EINVAL;	     // if (repeat) {		     //  return -EAGAIN;	      //  }        copy_to_user(buffer, &key_value, sizeof key_value);	      last_value = key_value;        ready = 0;        return sizeof key_value;}static unsigned int buttons4x4_select(        struct file *file,        struct poll_table_struct *wait){        if (ready)                return 1;        poll_wait(file, &buttons_wait, wait);        return 0;}static int buttons4x4_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	switch(cmd) {	default:		return -EINVAL;	}}static int buttons4x4_open(struct inode *inode, struct file *file){	int i,ret;	//int port_irq;	for (i = 0; i < COL_NUM; i++) {		int irq = irq_col_tab[i];		set_irq_type(irq,IRQT_LOW);		s3c2410_gpio_pullup(gpio_col_tab[i],1);	  ret = request_irq(irq, buttons_irq, SA_INTERRUPT, DEVICE_NAME, NULL);	  		if (ret) {			unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);			printk(DEVICE_NAME " can't request irq %d\n", irq);			return ret;	     }     }  printk("keybutton interrupt register!\n");  return 0;}static int buttons4x4_release(struct inode *inode, struct file *file){	free_irqs();	return 0;}static struct file_operations buttons4x4_fops = {	.owner = THIS_MODULE,	.open  = buttons4x4_open,	.ioctl = buttons4x4_ioctl,	.poll  = buttons4x4_select,	.read  = buttons4x4_read,	.release = buttons4x4_release,};static int __init buttons4x4_init(void){	int ret;	//int i;	ready = 0;	#ifdef  CONFIG_DEVFS_FS   devfs_mk_cdev(MKDEV(BUTTON_MAJOR,BUTTON_MINOR),S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,DEVICE_NAME);  #endif	ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &buttons4x4_fops);	if (ret < 0) {	  printk(DEVICE_NAME " can't register major number\n");	  return ret;	}	printk(DEVICE_NAME " keybutton register \n");	buttons_io_port_init();	gpbase=ioremap_nocache(0x56000000,0x80);	kbd_status = KBDSTATUS_UP;	return 0;}static void __exit buttons4x4_exit(void){	iounmap(gpbase);  #ifdef CONFIG_DEVFS_FS    devfs_remove(DEVICE_NAME);    #endif	unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);	printk(DEVICE_NAME " keybutton unregister \n");}module_init(buttons4x4_init);module_exit(buttons4x4_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("guibaijun");MODULE_DESCRIPTION("s3c2410_kdb_4x4 driver--07-08-07");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -