zForce红外触屏处理芯片驱动分析

本文主要分析zForce红外触屏处理芯片在Linux系统的驱动实现。内容涉及硬件接口、I2C通信协议以及触屏模块的硬件和软件适配修改,包括设置IRQ、GPIO中断和I2C3的对接。驱动工作流程包括中断上下半部处理和内核线程同步。

zForce红外触屏处理芯片驱动源码有两套,分别为linux&Android、wince系统实现。

我用的是linux系统,应用不是QT实现的,界面都是opengl实现,所以,要自行处理触屏输入控制。

linux的触屏驱动使用了input子系统,前一天已经做了一个基本学习,现在分析一下驱动实现。


硬件接口:

IR触屏使用I2C访问,有数据时,DATAREADY会置低,3.3V供电,PIN10接地。

I2C访问不是一般器件的寄存器式的读写操作,而是基于zForce的通信协议访问。

测试时可以参考zForce的通信协议说明,实际驱动已经实现所有协议内容,不做具体分析。

触屏模块硬件和软件适配修改有:

1. 需要提供一个IRQ,连接DATAREADY

我的板子上用的是GPIO的IRQ,需要初始化GPIO pin mux,输入和中断使能,下降沿触发(以后再具体分析GPIO的驱动架构)

2. 对接I2C3

使用TI的芯片,其linux内核中I2C的驱动使用的是new style驱动模型。

在I2C模块,修改全局变量:

static struct i2c_board_info __initdata ti814x_i2c_boardinfo1[] = {
	{
        .type = "zforce",
        .addr  = 0x50,// zForce I2C address
        .irq  = 200,  // gpio irq number
	},
};
I2C初始化函数中增加:

omap_register_i2c_bus(3, 100, ti814x_i2c_boardinfo1,ARRAY_SIZE(ti814x_i2c_boardinfo1));
这个函数是由CPU提供商实现,作用是用new style方式注册I2C总线及设备,具体实现以后分析。

zForce模块初始化函数调用

static struct i2c_driver zforce_ts_driver =
{
    .driver = { 
        .name = "zforce",
        .owner = THIS_MODULE,
    },
    .probe = zforce_ts_probe,
    .remove = zforce_ts_remove,
    .suspend = zforce_ts_suspend,
    .resume = zforce_ts_resume,
    .id_table = zforce_ts_id,
};
i2c_add_driver ( &zforce_ts_driver );
driver和device匹配,OS会调用driver的probe函数:zforce_ts_probe

配置input参数:

    dev_set_drvdata ( &client->dev, priv );

    input = input_allocate_device();
    if ( !input )
    {
        dev_err ( &client->dev, "Failed to allocate input device.\n" );
        error = -ENOMEM;
        goto err1;
    }

    input->evbit[0] = BIT_MASK ( EV_KEY ) | BIT_MASK ( EV_ABS );
    input->keybit[BIT_WORD ( BTN_TOUCH )] = BIT_MASK ( BTN_TOUCH );

    // Setup the coordinate system (span from 0 to MAX in both axis)

    input_set_abs_params( input, ABS_MT_TOUCH_MAJOR, 0, 0xFF, 0, 0);
    input_set_abs_params( input, ABS_MT_TOUCH_MINOR, 0, 0xFF, 0, 0);
    input_set_abs_params( input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
    input_set_abs_params( input, ABS_MT_TRACKING_ID, 0, 0XFFF, 0, 0);
    
    input_set_abs_params ( input, ABS_MT_POSITION_X, 0, MAX_X, 0, 0 );
    input_set_abs_params ( input, ABS_MT_POSITION_Y, 0, MAX_Y, 0, 0 );
    
    input_mt_create_slots( input, MAX_COORDS);

    input->name = client->name;
    input->id.bustype = BUS_I2C;
    input->dev.parent = &client->dev;

    input_set_drvdata ( input, priv );

    error = input_register_device ( input );
配置中断和中断处理函数:

    INIT_DELAYED_WORK ( &priv->work, zforce_ts_isr_bh );
    init_completion ( &priv->complete );
    error = request_irq ( priv->irq, zforce_ts_isr_th, IRQF_TRIGGER_LOW, client->name, priv );
这里使用:

1.工作队列实现中断的上下半部分处理,

2.完成量实现内核线程同步。

最终,驱动获取触屏信息后:

    for ( ; i < numberOfTouches; ++i )
    {
        priv->tInfo[i].id -= 1;
        input_mt_slot( priv->input, priv->tInfo[i].id);
        /* Report input */
        if ( ( priv->tInfo[i].state == 0 ) || ( priv->tInfo[i].state == 1 ) )
        {
            input_event( priv->input, EV_ABS, ABS_MT_TRACKING_ID, priv->tInfo[i].id );
            priv->tInfo[i].x = MAX_X - ( ( scaledMax_X  / ( priv->width ) ) * ( priv->tInfo[i].x ) ) >> 16;
            priv->tInfo[i].y = MAX_Y - ( ( scaledMax_Y / ( priv->height ) ) * ( priv->tInfo[i].y ) ) >> 16;
            input_event( priv->input, EV_ABS, ABS_MT_POSITION_X, priv->tInfo[i].x );
            input_event( priv->input, EV_ABS, ABS_MT_POSITION_Y, priv->tInfo[i].y );   
        }
        else
        {
            input_event( priv->input, EV_ABS, ABS_MT_TRACKING_ID, -1);   
        }
    }
    
    input_event( priv->input, EV_KEY, BTN_TOUCH, 1);
其中,<span style="font-family: Arial, Helvetica, sans-serif;">ABS_MT_TRACKING_ID对应多点触控的不同点ID。</span>






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值