Chinaunix首页 | 论坛 | 博客
  • 博客访问: 755780
  • 博文数量: 230
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 2188
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-27 19:53
个人简介

just for fun

文章分类

全部博文(230)

文章存档

2021年(2)

2020年(30)

2019年(11)

2018年(27)

2017年(54)

2016年(83)

2015年(23)

我的朋友

分类: LINUX

2020-12-07 09:23:00

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include //新版内核
     
    #include
    #include
     
     
    static struct class *key_irq_class;
    static struct class_device  *key_class_irq;
    volatile unsigned long  *gpncon=NULL;
    volatile unsigned long  *gpndat=NULL;
     
    static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
     
    /* 中断事件标志, 中断服务程序将它置1,third_drv_read将它清0 */
    static volatile int ev_press = 0;
    struct key_desc{
        unsigned int pin;
        unsigned int key_val;
        };
    /*键值:按下时,0x01,0x02,0x03,0x04,0x05,0x06*/
    /*键值:松开时,0x81,0x82,0x83,0x84,0x85,0x86*/
    static unsigned char key_num;
    struct key_desc keys_desc[6]={
        {1,0x01},
        {2,0x02},
        {3,0x03},
        {4,0x04},
        {5,0x05},
        {6,0x06},
    };
     
    static irqreturn_t key_irq(int irq, void *dev_id)
    {
        struct key_desc *pin=(struct key_desc*)dev_id;
        unsigned int pinval;
        pinval=gpio_get_value(S3C64XX_GPN(pin->pin));
        if(pinval)
            {
                key_num=0x80|pin->key_val;
            }
        else
            {
                key_num=pin->key_val;
            }
        //printk("*********************");
        //printk("key_num= %x\n",key_num);
        //printk("*********************");
        //ev_press=1;/*表示中断发生了*/
        wake_up_interruptible(&button_waitq);/*唤醒休眠的进程*/
        return IRQ_HANDLED;
    }
     
    static int key_drv_open(struct inode  * inode, struct file * file)
    {
        request_irq(IRQ_EINT(1),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S1",&keys_desc[0]);
        request_irq(IRQ_EINT(2),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S2",&keys_desc[1]);
        request_irq(IRQ_EINT(3),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S3",&keys_desc[2]);
        request_irq(IRQ_EINT(4),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S4",&keys_desc[3]);
        request_irq(IRQ_EINT(5),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S5",&keys_desc[4]);
        request_irq(IRQ_EINT(6),key_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,"S6",&keys_desc[5]);
        return 0;
    }
    static ssize_t key_drv_write(struct inode * file, const char __user *buf, size_t count, loff_t *ppos)
    {
     
        return 0;
    }
    ssize_t key_drv_read (struct file *file, char __user *buf, size_t size, loff_t *ppos)
    {
        //返回四个引脚的电平
        if(size != 1)
            return -EINVAL;
        /*如果没有按键动作发生就休眠*/
        wait_event_interruptible(button_waitq, ev_press);
        /*如果有按键动作,返回键值*/
        copy_to_user(buf,&key_num,1);
        ev_press=0;
        return 1;
    }
    int key_drv_release(struct inode * inode, struct file * file)
    {
        free_irq(IRQ_EINT(1),&keys_desc[0]);
        free_irq(IRQ_EINT(2),&keys_desc[1]);
        free_irq(IRQ_EINT(3),&keys_desc[2]);
        free_irq(IRQ_EINT(4),&keys_desc[3]);
        free_irq(IRQ_EINT(5),&keys_desc[4]);
        free_irq(IRQ_EINT(6),&keys_desc[5]);
         
        return 0;
    }
    static struct file_operations key_drv_openration ={
        .owner = THIS_MODULE,
        .open = key_drv_open,
        .write =key_drv_write,
        .read=key_drv_read,
        .release=key_drv_release,
    };
    int major;
    static int key_drv_init(void)
    {
        major=register_chrdev(0,"key_irq",&key_drv_openration);
         
        key_irq_class = class_create(THIS_MODULE, "key_irq");
            //自动创建设备节点
        /* 新版的内核不能用class_device_create 要用device_create*/
        key_class_irq = device_create(key_irq_class, NULL, MKDEV(major, 0), NULL, "key"); /* /dev/xyz */
             
        gpncon = (volatile unsigned long*)ioremap(0x7F008830,16);
        gpndat=gpncon+1;//指针的操作是按照指针指向的长度为单位?
                            /*本例中使用的是unsigned long类型刚好是4个字节*/
     
        return 0;
    }
    static void key_drv_exit(void)
    {
        unregister_chrdev(major,"key_irq");
        device_unregister(key_class_irq);
        class_destroy(key_irq_class);
     
        iounmap(gpncon);
        return 0;
    }
     
    module_init(key_drv_init);
    module_exit(key_drv_exit);
    MODULE_LICENSE("GPL");

///////////////////////////////////////////////////

#define S3C_IRQ_EINT_BASE    S3C_IRQ(64+5)

#define S3C_EINT(x)        ((x) + S3C_IRQ_EINT_BASE)
#define IRQ_EINT(x)        S3C_EINT(x)

图片

    XEINT0/GPN0    XEINT1/GPN1    XEINT2/GPN2    XEINT3/GPN3
    XEINT4/GPN4    XEINT5/GPN5    XEINT6/GPN6    XEINT7/GPN7
阅读(18536) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~