多点触摸参考程序

/* drivers/input/keyboard/synaptics_i2c_rmi.c
*
* Copyright (C) 2007 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
*/
#include <linux/module.h>;
#include <linux/delay.h>;
#include <linux/earlysuspend.h>;
#include <linux/hrtimer.h>;
#include <linux/i2c.h>;
#include <linux/input.h>;
#include <linux/interrupt.h>;
#include <linux/io.h>;
#include <linux/platform_device.h>;
#include <linux/synaptics_i2c_rmi.h>;
#include <asm/gpio.h>;
#include <plat/gpio-cfg.h>;
static struct workqueue_struct *synaptics_wq;
struct synaptics_ts_data {
        uint16_t addr;
        struct i2c_client *client;
        struct input_dev *input_dev;
        int use_irq;
        bool has_relative_report;
        struct hrtimer timer;
        struct work_struct  work;
        uint16_t max[2];
        int snap_state[2][2];
        int snap_down_on[2];
        int snap_down_off[2];
        int snap_up_on[2];
        int snap_up_off[2];
        int snap_down[2];
        int snap_up[2];
        uint32_t flags;
        int reported_finger_count;
        int8_t sensitivity_adjust;
        int (*power)(int on);
        struct early_suspend early_suspend;
};
#ifdef CONFIG_HAS_EARLYSUSPEND
static void synaptics_ts_early_suspend(struct early_suspend *h);
static void synaptics_ts_late_resume(struct early_suspend *h);
#endif
static int synaptics_init_panel(struct synaptics_ts_data *ts)
{
        int ret;
        ret = i2c_smbus_write_byte_data(ts->;client, 0x5b, 0x01);
        if (ret < 0)
                printk(KERN_ERR "i2c_smbus_write_byte_data failed for RESET/n");
        return ret;
}
static void synaptics_ts_work_func(struct work_struct *work)
{
        int i;
        int ret;
        int bad_data = 0;
        struct i2c_msg msg[2];
        uint8_t start_reg;
        uint8_t buf[24];
        struct synaptics_ts_data *ts = container_of(work, struct synaptics_ts_data, work);
        int buf_len = 24;
        int absmark=0;
        int fingermark=0;
        long int f1x,f1y,f1wx,f1wy,f1z,f2x,f2y,f2wx,f2wy,f2z;
        int ftemp;

        buf[0] = i2c_smbus_read_byte_data(ts->;client, 0x12);
        buf[1] = i2c_smbus_read_byte_data(ts->;client, 0x13);
        buf[2] = i2c_smbus_read_byte_data(ts->;client, 0x14);
        buf[3] = i2c_smbus_read_byte_data(ts->;client, 0x15);
        buf[4] = i2c_smbus_read_byte_data(ts->;client, 0x16);
        buf[5] = i2c_smbus_read_byte_data(ts->;client, 0x17);
        buf[6] = i2c_smbus_read_byte_data(ts->;client, 0x18);
        buf[7] = i2c_smbus_read_byte_data(ts->;client, 0x19);
        buf[8] = i2c_smbus_read_byte_data(ts->;client, 0x1a);
        buf[9] = i2c_smbus_read_byte_data(ts->;client, 0x1b);
        buf[10] = i2c_smbus_read_byte_data(ts->;client, 0x1c);
        buf[11] = i2c_smbus_read_byte_data(ts->;client, 0x1d);
        buf[12] = i2c_smbus_read_byte_data(ts->;client, 0x1e);
        buf[13] = i2c_smbus_read_byte_data(ts->;client, 0x1f);
        printk(KERN_INFO "M8 READ buf: %X %X %X %X %X %X %X %X %X %X %X %X %X %X/n",
                        buf[0],buf[1],buf[2],buf[3],buf[4],
                        buf[5],buf[6],buf[7],buf[8],buf[9],
                        buf[10],buf[11],buf[12],buf[13]);
        if(buf[2]==4) absmark=1;
        if(buf[3]==0x0a) fingermark=2;
        else if(buf[3]==0x01) fingermark=1;
        else fingermark=0;
        f1x=buf[4];
        f1x=f1x<<4;
        ftemp=(buf[6]&amp;0x0f);
        f1x=f1x+ftemp;
        f1y=buf[5];
        f1y=f1y<<4;
        ftemp=(buf[6]&amp;0xf0)>;>;4;
        f1y=f1y+ftemp;
        f1wx=(buf[7]&amp;0xf0)>;>;4;
        f1wy=(buf[7]&amp;0x0f);
        f1z=buf[8];
        f2x=buf[9];
        f2x=f2x<<4;
        ftemp=(buf[11]&amp;0x0f);
        f2x=f2x+ftemp;
        f2y=buf[10];
        f2y=f2y<<4;
        ftemp=(buf[11]&amp;0xf0)>;>;4;
        f2y=f2y+ftemp;
        f2wx=(buf[12]&amp;0xf0)>;>;4;
        f2wy=(buf[12]&amp;0x0f);
        f2z=buf[13];
        ftemp=f1y;
        f1y=f1x;
        f1x=2872-ftemp;
        ftemp=f2y;
        f2y=f2x;
        f2x=2872-ftemp;

        printk(KERN_INFO "f:%d,1x:%ld,1y:%ld,1wx:%ld,1wy:%ld,1z:%ld,2x:%ld,2y:%ld,2wx:%ld,2wy:%ld,2z:%ld/n",fingermark,f1x,f1y,f1wx,f1wy,f1z,f2x,f2y,f2wx,f2wy,f2z);

    if(fingermark==2)
    {
        input_report_key(ts->;input_dev,ABS_MT_TRACKING_ID,0);
        input_report_abs(ts->;input_dev, ABS_MT_TOUCH_MAJOR, f1z);
        input_report_abs(ts->;input_dev, ABS_MT_POSITION_X, f1x);
        input_report_abs(ts->;input_dev, ABS_MT_POSITION_Y, f1y);
        input_mt_sync(ts->;input_dev);
        input_report_key(ts->;input_dev,ABS_MT_TRACKING_ID,1);
        input_report_abs(ts->;input_dev, ABS_MT_TOUCH_MAJOR, f2z);
        input_report_abs(ts->;input_dev, ABS_MT_POSITION_X, f2x);
        input_report_abs(ts->;input_dev, ABS_MT_POSITION_Y, f2y);
        input_mt_sync(ts->;input_dev)
        input_sync(ts->;input_dev);
    }
    else if(fingermark==1)
    {
        input_report_key(ts->;input_dev,ABS_MT_TRACKING_ID,0);
        input_report_abs(ts->;input_dev, ABS_MT_TOUCH_MAJOR, f1z);
        input_report_abs(ts->;input_dev, ABS_MT_POSITION_X, f1x);
        input_report_abs(ts->;input_dev, ABS_MT_POSITION_Y, f1y);
        input_mt_sync(ts->;input_dev);
        input_sync(ts->;input_dev);
    }
    else
    {
        input_report_abs(ts->;input_dev, ABS_MT_TOUCH_MAJOR, 0);
        input_mt_sync(ts->;input_dev);
        input_sync(ts->;input_dev);
    }


        /*if(f1z)
        {
                input_report_abs(ts->;input_dev, ABS_X, f1x);
                input_report_abs(ts->;input_dev, ABS_Y, f1y);
                input_report_abs(ts->;input_dev, ABS_PRESSURE, f1z);
                if(fingermark==2)
                {
                        input_report_key(ts->;input_dev, BTN_2, 1);
                        input_sync(ts->;input_dev);
                        input_report_abs(ts->;input_dev, ABS_HAT0X, f2x);
                        input_report_abs(ts->;input_dev, ABS_HAT0Y, f2y);
                        input_report_key(ts->;input_dev, BTN_TOUCH, 1);
                }
                else if(fingermark==1)
                {
                        input_report_key(ts->;input_dev, BTN_2, 0);
                        input_report_key(ts->;input_dev, BTN_TOUCH, 1);
                }
                else
                {
                        input_report_key(ts->;input_dev, BTN_TOUCH, 0);
                }
        }
        else
        {
                input_report_key(ts->;input_dev, BTN_TOUCH, 0);
                input_report_abs(ts->;input_dev, ABS_MT_TOUCH_MAJOR, 0);
                input_report_abs(ts->;input_dev, ABS_MT_WIDTH_MAJOR, 0);
                input_report_abs(ts->;input_dev, ABS_MT_POSITION_X, f1x);
                input_report_abs(ts->;input_dev, ABS_MT_POSITION_Y, f1y);
                input_mt_sync(ts->;input_dev);
        }
        input_sync(ts->;input_dev);*/
        if (ts->;use_irq)
                enable_irq(ts->;client->;irq);
}
static enum hrtimer_restart synaptics_ts_timer_func(struct hrtimer *timer)
{
        struct synaptics_ts_data *ts = container_of(timer, struct synaptics_ts_data, timer);
        /* printk("synaptics_ts_timer_func/n"); */
        queue_work(synaptics_wq, &amp;ts->;work);
        hrtimer_start(&amp;ts->;timer, ktime_set(0, 12500000), HRTIMER_MODE_REL);
        return HRTIMER_NORESTART;
}
static irqreturn_t synaptics_ts_irq_handler(int irq, void *dev_id)
{
        struct synaptics_ts_data *ts = dev_id;
        disable_irq_nosync(ts->;client->;irq);
        queue_work(synaptics_wq, &amp;ts->;work);
        return IRQ_HANDLED;
}
static int synaptics_ts_probe(
        struct i2c_client *client, const struct i2c_device_id *id)
{
        struct synaptics_ts_data *ts;
        int ret = 0;
        unsigned long irqflags;
        long int max_x,max_y,max_temp;
        if (!i2c_check_functionality(client->;adapter, I2C_FUNC_I2C)) {
                printk(KERN_ERR "synaptics_ts_probe: need I2C_FUNC_I2C/n");
                ret = -ENODEV;
                goto err_check_functionality_failed;
        }
        ts = kzalloc(sizeof(*ts), GFP_KERNEL);
        if (ts == NULL) {
                ret = -ENOMEM;
                goto err_alloc_data_failed;
        }
        INIT_WORK(&amp;ts->;work, synaptics_ts_work_func);
        ts->;client = client;
        i2c_set_clientdata(client, ts);

