020_linux驱动之_输入子系统按键应用

(一)分配一个输入子系统结构体

static struct input_dev *buttons_dev;        /*分配一个input_dev结构体*/

(二)设置这个输入子系统需要的动作

    /* 1. 分配一个input_dev结构体 */
    buttons_dev = input_allocate_device();;    /*使用这个函数分配一个input_dev结构体*/
/*
    unsigned long evbit [NBITS(EV_MAX)];   // 表示能产生哪类事件
    unsigned long keybit[NBITS(KEY_MAX)]; // 表示能产生哪些按键
    unsigned long relbit[NBITS(REL_MAX)]; // 表示能产生哪些相对位移事件, x,y,滚轮
    unsigned long absbit[NBITS(ABS_MAX)]; // 表示能产生哪些绝对位移事件, x,y
*/
    /* 2. 设置 */
    /* 2.1 能产生哪类事件 */
    /*按键类事件      buttons_dev里面的哪一类事件*/
    set_bit(EV_KEY, buttons_dev->evbit);
    /*能够产生重复类事件,就是按键按下可以重复输出*/
    set_bit(EV_REP, buttons_dev->evbit);
    
    /* 2.2 能产生这类操作里的哪些事件: L,S,ENTER,LEFTSHIT */
    set_bit(KEY_L, buttons_dev->keybit);            /*L*/
    set_bit(KEY_S, buttons_dev->keybit);            /*S*/
    set_bit(KEY_ENTER, buttons_dev->keybit);        /*回车*/
    set_bit(KEY_LEFTSHIFT, buttons_dev->keybit);    /*shift*/

    /* 3. 注册 */
    input_register_device(buttons_dev);            /*初始化完成上面的参数之后进行初始化*/
View Code

(三)当有动作产生时候,上报事件

        /*上报事件*/
        /*上报给哪个结构体     上报什么事件  上报值        值*/
        input_event(buttons_dev, EV_KEY, pindesc->key_val, 0);
        input_sync(buttons_dev);/*上报同步事件,表示上面的事件已经上报完成*/

(四)删除这个字输入系统结构体

    input_unregister_device(buttons_dev);    
    input_free_device(buttons_dev);    

(五)示例,按键输入子系统全部代码(详解)

/* 参考drivers\input\keyboard\gpio_keys.c */

#include <linux/module.h>
#include <linux/version.h>

#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/irq.h>

#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>

struct pin_desc{
    int irq;                /*中断号*/
    char *name;                /*按键名字*/
    unsigned int pin;        /*按键引脚*/
    unsigned int key_val;    /*键值*/
};

struct pin_desc pins_desc[4] = {
    {IRQ_EINT0,  "S2", S3C2410_GPF0,   KEY_L},
    {IRQ_EINT2,  "S3", S3C2410_GPF2,   KEY_S},
    {IRQ_EINT11, "S4", S3C2410_GPG3,   KEY_ENTER},
    {IRQ_EINT19, "S5",  S3C2410_GPG11, KEY_LEFTSHIFT},
};

static struct input_dev *buttons_dev;        /*分配一个input_dev结构体*/
static struct pin_desc *irq_pd;
static struct timer_list buttons_timer;        /*定时器结构体*/

static irqreturn_t buttons_irq(int irq, void *dev_id)    /*按键中断处理函数*/
{
    /* 10ms后启动定时器 */
    irq_pd = (struct pin_desc *)dev_id;            /*按键中断触发之后,获取按键相关参数*/
    /*修改超时时间   超时结构体       超时时间   在jiffies上加一,也就是10ms,因为10ms加一次*/
    mod_timer(&buttons_timer, jiffies+HZ/100);
    return IRQ_RETVAL(IRQ_HANDLED);
}

static void buttons_timer_function(unsigned long data)    /*定时器超时处理函数*/
{
    struct pin_desc * pindesc = irq_pd;                /*获取按键中断中保留下来的数据*/
    unsigned int pinval;                    
    
    if (!pindesc)                /*假如没有按下就返回,因为初始化时候会自动调用一次,因为我们初始化时候没有设置超时时间*/
        return;
    
    pinval = s3c2410_gpio_getpin(pindesc->pin);/*获取按键值*/

    if (pinval)
    {
        /* 松开 : 最后一个参数: 0-松开, 1-按下 */
        /*上报事件*/
        /*上报给哪个结构体     上报什么事件  上报值        值*/
        input_event(buttons_dev, EV_KEY, pindesc->key_val, 0);
        input_sync(buttons_dev);/*上报同步事件,表示上面的事件已经上报完成*/
    }
    else
    {
        /* 按下 */
        input_event(buttons_dev, EV_KEY, pindesc->key_val, 1);
        input_sync(buttons_dev);
    }
}

static int buttons_init(void)
{
    int i;
    
    /* 1. 分配一个input_dev结构体 */
    buttons_dev = input_allocate_device();;    /*使用这个函数分配一个input_dev结构体*/

/*
    unsigned long evbit [NBITS(EV_MAX)];   // 表示能产生哪类事件
    unsigned long keybit[NBITS(KEY_MAX)]; // 表示能产生哪些按键
    unsigned long relbit[NBITS(REL_MAX)]; // 表示能产生哪些相对位移事件, x,y,滚轮
    unsigned long absbit[NBITS(ABS_MAX)]; // 表示能产生哪些绝对位移事件, x,y
*/
    /* 2. 设置 */
    /* 2.1 能产生哪类事件 */
    /*按键类事件      buttons_dev里面的哪一类事件*/
    set_bit(EV_KEY, buttons_dev->evbit);
    /*能够产生重复类事件,就是按键按下可以重复输出*/
    set_bit(EV_REP, buttons_dev->evbit);
    
    /* 2.2 能产生这类操作里的哪些事件: L,S,ENTER,LEFTSHIT */
    set_bit(KEY_L, buttons_dev->keybit);            /*L*/
    set_bit(KEY_S, buttons_dev->keybit);            /*S*/
    set_bit(KEY_ENTER, buttons_dev->keybit);        /*回车*/
    set_bit(KEY_LEFTSHIFT, buttons_dev->keybit);    /*shift*/

    /* 3. 注册 */
    input_register_device(buttons_dev);            /*初始化完成上面的参数之后进行初始化*/
    
    /* 4. 硬件相关的操作 */
    init_timer(&buttons_timer);                            /*初始化time*/
    buttons_timer.function = buttons_timer_function;    /*但超时时间到了之后调用这个函数*/
    add_timer(&buttons_timer);                            /*将这个定时器告诉给内核,相当于初始化*/
    
    for (i = 0; i < 4; i++)        /*注册四个中断号*/
    {
        request_irq(pins_desc[i].irq, buttons_irq, IRQT_BOTHEDGE, pins_desc[i].name, &pins_desc[i]);
    }
    
    return 0;
}

static void buttons_exit(void)
{
    int i;
    for (i = 0; i < 4; i++)
    {
        free_irq(pins_desc[i].irq, &pins_desc[i]);/*释放中断*/
    }

    del_timer(&buttons_timer);            /*删除定时器结构体*/
    input_unregister_device(buttons_dev);    
    input_free_device(buttons_dev);    
}

module_init(buttons_init);

module_exit(buttons_exit);

MODULE_LICENSE("GPL");
buttons.c

 

posted @ 2018-09-22 16:24  陆小果哥哥  阅读(209)  评论(0编辑  收藏  举报