imx287按键处理第二篇:通用版本

这里整理一下按键的通用版本,也就大家都用的按键处理版本,结构比较清晰:
直接上代码:
five_buttons.c

/*

   GPIO Driver driver for EasyARM-iMX283

   AUTHOR:JIAOCHENGLIANG

*/

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/types.h>

#include <linux/sched.h>

#include <linux/init.h>

#include <linux/fs.h>

#include <linux/ioctl.h>

#include <linux/delay.h>


#include <linux/bcd.h>

#include <linux/capability.h>

#include <linux/rtc.h>

#include <linux/cdev.h>

#include <linux/miscdevice.h>

#include <linux/gpio.h>

#include <linux/slab.h>

#include </usr/src/linux-2.6.35.3/arch/arm/mach-mx28/mx28_pins.h>

#include <linux/list.h>

#include<linux/init.h>

#include<linux/module.h>

#include<mach/gpio.h>  

#include <linux/gpio.h>                                                 

#include<asm/io.h>                                                 

#include"/usr/src/linux-2.6.35.3/arch/arm/mach-mx28/mx28_pins.h"

#include "/usr/src/linux-2.6.35.3/arch/arm/plat-mxs/include/mach/pinctrl.h"

#include "/usr/src/linux-2.6.35.3/arch/arm/mach-mx28/include/mach/mx28.h"

#include<linux/fs.h>

#include <linux/io.h>

#include<asm/uaccess.h>                                     

#include<linux/miscdevice.h>                          

#include<linux/irq.h>   

#include <asm/irq.h>                        

#include<linux/sched.h>                   

#include<linux/interrupt.h>              

#include<linux/timer.h>

#include <linux/poll.h> 

#include <linux/input.h>

#include <linux/time.h>

#include <linux/list.h>

#include <linux/errno.h>

#include <asm/uaccess.h> 


#define KEY_GPIO_1      MXS_PIN_TO_GPIO(PINID_LCD_D17)

#define KEY_GPIO_2      MXS_PIN_TO_GPIO(PINID_LCD_D18)

#define KEY_GPIO_3      MXS_PIN_TO_GPIO(PINID_SSP0_DATA4)

#define KEY_GPIO_4      MXS_PIN_TO_GPIO(PINID_SSP0_DATA5)

#define KEY_GPIO_5      MXS_PIN_TO_GPIO(PINID_SSP0_DATA6)

/*set to 0 自动分配主设备号,否则手动分配,但是如果已经被占用,便会分配失败*/

#define BUTTON_MAJOR         0



#define KEY_STATUS_DOWN     '0'

#define KEY_STATUS_UP       '1'

#define DEVICE_NAME     "five_buttons"

struct button_desc {

    int gpio;

    int number;

    char *name; 

    struct timer_list timer;

};

static struct button_desc buttons[] = {

    { KEY_GPIO_1, 1, "KEY_A" },

    { KEY_GPIO_2, 2, "KEY_B" },

    { KEY_GPIO_3, 3, "KEY_C" },

    { KEY_GPIO_4, 4, "KEY_D" },

    { KEY_GPIO_5, 5, "KEY_E" },

};

static volatile char key_values[] = {

    '0', '0', '0', '0', '0', '0', '0', '0'

};

static DECLARE_WAIT_QUEUE_HEAD(button_waitq);



static volatile int ev_press = 0;

static struct fasync_struct *button_async;

static void IMX287_buttons_timer(unsigned long _data)
{
    struct button_desc *bdata = (struct button_desc *)_data;

    int down;

    int number;

    unsigned tmp;

    tmp = gpio_get_value(bdata->gpio);

    /* active low */

    down = !tmp;

    printk("KEY %d: %08x\n", bdata->number, down);

    number = bdata->number;

    if (down != (key_values[number] & 1)) {

        key_values[number] = '0' + down;

        ev_press = 1;

        wake_up_interruptible(&button_waitq);

    }
}


