android字符驱动,android内核驱动之input输入驱动分析

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

输入子系统由驱动层、输入子系统核心、事件处理层三部分组成。一个输入事件,如鼠标移动、键盘按下等通过Driver->Inputcore->Event

handler->userspace的顺序到达用户控件的应用程序。Android中的input设备驱动主要包括:游戏杆(joystick)、鼠标(mouse)和事件设备(Event)。

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

a4c26d1e5885305701be709a3d33442f.png

驱动层:将底层的硬件输入转化为统一事件形式,向输入核心(Input

Core)汇报。

输入子系统核心:承上启下。为驱动层提供输入设备注册与操作接口,如:input_register_device;通知事件处理层对事件进行处理;在/Proc下产生相应的设备信息

事件处理层:主要是和用户空间交互。(Linux中在用户空间将所有的设备都当作文件来处理,由于在一般的驱动程序中都有提供fops接口,以及在/dev下生成相应的设备文件nod,这些操作在输入子系统中由事件处理层完成)

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

a4c26d1e5885305701be709a3d33442f.png

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事件驱动原理及其实现

+++++++++Event事件驱动原理

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

input_dev *dev)来注册一个input设备

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

struct input_dev {

。。。。。。。。。。。

struct

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

__set_bit(EV_SYN, dev->evbit);//see to

inpu.h

__clear_bit(KEY_RESERVED, dev->keybit);

input_cleanse_bitmasks(dev);

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&

dev->bit) != id->bit) \

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;

}

驱动层只是把输入设备注册到输入子系统中,驱动层的代码本身是没有创建设备节点的,而是由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);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值