简单键盘驱动

 #include<linux/timer.h>
#include<linux/fs.h>
#include<linux/delay.h>
#include<linux/jiffies.h>
#include<linux/kernel.h>
#include<asm/string.h>
#include<asm/io.h>
#include<linux/module.h>
#include<linux/types.h>
#include<linux/mm.h>
#include<linux/gpio.h>
#include<linux/cdev.h>
#include<linux/wait.h>
#include<linux/sched.h>
#include<linux/poll.h>
#define MAX_KEYS 6
#define KEY_TIMER_DELAY HZ/5
MODULE_LICENSE("Dual BSD/GPL");
static struct timer_list key_timer;
static int key_major=0;
static int key_values[MAX_KEYS]={0};
static int ev_press=0;
static struct timer_list key_timer;
static struct cdev KeyDevs;
wait_queue_head_t key_waitq;
unsigned int key_desc[MAX_KEYS]={S3C2410_GPG(0),S3C2410_GPG(3),S3C2410_GPG(5),S3C2410_GPG(6),S3C2410_GPG(7),S3C2410_GPG(11)};
void key_timer_handle(unsigned long data)

{
        unsigned int *key_p=(unsigned int *)data;
        int down;
        static unsigned char pressed[MAX_KEYS]={0};
        int i;
        for(i=0;i<MAX_KEYS;i++,key_p++)
        {
                s3c2410_gpio_setpin(*key_p,0<<0);
                down=s3c2410_gpio_getpin(*key_p);
                if(down==0)
                {
                        pressed[i]++;
                }
                ndelay(10);
                if(down==0&&pressed[i]==1)
                {
                        printk("pressed ");
                        key_values[i]=i+1;
                        ev_press=1;
                        wake_up_interruptible(&key_waitq);
                }
                if(down==1&&pressed[i]==1)
                        pressed[i]=0;
        }
        key_timer.expires=jiffies+KEY_TIMER_DELAY;
        add_timer(&key_timer);
}

static int key_open(struct inode *inode,struct file *filp)
{
         init_waitqueue_head(&key_waitq);
         init_timer(&key_timer);
         key_timer.function=&key_timer_handle;
         key_timer.data=(unsigned long)&key_desc;
         key_timer.expires=jiffies+KEY_TIMER_DELAY;
         add_timer(&key_timer);
         return 0;
}
static unsigned int key_poll(struct file *file,struct poll_table_struct *wait)
{
        unsigned int mask=0;
        poll_wait(file,&key_waitq,wait);
        if(ev_press)
                mask|=POLLIN|POLLRDNORM;
        return mask;
}
static ssize_t key_read(struct file *filp,char __user *buff,size_t count,loff_t *offp)
{
        unsigned long err;
        if(!ev_press)
        {
                if(filp->f_flags&O_NONBLOCK)
                        return -EAGAIN;
                else
                        wait_event_interruptible(key_waitq,ev_press);
        }

        ev_press=0;
        err=copy_to_user(buff,key_values,min(sizeof(key_values),count));
        memset(key_values,0,sizeof(key_values));
        return err?-EFAULT:min(sizeof(key_values),count);
}
static int key_release(struct inode *node,struct file *file)
{
        del_timer(&key_timer);
        return 0;
}
static void key_setup_cdev(struct cdev *dev,int minor,struct file_operations *fops)
{
        int err,devno=MKDEV(key_major,minor);
        cdev_init(dev,fops);
        dev->owner=THIS_MODULE;
        dev->ops=fops;
        err=cdev_add(dev,devno,1);
        if(err)
                printk(KERN_NOTICE "Error %d adding key %d",err,minor);
}
static struct file_operations key_ops={
.owner=THIS_MODULE,
.open=key_open,
.release=key_release,
.read=key_read,
.poll=key_poll,

};
static int __init keys_init(void)
{
        int result;
        dev_t dev=MKDEV(key_major,0);
        result=alloc_chrdev_region(&dev,0,1,"key");
        key_major=MAJOR(dev);
        if(result<0)
        {
                printk(KERN_WARNING "key: unable to get major %d ",key_major);
                return result;
        }
        if(key_major==0)
                key_major=result;
        key_setup_cdev(&KeyDevs,0,&key_ops);
        printk("key device installed,with major %d ",key_major);
        return 0;
}
static void __exit key_exit(void)
{
        cdev_del(&KeyDevs);
        unregister_chrdev_region(MKDEV(key_major,0),1);
        printk("key devices uninstalled ");
}
module_init(keys_init);

module_exit(key_exit);

原文地址:https://www.cnblogs.com/3ddan/p/3263694.html