static irqreturn_t button_interrupt(int irq, void *dev_id)
{
    struct button_desc *bdata = (struct button_desc *)dev_id;

    mod_timer(&bdata->timer, jiffies + msecs_to_jiffies(40));

        //发送信号SIGIO信号给fasync_struct 结构体所描述的PID,触发应用程序的SIGIO信号处理函数  

    kill_fasync(&button_async, SIGIO, POLL_IN);  

    return IRQ_HANDLED;
}

static int IMX287_buttons_open(struct inode *inode, struct file *file)
{
    int irq;

    int i;

    int err = 0;

    for (i = 0; i < ARRAY_SIZE(buttons); i++) {

        if (!buttons[i].gpio)

            continue;

        setup_timer(&buttons[i].timer, IMX287_buttons_timer,

                (unsigned long)&buttons[i]);

        irq = gpio_to_irq(buttons[i].gpio);
        //设置中断触发模式
        **err = request_irq(irq, button_interrupt, IRQ_TYPE_EDGE_FALLING, 
                buttons[i].name, (void *)&buttons[i]);**

        if (err)

            break;
    }

    if (err) {

        i--;
        for (; i >= 0; i--) {

            if (!buttons[i].gpio)

                continue;

            irq = gpio_to_irq(buttons[i].gpio);

            disable_irq(irq);

            free_irq(irq, (void *)&buttons[i]);

            del_timer_sync(&buttons[i].timer);

        }

        return -EBUSY;

    }

    ev_press = 1;

    return 0;

}

static int IMX287_buttons_close(struct inode *inode, struct file *file)
{

    int irq, i;

    for (i = 0; i < ARRAY_SIZE(buttons); i++) {

        if (!buttons[i].gpio)

            continue;

        irq = gpio_to_irq(buttons[i].gpio);

        free_irq(irq, (void *)&buttons[i]);

        del_timer_sync(&buttons[i].timer);

    }

    return 0;

}

static int IMX287_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((void *)buff, (const void *)(&key_values),

            min(sizeof(key_values), count));

    return err ? -EFAULT : min(sizeof(key_values), count);

}

static unsigned int IMX287_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 int IMX287_buttons_fasync (int fd, struct file *filp, int on)  
{  
    printk("driver: fifth_drv_fasync\n");  

    //初始化/释放 fasync_struct 结构体 (fasync_struct->fa_file->f_owner->pid)  

    return fasync_helper(fd, filp, on, &button_async);

} 

static struct file_operations dev_fops = {

    .owner      = THIS_MODULE,

    .open       = IMX287_buttons_open,

    .release    = IMX287_buttons_close, 

    .read       = IMX287_buttons_read,

    .poll       = IMX287_buttons_poll,

    .fasync     = IMX287_buttons_fasync,

};

static struct miscdevice misc = {

    .minor      = MISC_DYNAMIC_MINOR,

    .name       = DEVICE_NAME,

    .fops       = &dev_fops,

};


static int __init button_dev_init(void)
{

    int ret;

    ret = misc_register(&misc);

    printk(DEVICE_NAME"\tinitialized\n");

    if(ret<0){

         printk("Add cdev failed!\n");

    }

    return ret;

}

static void __exit button_dev_exit(void)

{

    misc_deregister(&misc);

}

module_init(button_dev_init);

module_exit(button_dev_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("BQRelay Inc.");






编译后,挂载到板子上
看到/dev下有five_buttons 这个设备文件

cat five_buttons

就会有按键键值和按下弹起的内容出现

当然,直接按键也可以看到。

程序设置里面,设置中断触发模式,要不然容易捕捉不到中断信号。

阅读更多
版权声明:本文为博主原创文章,转载请注明链接,jcljob@126.com,欢迎交流 https://blog.csdn.net/liboxiu/article/details/80695216
个人分类: linux
上一篇imx287按键处理第一篇:原始版本
下一篇COMTRADE格式录波数据分析以及函数实现(一)
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