input子系统与实例

Iuput子系统说明

  

      当我们需要编写或调试输入设备时,如keyboard、mouse、touchscreen、joystick,会发现代码会有很多通用的部分,如申请设备号,创建文件,实现fop等操作。内核就会将通用的代码编写好,将差异化的代码留给驱动工程师,使得应用编程人员和驱动编程人员点成的时候变得简单统一。

输入子系统框架可以分为三层,分别是input handler层、input核心层、input dev层。

Input handler层(evdev.c):数据处理者

  1. 向input.c中注册evdev_handler

input子系统与实例

  1. 将evdev_handler添加到链表中

input子系统与实例

  1. 实现fops

input子系统与实例

Input核心层(input.c)

  1. 注册类
  2. 在/proc文件系统中创建文件记录信息
  3. 创建设备

input子系统与实例

Input dev层:(需要自己编写的)

  1. 抽象出一个对象,描述设备信息
  2. 初始化输入设备硬件,获取到数据
  3. 上报数据

编写步骤:

  1. 分配输入设备

Inputdev = Input_allocate_device();

  1. 初始化支持的事件类型和事件码

__set_bit(EV_KEY, inputdev->evbit);

__set_bit(KEY_POWER, inputdev->keybit);

  1. 注册输入设备

Input_register_device(inputdev);

  1. 上报数据

Input_event(inputdev, EV_KEY, KEY_POWER, 0);

Input_sync(inputdev);

#include <linux/init.h>

#include <linux/module.h>

#include <linux/input.h>

#include <linux/interrupt.h>

#include <linux/of.h>

#include <linux/of_irq.h>

#include <linux/gpio_keys.h>

#include <linux/platform_device.h>

 

#include <linux/fs.h>

#include <linux/irq.h>

#include <linux/sched.h>

#include <linux/pm.h>

#include <linux/slab.h>

#include <linux/sysctl.h>

#include <linux/proc_fs.h>

#include <linux/delay.h>

#include <linux/workqueue.h>

#include <linux/gpio.h>

#include <linux/of_platform.h>

#include <linux/of_gpio.h>

#include <linux/spinlock.h>

 

 

#include <asm/io.h>

#include <asm/gpio.h>

 

#define IMX_GPIO_NR(bank, nr)       (((bank) -1) * 32 + (nr))

#define GPIO1_31                     IMX_GPIO_NR(1,31)

 

static struct input_dev *inputdev;

struct work_struct my_wq;

void my_wq_func(struct work_struct *work);

 

struct timer_list my_timer;

 

 

int irq;

 

/*top half*/

static irqreturn_t input_gpio_irq_handler(int irq, void *dev_id)

{

    printk(KERN_ALERT "-----------input_gpio_irq_handler------\n" );

    schedule_work(&my_wq);

    return IRQ_HANDLED;

}

 

/*bottom half*/

static void my_do_work(struct work_struct *work)

{

    gpio_direction_input(GPIO1_31);

    //mod_timer(&my_timer, jiffies + HZ/99);

    my_timer.expires = jiffies + HZ/100;

    add_timer(&my_timer);

}

 

static void my_timer_function(unsigned long arg)

{

    if(!gpio_get_value(GPIO1_31))

    {

        input_event(inputdev, EV_KEY, KEY_POWER, 0);

        input_sync(inputdev);

        printk(KERN_ALERT "A\n");

    }

    else{

        input_event(inputdev, EV_KEY, KEY_POWER, 1);

        input_sync(inputdev);

        printk(KERN_ALERT "B\n");

    }

 

    //my_timer.expires = jiffies + HZ/100;

    //add_timer(&my_timer);

}

 

static int __init gpio_input_init(void)

{

    printk(KERN_ALERT "-------hsae_gpio_init--------\n");

    int ret;

    /*分配输入设备*/

    inputdev = input_allocate_device();

 

    if (inputdev == NULL)

    {

        printk(KERN_ALERT "input_allocate_device error!\n");

        return -ENOMEM;

    }

    /*添加/sys/class/event/device信息*/

    inputdev->name = "qiwangwang";

    inputdev->phys   = "gpio-keys/input0";

 

    inputdev->id.bustype = BUS_HOST;

    inputdev->id.vendor = 0x0001;

    inputdev->id.product = 0x0001;

    inputdev->id.version = 0x0100;

 

    /*初始化支持的事件类型*/

    __set_bit(EV_KEY, inputdev->evbit);

    /*设置支持的事件码*/

    __set_bit(KEY_POWER,inputdev->keybit);

 

    /*注册输入设备*/

    ret = input_register_device(inputdev);

    if (ret != 0)

    {

        printk(KERN_ALERT "input_register_device error!\n");

        goto err_0;

    }

 

    /*获取中断号*/

    irq = gpio_to_irq(GPIO1_31);

 

    /*注册中断*/

    ret = request_irq(irq, input_gpio_irq_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "hsae_gpio_irq", NULL);

    if(ret < 0)

    {

        printk(KERN_ALERT "----request_irq failed----\n");

        goto err_1;

    }

 

    /*初始化工作队列*/

    INIT_WORK(&my_wq, my_do_work);

 

    /*初始化定时器,用于按键消抖*/

    init_timer(&my_timer);

    my_timer.function = my_timer_function;

    //add_timer(&my_timer);

    return 0;

 

err_1:

    input_unregister_device(inputdev);

err_0:

    input_free_device(inputdev);

    return ret;

}

 

static void __exit gpio_input_exit(void)

{

    free_irq(irq, NULL);

    del_timer(&my_timer);

    input_unregister_device(inputdev);

    input_free_device(inputdev);

}

 

 

 

module_init(gpio_input_init);

module_exit(gpio_input_exit);

MODULE_LICENSE("GPL");