        ts->;input_dev = input_allocate_device();
        if (ts->;input_dev == NULL) {
                ret = -ENOMEM;
                printk(KERN_ERR "synaptics_ts_probe: Failed to allocate input device/n");
                goto err_input_dev_alloc_failed;
        }
        ts->;input_dev->;name = "synaptics-rmi-touchscreen";

        set_bit(EV_SYN, ts->;input_dev->;evbit);
        set_bit(EV_KEY, ts->;input_dev->;evbit);
        set_bit(BTN_TOUCH, ts->;input_dev->;keybit);
        set_bit(BTN_2, ts->;input_dev->;keybit);
        set_bit(EV_ABS, ts->;input_dev->;evbit);

        /*max_x = i2c_smbus_read_byte_data(ts->;client, 0x28);
        max_temp = i2c_smbus_read_byte_data(ts->;client, 0x29);
        max_x=max_x+max_temp<<8;
        max_y = i2c_smbus_read_byte_data(ts->;client, 0x2a);
        max_temp = i2c_smbus_read_byte_data(ts->;client, 0x2b);
        max_y=max_y+max_temp<<8;
        printk(KERN_INFO "max_x:%ld,max_y:%ld/n",max_x,max_y);*/
        max_x=0x77b;
        max_y=0xb38;

