主要流程框架
系统初始化
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
* to SMDK2410 */
/* Maintainer: Jonas Dietsche */
.phys_io = S3C2410_PA_UART,
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100,
.map_io = smdk2410_map_io,
.init_irq = s3c24xx_init_irq,
.init_machine = smdk2410_init,
.timer = &s3c24xx_timer,
MACHINE_END
将上面的宏展开为
static const struct machine_desc __mach_desc_SMDK2410
__attribute_used__
__attribute__((__section__(".arch.info.init"))) = {
.nr = MACH_TYPE_SMDK2410, /* architecture number */
.name = "SMDK2410", /* architecture name */
/* Maintainer: Jonas Dietsche */
.phys_io = S3C2410_PA_UART, /* start of physical io */
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100, /* tagged list */
.map_io = smdk2410_map_io, /* IO mapping function */
.init_irq = s3c24xx_init_irq,
.init_machine = smdk_machine_init,
.timer = &s3c24xx_timer,
}
MACHINE_START主要是定义了"struct machine_desc"的类型,放在 section(".arch.info.init"),是初始化数据,Kernel 起来之后将被丢弃。
各个成员函数在不同时期被调用:
1. .init_machine 在 arch/arm/kernel/setup.c 中被 customize_machine 调用,放在 arch_initcall() 段里面,会自动按顺序被调用。2. init_irq在start_kernel() -> init_IRQ() -> init_arch_irq() 被调用
3. map_io 在 setup_arch() -> paging_init() -> devicemaps_init()被调用其他主要都在 setup_arch() 中用到。
内核加载触摸模块
static int __init s3c2410ts_init(void)
{
// init_MUTEX(&gADClock);
return platform_driver_register(&s3c2410ts_driver);
}
s3c2410ts_driver 设置驱动name 为“s3c2410-ts” 将来和上面的平台设备相匹配。
static struct platform_driver s3c2410ts_driver = {
.driver = {
.name = "s3c2410-ts",
.owner = THIS_MODULE,
},
.probe = s3c2410ts_probe,
.remove = s3c2410ts_remove,
};
和平台设备相匹配后,就会执行驱动的probe函数。
在s3c2410ts_probe中,
首先申请设备
input_dev = input_allocate_device();
if (!input_dev) {
printk(KERN_ERR "Unable to allocate the input device !!\n");
return -ENOMEM;
}
ts.dev = input_dev;
然后设置设备
ts.dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS); // 同步类事件、按键事件、绝对位移事件
ts.dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); // 按键类事件中的具体事件
input_set_abs_params(ts.dev, ABS_X, 0, 0x3FF, 0, 0); // 绝对位移事件中的具体事件
input_set_abs_params(ts.dev, ABS_Y, 0, 0x3FF, 0, 0);
input_set_abs_params(ts.dev, ABS_PRESSURE, 0, 1, 0, 0);
ts.dev->private = &ts;
ts.dev->name = s3c2410ts_name;
ts.dev->id.bustype = BUS_RS232;
ts.dev->id.vendor = 0xDEAD;
ts.dev->id.product = 0xBEEF;
ts.dev->id.version = S3C2410TSVERSION;
最后注册到输入子系统
/* All went ok, so register to the input system */
input_register_device(ts.dev);
注册到输入子系统后就会和输入子系统架构中的事件处理层evdev程序匹配,从而使得应用程序取得触摸消息。具体的输入子系统框架见本专栏上一篇文章。