转自:http://blog.csdn.net/eilianlau/article/details/6969361

话说Android中Event输入设备驱动原理分析还不如说Linux输入子系统呢,反正这个是没变的,在android的底层开发中对于Linux的基本驱动程序设计还是没变的,当然Android底层机制也增加几个属于android自己的机制。典型的IPC

Android中的input设备驱动主要包括:游戏杆(joystick)、鼠标(mouse)和事件设备(Event)。

1、Input输入子系统的构架,在网上找到两幅灰常漂亮的图。

下面这幅更漂亮,更直观的能看出input型输入子系统究竟是什么咚咚,更能够体现出,用户空间,内核空间,驱动程序是怎么关联起来的。。。

Input驱动同样也是字符设备,主设备号是13,次设备号是64~95之间自动生成的,这个Input驱动程序那是相当相当的复杂。在android内核中主要需要关注一下几个文件

a)include/linux/input.h(驱动头文件)

b)driver/input/input.c (驱动核心实现,包含大量的操作接口)

c)driver/input/event.c (event机制)

d)driver/input/joydev.c (joystick驱动)

e)driver/input/mousedev.c(鼠标驱动)

其实上面这些东西都不要我们自己去实现内核已经帮我们实现好了,不过我们在写硬件驱动的时候需要和Inputcore交互,所以需要用到上面这些函数中的接口,也就是说上面这些函数是透明的。

2、Event事件驱动原理及其实现

在内核中,用input_dev来描述一个Input设备,该结构的定义如下,其中内核中使用input_register_device(struct input_dev *dev)来注册一个input设备

这个结构体好长,所以就列了几个。。。。它的定义在input.h当中

struct input_dev {

。。。。。。。。。。。
    struct input_id id;/*指向input_id结构*/
    bool sync;              
    struct device dev;/**这些设备都归属总线设备模型*/
    struct list_head    h_list; //
    struct list_head    node;  //input_handle链表的list节点
};

用input_handler表示input设备的接口,使用input_register_handler(structinput_handler *handler)注册

struct input_handler {

void *private;

。。。。。。。。。。
    int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
    void (*disconnect)(struct input_handle *handle);
    void (*start)(struct input_handle *handle);

const struct file_operations *fops;
    int minor;
    const char *name;

const struct input_device_id *id_table;

struct list_head    h_list;
    struct list_head    node;
};

Event事件驱动实现过程

1)Input设备注册

int input_register_device(struct input_dev *dev)
{
    static atomic_t input_no = ATOMIC_INIT(0);
    struct input_handler *handler;
    const char *path;
    int error;
    /* Every input device generates EV_SYN/SYN_REPORT events. */
    __set_bit(EV_SYN, dev->evbit);//see to inpu.h

/* KEY_RESERVED is not supposed to be transmitted to userspace. */
    __clear_bit(KEY_RESERVED, dev->keybit);
    /* Make sure that bitmasks not mentioned in dev->evbit are clean. */
    input_cleanse_bitmasks(dev);
    /*
     * If delay and period are pre-set by the driver, then autorepeating
     * is handled by the driver itself and we don't do it in input.c.
     */
    init_timer(&dev->timer);
    //处理重复按键.如果没赋值则为其赋默认的值
    if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) {
        dev->timer.data = (long) dev;
        dev->timer.function = input_repeat_key;
        dev->rep[REP_DELAY] = 250;
        dev->rep[REP_PERIOD] = 33;
    }
    if (!dev->getkeycode)//获取键的扫描码
        dev->getkeycode = input_default_getkeycode;
    if (!dev->setkeycode)//设置键值
        dev->setkeycode = input_default_setkeycode;
    dev_set_name(&dev->dev, "input%ld",
             (unsigned long) atomic_inc_return(&input_no) - 1);
    //将input_dev中封装的device注册到sysfs
    error = device_add(&dev->dev);
    if (error)
        return error;
    path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
    printk(KERN_INFO "input: %s as %s\n",
        dev->name ? dev->name : "Unspecified device", path ? path : "N/A");
    kfree(path);

