Android中Input型输入设备驱动原理分析

话说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 (事件驱动)

d)driver/input/joydev.c(游戏杆驱动)

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;
};




驱动层只是把输入设备注册到输入子系统中,驱动层的代码本身是没有创建设备节点的,而是由EventHander层调用InputCore中的函数来实现,当某个事件触发时都将通过input _event()来将input event传送到input.c中,再由input.c分配事件到每一个"input handler"

2)input _event()是怎么实现的

void input_event(struct input_dev *dev,unsigned int type, unsigned int code, int value)
{
    unsigned long flags;
    if (is_event_supported(type, dev->evbit, EV_MAX)) {
        spin_lock_irqsave(&dev->event_lock, flags);
        add_input_randomness(type, code, value);
        input_handle_event(dev, type, code, value);
        spin_unlock_irqrestore(&dev->event_lock, flags);
    }
}

static void input_handle_event(struct input_dev *dev,unsigned int type, unsigned int code, int value)
{
    int disposition = INPUT_IGNORE_EVENT;
    switch (type) {
    case EV_SYN:
        switch (code) {
        case SYN_CONFIG:
            disposition = INPUT_PASS_TO_ALL;
            break;
        case SYN_REPORT:
            if (!dev->sync) {
                dev->sync = true;
                disposition = INPUT_PASS_TO_HANDLERS;
            }
            break;
        case SYN_MT_REPORT:
            dev->sync = false;
            disposition = INPUT_PASS_TO_HANDLERS;
            break;
        }
        break;
    case EV_KEY:
        if (is_event_supported(code, dev->keybit, KEY_MAX) &&
            !!test_bit(code, dev->key) != value) {
            if (value != 2) {
                __change_bit(code, dev->key);
                if (value)
                    input_start_autorepeat(dev, code);
                else
                    input_stop_autorepeat(dev);
            }
            disposition = INPUT_PASS_TO_HANDLERS;
        }
        break;
    case EV_SW:
        if (is_event_supported(code, dev->swbit, SW_MAX) &&
            !!test_bit(code, dev->sw) != value) {
            __change_bit(code, dev->sw);
            disposition = INPUT_PASS_TO_HANDLERS;
        }
        break;

    case EV_ABS:
        if (is_event_supported(code, dev->absbit, ABS_MAX))
            disposition = input_handle_abs_event(dev, code, &value);
        break;
    case EV_REL:
        if (is_event_supported(code, dev->relbit, REL_MAX) && value)
            disposition = INPUT_PASS_TO_HANDLERS;
        break;
    case EV_MSC:
        if (is_event_supported(code, dev->mscbit, MSC_MAX))
            disposition = INPUT_PASS_TO_ALL;
        break;
    case EV_LED:
        if (is_event_supported(code, dev->ledbit, LED_MAX) &&
            !!test_bit(code, dev->led) != value) {
            __change_bit(code, dev->led);
            disposition = INPUT_PASS_TO_ALL;
        }
        break;
    case EV_SND:
        if (is_event_supported(code, dev->sndbit, SND_MAX)) {
            if (!!test_bit(code, dev->snd) != !!value)
                __change_bit(code, dev->snd);
            disposition = INPUT_PASS_TO_ALL;
        }
        break;
    case EV_REP:
        if (code <= REP_MAX && value >= 0 && dev->rep[code] != value) {
            dev->rep[code] = value;
            disposition = INPUT_PASS_TO_ALL;
        }
        break;
    case EV_FF:
        if (value >= 0)
            disposition = INPUT_PASS_TO_ALL;
        break;
    case EV_PWR:
        disposition = INPUT_PASS_TO_ALL;
        break;
    }
    if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
        dev->sync = false;
    if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)
        dev->event(dev, type, code, value);
    if (disposition & INPUT_PASS_TO_HANDLERS)
        input_pass_event(dev, type, code, value);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值