Chinaunix首页 | 论坛 | 博客
  • 博客访问: 264937
  • 博文数量: 25
  • 博客积分: 329
  • 博客等级: 一等列兵
  • 技术积分: 1380
  • 用 户 组: 普通用户
  • 注册时间: 2012-08-24 09:43
文章分类

全部博文(25)

文章存档

2014年(4)

2013年(12)

2012年(9)

分类: LINUX

2012-08-24 11:21:56


Intput子系统内核源码分析

linux-2.6.32.2/drivers/input/input.c

使用register_chrdev(INPUT_MAJOR, "input", &input_fops)函数注册字符设备驱动

定义的file_operations的结构为:

static const struct file_operations input_fops = {

.owner = THIS_MODULE,

.open = input_open_file,

};

在该file_operations结构中只有open函数,没有其他的操作函数,进入input_open_file函数内部可以分析可知

/* 以次设备号在input_table结构体数组中找到一项input_handler */

struct input_handler *handler = input_table[iminor(inode) >> 5]; 

input_handler 结构为:

 struct input_handler {

void *private;

// 建立连接

void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);

// 事件处理函数

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;

const struct input_device_id *blacklist;

struct list_head h_list;

struct list_head node;

};

/* input_handler结构中获得fops*/

new_fops = fops_get(handler->fops)

/* 将获得的fops作为字符设置新的操作函数集file_operations */

file->f_op = new_fops;

/* 调用新的file_operations中的open函数 */

new_fops->open(inode, file);

app: read > ... > file->f_op->read 

问:input_table数组由谁构造?

答:input_register_handler函数实现。

分析input_register_handler函数:

int input_register_handler(struct input_handler *handler)

/* 将 input_handler 结构体添加到input_table数组中 */

input_table[handler->minor >> 5] = handler;  

/* input_handler结构放入链表 */

list_add_tail(&handler->node, &input_handler_list);

/* 对于每个input_dev,调用input_attach_handler */

list_for_each_entry(dev, &input_dev_list, node)

input_attach_handler(dev, handler);

注册输入设备:

int input_register_device(struct input_dev *dev)

/*  input_dev结构放入链表 */

list_add_tail(&dev->node, &input_dev_list);

/* 对于每个input_handler,调用input_attach_handler */

list_for_each_entry(handler, &input_handler_list, node)

input_attach_handler(dev, handler);

input_attach_handler函数:
int input_attach_handler(struct input_dev *dev, struct input_handler *handler)

/* 判断该驱动是否支持该输入设备, */

input_match_device(handler->id_table, dev);

/* 如果支持,则调用connect函数建立连接 */

handler->connect(handler, dev, id);

注册input_devinput_handler时,会两两比较左边的input_dev和右边的input_handler,

根据input_handlerid_table判断这个input_handler能否支持这个input_dev

如果能支持,则调用input_handlerconnect函数建立"连接"

问:怎么建立连接?

答:1. 分配一个input_handle结构体

2. 

   input_handle.dev = input_dev;  // 指向左边的input_dev

   input_handle.handler = input_handler;  // 指向右边的input_handler

3. 注册:

   input_handler->h_list = &input_handle;

   input_dev->h_list   = &input_handle;

evdev.c为例:

evdev_connect

evdev = kzalloc(sizeof(struct evdev), GFP_KERNEL); // 分配一个input_handle

// 设置

evdev->handle.dev = dev;  // 指向左边的input_dev

evdev->handle.name = evdev->name;

evdev->handle.handler = handler;  // 指向右边的input_handler

evdev->handle.private = evdev;

// 注册

error = input_register_handle(&evdev->handle); 

怎么读按键?

app: read

--------------------------

   .......

    evdev_read

    // 无数据并且是非阻塞方式打开,则立刻返回

if (client->head == client->tail && evdev->exist && (file->f_flags &  O_NONBLOCK))

return -EAGAIN;

// 否则休眠

retval = wait_event_interruptible(evdev->wait,

client->head != client->tail || !evdev->exist);

谁来唤醒?

evdev_event

wake_up_interruptible(&evdev->wait);

evdev_event被谁调用?

猜:应该是硬件相关的代码,input_dev那层调用的

在设备的中断服务程序里,确定事件是什么,然后调用相应的input_handlerevent处理函数 

// 上报事件

input_event(input, type, button->code, !!state);

input_sync(input);

void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)

input_handle_event(dev, type, code, value);

input_pass_event(dev, type, code, value);

handle = rcu_dereference(dev->grab);

if (handle)

handle->handler->event(handle, type, code, value);

else

list_for_each_entry_rcu(handle, &dev->h_list, d_node)

if (handle->open)

handle->handler->event(handle,

type, code, value);






以上内容全是本人凭个人理解写出的:如果错误请多包涵,若能指出,本人将万分感激。

阅读(2705) | 评论(1) | 转发(0) |
0

上一篇:总线设备驱动

下一篇:触摸屏驱动设计

给主人留下些什么吧!~~

铸道的汉子2012-08-25 16:52:43

我还以为是Android的Input子系统