error = mutex_lock_interruptible(&input_mutex);
    if (error) {
        device_del(&dev->dev);
        return error;
    }
    //将input_device挂到input_dev_list链表中
    list_add_tail(&dev->node, &input_dev_list);
    //对挂载在input_dev_list中的每一个handler调用input_attach_handler(dev, handler);
    list_for_each_entry(handler, &input_handler_list, node)
        input_attach_handler(dev, handler);
    input_wakeup_procfs_readers();
    mutex_unlock(&input_mutex);
    return 0;
}

上述函数首先将input_device挂接到input_dev_list链表上,然后对挂载在input_dev_list中的每一个handler调用input_attach_handler(dev, handler)来进行匹配,举个例子,设备模型中的device和driver的匹配,所有的input device都挂载在input_dev_list上而所有的handler都挂载在input_handler_list上,那么它们是怎么联系起来的?匹配过程如下

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 (!id)
        return -ENODEV;
    error = handler->connect(handler, dev, id);
    if (error && error != -ENODEV)
        printk(KERN_ERR
            "input: failed to attach handler %s to device %s, "
            "error: %d\n",
            handler->name, kobject_name(&dev->dev.kobj), error);
    return error;
}

上面函数调用input_match_device来对handler, dev通过input_device_id *id来进行匹配如果匹配成功则调用handler->connect来关联struct input_dev *dev, 和struct input_handler *handler结构。下面看看input_match_device(handler, dev)的过程

#define MATCH_BIT(bit, max) \
        for (i = 0; i < BITS_TO_LONGS(max); i++) \
            if ((id->bit[i] & dev->bit[i]) != id->bit[i]) \
                break; \
        if (i != BITS_TO_LONGS(max)) \
            continue;

static const struct input_device_id *input_match_device(struct input_handler *handler,struct input_dev *dev)
{
    const struct input_device_id *id;
    int i;
    for (id = handler->id_table; id->flags || id->driver_info; id++) {//flags配置匹配的类型
        if (id->flags & INPUT_DEVICE_ID_MATCH_BUS)//匹配总线类型
            if (id->bustype != dev->id.bustype)
               continue;
        if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR)//匹配厂商
            if (id->vendor != dev->id.vendor)
                continue;
        if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT)//匹配制造商
            if (id->product != dev->id.product)
                continue;
        if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION)//匹配版本号
            if (id->version != dev->id.version)
                continue;
      //如果上面的id->flags匹配成功或者是id->flags没有定义则执行下面的函数
        MATCH_BIT(evbit,  EV_MAX);
        MATCH_BIT(keybit, KEY_MAX);
        MATCH_BIT(relbit, REL_MAX);
        MATCH_BIT(absbit, ABS_MAX);
        MATCH_BIT(mscbit, MSC_MAX);
        MATCH_BIT(ledbit, LED_MAX);
        MATCH_BIT(sndbit, SND_MAX);
        MATCH_BIT(ffbit,  FF_MAX);
        MATCH_BIT(swbit,  SW_MAX);
        if (!handler->match || handler->match(handler, dev))
            return id;
    }
    return NULL;
}

其中handler的注册和上述类似,感兴趣的朋友可以读linux内核源码

 

