| 
 | 
内核版本:2.6.25.8 
#include<linux/module.h> 
#include<linux/kernel.h> 
#include<linux/fs.h> 
#include<linux/init.h> 
#include<linux/delay.h> 
#include<asm/irq.h> 
#include<linux/interrupt.h> 
#include<asm/uaccess.h> 
#include<asm/arch/regs-gpio.h> 
#include<asm/hardware.h> 
#include<linux/device.h> 
#include<linux/poll.h> 
 
#define DEVICE_NAME  "ZJF-Buttons" 
 
#define BUTTON_MAJOR 232 
 
struct button_irq_desc 
{ 
        int irq; 
        int pin; 
        int pin_setting; 
        int number; 
        char *name; 
}; 
 
static struct button_irq_desc button_irqs[]= 
{ 
                {IRQ_EINT1,S3C2410_GPF1, S3C2410_GPF1_EINT1,  1,"KEY1"},  //K1 
                {IRQ_EINT2,S3C2410_GPF2, S3C2410_GPF2_EINT2,  2,"KEY2"},  //K2 
                {IRQ_EINT3,S3C2410_GPF3, S3C2410_GPF3_EINT3,  3,"KEY3"},  //K3 
}; 
 
static volatile int key_values[]={0,0,0,0}; 
 
static DECLARE_WAIT_QUEUE_HEAD(button_waitq); 
 
static volatile int ev_press=0; 
 
static irqreturn_t buttons_interrupt(int irq,void *dev_id) 
{ 
        struct button_irq_desc *button_irqs=(struct button_irq_desc *)dev_id; 
 
        int up=s3c2410_gpio_getpin(button_irqs->pin); 
        if(up) 
                key_values[button_irqs->number]=(button_irqs->number+1)+0x80; 
        else 
                key_values[button_irqs->number]=(button_irqs->number+1); 
 
        ev_press=1; 
        wake_up_interruptible(&button_waitq); 
        return IRQ_RETVAL(IRQ_HANDLED); 
} 
 
static int EmbedSky_buttons_open(struct inode *inode,struct file *file) 
{ 
        int i; 
        int err; 
 
        for(i=0;i<sizeof(button_irqs)/sizeof(button_irqs[0]);i++) 
        { 
                s3c2410_gpio_cfgpin(button_irqs[i].pin,button_irqs[i].pin_setting); 
                err=request_irq(button_irqs[i].irq, buttons_interrupt, NULL,button_irqs[i].name,(void *)&button_irqs[i]); 
                if(err)break; 
        } 
        if(err) 
        { 
                i--; 
                for(;i>=0;i--) 
                { 
                        disable_irq(button_irqs[i].irq); 
                        free_irq(button_irqs[i].irq,(void*)&button_irqs[i]); 
                } 
                return -EBUSY; 
        } 
        return 0; 
} 
 
static int EmbedSky_buttons_close(struct inode *inode,struct file *file) 
{ 
        int i; 
        for(i=0;i<sizeof(button_irqs)/sizeof(button_irqs[0]);i++) 
        { 
     disable_irq(button_irqs[i].irq); 
     free_irq(button_irqs[i].irq,(void*)&button_irqs[i]); 
        } 
        return 0; 
} 
 
static int EmbedSky_buttons_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(button_waitq,ev_press); 
        } 
        ev_press=0; 
 
        err=copy_to_user(buff,(const void *)key_values,min(sizeof(key_values),count)); 
        memset((void *)key_values,0,sizeof(key_values)); 
        return err ? -EFAULT:min(sizeof(key_values),count); 
} 
 
static unsigned int EmbedSky_buttons_poll(struct file *file,struct poll_table_struct *wait) 
{ 
        unsigned int mask=0; 
        poll_wait(file,&button_waitq,wait); 
        if(ev_press) 
                mask|=POLLIN|POLLRDNORM; 
        return mask; 
} 
 
static struct file_operations EmbedSky_buttons_fops= 
{ 
                .owner =  THIS_MODULE, 
                .open  =  EmbedSky_buttons_open, 
                .release= EmbedSky_buttons_close, 
                .read  =  EmbedSky_buttons_read, 
                .poll  =  EmbedSky_buttons_poll, 
}; 
 
static char __initdata banner[]="TQ2440/SKY2440 LEDS,(c)2008,2009www.embedsky.net\n"; 
//static struct class *button_class; 
 
static int __init EmbedSky_buttons_init(void) 
{ 
        int ret; 
        printk(banner); 
        ret=register_chrdev(BUTTON_MAJOR,DEVICE_NAME,&EmbedSky_buttons_fops); 
        if(ret<0) 
        { 
                printk(DEVICE_NAME"can't register major number\n"); 
                return ret; 
        } 
        //注册一个类,使mdev可以在"/dev/"目录下面建立设备 节点 
/*        button_class=class_create(THIS_MODULE,DEVICE_NAME); 
        if(IS_ERR(button_class)) 
        { 
      printk("Err:failed in EmbedSky-leds class.\n"); 
      return -1; 
        } 
        class_device_create(button_class,NULL,MKDEV(BUTTON_MAJOR,0),NULL,DEVICE_NAME); 
*/ 
        printk(DEVICE_NAME"initialized\n"); 
        return 0; 
 
} 
 
static void __exit EmbedSky_buttons_exit(void) 
{ 
        unregister_chrdev(BUTTON_MAJOR,DEVICE_NAME); 
        class_device_destroy(button_class,MKDEV(BUTTON_MAJOR,0));  //删掉设备节点节点 
        class_destroy(button_class);       //注销类类 
} 
 
module_init(EmbedSky_buttons_init); 
module_exit(EmbedSky_buttons_exit); 
 
谢谢! |   
 
 
 
 |