Linux input子系统驱动示例

input 就是输入的意思,因此 input 子系统就是管理输入的子系统 。比如按键输入、键盘、鼠标、触摸屏等 等这些都属于输入设备,不同的输入设备所代表的含义不同,按键和键盘就是代表按键信息, 鼠标和触摸屏代表坐标信息,因此在应用层的处理就不同,对于驱动编写者而言不需要去关心应用层的事情,我们只需要按照要求上报这些输入事件即可。
input 子系统分为 input 驱动 层、input 核心层、 input 事件处理层,最终给用户空间提供可访问的设备节点, input 子系统框 架如图所示:
1、注册 input_dev
struct input_dev *inputdev; /* input 结构体变量 */
 
 /* 驱动入口函数 */
 static int __init xxx_init(void) 
{ 
......
inputdev = input_allocate_device(); /* 申请 input_dev */
inputdev->name = "test_inputdev"; /* 设置 input_dev 名字 */

/*********设置事件和事件值的方法***********/
__set_bit(EV_KEY, inputdev->evbit); /* 设置产生按键事件 */
__set_bit(EV_REP, inputdev->evbit); /* 重复事件 */
__set_bit(KEY_0, inputdev->keybit); /*设置产生哪些按键值 */



/* 注册 input_dev */
input_register_device(inputdev);
......
return 0;
}

 /* 驱动出口函数 */
static void __exit xxx_exit(void)
{
input_unregister_device(inputdev); /* 注销 input_dev */
input_free_device(inputdev); /* 删除 input_dev */
}

具体步骤为:


1、定义input 结构体变量
2、驱动入口函数

 1)申请 input_dev

 2)设置input_dev名字、事件、事件值

 3)注册input_dev
3、驱动出口函数

1)注销 input_dev

2)删除 input_dev



2、上报输入事件

/* 用于按键消抖的定时器服务函数 */
void timer_function(unsigned long arg)
{ 
 unsigned char value;

  value = gpio_get_value(keydesc->gpio); /* 读取 IO 值 */
   if(value == 0){ /* 按下按键 */
   /* 上报按键值 */
   input_report_key(inputdev, KEY_0, 1); /* 最后一个参数 1,按下 */
   input_sync(inputdev); /* 同步事件 */
   } else { /* 按键松开 */
  input_report_key(inputdev, KEY_0, 0); /* 最后一个参数 0,松开 */
  input_sync(inputdev); /* 同步事件 */
  } 
}

1、使用input_report_key函数上报事件
2、使用
input_sync 函数告诉 Linux 内核 input 子系统上报结束

 

示例驱动代码:

 



#define KEYINPUT_CNT 1
#define KEYINPUT_NAME "keyinput"
#define KEY_NUM 1
#define KEY0VALUE 0x01
#define INVAKEY 0xFF

/*key 结构体*/
struct irq_keydesc
{
    int gpio;                            /*io 编号*/
    int irqnum;                          /*中断号*/
    int value;                           /*键值*/
    char name[10];                       /*名字*/
    irqreturn_t (*handler)(int, void *); /*中断处理函数*/
};

/*keyinput 设备结构体*/
struct keyinput_dev
{
    struct device_node *nd;
    struct irq_keydesc irqkey[KEY_NUM];
    struct timer_list timer;

    struct input_dev *inputdev; /* 输入设备 */
};

struct keyinput_dev keyinputdev; /*irq设备 */

/*按键中断处理函数*/
static irqreturn_t key0_handler(int irq, void *dev_id)
{
    struct keyinput_dev *dev = dev_id;

    dev->timer.data = (volatile unsigned long)dev_id;
    mod_timer(&dev->timer, jiffies + msecs_to_jiffies(20)); /*20ms定时*/
    return IRQ_HANDLED;
}

/*定时器处理函数*/
static void timer_func(unsigned long arg)
{
    int value = 0;
    struct keyinput_dev *dev = (struct keyinput_dev *)arg;

    value = gpio_get_value(dev->irqkey[0].gpio);
    if (value == 0) /*按下*/
    {
        /*上报按键值*/
        input_event(dev->inputdev, EV_KEY, BTN_0, 1);
        input_sync(dev->inputdev);
    }
    else if (value == 1) /*释放*/
    {
        /*上报按键值*/
        input_event(dev->inputdev, EV_KEY, BTN_0, 0);
        input_sync(dev->inputdev);
    }
}

/*按键初始化*/
static int keyio_init(struct keyinput_dev *dev)
{
    int ret = 0;
    int i = 0;
    /*1,按键初始化*/
  
    /*2,按键中断初始化*/
  

    /*初始化定时器*/
    return 0;

}

/*驱动入口函数*/
static int __init keyinput_init(void)
{
    int ret = 0;

    /*1、初始化IO*/
    ret = keyio_init(&keyinputdev);

  
    /* 2、注册input_dev */
    keyinputdev.inputdev = input_allocate_device();

    keyinputdev.inputdev->name = KEYINPUT_NAME;
    __set_bit(EV_KEY, keyinputdev.inputdev->evbit); /*按键事件*/
    __set_bit(EV_REP, keyinputdev.inputdev->evbit); /*重复事件*/
    __set_bit(BTN_0, keyinputdev.inputdev->keybit); /*按键值*/

    ret = input_register_device(keyinputdev.inputdev);
    if (ret)
    {
       
    }

    return 0;


}

/*驱动出口函数*/
static void __exit keyinput_exit(void)
{
    int i = 0;
    /*1、释放中断*/


    /*2、释放IO*/
  

    /*3、删除定时器*/
  
    /*4、注销input_dev*/
    input_unregister_device(keyinputdev.inputdev);
    input_free_device(keyinputdev.inputdev);
}

module_init(keyinput_init);
module_exit(keyinput_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("supersmart");

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值