s3c2410触摸板的驱动程序

原创 2011年11月01日 09:03:47
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/irq.h>

#include <asm/arch/regs-gpio.h>

struct s3c_adc_regs {
    unsigned long adccon;
    unsigned long adctsc;
    unsigned long adcdly;
    unsigned long adcdat0;
    unsigned long adcdat1;
};

static struct input_dev *s3c_ts_dev;
static struct s3c_adc_regs *s3c_adc_regs;


static struct timer_list s3c_ts_timer;
//等待触摸笔的按下
static void enter_wait_pen_down(void)
{
    s3c_adc_regs->adctsc = (1<<7) | (1<<6) | (0<<5) | (1 << 4) | (0 << 3) | (3<<0);
}

static void enter_wait_pen_up(void)
{
    s3c_adc_regs->adctsc = (1<<8) | (1<<7) | (1<<6) | (0<<5) | (1 << 4) | (0 << 3) | (3<<0);
}
//测量xy的值
static void enter_measure_xy_mode(void)
{
    s3c_adc_regs->adctsc = (1<<7) | (1<<6) | (1<<4) | (1<<3) | (1<<2);
}

static void start_adc(void)
{
    s3c_adc_regs->adccon |= (1<<0);
}
//时间函数,时间到的时间,自动启动xy的转换,开始adc
static void s3c_ts_timer_function(unsigned long h)
{
    enter_measure_xy_mode();
    start_adc();
}


static irqreturn_t pen_down_up_isr(int irq, void *devid)
{
    static int cnt = 0;

    if (s3c_adc_regs->adcdat0 & (1<<15))
    {
        //printk("pen_down_up_isr up: %d\n", ++cnt);

        /* 进入"等待中断模式": 等待按下 */
        enter_wait_pen_down();
        
        /*上报事件 ,完成一次上报事件*/
        input_event(s3c_ts_dev, EV_ABS, ABS_PRESSURE, 0);
        input_event(s3c_ts_dev, EV_KEY, BTN_TOUCH, 0);
        input_sync(s3c_ts_dev);

    }
    else
    {
#if 0
        printk("pen_down_up_isr down: %d\n", ++cnt);

        /* 进入"等待中断模式": 等待松开 */
        s3c_adc_regs->adctsc = (1<<8) | (1<<7) | (1<<6) | (0<<5) | (1 << 4) | (0 << 3) | (3<<0);
#endif
        //printk("pen_down_up_isr down: %d\n", ++cnt);
        enter_measure_xy_mode();
        start_adc();
    }
    
    return IRQ_HANDLED;
}
//  过滤  让定位更准确
static int s3c_ts_filtering(int *px, int *py)
{
    int avr_x, avr_y;
    int dx, dy;

#define FILTER_LIMIT 25

    avr_x = (px[0] + px[1]) / 2;
    avr_y = (py[0] + py[1]) / 2;

    dx = (px[2] > avr_x) ? (px[2] - avr_x) : (avr_x - px[2]);
    dy = (py[2] > avr_y) ? (py[2] - avr_y) : (avr_y - py[2]);

    if ((dx > FILTER_LIMIT) || (dy > FILTER_LIMIT))
        return 0;

    avr_x = (px[1] + px[2]) / 2;
    avr_y = (py[1] + py[2]) / 2;

    dx = (px[3] > avr_x) ? (px[3] - avr_x) : (avr_x - px[3]);
    dy = (py[3] > avr_y) ? (py[3] - avr_y) : (avr_y - py[3]);

    if ((dx > FILTER_LIMIT) || (dy > FILTER_LIMIT))
        return 0;

    return 1;
}


static irqreturn_t adc_isr(int irq, void *devid)
{
    static int cnt = 0;    
    static int xs[4];
    static int ys[4];
    static int x = 0, y = 0;
//    static int pre_x = 0, pre_y = 0;
    int data0, data1;
    
    //printk("adc_isr : %d\n", ++cnt);

    data0 = s3c_adc_regs->adcdat0;
    data1 = s3c_adc_regs->adcdat1;

    if (data0 & (1<<15))
    {
        /* 已经松开 */
        enter_wait_pen_down();

        input_event(s3c_ts_dev, EV_ABS, ABS_PRESSURE, 0);
        input_event(s3c_ts_dev, EV_KEY, BTN_TOUCH, 0);
        input_sync(s3c_ts_dev);

        x = y = cnt = 0;
    }
    else
    {
        //printk("x = %d, y = %d\n", x, y);
        x += (data0 & 0x3ff);
        y += (data1 & 0x3ff);
        xs[cnt] = (data0 & 0x3ff);
        ys[cnt] = (data0 & 0x3ff);
        
        cnt++;
        
        if (cnt == 4)
        {
            if (s3c_ts_filtering(xs, ys))
            {
                input_event(s3c_ts_dev, EV_ABS, ABS_X, x/4);
                input_event(s3c_ts_dev, EV_ABS, ABS_Y, y/4);
                input_event(s3c_ts_dev, EV_ABS, ABS_PRESSURE, 1);
                input_event(s3c_ts_dev, EV_KEY, BTN_TOUCH, 1);
                input_sync(s3c_ts_dev);
            }

            x = y = cnt = 0;
            
            /* 进入"等待中断模式": 等待松开 */
            enter_wait_pen_up();
            
            mod_timer(&s3c_ts_timer, jiffies + HZ/100);
        }
        else
        {
            enter_measure_xy_mode();
            start_adc();
        }

    }

    return IRQ_HANDLED;
}