Android中Input型输入设备驱动原理分析(一)的更多相关文章

  1. Android中Input型输入设备驱动原理分析<一>

    话说Android中Event输入设备驱动原理分析还不如说Linux输入子系统呢,反正这个是没变的,在android的底层开发中对于Linux的基本驱动程序设计还是没变的,当然Android底层机制也 ...

  2. android 脱壳 之 dvmDexFileOpenPartial断点脱壳原理分析

    android 脱壳 之 dvmDexFileOpenPartial断点脱壳原理分析 导语: 笔者主要研究方向是网络通信协议的加密解密, 对应用程序加固脱壳技术很少研究, 脱壳壳经历更是经历少之甚少. ...

  3. Android 中View的绘制机制源代码分析 三

    到眼下为止,measure过程已经解说完了,今天開始我们就来学习layout过程.只是在学习layout过程之前.大家有没有发现我换了编辑器,哈哈.最终下定决心从Html编辑器切换为markdown编 ...

  4. Android中相机和相冊使用分析

    Android中相机和相冊使用分析 欢迎转载,但请尊重原创(文章来自不易,转载请标明转载出处,谢谢) 在手机应用程序中,使用自带的相机拍照以及相冊选择喜欢的图片是最常见只是的用户需求,那么怎么合理使用 ...

  5. Android 中View的绘制机制源代码分析 一

    尊重原创: http://blog.csdn.net/yuanzeyao/article/details/46765113 差点儿相同半年没有写博客了,一是由于工作比較忙,二是认为没有什么内容值得写, ...

  6. Android 中View的绘制机制源代码分析 二

    尊重原创:http://blog.csdn.net/yuanzeyao/article/details/46842891 本篇文章接着上篇文章的内容来继续讨论View的绘制机制,上篇文章中我们主要解说 ...

  7. 阿里面试官:Android中binder机制的实现原理及过程?

    Binder 是 Android 系统中非常重要的组成部分.Android 系统中的许多功能建立在 Binder 机制之上.在这篇文章中,我们会对 Android 中的 Binder 在系统架构中的作 ...

  8. Android大图片裁剪终极解决方案 原理分析

    约几个月前,我正为公司的APP在Android手机上实现拍照截图而烦恼不已. 上网搜索,确实有不少的例子,大多都是抄来抄去,而且水平多半处于demo的样子,可以用来讲解知识点,但是一碰到实际项目,就漏 ...

  9. Android中对Log日志文件的分析[转]

    一,Bug出现了, 需要“干掉”它 bug一听挺吓人的,但是只要你懂了,android里的bug是很好解决的,因为android里提供了LOG机制,具体的底层代码,以后在来分析,只要你会看bug, a ...

随机推荐

  1. django request对象和HttpResponse对象

    HttpRequest对象(除非特殊说明,所有属性都是只读,session属性是个例外)HttpRequest.scheme 请求方案(通常为http或https)HttpRequest.body 字 ...

  2. Asp.Net MVC中Action跳转小结

    首先我觉得action的跳转大致可以这样归一下类,跳转到同一控制器内的action和不同控制器内的action.带有参数的action跳转和不带参数的action跳转. 一.RedirectToAct ...

  3. bzoj4726【POI2017】Sabota?

    首先可以推出来如果i没有带头叛变,那么i的父亲也一定不会带头叛变,证明显然 所以最劣情况初始的叛徒肯定是叶子,并且带头叛变的人一定是从某个叶子往上走一条链 f[i]表示i不带头叛变的话最小的x 那么我 ...

  4. zookeeper系列之通信模型(转)

    本文的主题就是讲解Zookeeper通信模型,本节将通过一个概要图来说明Zookeeper的通信模型. Zookeeper的通信架构 在Zookeeper整个系统中,有3中角色的服务,client.F ...

  5. JDK小Bug汇总

    Java官方的Logger.getGlobal().info无效 无效代码 Logger.getGlobal().info("start"); 解决方案(三选一): Logger. ...

  6. C#重构之道

    定义 重构的定义:在不改变软件可观察行为的前提下,改善其内部结构. 其中,不改变软件行为,是重构最基本的要求.要想真正发挥威力,就必须做到“不需了解软件行为”. 如果一段代码能让你容易了解其行为,说明 ...

  7. Beta阶段第三次Scrum Meeting

    情况简述 Beta阶段第三次Scrum Meeting 敏捷开发起始时间 2016/12/12 22:00 敏捷开发终止时间 2016/12/13 22:00 会议基本内容摘要 讨论决定了APP的名称 ...

  8. 手机端多种分享plugin插件地址

    //qq cordova plugin add https://github.com/iVanPan/Cordova_QQ.git --variable QQ_APP_ID=app_id 参考文档 h ...

  9. 《Python核心编程》18.多线程编程(二)

    18.1没有线程支持 #!/usr/bin/env python # -*- coding:utf-8 -*- from time import sleep, ctime def loop0(): p ...

  10. nltk27_NLTK聚类分析

    http://www.pythontip.com/blog/post/10044/ Python自然语言处理(三) -- 利用NLTK进行聚类 这篇文章介绍如何利用NLTK进行聚类,和上两篇文章Pyt ...