zoukankan      html  css  js  c++  java
  • Linux设备驱动剖析之Input(一)

    前言

           以前在移植Qt到开发板上时只知道在配置文件中需要指定触摸屏的设备文件/dev/input/event0,仅此而已。直到一年半前突然想到用红外遥控器控制Tiny6410开发板上的Android系统,从而代替物理按键。实现原理是很简单的,就是首先解码红外信号,然后根据解码出的键值模拟一个按键信号。既然要模拟按键信号,那得首先找到按键信号产生的地方,通过查看内核编译生成的文件知道drivers/input/keyboard/gpio_keys.c文件是产生按键信号的源头,这是一个通用的用IO口模拟键盘的驱动程序。别小看这样一个功能,这是开发Android机顶盒、Android盒子必须要接触到的。

         虽说当时功能是实现了,但是对Linux的整个Input子系统的了解一点都不深入,本文就是来解决这个问题的。基于Linux-2.6.36版本,本文讲解的Input子系统的主线是这样的:和前面讲SPI、IIC子系统的方法类似,先讲Input核心的初始化,再从底层往上,分别是Input设备驱动程序(以drivers/input/keyboard/gpio_keys.c为例)、Input核心、Input事件驱动程序(以drivers/input/evdev.c为例)。按照输入信号的产生以及在内核中的传递过程,最后到应用程序这条线路,从而深入理解Linux的Input子系统。

         先给出Linux Input子系统的架构图,如下图所示。

                                                   Linux Input子系统架构图

    下面开始进入Input子系统的学习。

    首先找到Input子系统的初始化函数,它是位于drivers/input/input.c中的input_init函数:

    00002052 static int __init input_init(void)
    00002053 {
    00002054     int err;
    00002055 
    00002056     err = class_register(&input_class);
    00002057     if (err) {
    00002058         printk(KERN_ERR "input: unable to register input_dev class
    ");
    00002059         return err;
    00002060     }
    00002061 
    00002062     err = input_proc_init();
    00002063     if (err)
    00002064         goto fail1;
    00002065 
    00002066     err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
    00002067     if (err) {
    00002068         printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
    00002069         goto fail2;
    00002070     }
    00002071 
    00002072     return 0;
    00002073 
    00002074  fail2:    input_proc_exit();
    00002075  fail1:    class_unregister(&input_class);
    00002076     return err;
    00002077 }

    2056行,向系统注册input_class这么一个类,以后向Input子系统注册设备时,所注册的设备都会从属于这个类。

    2062行,proc文件系统相关的,不细讲,但可以看下它的定义:

    00001110 static int __init input_proc_init(void)
    00001111 {
    00001112     struct proc_dir_entry *entry;
    00001113 
    00001114     proc_bus_input_dir = proc_mkdir("bus/input", NULL);
    00001115     if (!proc_bus_input_dir)
    00001116         return -ENOMEM;
    00001117 
    00001118     entry = proc_create("devices", 0, proc_bus_input_dir,
    00001119                 &input_devices_fileops);
    00001120     if (!entry)
    00001121         goto fail1;
    00001122 
    00001123     entry = proc_create("handlers", 0, proc_bus_input_dir,
    00001124                 &input_handlers_fileops);
    00001125     if (!entry)
    00001126         goto fail2;
    00001127 
    00001128     return 0;
    00001129 
    00001130  fail2:    remove_proc_entry("devices", proc_bus_input_dir);
    00001131  fail1: remove_proc_entry("bus/input", NULL);
    00001132     return -ENOMEM;
    00001133 }

    1114行,很明显,在/proc下创建一个目录bus/input。

    1118行,在/proc/bus/input目录下创建proc文件,文件名为devices。

    1123行,在/proc/bus/input目录下创建proc文件,文件名为handlers。

    回到input_init函数,2066行,注册字符设备,主设备号为INPUT_MAJOR,它的值为13,该设备的文件操集作实例为input_fops,它的定义为:

    00002047 static const struct file_operations input_fops = {
    00002048     .owner = THIS_MODULE,
    00002049     .open = input_open_file,
    00002050 };

    可以看到,里面只将open函数指针指向input_open_file函数,这个函数放到最后再说。

    input_init函数说完了,下面进入Input设备驱动程序,也就是Input子系统的最底层部分。首先看drivers/input/keyboard/gpio_keys.c驱动程序的初始化函数gpio_keys_init的定义:

    00000632 static int __init gpio_keys_init(void)
    00000633 {
    00000634     return platform_driver_register(&gpio_keys_device_driver);
    00000635 }

    这是一个平台驱动,关于平台设备和平台驱动绑定过程应该都很了解了吧,634行,platform_driver_register函数参数gpio_keys_device_driver的定义:

    00000620 static struct platform_driver gpio_keys_device_driver = {
    00000621     .probe        = gpio_keys_probe,
    00000622     .remove        = __devexit_p(gpio_keys_remove),
    00000623     .driver        = {
    00000624         .name    = "gpio-keys",
    00000625         .owner    = THIS_MODULE,
    00000626 #ifdef CONFIG_PM
    00000627         .pm    = &gpio_keys_pm_ops,
    00000628 #endif
    00000629     }
    00000630 };

    注意,该结构体实例里没有为id_table变量赋值,因此写平台设备结构体实例的时候name成员的值要设置为gpio-keys,这样才能与该驱动匹配和绑定,从而该驱动中的probe函数才会被调用。下面看gpio_keys_probe函数的定义:

    00000443 static int __devinit gpio_keys_probe(struct platform_device *pdev)
    00000444 {
    00000445     struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
    00000446     struct gpio_keys_drvdata *ddata;
    00000447     struct device *dev = &pdev->dev;
    00000448     struct input_dev *input;
    00000449     int i, error;
    00000450     int wakeup = 0;
    00000451 
    00000452     ddata = kzalloc(sizeof(struct gpio_keys_drvdata) +
    00000453             pdata->nbuttons * sizeof(struct gpio_button_data),
    00000454             GFP_KERNEL);
    00000455     input = input_allocate_device();
    00000456     if (!ddata || !input) {
    00000457         dev_err(dev, "failed to allocate state
    ");
    00000458         error = -ENOMEM;
    00000459         goto fail1;
    00000460     }
    00000461 
    00000462     ddata->input = input;
    00000463     ddata->n_buttons = pdata->nbuttons;
    00000464     ddata->enable = pdata->enable;
    00000465     ddata->disable = pdata->disable;
    00000466     mutex_init(&ddata->disable_lock);
    00000467 
    00000468     platform_set_drvdata(pdev, ddata);
    00000469     input_set_drvdata(input, ddata);
    00000470 
    00000471     input->name = pdev->name;
    00000472     input->phys = "gpio-keys/input0";
    00000473     input->dev.parent = &pdev->dev;
    00000474     input->open = gpio_keys_open;
    00000475     input->close = gpio_keys_close;
    00000476 
    00000477     input->id.bustype = BUS_HOST;
    00000478     input->id.vendor = 0x0001;
    00000479     input->id.product = 0x0001;
    00000480     input->id.version = 0x0100;
    00000481 
    00000482     /* Enable auto repeat feature of Linux input subsystem */
    00000483     if (pdata->rep)
    00000484         __set_bit(EV_REP, input->evbit);
    00000485 
    00000486     for (i = 0; i < pdata->nbuttons; i++) {
    00000487         struct gpio_keys_button *button = &pdata->buttons[i];
    00000488         struct gpio_button_data *bdata = &ddata->data[i];
    00000489         unsigned int type = button->type ?: EV_KEY;
    00000490 
    00000491         bdata->input = input;
    00000492         bdata->button = button;
    00000493 
    00000494         error = gpio_keys_setup_key(pdev, bdata, button);
    00000495         if (error)
    00000496             goto fail2;
    00000497 
    00000498         if (button->wakeup)
    00000499             wakeup = 1;
    00000500 
    00000501         input_set_capability(input, type, button->code);
    00000502     }
    00000503 
    00000504     error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group);
    00000505     if (error) {
    00000506         dev_err(dev, "Unable to export keys/switches, error: %d
    ",
    00000507             error);
    00000508         goto fail2;
    00000509     }
    00000510 
    00000511     error = input_register_device(input);
    00000512     if (error) {
    00000513         dev_err(dev, "Unable to register input device, error: %d
    ",
    00000514             error);
    00000515         goto fail3;
    00000516     }
    00000517 
    00000518     /* get current state of buttons */
    00000519     for (i = 0; i < pdata->nbuttons; i++)
    00000520         gpio_keys_report_event(&ddata->data[i]);
    00000521     input_sync(input);
    00000522 
    00000523     device_init_wakeup(&pdev->dev, wakeup);
    00000524 
    00000525     return 0;
    00000526 
    00000527  fail3:
    00000528     sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group);
    00000529  fail2:
    00000530     while (--i >= 0) {
    00000531         free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]);
    00000532         if (ddata->data[i].timer_debounce)
    00000533             del_timer_sync(&ddata->data[i].timer);
    00000534         cancel_work_sync(&ddata->data[i].work);
    00000535         gpio_free(pdata->buttons[i].gpio);
    00000536     }
    00000537 
    00000538     platform_set_drvdata(pdev, NULL);
    00000539  fail1:
    00000540     input_free_device(input);
    00000541     kfree(ddata);
    00000542 
    00000543     return error;
    00000544 }

    445行,获取平台设备数据。

    452行,为struct gpio_keys_drvdata对象分配内存,注意,另外还分配pdata->nbuttons * sizeof(struct gpio_button_data)内存,pdata->nbuttons的值为按键的个数。struct gpio_keys_platform_data的定义在include/linux/gpio_keys.h:

    00000016 struct gpio_keys_platform_data {
    00000017     struct gpio_keys_button *buttons;
    00000018     int nbuttons;
    00000019     unsigned int rep:1;        /* enable input subsystem auto repeat */
    00000020     int (*enable)(struct device *dev);
    00000021     void (*disable)(struct device *dev);
    00000022 };

    17行,buttons,指向板文件中定义的struct gpio_keys_button数组。

    18行,nbuttons,按键的个数。

    19行,rep,是否支持按键自动重复。

    20、21行,使能和失能按键的函数指针。

    下面看一下struct gpio_keys_drvdata的定义:

    00000038 struct gpio_keys_drvdata {
    00000039     struct input_dev *input;
    00000040     struct mutex disable_lock;
    00000041     unsigned int n_buttons;
    00000042     int (*enable)(struct device *dev);
    00000043     void (*disable)(struct device *dev);
    00000044     struct gpio_button_data data[0];
    00000045 };

    39行,input,当前Input设备。

    41行,n_buttons,按键的个数。

    44行,是一个变长数组,当获取到平台数据时才能确定该数组的长度。看下该数组类型struct gpio_button_data的定义:

    00000029 struct gpio_button_data {
    00000030     struct gpio_keys_button *button;
    00000031     struct input_dev *input;
    00000032     struct timer_list timer;
    00000033     struct work_struct work;
    00000034     int timer_debounce;    /* in msecs */
    00000035     bool disabled;
    00000036 };

    先看31行,input,设备的指针。

    32行,timer,用来延时的定时器。

    33行,work,工作队列。

    34行,timer_debounce,定时器的定时时间,单位为ms。

    35行,disabled,按键是否已经使能。

    看回30行,struct gpio_keys_button的定义在include/linux/gpio_keys.h中:

    00000004 struct gpio_keys_button {
    00000005     /* Configuration parameters */
    00000006     int code;        /* input event code (KEY_*, SW_*) */
    00000007     int gpio;
    00000008     int active_low;
    00000009     char *desc;
    00000010     int type;        /* input event type (EV_KEY, EV_SW) */
    00000011     int wakeup;        /* configure the button as a wake-up source */
    00000012     int debounce_interval;    /* debounce ticks interval in msecs */
    00000013     bool can_disable;
    00000014 };

    6行,code,键值。

    7行,gpio,所使用的IO口。

    8行,active_low,1表示低电平有效。

    9行,desc,按键的名字。

    10行,type,按键的事件类型。

    11行,wakeup,1表示按键作为唤醒源。

    12行,debounce_interval,延时消抖所需要的时间,单位为ms。

    13行,can_disable,按键是否可以失能。

    回到gpio_keys_probe函数,455行,分配Input设备,input_allocate_device函数在drivers/input/input.c里定义:

    00001555 struct input_dev *input_allocate_device(void)
    00001556 {
    00001557     struct input_dev *dev;
    00001558 
    00001559     dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL);
    00001560     if (dev) {
    00001561         dev->dev.type = &input_dev_type;
    00001562         dev->dev.class = &input_class;
    00001563         device_initialize(&dev->dev);
    00001564         mutex_init(&dev->mutex);
    00001565         spin_lock_init(&dev->event_lock);
    00001566         INIT_LIST_HEAD(&dev->h_list);
    00001567         INIT_LIST_HEAD(&dev->node);
    00001568 
    00001569         __module_get(THIS_MODULE);
    00001570     }
    00001571 
    00001572     return dev;
    00001573 }

    1557行,看下struct input_dev结构体在include/linux/input.h中的定义:

    00001150 struct input_dev {
    00001151     const char *name;
    00001152     const char *phys;
    00001153     const char *uniq;
    00001154     struct input_id id;
    00001155 
    00001156     unsigned long evbit[BITS_TO_LONGS(EV_CNT)];
    00001157     unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];
    00001158     unsigned long relbit[BITS_TO_LONGS(REL_CNT)];
    00001159     unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];
    00001160     unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
    00001161     unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
    00001162     unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
    00001163     unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
    00001164     unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
    00001165 
    00001166     unsigned int hint_events_per_packet;
    00001167 
    00001168     unsigned int keycodemax;
    00001169     unsigned int keycodesize;
    00001170     void *keycode;
    00001171     int (*setkeycode)(struct input_dev *dev,
    00001172               unsigned int scancode, unsigned int keycode);
    00001173     int (*getkeycode)(struct input_dev *dev,
    00001174               unsigned int scancode, unsigned int *keycode);
    00001175 
    00001176     struct ff_device *ff;
    00001177 
    00001178     unsigned int repeat_key;
    00001179     struct timer_list timer;
    00001180 
    00001181     int rep[REP_CNT];
    00001182 
    00001183     struct input_mt_slot *mt;
    00001184     int mtsize;
    00001185     int slot;
    00001186 
    00001187     struct input_absinfo *absinfo;
    00001188 
    00001189     unsigned long key[BITS_TO_LONGS(KEY_CNT)];
    00001190     unsigned long led[BITS_TO_LONGS(LED_CNT)];
    00001191     unsigned long snd[BITS_TO_LONGS(SND_CNT)];
    00001192     unsigned long sw[BITS_TO_LONGS(SW_CNT)];
    00001193 
    00001194     int (*open)(struct input_dev *dev);
    00001195     void (*close)(struct input_dev *dev);
    00001196     int (*flush)(struct input_dev *dev, struct file *file);
    00001197     int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
    00001198 
    00001199     struct input_handle *grab;
    00001200 
    00001201     spinlock_t event_lock;
    00001202     struct mutex mutex;
    00001203 
    00001204     unsigned int users;
    00001205     bool going_away;
    00001206 
    00001207     bool sync;
    00001208 
    00001209     struct device dev;
    00001210 
    00001211     struct list_head    h_list;
    00001212     struct list_head    node;
    00001213 };

    1151行,name,设备的名字。

    1152行,phys,设备在系统层次结构中的路径。

    1153行,uniq,设备的识别码。

    1154行,id,还是ID,直接看它的定义更直接。

    00000043 struct input_id {
    00000044     __u16 bustype;
    00000045     __u16 vendor;
    00000046     __u16 product;
    00000047     __u16 version;
    00000048 };
  • 相关阅读:
    JDBC_批处理Batch_插入2万条数据的测试
    JDBC_ResultSet结果集用法_游标原理_关闭连接问题
    JDBC_PreparedStatement用法_占位符_参数处理
    python_字符串_常用处理
    R-biomaRt使用-代码备份
    R-描述性统计
    django开发傻瓜教程-3-celery异步处理
    Head First Java-图形化界面
    javascript隐藏和显示元素以及清空textarea
    Entrez Direct
  • 原文地址:https://www.cnblogs.com/lknlfy/p/3275781.html
Copyright © 2011-2022 走看看