| 
 | 
- /*
 
 - misc device driver ,add the extern interrupt to asy connect with
 
 - the user application.
 
 - */
 
 - #include <linux/module.h>
 
 - #include <linux/fs.h>
 
 - #include <linux/miscdevice.h>
 
 - #include <linux/init.h>
 
 - #include <linux/gpio.h>
 
 - #include <linux/interrupt.h>
 
  
- #include <linux/mm.h>
 
 - #include <linux/slab.h>
 
 - #include <linux/sched.h>
 
  
- #include <asm/uaccess.h>
 
  
- #define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio)) 
 
  
- #define DEVICE_NAME         "hello"
 
 - #define MAX_KEY_BUF      16
 
 - #define KEY_NUM          2
 
  
- #define KEYSTATUS_UP    0
 
 - #define KEYSTATUS_DOWNX 2
 
 - #define KEYSTATUS_DOWN  1
 
  
- #define KEY_TIMER_DELAY 200
 
  
- typedef unsigned char KEY_RET ;
 
  
- static struct key_info
 
 - {
 
 -         const char *desc;
 
 -         int gpio_port;
 
 -         int key_no;
 
 - } key_info_tab[KEY_NUM] = 
 
 - {
 
 -         {"KEY_1",GPIO_TO_PIN(1, 16),0},
 
 -         {"KEY_2",GPIO_TO_PIN(1, 17),1},
 
 - };
 
  
- static struct key_dev
 
 - {
 
 -         unsigned int keystatus[KEY_NUM];
 
 -         KEY_RET buf[MAX_KEY_BUF];
 
 -         unsigned int head ,tail;
 
 -         wait_queue_head_t wq;
 
 -         struct miscdevice miscdev;
 
 - } *keydevp;
 
  
- static struct timer_list key_timer[KEY_NUM];/*按键的延时*/
 
  
- int ISKEY_DOWN(int k)
 
 - {
 
 -         unsigned int gpio = key_info_tab[k].gpio_port;
 
 -         printk("gpio(%d)_get_value:%d\n",gpio,gpio_get_value(gpio));
 
 -         return gpio_get_value(gpio);
 
 - }
 
 - /*按键延时处理函数*/
 
 - void keyboard_timer_handler(unsigned long data)
 
 - {
 
 -         int key = data;
 
 -         printk("handler data is:%d",key);
 
 -         if (ISKEY_DOWN(key))
 
 -         {
 
 -                 if (keydevp->keystatus[key] == KEYSTATUS_DOWNX)
 
 -                 {
 
 -                         keydevp->keystatus[key] = KEYSTATUS_DOWN;
 
 -                         if(keydevp->tail<MAX_KEY_BUF)
 
 -                         {
 
 -                                 keydevp->buf[keydevp->tail] = key;
 
 -                                 keydevp->tail++;
 
 -                         }
 
 -                         else
 
 -                         {
 
 -                                 keydevp->tail=0;
 
 -                                 keydevp->buf[keydevp->tail] = key;
 
 -                                 keydevp->tail++;
 
 -                         }
 
 -                         wake_up_interruptible(&(keydevp->wq));
 
 -                         key_timer[key].expires = jiffies + KEY_TIMER_DELAY;
 
 -                         add_timer(&key_timer[key]);
 
 -                 }
 
 -                 else
 
 -                 {
 
 -                         key_timer[key].expires = jiffies + KEY_TIMER_DELAY;
 
 -                         add_timer(&key_timer[key]);
 
 -                 }
 
 -         }
 
 -         else
 
 -         {
 
 -                 keydevp->keystatus[key] = KEYSTATUS_UP;
 
 -                 del_timer(&key_timer[key]);
 
 -                 enable_irq(gpio_to_irq(key_info_tab[key].gpio_port));
 
 -         }
 
 - }
 
  
- /*中断处理顶半部*/
 
 - static irqreturn_t keyboard_interrupt(int irq,void *dev_id){
 
 -         struct key_info *key;
 
 -         key = dev_id;
 
 -         disable_irq(gpio_to_irq(key->gpio_port));
 
  
-         keydevp->keystatus[key->key_no] = KEYSTATUS_DOWNX;
 
 -         key_timer[key->key_no].expires = jiffies + KEY_TIMER_DELAY;
 
 -         add_timer(&key_timer[key->key_no]);
 
 -         return IRQ_HANDLED;
 
 - }
 
  
- static ssize_t hello_read(struct file *filp, char __user *buf, size_t count,loff_t*ppos)
 
 - {
 
 -         int ret ;
 
 -         retry: if (keydevp->head != keydevp->tail)
 
 -         {
 
 -                 if(keydevp->head<MAX_KEY_BUF)
 
 -                 {
 
 -                         ret=copy_to_user(buf,&keydevp->buf[keydevp->head],1);
 
 -                         keydevp->buf[keydevp->head]=0;
 
 -                         keydevp->head++;
 
 -                         return ret;
 
 -                 }
 
 -                 else
 
 -                 {
 
 -                         keydevp->head=0;
 
 -                         ret=copy_to_user(buf,&keydevp->buf[keydevp->head],1);
 
 -                         keydevp->buf[keydevp->head]=0;
 
 -                         keydevp->head++;
 
 -                         return ret;
 
 -                 }
 
 -         }
 
 -         else
 
 -         {
 
 -                 if (filp->f_flags &O_NONBLOCK)
 
 -                 {
 
 -                         return - EAGAIN;
 
 -                 }
 
 -                 interruptible_sleep_on(&(keydevp->wq));
 
 -         goto retry;
 
 -         }
 
 -         return 0;
 
 - }
 
  
