内核:一个中断如何对应多个句柄

input子系统


input子系统代码位置:kernel/drivers/input/input.c

这个文件完成input系统最原始的初始化,subsys_initcall开始子系统的初始化,并封装EXPORT_SYMBOL给其他驱动调用的接口


在input_init中,三件事:

	err = class_register(&input_class);
	if (err) {
		pr_err("unable to register input_dev class\n");
		return err;
	}

	err = input_proc_init();
	if (err)
		goto fail1;

	err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
	if (err) {
		pr_err("unable to register char major %d", INPUT_MAJOR);
		goto fail2;
	}

创建一个class,proc目录下节点,和注册input的方法集

对开发很有用的是proc的节点,我们看下代码,才能更好地利用它

static int __init input_proc_init(void)
{
	struct proc_dir_entry *entry;

	proc_bus_input_dir = proc_mkdir("bus/input", NULL);
	if (!proc_bus_input_dir)
		return -ENOMEM;

	entry = proc_create("devices", 0, proc_bus_input_dir,
			    &input_devices_fileops);
	if (!entry)
		goto fail1;

	entry = proc_create("handlers", 0, proc_bus_input_dir,
			    &input_handlers_fileops);
	if (!entry)
		goto fail2;

	return 0;

 fail2:	remove_proc_entry("devices", proc_bus_input_dir);
 fail1: remove_proc_entry("bus/input", NULL);
	return -ENOMEM;
}

分如下步骤:

1. "bus/input"目录创建

2. 在"bus/input"目录下创建proc目录devices,它的方法集有

static const struct file_operations input_devices_fileops = {
	.owner		= THIS_MODULE,
	.open		= input_proc_devices_open,
	.poll		= input_proc_devices_poll,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= seq_release,
};

这里要高度重视这些方法集,因为方法集才是创建这些节点的目的,内核很多的调用都是通过方法集调用,所以即使用sourceinsight也很难直接找到注册位置和调用位置

static const struct seq_operations input_devices_seq_ops = {
	.start	= input_devices_seq_start,
	.next	= input_devices_seq_next,
	.stop	= input_seq_stop,
	.show	= input_devices_seq_show,
};

static int input_proc_devices_open(struct inode *inode, struct file *file)
{
	return seq_open(file, &input_devices_seq_ops);
}

open方法就完成一件事:open这个节点的文件,这个节点又对应着一系列的调用,分别有start next stop show;看方法的名字也能知道,这些方法的调用是先start,再next,最后stop,可以通过show,用cat查看一些信息。明白这些,就可以理解,这些方法里面,是一些句柄的链表,每次调用device的open,都会把devices的所有句柄,按照start-next-next-...-stop的方式,这就实现了一个open,能够有多个功能。

“handlers”节点和“devieces”节点注册方式类似,里面关联的是很多的中断句柄

static const struct seq_operations input_handlers_seq_ops = {
	.start	= input_handlers_seq_start,
	.next	= input_handlers_seq_next,
	.stop	= input_seq_stop,
	.show	= input_handlers_seq_show,
};

static int input_proc_handlers_open(struct inode *inode, struct file *file)
{
	return seq_open(file, &input_handlers_seq_ops);
}

static const struct file_operations input_handlers_fileops = {
	.owner		= THIS_MODULE,
	.open		= input_proc_handlers_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= seq_release,
};

我们实际用下这些节点

shell@android:/proc/bus/input # ls
devices
handlers
shell@android:/proc/bus/input # 

shell@android:/proc/bus/input # cat devices                                    
I: Bus=0000 Vendor=0001 Product=0001 Version=0100
N: Name="headsetdet"
P: Phys=
S: Sysfs=/devices/platform/headsetdet.0/input/input0
U: Uniq=
H: Handlers=event0 
B: PROP=0
B: EV=3
B: KEY=1

I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="keypad"
P: Phys=gpio-keys/input0
S: Sysfs=/devices/platform/keypad/input/input1
U: Uniq=
H: Handlers=kbd event1 keychord 
B: PROP=0
B: EV=3
B: KEY=8000 100000 0 0 0

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="ft5x0x_ts"
P: Phys=
S: Sysfs=/devices/virtual/input/input2
U: Uniq=
H: Handlers=cpufreq_interactive event2 
B: PROP=2
B: EV=9
B: ABS=2658000 0

I: Bus=0000 Vendor=0000 Product=0000 Version=0000
N: Name="lightsensor-level"
P: Phys=
S: Sysfs=/devices/virtual/input/input3
U: Uniq=
H: Handlers=event3 
B: PROP=0
B: EV=9
B: ABS=100 10000000

shell@android:/proc/bus/input # 

shell@android:/proc/bus/input # cat handlers                                   
N: Number=0 Name=kbd
N: Number=1 Name=cpufreq_interactive
N: Number=2 Name=sysrq (filter)
N: Number=3 Name=evdev Minor=64
N: Number=4 Name=keychord
shell@android:/proc/bus/input # 

cpufreq_interactive就是interactive策略,增加对input及时响应的一个句柄。
























你可能感兴趣的:(android,struct,shell,File,Class,input)