jz2440下的input输入子系统
2015-09-24 16:18
288 查看
********************************************************************
static const struct seq_operations input_devices_seq_ops
static const struct file_operations input_devices_fileops
static const struct seq_operations input_handlers_seq_ops
static const struct file_operations input_handlers_fileops
static struct attribute *input_dev_id_attrs[]
static struct attribute_group input_dev_id_attr_group
static struct attribute *input_dev_caps_attrs[]
static struct attribute_group input_dev_caps_attr_group
static const struct attribute_group *input_dev_attr_groups[]
static struct device_type input_dev_type
struct class input_class
static const struct file_operations input_fops = {
.owner = THIS_MODULE,
.open = input_open_file,
.llseek = noop_llseek,
};
input.c输入子系统函数分析:
input_open_file
->handler = input_table[iminor(inode) >> 5];
static struct input_handler *input_table[8];
struct input_handler {
void *private;
void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
.....
bool (*match)(struct input_handler *handler, struct input_dev *dev);
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);
.....
}
上面是将input_handler类型的handler放入input_table[8]中。
input_table[iminor(inode)>>5]存放着input_handler结构体。在许多函数传递的参数就是input_handler
,在函数中就是根据传入的不同input_handler,对其成员变量做处理。
例如在input_open_file()函数中有:
handler = input_table[iminor(inode)>>5]; //将input_table[]中的其中一个input_handler取出,
//通过iminor次设备号来
if(handler)
new_fops = fops_get(handler->fops); //将取出的对应的handler中的fops赋值给new_fops,
file->f_op = new_fops; //new_fops最终还是赋给了打开的文件。
input_register_handler
input_table[handler->minor >> 5] //在input_register_handler函数中构造了input_table
********************************************************************************
核心层
************************************************************************************
那么哪些函数需要调用input_register_handler进行构造input_table[]呢?
Evdev.c (drivers\input)
Keyboard.c (drivers\char)
Mousedev.c (drivers\input)
Tsdev.c (drivers\input)
在evdev.c函数中evdev_init()中,有:
evdev_init
->input_register_handler(&evdev_handler) 向核心层中注册一个input_handler类型的evdev_handler
static struct input_handler evdev_handler = {
.event = evdev_event,
.connect = evdev_connect,
.disconnect = evdev_disconnect,
.fops = &evdev_fops,
.minor = EVDEV_MINOR_BASE,
.name = "evdev",
.id_table = evdev_ids,
};
其中对于之前在核心层中的new_fops = fops_get(handler->fops),对应于new_fops = fops_get(&evdev_fops);
如果调用到了read()函数,则会调用evdev_fops = { .open = ..; .read = ..;... }中的read函数。
对于handler,如果id_table中的内容,与device中的id_table能够对应的上,则evdev.c会调用input_handler中的.connect函数。
input_device会与id_table进行比较,如果匹配则支持这个设备。然后调用connect,建立连接。
***********************************************************
《左边》:
那么哪些会调用input_register_device
例如gpio_keys.c:
gpio_keys_probe
input_allocate_device //分配一个input_dev设备
input_register_device //将dev放入链表
->device_add(&dev->dev); //将设备添加到
->list_add_tail(&dev->node, &input_dev_list);//将设备的node添加到input_dev_list列表中
->list_for_each_entry(handler, &input_handler_list, node) //将新的handler结构体指向相对应的handler
->input_attach_handler(dev, handler);
->input_match_device //将handler中的id_table与input_devdev比对
gpio_keys_gpio_report_event
->input_event(input, type, button->code, button->value); //上报事件,调用evdev中的event函数!!!!!!!!!!!
->input_handle_event //调用handler中的handle->handler->event!!!!!!!
->input_pass_event
handle->handler->event(handle, type, code, value);
在evdev.c的evdev_event中记录buffer值,然后发信号,唤醒应用程序
因为在读的时候没有数据的时候是休眠的。
->input_sync(input);
《右边》:
在keyboard.c中kbd_init()函数中有:
kbd_init
->input_register_handle(handle) //
->INIT_LIST_HEAD(&handler->h_list);
->input_table[handler->minor >> 5] = handler;
->list_add_tail(&handler->node, &input_handler_list);
->list_for_each_entry(dev, &input_dev_list, node) //将新的dev设备结构体指向对应的dev
->input_attach_handler(dev, handler);
->input_match_device //将handler中的id_table与input_devdev比对
***************************************************************************************************
在buttons函数中
设置定时器函数、
注册中断
static const struct seq_operations input_devices_seq_ops
static const struct file_operations input_devices_fileops
static const struct seq_operations input_handlers_seq_ops
static const struct file_operations input_handlers_fileops
static struct attribute *input_dev_id_attrs[]
static struct attribute_group input_dev_id_attr_group
static struct attribute *input_dev_caps_attrs[]
static struct attribute_group input_dev_caps_attr_group
static const struct attribute_group *input_dev_attr_groups[]
static struct device_type input_dev_type
struct class input_class
static const struct file_operations input_fops = {
.owner = THIS_MODULE,
.open = input_open_file,
.llseek = noop_llseek,
};
input.c输入子系统函数分析:
input_open_file
->handler = input_table[iminor(inode) >> 5];
static struct input_handler *input_table[8];
struct input_handler {
void *private;
void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
.....
bool (*match)(struct input_handler *handler, struct input_dev *dev);
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);
.....
}
上面是将input_handler类型的handler放入input_table[8]中。
input_table[iminor(inode)>>5]存放着input_handler结构体。在许多函数传递的参数就是input_handler
,在函数中就是根据传入的不同input_handler,对其成员变量做处理。
例如在input_open_file()函数中有:
handler = input_table[iminor(inode)>>5]; //将input_table[]中的其中一个input_handler取出,
//通过iminor次设备号来
if(handler)
new_fops = fops_get(handler->fops); //将取出的对应的handler中的fops赋值给new_fops,
file->f_op = new_fops; //new_fops最终还是赋给了打开的文件。
input_register_handler
input_table[handler->minor >> 5] //在input_register_handler函数中构造了input_table
********************************************************************************
核心层
************************************************************************************
那么哪些函数需要调用input_register_handler进行构造input_table[]呢?
Evdev.c (drivers\input)
Keyboard.c (drivers\char)
Mousedev.c (drivers\input)
Tsdev.c (drivers\input)
在evdev.c函数中evdev_init()中,有:
evdev_init
->input_register_handler(&evdev_handler) 向核心层中注册一个input_handler类型的evdev_handler
static struct input_handler evdev_handler = {
.event = evdev_event,
.connect = evdev_connect,
.disconnect = evdev_disconnect,
.fops = &evdev_fops,
.minor = EVDEV_MINOR_BASE,
.name = "evdev",
.id_table = evdev_ids,
};
其中对于之前在核心层中的new_fops = fops_get(handler->fops),对应于new_fops = fops_get(&evdev_fops);
如果调用到了read()函数,则会调用evdev_fops = { .open = ..; .read = ..;... }中的read函数。
对于handler,如果id_table中的内容,与device中的id_table能够对应的上,则evdev.c会调用input_handler中的.connect函数。
input_device会与id_table进行比较,如果匹配则支持这个设备。然后调用connect,建立连接。
***********************************************************
《左边》:
那么哪些会调用input_register_device
例如gpio_keys.c:
gpio_keys_probe
input_allocate_device //分配一个input_dev设备
input_register_device //将dev放入链表
->device_add(&dev->dev); //将设备添加到
->list_add_tail(&dev->node, &input_dev_list);//将设备的node添加到input_dev_list列表中
->list_for_each_entry(handler, &input_handler_list, node) //将新的handler结构体指向相对应的handler
->input_attach_handler(dev, handler);
->input_match_device //将handler中的id_table与input_devdev比对
gpio_keys_gpio_report_event
->input_event(input, type, button->code, button->value); //上报事件,调用evdev中的event函数!!!!!!!!!!!
->input_handle_event //调用handler中的handle->handler->event!!!!!!!
->input_pass_event
handle->handler->event(handle, type, code, value);
在evdev.c的evdev_event中记录buffer值,然后发信号,唤醒应用程序
因为在读的时候没有数据的时候是休眠的。
->input_sync(input);
《右边》:
在keyboard.c中kbd_init()函数中有:
kbd_init
->input_register_handle(handle) //
->INIT_LIST_HEAD(&handler->h_list);
->input_table[handler->minor >> 5] = handler;
->list_add_tail(&handler->node, &input_handler_list);
->list_for_each_entry(dev, &input_dev_list, node) //将新的dev设备结构体指向对应的dev
->input_attach_handler(dev, handler);
->input_match_device //将handler中的id_table与input_devdev比对
***************************************************************************************************
在buttons函数中
设置定时器函数、
注册中断
相关文章推荐
- iOS学习笔记(二)
- android ORM框架LitePal 封装SQLite
- Python快速入门
- 公司正能量语录
- tcp三次握手与四次握手详解
- TabHost的一点注意事项
- subList方法
- MPAndroidChart的使用
- 在linux下安装图形界面
- loadrunner脚本报错解决办法
- 如何调试makefile
- mysql用户管理(新增用户及权限管理)
- MSSQL复制表
- SpringMVC、MyBatis声明式事务管理
- OpenCV库的使用
- GCD的使用方法
- mysql添加远程访问
- codeforces 321# D. Kefa and Dishes (状态压缩DP)
- Cognos Schedules does not work
- 布隆过滤器