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

来源:互联网 发布:天地图框架数据标准 编辑:程序博客网 时间:2024/05/17 03:54

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>






0 0
原创粉丝点击