看得两个眼睛冒星星,不过还是把流程大概缕了下。看来内核很喜欢搞成那种总线、设备、驱动这样的结构,输入子系统也很像。把阅读的关键代码记录一下,有关输入子系统的详细内容还需要查阅相关的资料。
#####################################################################
arch/arm/plat-s3c24xx/devs.c
struct platform_device s3c_device_ts = {
.name = "s3c2410-ts",
.id = -1,
};
######################################################################
######################################################################
arch/arm/mach-s3c2410/mach-smdk2410.c
static struct platform_device *smdk2410_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
&s3c_device_sdi,
&s3c_device_dm9000,
&te2410_cs89x0,
&s3c_device_ts,
};
static void __init smdk2410_init(void)
{
s3c24xx_fb_set_platdata(&smdk2410_fb_info);
set_s3c2410ts_info(&smdk2410_ts_cfg);
platform_add_devices(smdk2410_devices, ARRAY_SIZE(smdk2410_devices));
smdk_machine_init();
}
#########################################################################
#########################################################################
drivers/input/touchscreen/s3c2410_ts.c
static struct platform_driver s3c2410ts_driver = {
.driver = {
.name = "s3c2410-ts",
.owner = THIS_MODULE,
},
.probe = s3c2410ts_probe,
.remove = s3c2410ts_remove,
.suspend = s3c2410ts_suspend,
.resume = s3c2410ts_resume,
};
static int __init s3c2410ts_probe(struct platform_device *pdev)
{
info = ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
input_dev = input_allocate_device();
rc = input_register_device(ts.dev);
|
init_timer(&dev->timer);
error = device_add(&dev->dev);
list_add_tail(&dev->node, &input_dev_list);
list_for_each_entry(handler, &input_handler_list, node)
input_attach_handler(dev, handler);
//这里让dev和handler进行匹配,最后跟tsdev.c中注册的handler匹配。
}
#########################################################################
输入子系统:
######################################################################################
drivers/input/input.c
static int __init input_init(void)
{
err = class_register(&input_class);
err = input_proc_init();
err = register_chrdev(INPUT_MAJOR, "input", &input_fops);
}
static const struct file_operations input_fops = {
.owner = THIS_MODULE,
.open = input_open_file,
};
static int input_open_file(struct inode *inode, struct file *file)
{
}
int input_register_device(struct input_dev *dev)
{
list_add_tail(&dev->node, &input_dev_list);
list_for_each_entry(handler, &input_handler_list, node)
input_attach_handler(dev, handler);
}
//搜索input_handler_list,发现在下面这个函数中
int input_register_handler(struct input_handler *handler)
{
list_add_tail(&handler->node, &input_handler_list);
}
static int input_attach_handler(struct input_dev *dev, struct input_handler *handler)
{
id = input_match_device(handler->id_table, dev);
|
for (; id->flags || id->driver_info; id++)
{
//比较id里面每一个字段的值,如果与dev有一项不符就跳出,直到所有dev设置的字段在id里面都匹配为止。
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;
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);
return id;
}
error = handler->connect(handler, dev, id);
}
void input_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
input_handle_event(dev, type, code, value);
|
dev->event(dev, type, code, value);
input_pass_event(dev, type, code, value);
|
list_for_each_entry_rcu(handle, &dev->h_list, d_node)
if (handle->open)
handle->handler->event(handle, type, code, value);
//这个envent是在tsdev_connect这个函数里面添加到相关联的dev的h_list中的。最后会调用到tsdev_event
}
########################################################################################
drivers/input/tsdev.c
//这里将tsdev_handler注册到上面的input_handler_list链表中。
static struct input_handler tsdev_handler = {
.event = tsdev_event,
.connect = tsdev_connect,
.disconnect = tsdev_disconnect,
.fops = &tsdev_fops,
.minor = TSDEV_MINOR_BASE,
.name = "tsdev",
.id_table = tsdev_ids,
};
static const struct input_device_id tsdev_ids[] = {
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_RELBIT,
.evbit = { BIT(EV_KEY) | BIT(EV_REL) },
.keybit = { [BTN_LEFT/32] = BIT(BTN_LEFT) },
.relbit = { BIT(REL_X) | BIT(REL_Y) },
}, /* A mouse like device, at least one button, two relative axes */
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_KEYBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
.evbit = { BIT(EV_KEY) | BIT(EV_ABS) },
.keybit = { [BTN_TOUCH/32] = BIT(BTN_TOUCH) },
.absbit = { BIT(ABS_X) | BIT(ABS_Y) },
}, /* A tablet like device, at least touch detection, two absolute axes */
{
.flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_ABSBIT,
.evbit = { BIT(EV_ABS) },
.absbit = { BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) },
}, /* A tablet like device with several gradations of pressure */
{} /* Terminating entry */
};
static int __init tsdev_init(void)
{
return input_register_handler(&tsdev_handler);
}
static int tsdev_connect(struct input_handler *handler, struct input_dev *dev,
const struct input_device_id *id)
{
tsdev = kzalloc(sizeof(struct tsdev), GFP_KERNEL);
if (!tsdev)
return -ENOMEM;
INIT_LIST_HEAD(&tsdev->client_list);
spin_lock_init(&tsdev->client_lock);
mutex_init(&tsdev->mutex);
init_waitqueue_head(&tsdev->wait);
snprintf(tsdev->name, sizeof(tsdev->name), "ts%d", minor);
tsdev->exist = 1;
tsdev->minor = minor;
tsdev->handle.dev = dev;
tsdev->handle.name = tsdev->name;
tsdev->handle.handler = handler;//这个handler就是在tsdev_init中注册的那个tsdev_hanlder
tsdev->handle.private = tsdev;
error = input_register_handle(&tsdev->handle);
error = tsdev_install_chrdev(tsdev);
error = device_add(&tsdev->dev);
}