static int s3c_ts_init(void)
{
    unsigned long *gpgcon = ioremap(0x56000060, 4);

    /* 1. 分配一个input_dev结构体 */
    s3c_ts_dev = input_allocate_device();

    /* 2. 设置 */

    /* 2.1 能产生哪类事件 */
    __set_bit(EV_KEY, s3c_ts_dev->evbit);
    __set_bit(EV_ABS, s3c_ts_dev->evbit);

    /* 2.1 能产生这类事件里的哪些 */
    __set_bit(BTN_TOUCH, s3c_ts_dev->keybit);
    /*触摸屏的初始化*/
    input_set_abs_params(s3c_ts_dev, ABS_X, 0, 0x3FF, 0, 0);
    input_set_abs_params(s3c_ts_dev, ABS_Y, 0, 0x3FF, 0, 0);
    input_set_abs_params(s3c_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);

    s3c_ts_dev->name = "s3c_ts";

    /* 3. 注册 */
    input_register_device(s3c_ts_dev);

    /* 4. 硬件相关的操作 */
    /* CLKCON  的使能*/
    clk_enable(clk_get(NULL, "adc"));

    /* 配置引脚用于触摸屏 */
    *gpgcon |= 0xff000000;
    iounmap(gpgcon);

    s3c_adc_regs = ioremap(0x58000000, 1024);

    /* bit14: A/D converter prescaler enable
     * bit[13:6]: A/D converter prescaler value,
     *            ADC CLK = PCLK/(49+1)
     */
    s3c_adc_regs->adccon = (1<<14) | (49 << 6);

    s3c_adc_regs->adcdly = 0xffff;
//添加定时器
    init_timer(&s3c_ts_timer);
    s3c_ts_timer.expires = 0;
    s3c_ts_timer.function = s3c_ts_timer_function;
    add_timer(&s3c_ts_timer);

    /* 进入"等待中断模式": 等待按下 */
    enter_wait_pen_down();
    
    request_irq(IRQ_TC, pen_down_up_isr, IRQF_SHARED, "touch_pen", 1);
    request_irq(IRQ_ADC, adc_isr, IRQF_SHARED, "adc_done", 1);
    
    return 0;
}

static void s3c_ts_exit(void)
{
    free_irq(IRQ_ADC, 1);
    free_irq(IRQ_TC, 1);
    input_unregister_device(s3c_ts_dev);
    input_free_device(s3c_ts_dev);
}

module_init(s3c_ts_init);
module_exit(s3c_ts_exit);


MODULE_LICENSE("GPL");


版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hejunw/article/details/6923580

S3C2410触摸屏驱动移植的完整过程(论文的操作部分,所以从第七章开始)

七 实验步骤: 7.1  配置虚拟机 网络配置: PC:右键点击主机右下角“网络”图标,选择“打开网络连接”,弹出如下图的对话框,Vmnet1是hostonly的接口,Vmnet8是NAT的网络...
  • dongfengkuayue
  • dongfengkuayue
  • 2013-06-17 21:45:51
  • 2256

s3c2410触摸屏驱动的介绍

.  S3C2410的触摸屏控制                                 (1).基础知识 要正确使用触摸屏,首先就要正确获取触摸屏的坐标。上一节我们已经介绍了触摸屏的...
  • huang_jinjin
  • huang_jinjin
  • 2012-05-07 13:55:43
  • 3128

Thinkpad触摸板关闭驱动工具

  • 2011年11月07日 10:19
  • 7.05MB
  • 下载

三星110s1j-K11W触摸板驱动程序_2.2.0.0_64bit

  • 2017年06月09日 15:36
  • 9.09MB
  • 下载

转:基于S3C2410的触摸屏驱动程序设计

摘要: 本文介绍了基于三星S3C2410X微处理器,采用SPI接口与ADS7843触摸屏控制器芯片完成触摸屏模块的设计。具体包括在嵌入式Linux操作系统中的软件驱动开发,采用内核定时器的下半部机制进...
  • slippercat
  • slippercat
  • 2008-04-03 19:25:00
  • 1681

Linux下笔记本禁用触摸板

Ubuntu Linux下笔记本禁用触摸板的方法在笔记本电脑上打字,总是不小心碰到触摸板,导致光标乱飞,这种情况如何解决呢?以下是禁用触摸板的方法。 一般情况下,是使用synaptics触摸板驱动。...
  • nancygreen
  • nancygreen
  • 2014-06-02 17:06:28
  • 2124

S3C2410 UART驱动

S3C2410 UART的驱动14.7.1 S3C2410串口硬件描述    S3C2410 内部具有3个独立的UART控制器,每个控制器都可以工作在Interrupt(中断)模式或DMA(直接内存访...
  • wyl123
  • wyl123
  • 2009-10-29 10:23:00
  • 2849

所有笔记本通用触摸板驱动

  • 2012年09月22日 20:50
  • 45.89MB
  • 下载

s3c2410+linux通过SPI驱动双数码管参考代码

学习了一段时间的嵌入式系统了,感觉它的复杂就体现在要和硬件打交道并且还要在操作系统中控制硬件。开发板上有一个实例,我把它改了一下便于理解,以作为以后学习的参考。        本人描述能力差,还是直...
  • zgrjkflmkyc
  • zgrjkflmkyc
  • 2013-02-25 19:12:28
  • 2035

关于无法连接至synaptics定点装置驱动程序

"开始“--”运行“--regedit(打开注册表)--依次打开  HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVERSION/Run ...
  • xiayezuixing
  • xiayezuixing
  • 2016-10-20 16:30:42
  • 1701
收藏助手
不良信息举报
您举报文章:s3c2410触摸板的驱动程序
举报原因:
原因补充:

(最多只允许输入30个字)