一、输入子系统情景回忆ING......
在Linux中,输入子系统是由输入子系统设备驱动层、输入子系统核心层(Input Core)和输入子系统事件处理层(Event Handler)组成。其中设备驱动层提供对硬件各寄存器的读写访问和将底层硬件对用户输入访问的响应转换为标准的输入事件,再通过核心层提交给事件处理层;而核心层对下提供了设备驱动层的编程接口,对上又提供了事件处理层的编程接口;而事件处理层就为我们用户空间的应用程序提供了统一访问设备的接口和驱动层提交来的事件处理。所以这使得我们输入设备的驱动部分不在用关心对设备文件的操作,而是要关心对各硬件寄存器的操作和提交的输入事件。下面用图形来描述一下这三者的关系吧!
二、S3C2440触摸屏接口预热ING......
S3C2440提供的触摸屏接口有4种处理模式,分别是:正常转换模式、单独的X/Y位置转换模式、自动X/Y位置转换模式
和等待中断模式,对于在每种模式下工作的要求,请详细查看数据手册的描述。本驱动实例将采用自动X/Y位置转换
模式和等待中断模式。
三、tq2440_ts.c源码分析
1.入口函数,为了方便分析,清晰架构,这里省去了返回值的判断,最详细的还请参考后面的源码。
static int __init tq2440ts_init(void)
{
struct input_dev *input_dev;
/* 获取ADC时钟,使能时钟(CLKCON[15])
* ADC(&Touch Screen) [15], Control PCLK into ADC block.
*/
adc_clock = clk_get(NULL, "adc");
clk_enable(adc_clock);
/* ADCCON寄存器地址:0x58000000 */
base_addr=ioremap(S3C2410_PA_ADC,0x20);
/* 使能预分频,预分频系数PRSCVL为0xff */
iowrite32(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(0xFF),base_addr+S3C2410_ADCCON);
/* ADCDLY = 0xffff */
iowrite32(0xffff, base_addr+S3C2410_ADCDLY);
/* 进入等待按下中断模式 */
iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
/* 分配一个input_dev结构体 */
input_dev = input_allocate_device();
/* 初始化输入设备,即input_dev成员 */
dev = input_dev;
/* 支持同步事件、按键事件、绝对位移事件 */
dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);
/* 支持按键类中的触摸屏点击 */
dev->keybit[BITS_TO_LONGS(BTN_TOUCH)] = BIT(BTN_TOUCH);
/* 设置触摸屏的X坐标、Y坐标、压力 */
input_set_abs_params(dev, ABS_X, 0, 0x3FF, 0, 0); /* Resolution: 10-bit,0x3ff即10位 */
input_set_abs_params(dev, ABS_Y, 0, 0x3FF, 0, 0);
input_set_abs_params(dev, ABS_PRESSURE, 0, 1, 0, 0);
/* 下面这些信息在驱动挂载后在/proc/bus/input/devices中看到 */
dev->name = tq2440ts_name;
dev->id.bustype = BUS_RS232;
dev->id.vendor = 0xDEAD;
dev->id.product = 0xBEEF;
dev->id.version = S3C2410TSVERSION;
/* 分别申请ADC、TC中断,在ADC中断里使用了IRQF_SHARED
* 共享中断标志,因为在ADC驱动里也使用了ADC中断
*/
request_irq(IRQ_ADC, stylus_action, IRQF_SHARED|IRQF_SAMPLE_RANDOM, tq2440ts_name, dev)
request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM, tq2440ts_name, dev)
printk(KERN_INFO "%s successfully loaded\n", tq2440ts_name);
/* 将触摸屏输入设备注册到输入子系统 */
input_register_device(dev);
return 0;
}
驱动加载函数tq2440ts_init主要做了以下一些事情:获取ADC时钟,使能ADC时钟,映射ADC的IO地址,