Android Input子系统浅谈

Android Input子系统浅谈

本文主要讲解[Android Input 子系统][6],我会从一下几个方面讲解:

  • linux kernel的input子系统框架
  • 以触摸屏驱动为例讲解内核input子系统
  • Android framework层Input子系统的框架
  • Input子系统的应用程序接口

linux kernel里面input子系统框架

  • **主要作用是维护两个重要的链表input_dev_list和input_handler_list
  • 下面这段代码便是内核里面Input子系统的框架层部分代码
    代码位置:/kernel/driver/input/input.c
    可以看到input的内核框架层也是以类似于driver的方式注册的
    这段代码便是Input子系统在内核中的核心框架;大家可能会疑惑怎么这
    么简单,看着什么也没有做,其实却是这样,这这段code里面主要建立
    了一些用于debug的节点,主要有如下节点:
class节点/sys/class/input :调用class_register生成
proc节点/proc/bus/input/devices和handles:调用input_proc_init生成
dev节点:/dev/input:调用register_chrdev_region

以上三种节点在后面会讲解分别用作什么

static int __init input_init(void)
{
    int err;

    err = class_register(&input_class);
    if (err) {
        pr_err("unable to register input_dev class\n");
        return err;
    }

    err = input_proc_init();
    if (err)
        goto fail1;

    err = register_chrdev_region(MKDEV(INPUT_MAJOR, 0),
                     INPUT_MAX_CHAR_DEVICES, "input");
    if (err) {
        pr_err("unable to register char major %d", INPUT_MAJOR);
        goto fail2;
    }

    return 0;

 fail2: input_proc_exit();
 fail1: class_unregister(&input_class);
    return err;
}

static void __exit input_exit(void)
{
    input_proc_exit();
    unregister_chrdev_region(MKDEV(INPUT_MAJOR, 0),
                 INPUT_MAX_CHAR_DEVICES);
    class_unregister(&input_class);
}

subsys_initcall(input_init);

两个重要的链表

两个重要的链表 input_register_device():
向input_dev_list里面添加input device
调用input_attach_handler去匹配input_handler
input_register_handler():
向input_handler_list天剑input handler
调用input_attach_handler去匹配input_handler

注意上面这两个函数都提到了input_attach_handler()这意味着我们在注册我们的input device的时候会去匹配我们的input handler同时当我们去注册input handler的时候会去匹配input device
通常这两个函数是在我们的driver里面调用的

以触摸屏驱动为例讲解内核input子系统

input_dev = input_allocate_device();
    if (!input_dev) {
        err = -ENOMEM;
        dev_err(&client->dev, "[Focal][Touch] %s: failed to allocate input device\n", __func__);
        goto exit_input_dev_alloc_failed;
    }


    ftxxxx_ts->input_dev = input_dev;

    set_bit(KEY_BACK, input_dev->keybit);
    set_bit(KEY_HOME, input_dev->keybit);
    set_bit(KEY_APPSELECT, input_dev->keybit);
    //set_bit(KEY_POWER, input_dev->keybit);

    __set_bit(EV_ABS, input_dev->evbit);
    __set_bit(EV_KEY, input_dev->evbit);
    __set_bit(BTN_TOUCH, input_dev->keybit);
    __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
//  printk("maxx=%d,maxy=%d\n",ftxxxx_ts->x_max,ftxxxx_ts->y_max);
    input_mt_init_slots(input_dev, CFG_MAX_TOUCH_POINTS, 0);
//  input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, CFG_MAX_TOUCH_POINTS, 0, 0);
    input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 31, 0, 0);
    input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ftxxxx_ts->x_max, 0, 0);
    input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ftxxxx_ts->y_max, 0, 0);
    input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, PRESS_MAX, 0, 0);

    input_dev->name = Focal_input_dev_name;
    err = input_register_device(input_dev);

上面这段代码便是我摘抄的触摸屏驱动的部分代码,主要是input device的注册过程,重点函数是input_register_device()正如我们上面所说的他会去input_handler_list里面去寻找匹配input handler,对于向触摸屏和鼠标等我们的内核已经为我们注册好了input handler代码位于:/kernel/driver/input/evdev.c:
这段代码主要注册了一个input handler,我们的触摸屏驱动匹配到的就是这个handler

/kernel/driver/input/evdev.c:
static int __init evdev_init(void)
{
    return input_register_handler(&evdev_handler);
}

static void __exit evdev_exit(void)
{
    input_unregister_handler(&evdev_handler);
}

module_init(evdev_init);
module_exit(evdev_exit);

在touch driver里面调用input_register_device()会有如下关键的一段代码:
将input device添加进input_dev_list,并且对于每一个注册好的input handler调用input_attach_handler()去匹配device(在这里使我们的触摸屏)

list_add_tail(&dev->node, &input_dev_list);
    list_for_each_entry(handler, &input_handler_list, node)
        input_attach_handler(dev, handler);
。。。

下面便是匹配的代码:对于我们的touch 这里匹配到的就是我们在evdev.c里面注册好的handler,紧接着调用handler->connect(handler, dev, id);
会到evdev.c里面会知道这里的connect是evdev_connect()

static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
    const struct input_device_id *id;
    int error;

    id = input_match_device(handler, dev);
    if (!
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值