rk3188--6.android 触摸屏驱动分析

在drivers/input/touchscreen/ft5302_tp/ft5302_ts.c中
module_init(ft5x0x_ts_init);
static int __init ft5x0x_ts_init(void)
{
ret = i2c_add_driver(&ft5x0x_ts_driver);
return ret;
}
其中ft5x0x_ts_driver结构如下:
static struct i2c_driver ft5x0x_ts_driver = {
.probe = ft5x0x_ts_probe,
.remove = __devexit_p(ft5x0x_ts_remove),
.id_table = ft5x0x_ts_id,
.driver = {
.name = FT5X0X_NAME,
.owner = THIS_MODULE,
},
};

在probe函数中
static int ft5x0x_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct ft5x0x_ts_dev *ft5x0x_ts;
struct ft5x0x_platform_data *pdata = pdata = client->dev.platform_data;
struct input_dev *input_dev;
u8 buf_w[1];
u8 buf_r[1];
unsigned char reg_value;
unsigned char reg_version;
int result, irq = 0;

ft5x0x_ts = (struct ft5x0x_ts_dev *)kzalloc(sizeof(*ft5x0x_ts), GFP_KERNEL);
input_dev = input_allocate_device();
ft5x0x_ts->input_dev = input_dev;
ft5x0x_ts->client = this_client = client;
ft5x0x_ts->irq = client->irq;

__set_bit(EV_ABS, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(EV_REP, input_dev->evbit);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
set_bit(ABS_MT_POSITION_X, input_dev->absbit);
set_bit(ABS_MT_POSITION_Y, input_dev->absbit);
set_bit(ABS_MT_TOUCH_MAJOR, input_dev->absbit);
set_bit(ABS_MT_WIDTH_MAJOR, input_dev->absbit);

input_mt_init_slots(input_dev, MAX_CONTACTS);

input_set_abs_params(input_dev,ABS_MT_POSITION_X, 0, SCREEN_MAX_X, 0, 0);
input_set_abs_params(input_dev,ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y, 0, 0);
input_set_abs_params(input_dev,ABS_MT_TOUCH_MAJOR, 0, PRESS_MAX, 0, 0);
input_set_abs_params(input_dev,ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);
input_dev->name        = FT5X0X_NAME;
input_register_device(input_dev);

g_dev = ft5x0x_ts;

i2c_set_clientdata(client, ft5x0x_ts);
INIT_WORK(&ft5x0x_ts->pen_event_work, ft5x0x_ts_pen_irq_work);   //动态建立一个工作队列
ft5x0x_ts->ts_workqueue = create_workqueue(FT5X0X_NAME);

ft5x0x_ts->irq = gpio_to_irq(ft5x0x_ts->irq);

err0:
msleep(200);
fts_register_read(FT5X0X_REG_FIRMID, &reg_version,1);
fts_register_read(FT5X0X_REG_REPORT_RATE, &reg_value,1);
fts_register_read(FT5X0X_REG_THRES, &reg_value,1);
fts_register_read(FT5X0X_REG_NOISE_MODE, &reg_value,1);

//注册中断
request_irq(ft5x0x_ts->irq, ft5x0x_ts_interrupt, IRQF_TRIGGER_FALLING, "ft5x0x_ts", ft5x0x_ts);
disable_irq_nosync(g_dev->irq);
//打开中断
enable_irq(g_dev->irq);

return 0;

}
当有按键按下时
static irqreturn_t ft5x0x_ts_interrupt(int irq, void *dev_id)
{
struct ft5x0x_ts_dev *ft5x0x_ts = dev_id;
del_timer(&ft5x0x_ts->timer); //关闭内核定时器
disable_irq_nosync(g_dev->irq); //关中断
queue_work(ft5x0x_ts->ts_workqueue, &ft5x0x_ts->pen_event_work); //把任务交给指定的工作队列
return IRQ_HANDLED;
}
INIT_WORK(&ft5x0x_ts->pen_event_work, ft5x0x_ts_pen_irq_work); //动态建立一个工作队列
进入工作队列处理函数:
static void ft5x0x_ts_pen_irq_work(struct work_struct *work)
{
ft5x0x_read_data();
ft5x0x_report_value();
enable_irq(g_dev->irq);
}

static int ft5x0x_read_data(void)
{
struct ft5x0x_ts_dev *data = i2c_get_clientdata(g_dev->client);
struct ts_event *event = &data->event;
u8 buf[61]= {0};
ret = ft5x0x_i2c_rxdata(buf, 61); //读取数据
memset(event, ~0x00, sizeof(struct ts_event));
event->touch_point = buf[2] & 0x0f; //查看有几个手指按下
if (event->touch_point == 0) { //如果没有手指按下,直接返回
return 0;
}
switch (event->touch_point) { //最多只能看到5个手指
case 5: //将手指的状态与坐标值记录下来
event->point[4].status = (buf[0x1b] & 0xc0)>>6;
event->point[4].id = (buf[0x1d] & 0xf0)>>4;
event->point[4].x = ((s16)(buf[0x1b] & 0x07)<<8 | (s16)buf[0x1c]);
event->point[4].y = (s16)(buf[0x1d] & 0x07)<<8 | (s16)buf[0x1e];
case 4:
case 3:
case 2:
case 1:
event->point[0].status = (buf[0x03] & 0xc0)>>6;
event->point[0].id = (buf[0x05] & 0xf0)>>4;
event->point[0].x= (s16)(buf[0x03] & 0x07)<<8 | (s16)buf[0x04];
event->point[0].y = (s16)(buf[0x05] & 0x07)<<8 | (s16)buf[0x06];
default:
return 0;
}
}

static void ft5x0x_report_value(void)
{
struct ft5x0x_ts_dev *data = i2c_get_clientdata(g_dev->client);
struct ts_event *event = &data->event;
int key_id = 0xff;
down_table = 0;
for(i=0; itouch_point; i++)
{
event->point[i].x=event->point[i].x;
input_mt_slot(data->input_dev, event->point[i].id);

    input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, event->point[i].id);

    down_table |= 1 << event->point[i].id;
    input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR, 100);
    input_report_abs(data->input_dev, ABS_MT_POSITION_X, event->point[i].x);
    input_report_abs(data->input_dev, ABS_MT_POSITION_Y, event->point[i].y);
    input_report_abs(data->input_dev, ABS_MT_WIDTH_MAJOR, 100);
}

for(i=0; i<MAX_CONTACTS; i++) {
    if( ( (~down_table) & 1<<i) && !(up_table & 1<<i) )
    {
        input_mt_slot(data->input_dev, i);
        input_report_abs(data->input_dev, ABS_MT_TRACKING_ID, -1);
    }
}
up_table = ~down_table;
input_sync(data->input_dev);

}

关于内核定时器:
setup_timer(&ft5x0x_ts->timer, Touch_timer_release, (unsigned long)ft5x0x_ts);
data->timer.expires = jiffies +8;
add_timer(&data->timer);
时间一到执行内核定时器处理函数
static void Touch_timer_release(unsigned long ft_ts_pdev)
{
do_something();
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值