BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / embedded-system / #608同步于 2008/6/11
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Embedded_System机器人发帖

好几天没什么动静了,上个键盘驱动吧

fzylijun886
2008/6/11镜像同步1 回复
#include<linux/module.h> #include<linux/init.h> #include<linux/config.h> #include<linux/kernel.h> #include<linux/fs.h> #include<linux/interrupt.h> #include<linux/wait.h> #include<linux/cdev.h> #include<linux/sched.h> #include<linux/devfs_fs_kernel.h> #include<asm/hardware.h> #include<asm/delay.h> #include<asm/uaccess.h> #include<asm/io.h> #include<asm/arch-s3c2410/regs-gpio.h> #include<asm/arch-s3c2410/irqs.h> #define KEY_NUM 4 #define DEVICE_NAME "key" #define KEY_MAJOR 0 #define KEY_MINOR 0 #define MAX_KEY_BUF 16 #define KEY_IRQ1 IRQ_EINT0 #define KEY_IRQ2 IRQ_EINT2 #define KEY_IRQ3 IRQ_EINT11 #define KEY_IRQ4 IRQ_EINT19 #define KEY_STATUS_1 0 #define KEY_STATUS_2 2 #define KEY_STATUS_3 11 #define KEY_STATUS_4 19 define KEY_STATUS_DOWNX 0 #define KEY_STATUS_DOWN 1 #define KEY_STATUS_UP 2 #define KEY_TIMER_DELAY1 HZ/100 //100ms #define KEY_TIMER_DELAY2 HZ/5 //200ms #define KEY_TIMER_DELAY3 HZ //1000ms //unsigned long rINTPND; void __iomem * rINTPND; void __iomem * rINTMASK; void __iomem * rEINPEND; void __iomem * rEINPMASK; void __iomem * rSRCPND; void __iomem * rEXTINT0; void __iomem * rEXTINT1; void __iomem * rEXTINT2; void __iomem * rGPFDATA; void __iomem * rGPGDATA; void __iomem * rGPFCON; void __iomem * rGPGCON; #define INT_IRQ1 1<<0 #define INT_IRQ2 1<<2 #define INT_IRQ11 1<<11 #define INT_IRQ19 1<<19 #define INT_IRQ8_23 1<<5 static int key_major=KEY_MAJOR; static int flag=0; typedef struct { unsigned int keyStatus[KEY_NUM]; unsigned char buf[MAX_KEY_BUF]; unsigned int head,tail; wait_queue_head_t wq; struct cdev k_dev; } key_dev; static struct timer_list key_timer[KEY_NUM]; static key_dev * k_dev; static struct key_info { int irq_no; unsigned int gpio_port; unsigned int gpio_function; int key_no; } key_info_tab[KEY_NUM]= { { KEY_IRQ1,S3C2410_GPF0,S3C2410_GPF0_EINT0 ,0 } , { KEY_IRQ2,S3C2410_GPF2,S3C2410_GPF2_EINT2,1 } , { KEY_IRQ3,S3C2410_GPG3,S3C2410_GPG3_EINT11,2 } , { KEY_IRQ4,S3C2410_GPG11,S3C2410_GPG11_EINT19 ,3 } }; static unsigned char key_read(void) { unsigned char ret; ret=k_dev->buf[k_dev->tail]; k_dev->tail++; k_dev->tail=(k_dev->tail)%(MAX_KEY_BUF); return ret; } static void key_write(unsigned char key) { k_dev->buf[k_dev->head]=key; k_dev->head++; k_dev->head=(k_dev->head)%(MAX_KEY_BUF); } static void key_event(int key) { unsigned char key_no='0'; printk("key_event key =%d !\n",key); if(key==0) key_no='a'; else if(key==1) key_no='b'; else if(key==2) key_no='c'; else if(key==3) key_no='d'; key_write(key_no); key_num=key; flag=1; wake_up_interruptible(&(k_dev->wq)); } static void clear_pending(unsigned int value) { writel(value,rSRCPND); writel(value,rINTPND); } static void clear_sub_pending(unsigned int value) { writel(value,rEINPEND); //writel(value,rINTPND); } static void clear_interrupt(int key) { unsigned int value; value=ioread32(rINTPND); if(value==INT_IRQ1) { clear_pending(INT_IRQ1); } else if(value==INT_IRQ2) { clear_pending(INT_IRQ1); } else if(value==INT_IRQ8_23) { clear_pending(INT_IRQ8_23); value=ioread32(rEINPEND); if(value==INT_IRQ11) { clear_sub_pending(INT_IRQ11); } else if(value==INT_IRQ19) { clear_sub_pending(INT_IRQ19); } } } static int Is_key_down(int key) { int ret; int value; value=s3c2410_gpio_getpin(key_info_tab[key].gpio_port); if(value==0) ret=1; else ret=0; return ret; } static void key_timer_handle(unsigned long arg) { int key=(int)arg; if(Is_key_down(key)) { if(k_dev->keyStatus[key]==KEY_STATUS_DOWNX) { k_dev->keyStatus[key]=KEY_STATUS_DOWN; key_timer[key].expires=jiffies+KEY_TIMER_DELAY3; key_event(key); add_timer(&key_timer[key]); } else { key_timer[key].expires=jiffies+KEY_TIMER_DELAY2; add_timer(&key_timer[key]); } } else { printk("key %d up!\n",key); k_dev->keyStatus[key]=KEY_STATUS_UP; enable_irq(key_info_tab[key].irq_no); } } static irqreturn_t s3c2410_key_ISR(int irq,void *dev_id,struct pt_regs *regs) { int value; int key; struct key_info * k; k=(struct key_info *)dev_id; key=k->key_no; if(key<0 || key>3 ) { printk("Error irq no!\n"); return -1; } disable_irq(key_info_tab[key].irq_no); //绂佹涓柇 clear_interrupt(key); k_dev->keyStatus[key]=KEY_STATUS_DOWNX; key_timer[key].expires=jiffies+KEY_TIMER_DELAY1; add_timer(&key_timer[key]); return 0; } static int key_request_irqs(void) { int i,ret=0; struct key_info *k; for(i=0; i<sizeof(key_info_tab)/sizeof(key_info_tab[0]); i++) { k=key_info_tab+i; ret=request_irq(k->irq_no,s3c2410_key_ISR,SA_INTERRUPT,DEVICE_NAME,k); if(ret) { printk("Request irq(irq_no=%d) failed!\n",k->irq_no); break; } else printk("Request irq(irq_no=%d) succed!\n",k->irq_no); } return ret; } static void key_free_irqs(void) { int i; struct key_info *k; for(i=0; i<sizeof(key_info_tab)/sizeof(key_info_tab[0]); i++) { k=key_info_tab+i; free_irq(k->irq_no,k); } } static void key_init_timer(void) { int i; for(i=0; i<KEY_NUM;i++) { init_timer(&key_timer[i]); key_timer[i].function=&key_timer_handle; key_timer[i].data=i; key_timer[i].expires=jiffies+KEY_TIMER_DELAY1; } } static int s3c2410_key_open(struct inode *inode,struct file *filp) { int i; key_request_irqs(); key_init_timer(); return 0; } static int s3c2410_key_release(struct inode *inode,struct file *filp) { key_free_irqs(); return 0; } static ssize_t s3c2410_key_read(struct file *filp,char *buffer,size_t count,loff_t *ppos) { unsigned char button_ret; retry: printk("OPEN:retry start\n"); if(k_dev->head!=k_dev->tail) { button_ret=key_read(); printk("s3c2410_key_read:the button_ret is %d\n",button_ret); copy_to_user(buffer,(char *)&button_ret,sizeof(unsigned char)); flag=0; return sizeof(unsigned char); } else { if(filp->f_flags & O_NONBLOCK) return -EAGAIN; printk("OPEN: sleep\n"); //interruptible_sleep_on(&(buttondev.wq)); wait_event_interruptible(k_dev->wq,flag); flag=0; printk("OPEN: sleep_after\n"); if(signal_pending(current)) { printk("rturn -ERESTARTSYS\n"); return -ERESTARTSYS; } goto retry; } return sizeof(unsigned char); } static struct file_operations key_fops= { .owner = THIS_MODULE, .open = s3c2410_key_open, .read = s3c2410_key_read, .release = s3c2410_key_release, }; static void key_enable_irq(void) { unsigned int value; value=0; value|=(1<11)|(1<<19); iowrite32(value,rEINPEND); value=ioread32(rEINPMASK); value&=~((1<11)|(1<<19)); iowrite32(value,rEINPMASK); clear_pending(INT_IRQ1|INT_IRQ2| INT_IRQ8_23); value=ioread32(rINTMASK); value&=~((INT_IRQ1|INT_IRQ2| INT_IRQ8_23)); iowrite32(value,rINTMASK); } static void key_init_irqs(void) { int i; struct key_info *k; for(i=0; i<sizeof(key_info_tab)/sizeof(key_info_tab[0]); i++) { k=key_info_tab+i; s3c2410_gpio_cfgpin(k->gpio_port, k->gpio_function); set_irq_type(k->irq_no,IRQT_LOW); //set_irq_type(k->irq_no,S3C2410_EXTINT_LOWLEV); } key_enable_irq(); } /* IO remap */ static void key_ioremap(void) { rINTPND=ioremap(0x4a000010,4); rEINPEND=ioremap(0x560000a8,4); rSRCPND=ioremap(0x4a000000,4); rEXTINT0=ioremap(0x56000088,4); rEXTINT1=ioremap(0x5600008c,4); rEXTINT2=ioremap(0x56000090,4); rGPFDATA=ioremap(0x56000054,4); rGPGDATA=ioremap(0x56000064,4); rEINPMASK=ioremap(0x560000a4,4); rINTMASK=ioremap(0x4a000008,4); rGPFCON=ioremap(0x56000050,4); rGPGCON=ioremap(0x56000060,4); } static void key_setup_cdev( key_dev * dev,int index) { int err,i; int devno=MKDEV(key_major,index); cdev_init(&dev->k_dev,&key_fops); dev->k_dev.owner=THIS_MODULE; dev->k_dev.ops=&key_fops; err=cdev_add(&dev->k_dev,devno,1); init_waitqueue_head(&(dev->wq)); for(i=0 ; i<KEY_NUM; i++) dev->keyStatus[i]=KEY_STATUS_UP; dev->head=dev->tail=0; key_ioremap(); if(err) printk(KERN_NOTICE"Error %d adding key %d",err,index); } static int __init s3c2410_key_init(void) { int ret; dev_t devno=MKDEV(key_major,0); if(key_major) { ret=register_chrdev_region(devno,1,DEVICE_NAME); } else { ret=alloc_chrdev_region(&devno,0,1,DEVICE_NAME); key_major=MAJOR(devno); } if(ret<0) return ret; k_dev=kmalloc(sizeof(key_dev),GFP_KERNEL); if(!k_dev) { ret=-ENOMEM; goto fail_malloc; } memset(k_dev,0,sizeof(key_dev)); key_setup_cdev(k_dev,0); key_init_irqs(); #ifdef CONFIG_DEVFS_FS devfs_mk_cdev(MKDEV(key_major,0),S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,DEVICE_NAME); #endif printk(DEVICE_NAME" initialized\n"); return 0; fail_malloc: #ifdef CONFIG_DEVFS_FS devfs_remove(DEVICE_NAME); #endif unregister_chrdev_region(devno,1); } static void __exit s3c2410_key_eixt(void) { printk(DEVICE_NAME" exited\n"); cdev_del(&k_dev->k_dev); kfree(k_dev); unregister_chrdev_region(MKDEV(key_major,0),1); #ifdef CONFIG_DEVFS_FS devfs_remove(DEVICE_NAME); #endif //key_free_irqs(); } MODULE_LICENSE("GPL"); MODULE_DESCRIPTION ("A key device driver"); module_init(s3c2410_key_init); module_exit(s3c2410_key_eixt);
订阅后,新回复会通过你的通知中心匿名送达。
1 条回复
zhangyf900机器人#1 · 2013/8/1
想问一下,你这是什么键盘的? 我在做一个i8042的101键盘驱动,不知道你接触过没?可以给点建议不?