输入子系统核心linux-2.6.29\drivers\input\input.c
1、输入子系统核心初始化
input_init
//注册了主设备号为13字符设备,fops为input_fops。app调用open打开设备时会调用input_fops.open
register_chrdev
2、输入子系统核向外提供了函数接口
input_register_device
input_register_handler
input_register_handle
input_event
2.1 input_register_handler向系统注册处理者
input_register_handler
input_table[handler->minor >> 5] = handler//将每一个注册的handler放入input_table数组(最多支持8个)
list_add_tail//将每一个注册的handler插入input_handler_list链表的尾部
list_for_each_entry(dev, &input_dev_list, node)//遍历input_dev_list链表的每一个dev
input_attach_handler(dev, handler);
2.2 input_register_device向系统注册输入设备
input_register_device
__set_bit(EV_SYN, dev->evbit);//设备支持SYN事件
list_add_tail(&dev->node, &input_dev_list);//将每一个注册的dev插入input_dev_list链表的尾部
list_for_each_entry(handler, &input_handler_list, node)//遍历input_handler_list链表的每一个handler
input_attach_handler(dev, handler);
2.3 分析input_attach_handler
handler->blacklist && input_match_device(handler->blacklist, dev)//查看设备是否是handler->blacklist指定需要忽略的设备
input_match_device//匹配dev和handler中的id
//从MATCH_BIT宏的定义可以看出。只有当iput device和input handler的ID成员在evbit、keybit、
//… swbit项相同才会匹配成功。而且匹配的顺序是从evbit、keybit到swbit。只要有一项不同,
//就会循环到ID中的下一项进行比较。
MATCH_BIT(evbit, EV_MAX);//展开如下:
#define MATCH_BIT(evbit, EV_MAX) \
for (i = 0; i < BITS_TO_LONGS(EV_MAX); i++) \
if ((id->evbit[i] & dev->evbit[i]) != id->evbit[i]) \
break; \
if (i != BITS_TO_LONGS(EV_MAX)) \
continue;
handler->connect(handler, dev, id);//调用handler中的connect函数
2.4 向子系统上报事件linux-2.6.29\include\linux\input.h
input_report_key
input_report_rel
input_report_abs
input_report_ff_status
input_report_switch
input_sync
input_event
is_event_supported(type, dev->evbit, EV_MAX)//判断dev是否支持type事件
input_handle_event
if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event)//调用dev->event
dev->event(dev, type, code, value);
input_pass_event//参考<linux驱动开发入门与实战>327页
//调用所有打开的handler->event(一个dev可能对应多个handler)
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
if (handle->open)//4.4中设置了打开标记
handle->handler->event(handle, type, code, value);
3、app调用open打开设备时会调用input_fops.open
input_open_file
handler = input_table[iminor(inode) >> 5];//在此input_table数组中根据此设备号,找到对应的handler
old_fops = file->f_op;//偷龙转凤换掉了主设备号13所对应的file_operations
file->f_op = new_fops;
new_fops->open(inode, file);//调用具体handler的open函数
4、实例分析drivers\input\mousedev.c和drivers\hid\usbhid\usbmouse.c
4.1 usb_mouse_init
usb_register(&usb_mouse_driver);//注册mouse驱动
usb_mouse_probe//当mouse设备接入usb会在usb总线上查找匹配的驱动,并调用驱动的probe
input_register_device//先初始化input_dev,再向input子系统注册input_dev,并寻找匹配的handler
usb_mouse_irq//urb完成处理函数,判断urb状态,上报事件
input_report_key//参考2.4会调用相对应的handler->event
input_report_rel
mousedev_event//很多具体主要的工作在这里完成
mousedev_touchpad_touch
mousedev_notify_readers//唤醒在队列mousedev->wait上面的等待
4.2 mousedev_init
input_register_handler(&mousedev_handler);//注册handler,并寻找匹配的dev
4.3 根据2.3匹配成功,调用handler->connect
mousedev_create//创建了结构体struct mousedev,建立input_dev和handler的handle被封装在struct mousedev中
input_register_handle//input_handler.h_list指向handle->h_node
list_add_tail_rcu(&handle->d_node, &dev->h_list);//handle->d_node添加到链表input_dev->h_list尾部(此链表在2.4中会使用)
list_add_tail(&handle->h_node, &handler->h_list);//handle->h_node添加到链表handler->h_list尾部
dev_set_name(&mousedev->dev, mousedev->name);//创建设备节点
device_add(&mousedev->dev);
mixdev_add_device
list_add_tail(&mousedev->mixdev_node, &mousedev_mix_list);添加mousedev->mixdev_node到链表mousedev_mix_list
4.4 app打开设备节点时,根据3会调用mousedev_open
mousedev_open
mousedev_open_device
input_open_device
handle->open++;//增加每一个handle的打开标记,2.4中会用到
dev->open(dev);//调用相对应的input_dev的open函数
usb_mouse_open//usbmouse.c中
usb_submit_urb//提交urb,调用4.1中的urb完成处理函数usb_mouse_irq
4.5 app读设备节点,根据3中的偷龙转凤会调用具体handler的read
mousedev_read
wait_event_interruptible//在mousedev->wait队列上等待,它被4.1中上报事件唤醒
struct input_device_id {
kernel_ulong_t flags;//定义要匹配的项
__u16 bustype;/*总线类型*/
__u16 vendor;/*制造商ID*/
__u16 product;/*产品ID*/
__u16 version;/*版本号*/
kernel_ulong_t evbit[INPUT_DEVICE_ID_EV_MAX / BITS_PER_LONG + 1];
kernel_ulong_t keybit[INPUT_DEVICE_ID_KEY_MAX / BITS_PER_LONG + 1];
kernel_ulong_t relbit[INPUT_DEVICE_ID_REL_MAX / BITS_PER_LONG + 1];
kernel_ulong_t absbit[INPUT_DEVICE_ID_ABS_MAX / BITS_PER_LONG + 1];
kernel_ulong_t mscbit[INPUT_DEVICE_ID_MSC_MAX / BITS_PER_LONG + 1];
kernel_ulong_t ledbit[INPUT_DEVICE_ID_LED_MAX / BITS_PER_LONG + 1];
kernel_ulong_t sndbit[INPUT_DEVICE_ID_SND_MAX / BITS_PER_LONG + 1];
kernel_ulong_t ffbit[INPUT_DEVICE_ID_FF_MAX / BITS_PER_LONG + 1];
kernel_ulong_t swbit[INPUT_DEVICE_ID_SW_MAX / BITS_PER_LONG + 1];
kernel_ulong_t driver_info;/*驱动额外的信息*/
};
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;//指向将input_handler和input_dev建立联系的input_handle的h_node
struct list_head node;//指向下一个input_handler.node
};
所有时间类型:
1. #define EV_SYN 0x00 /*表示同步事件*/
2. #define EV_KEY 0x01 /*键盘或者按键,表示一个键码*/
3. #define EV_REL 0x02 /*鼠标设备,表示一个相对的光标位置结果*/
4. #define EV_ABS 0x03 /*手写板产生的值,其是一个绝对整数值*/
5. #define EV_MSC 0x04 /*其他类型*/
6. #define EV_LED 0x11 /*LED灯设备*/
7. #define EV_SND 0x12 /*蜂鸣器,输入声音*/
8. #define EV_REP 0x14 /*允许重复按键类型*/
9. #define EV_PWR 0x16 /*电源管理事件*/
struct input_dev {
const char *name;
const char *phys;
const char *uniq;
struct input_id id;
unsigned long evbit[BITS_TO_LONGS(EV_CNT)];// 表示能产生哪类事件
unsigned long keybit[BITS_TO_LONGS(KEY_CNT)];// 表示能产生哪些按键
unsigned long relbit[BITS_TO_LONGS(REL_CNT)];// 表示能产生哪些相对位移事件, x,y,滚轮
unsigned long absbit[BITS_TO_LONGS(ABS_CNT)];// 表示能产生哪些绝对位移事件, x,y
unsigned long mscbit[BITS_TO_LONGS(MSC_CNT)];
unsigned long ledbit[BITS_TO_LONGS(LED_CNT)];
unsigned long sndbit[BITS_TO_LONGS(SND_CNT)];
unsigned long ffbit[BITS_TO_LONGS(FF_CNT)];
unsigned long swbit[BITS_TO_LONGS(SW_CNT)];
unsigned int keycodemax;
unsigned int keycodesize;
void *keycode;
int (*setkeycode)(struct input_dev *dev, int scancode, int keycode);
int (*getkeycode)(struct input_dev *dev, int scancode, int *keycode);
struct ff_device *ff;
unsigned int repeat_key;
struct timer_list timer;
int sync;
int abs[ABS_MAX + 1];
int rep[REP_MAX + 1];
unsigned long key[BITS_TO_LONGS(KEY_CNT)];
unsigned long led[BITS_TO_LONGS(LED_CNT)];
unsigned long snd[BITS_TO_LONGS(SND_CNT)];
unsigned long sw[BITS_TO_LONGS(SW_CNT)];
int absmax[ABS_MAX + 1];
int absmin[ABS_MAX + 1];
int absfuzz[ABS_MAX + 1];
int absflat[ABS_MAX + 1];
int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev);
int (*flush)(struct input_dev *dev, struct file *file);
int (*event)(struct input_dev *dev, unsigned int type, unsigned int code, int value);
struct input_handle *grab;
spinlock_t event_lock;
struct mutex mutex;
unsigned int users;
int going_away;
struct device dev;
struct list_head h_list;//指向将input_handler和input_dev建立联系的input_handle的d_node
struct list_head node;//指向下一个input_dev.node
};