- static int hello_open(struct inode *inode, struct file *file)
 
 - {
 
 -         return 0;
 
 - }
 
  
- static int hello_close(struct inode *inode, struct file *file)
 
 - {
 
 -         return 0;
 
 - }
 
  
- static struct file_operations hello_fops=
 
 - {
 
 -         .owner                        =        THIS_MODULE,
 
 -         .open                         =         hello_open,
 
 -         .release                 =         hello_close,
 
 -         .read                   =       hello_read,
 
 - };
 
  
- static struct miscdevice misc = {
 
 -         .minor        = MISC_DYNAMIC_MINOR,
 
 -         .name        = DEVICE_NAME,
 
 -         .fops        = &hello_fops,
 
 - };
 
  
- /*注册按键中断*/
 
 - int keyboard_request_irqs(void)
 
 - {
 
 -         struct key_info *k;
 
 -         int i, ret ,irq ,irqflags;
 
 -         for(i=0;i<sizeof(key_info_tab)/sizeof(struct key_info);i++)
 
 -         {
 
 -                 k = &key_info_tab[i];
 
 -                 /*缺少外部中断状态设置*/
 
  
-                 ret = gpio_request(k->gpio_port,k->desc);
 
 -                 if(ret < 0 )
 
 -                 {        
 
 -                         printk("can't request gpio!%d error:%d\n",k->gpio_port,ret);
 
 -                         return -1;        
 
 -                 }
 
  
-                 ret = gpio_direction_input(k->gpio_port);
 
 -                 if(ret < 0)
 
 -                 {
 
 -                         printk("can't config gpio!%d error:%d\n",k->gpio_port,ret);
 
 -                         return -1;
 
 -                 }
 
 -         /*
 
 -                 ret = gpio_set_debounce(k->gpio_port,2000);
 
 -                 if(ret < 0)
 
 -                 {
 
 -                         printk("can't set debounce!%d error:%d\n",k->gpio_port,ret);
 
 -                         return -1;
 
 -                 }
 
 -         */
 
 -                 irq = gpio_to_irq(k->gpio_port);
 
  
-                 irqflags = IRQF_SHARED | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;
 
 -                 if(irq < 0)
 
 -                 {
 
 -                         printk("unable to get irq number for GPIO%d\n",k->gpio_port);
 
 -                         return -1;
 
 -                 }
 
 -                 else    
 
 -                         printk("get irq(%d) number for GPIO\n",irq);
 
  
-                 enable_irq(irq);
 
  
-                 ret = request_irq(irq,keyboard_interrupt,irqflags,k->desc,k);
 
 -                 if(ret < 0)
 
 -                 {
 
 -                         printk("can't request irq!%d error:%d\n",irq,ret);
 
 -                         return -1;                
 
 -                 }
 
  
-                 printk("request resources ok!%d\n",i);
 
 -         }
 
 -         return 0;
 
 - }
 
  
- /*释放按键中断*/
 
 - void keyboard_free_irqs(void)
 
 - {
 
 -         struct key_info *k;
 
 -         int i;
 
 -         for (i = 0; i < sizeof(key_info_tab) / sizeof(struct key_info); i++)
 
 -         {
 
 -                 k = &key_info_tab[i];
 
 -                 gpio_free(k->gpio_port);
 
 -                 free_irq(gpio_to_irq(k->gpio_port), k);
 
 -                 printk("free resources ok!%d\n",i);
 
 -         }
 
 - }
 
  
- static int __init hello_init(void)
 
 - {
 
 -         int ret , i;
 
  
-         ret=keyboard_request_irqs();
 
 -         
 
 -         /*初始化设备结构体*/
 
 -         keydevp=kmalloc(sizeof(struct key_dev),GFP_KERNEL);
 
 -         if(!keydevp)
 
 -                 return - ENOMEM;
 
 -         memset(keydevp, 0, sizeof(struct key_dev));
 
 -         keydevp->head=keydevp->tail = 0;
 
 -         keydevp->miscdev=misc;
 
 -         for(i=0;i<KEY_NUM;i++)
 
 -                 keydevp->keystatus[i] = KEYSTATUS_UP;
 
  
-         /*初始化等待队列*/
 
 -         init_waitqueue_head(&(keydevp->wq));
 
 -         /*初始化延时定时器*/
 
 -         for(i=0;i<KEY_NUM;i++)
 
 -                 setup_timer(&key_timer[i],keyboard_timer_handler,i);
 
  
-         /*注册misc设备*/
 
 -         ret = misc_register(&(keydevp->miscdev));
 
 -         if(ret!=0)
 
 -         {
 
 -                 printk("init hello unsuccessfully!\n");
 
 -                 return -1;
 
 -         }
 
 -         printk("hello init!\n");
 
 -         return 0;
 
 - }
 
  
- static void __exit hello_exit(void)
 
 - {
 
 -         int i ;
 
 -         keyboard_free_irqs();
 
 -         for(i=0;i<KEY_NUM;i++)
 
 -                 del_timer(&key_timer[i]);
 
 -         kfree(keydevp);
 
 -         misc_deregister(&(keydevp->miscdev));
 
 -         printk("hello  exit!\n");
 
 - }
 
  
- MODULE_LICENSE("GPL");
 
 - module_init(hello_init);
 
 - module_exit(hello_exit);
 
  复制代码 
这是我的全部代码,照着一些书上的例子做的。 |   
 
 
 
 |