linux中触摸屏驱动的实现(1)——基于s3c6410处理器的链接地址



上一篇主要讲述了linux中触摸屏设备作为平台设备存在的模块加载和卸载函数,还有就是对应的probe函数和remove函数,这一篇说下在probe函数中注册的两个中断处理函数。

1、先来说第一个中断处理函数——触摸屏中断,对应的中断处理函数是stylus_updown,当触摸屏被按下时,会产生中断信号IRQ_PENDUP。函数源码如下:

static irqreturn_t stylus_updown(int irqno, void *param)
{
unsigned long data0;
unsigned long data1;
int updown;定义一个整型变量,用来表示触摸屏是否被按下,如果按下,这个值是1;如果没按下,这个值是0。

data0 = readl(ts_base+S3C_ADCDAT0);
data1 = readl(ts_base+S3C_ADCDAT1);读取寄存器ADCDAT0和寄存器ADCDAT1

updown = (!(data0 & S3C_ADCDAT0_UPDOWN)) && (!(data1 & S3C_ADCDAT1_UPDOWN));
重点来分析,有如下定义:

#define S3C_ADCDAT0_UPDOWN(1<<15)

#define S3C_ADCDAT1_UPDOWN(1<<15)

从这里可知与这两个寄存器的第15位有关,而寄存器ADCDAT0和寄存器ADCDAT1分别表示X和Y方向检测到触摸屏是否被按下,也就是说只有当寄存器ADCDAT0和寄存器ADCDAT1两个寄存器的UPDOWN都等于0时,采表示触摸屏被按下。看下面这个图:



#ifdef CONFIG_TOUCHSCREEN_S3C_DEBUG
       printk(KERN_INFO "   %c\n",updown ? 'D' : 'U');
#endif


/* TODO we should never get an interrupt with updown set while
* the timer is running, but maybe we ought to verify that the
* timer isn't running anyways. */
if (updown)     updown 等于1,表示触摸屏按下
{
downflag=1;
//printk("touch_timer_fire(0)\n");
touch_timer_fire(0);调用此函数处理触摸屏的按下,这个函数下面再讲。
}


if(ts->s3c_adc_con==ADC_TYPE_2) {
       __raw_writel(0x0, ts_base+S3C_ADCCLRWK);
        __raw_writel(0x0, ts_base+S3C_ADCCLRINT);
}

其中有如下定义:

#define S3C_ADCCLRINTS3C_ADCREG(0x18)

#define S3C_ADCCLRWKS3C_ADCREG(0x20)

直接看图:


        

return IRQ_HANDLED;
}

好了现在可以分析我们上面没有分析的那一个函数了touch_timer_fire,源码如下:

static void touch_timer_fire(unsigned long data)
{
unsigned long data0;
unsigned long data1;
int updown;


data0 = readl(ts_base+S3C_ADCDAT0);
data1 = readl(ts_base+S3C_ADCDAT1);

updown = (!(data0 & S3C_ADCDAT0_UPDOWN)) && (!(data1 & S3C_ADCDAT1_UPDOWN));
上面这些和刚才分析的一样,都是为了判断触摸屏是否被按下

if (updown) {  为1,触摸屏被按下
//printk("updown=1.\n");
if (ts->count) {

#ifdef CONFIG_TOUCHSCREEN_S3C_DEBUG
........
#endif
   if(downflag==0)
                     {
input_report_abs(ts->dev, ABS_X, ts->xp);
input_report_abs(ts->dev, ABS_Y, ts->yp);

input_report_key(ts->dev, BTN_TOUCH, 1);
input_report_abs(ts->dev, ABS_PRESSURE, 1);
input_sync(ts->dev);
                     }    上面这一段用来向输入子系统报告当前触摸笔的位置
                    else
                    {
                       // printk("downflag=1.ignore this data.\n");
    downflag=0;
                    }
}
ts->xp = 0;
ts->yp = 0;  
ts->count = 0;

  表示缓冲区中没有数据,也就是没有触摸屏按下时间发生




writel(S3C_ADCTSC_PULL_UP_DISABLE | AUTOPST, ts_base+S3C_ADCTSC);主要是将AD转化模式设置在自动转化模式。

其中有如下定义:

#define S3C_ADCTSC_PULL_UP_DISABLE(1<<3)

#define AUTOPST    (S3C_ADCTSC_YM_SEN | S3C_ADCTSC_YP_SEN | S3C_ADCTSC_XP_SEN | \
    S3C_ADCTSC_AUTO_PST | S3C_ADCTSC_XY_PST(0))


writel(readl(ts_base+S3C_ADCCON) | S3C_ADCCON_ENABLE_START, ts_base+S3C_ADCCON);启动AD转化功能
}
else {    表示触摸屏没有被按下时的操作。


ts->count = 0;
input_report_key(ts->dev, BTN_TOUCH, 0);调用这个函数向输入子系统报告触摸屏被弹起事件,表示按键被释放。
input_report_abs(ts->dev, ABS_PRESSURE, 0);  发送触摸屏的一个绝对坐标
input_sync(ts->dev);  该函数通知事件发送者发送一个完整的报告。


writel(WAIT4INT(0), ts_base+S3C_ADCTSC);  把触摸屏的模式设为等待中断模式
}
}

linux中触摸屏驱动的实现(3)——基于s3c6410处理器的链接地址





Logo

更多推荐