        input_set_abs_params(ts->;input_dev, ABS_X, 0, max_y, 0, 0);
        input_set_abs_params(ts->;input_dev, ABS_Y, 0, max_x, 0, 0);
        input_set_abs_params(ts->;input_dev, ABS_PRESSURE, 0, 255, 0, 0);
        input_set_abs_params(ts->;input_dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
        input_set_abs_params(ts->;input_dev, ABS_HAT0X, 0, max_y, 0, 0);
        input_set_abs_params(ts->;input_dev, ABS_HAT0Y, 0, max_x, 0, 0);
        input_set_abs_params(ts->;input_dev, ABS_MT_POSITION_X, 0, max_y, 0, 0);
        input_set_abs_params(ts->;input_dev, ABS_MT_POSITION_Y, 0, max_x, 0, 0);
        input_set_abs_params(ts->;input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
        input_set_abs_params(ts->;input_dev, ABS_MT_WIDTH_MAJOR, 0, 15, 0, 0);
        /* ts->;input_dev->;name = ts->;keypad_info->;name; */
        ret = input_register_device(ts->;input_dev);
        if (ret) {
                printk(KERN_ERR "synaptics_ts_probe: Unable to register %s input device/n", ts->;input_dev->;name);
                goto err_input_register_device_failed;
        }
        /*add by meizu to support interrupt mode*/
        s3c_gpio_cfgpin(S3C64XX_GPN(15),S3C_GPIO_SFN(2));
        client->;irq = gpio_to_irq(S3C64XX_GPN(15));
        irqflags = IRQF_TRIGGER_LOW;
        /*add end*/
        if (client->;irq) {
                ret = request_irq(client->;irq, synaptics_ts_irq_handler, irqflags, client->;name, ts);
                #if 0
                if (ret == 0) {
                        ret = i2c_smbus_write_byte_data(ts->;client, 0xf1, 0x01); /* enable abs int */
                        if (ret)
                                free_irq(client->;irq, ts);
                }
                #endif
                if (ret == 0)
                        ts->;use_irq = 1;
                else
                        dev_err(&amp;client->;dev, "request_irq failed/n");
        }
        if (!ts->;use_irq) {
                hrtimer_init(&amp;ts->;timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
                ts->;timer.function = synaptics_ts_timer_func;
                hrtimer_start(&amp;ts->;timer, ktime_set(10, 0), HRTIMER_MODE_REL);
        }
#ifdef CONFIG_HAS_EARLYSUSPEND
        ts->;early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
        ts->;early_suspend.suspend = synaptics_ts_early_suspend;
        ts->;early_suspend.resume = synaptics_ts_late_resume;
        register_early_suspend(&amp;ts->;early_suspend);
#endif
        printk(KERN_INFO "synaptics_ts_probe: Start touchscreen %s in %s mode/n", ts->;input_dev->;name, ts->;use_irq ? "interrupt" : "polling");
        return 0;
err_input_register_device_failed:
        input_free_device(ts->;input_dev);
err_input_dev_alloc_failed:
err_detect_failed:
err_power_failed:
        kfree(ts);
err_alloc_data_failed:
err_check_functionality_failed:
        return ret;
}
static int synaptics_ts_remove(struct i2c_client *client)
{
        struct synaptics_ts_data *ts = i2c_get_clientdata(client);
        unregister_early_suspend(&amp;ts->;early_suspend);
        if (ts->;use_irq)
                free_irq(client->;irq, ts);
        else
                hrtimer_cancel(&amp;ts->;timer);
        input_unregister_device(ts->;input_dev);
        kfree(ts);
        return 0;
}
static int synaptics_ts_suspend(struct i2c_client *client, pm_message_t mesg)
{
        int ret;
        struct synaptics_ts_data *ts = i2c_get_clientdata(client);
        if (ts->;use_irq)
                disable_irq(client->;irq);
        else
                hrtimer_cancel(&amp;ts->;timer);
        ret = cancel_work_sync(&amp;ts->;work);
        if (ret &amp;&amp; ts->;use_irq) /* if work was pending disable-count is now 2 */
                enable_irq(client->;irq);
        ret = i2c_smbus_write_byte_data(ts->;client, 0xf1, 0); /* disable interrupt */
        if (ret < 0)
                printk(KERN_ERR "synaptics_ts_suspend: i2c_smbus_write_byte_data failed/n");
        ret = i2c_smbus_write_byte_data(client, 0xf0, 0x86); /* deep sleep */
        if (ret < 0)
                printk(KERN_ERR "synaptics_ts_suspend: i2c_smbus_write_byte_data failed/n");
        if (ts->;power) {
                ret = ts->;power(0);
                if (ret < 0)
                        printk(KERN_ERR "synaptics_ts_resume power off failed/n");
        }
        return 0;
}
static int synaptics_ts_resume(struct i2c_client *client)
{
        int ret;
        struct synaptics_ts_data *ts = i2c_get_clientdata(client);
        if (ts->;power) {
                ret = ts->;power(1);
                if (ret < 0)
                        printk(KERN_ERR "synaptics_ts_resume power on failed/n");
        }
        synaptics_init_panel(ts);
        if (ts->;use_irq)
                enable_irq(client->;irq);
        if (!ts->;use_irq)
                hrtimer_start(&amp;ts->;timer, ktime_set(1, 0), HRTIMER_MODE_REL);
        else
                i2c_smbus_write_byte_data(ts->;client, 0xf1, 0x01); /* enable abs int */
        return 0;
}
#ifdef CONFIG_HAS_EARLYSUSPEND
static void synaptics_ts_early_suspend(struct early_suspend *h)
{
        struct synaptics_ts_data *ts;
        ts = container_of(h, struct synaptics_ts_data, early_suspend);
        synaptics_ts_suspend(ts->;client, PMSG_SUSPEND);
}
static void synaptics_ts_late_resume(struct early_suspend *h)
{
        struct synaptics_ts_data *ts;
        ts = container_of(h, struct synaptics_ts_data, early_suspend);
        synaptics_ts_resume(ts->;client);
}
#endif
static const struct i2c_device_id synaptics_ts_id[] = {
        { SYNAPTICS_I2C_RMI_NAME, 0 },
        { }
};
static struct i2c_driver synaptics_ts_driver = {
        .probe                = synaptics_ts_probe,
        .remove                = synaptics_ts_remove,
#ifndef CONFIG_HAS_EARLYSUSPEND
        .suspend        = synaptics_ts_suspend,
        .resume                = synaptics_ts_resume,
#endif
        .id_table        = synaptics_ts_id,
        .driver = {
                .name        = SYNAPTICS_I2C_RMI_NAME,
        },
};
static int __devinit synaptics_ts_init(void)
{
        synaptics_wq = create_singlethread_workqueue("synaptics_wq");
        if (!synaptics_wq)
                return -ENOMEM;
        return i2c_add_driver(&amp;synaptics_ts_driver);
}
static void __exit synaptics_ts_exit(void)
{
        i2c_del_driver(&amp;synaptics_ts_driver);
        if (synaptics_wq)
                destroy_workqueue(synaptics_wq);
}
module_init(synaptics_ts_init);
module_exit(synaptics_ts_exit);
MODULE_DESCRIPTION("Synaptics Touchscreen Driver");
MODULE_LICENSE("GPL");

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值