/******************************************************************************
Copyright (C), 2015-2025, SHARPNOW Co., Ltd.
*******************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Copyright (C) Juven, 2016
*/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/delay.h>
#define VIDOOTS_DEVICE_NAME "vidoo_ts"
#define WIDTH 1400
#define HEIGHT 2550
#define PERCENT (30*100/1440) //1440*2560
//#define VIDOO_TAP "vidoo_tap"
/* Per-touchscreen data. */
/**
* struct vidoo ts - driver touchscreen state.
* @dev: The device we are bound to.
* @input: The input device we registered with the input subsystem.
* @xp: The accumulated X position data.
* @yp: The accumulated Y position data.
* @count: The number of samples collected.
*/
struct vidoo_ts_info {
struct i2c_client *client;
struct input_dev *input;
unsigned long xp;
unsigned long yp;
int count;
};
static struct input_dev *g_input_dev = NULL;
static struct timer_list s_timer;
#ifdef VIDOO_TAP
static bool g_bHome = true;
#else
static bool g_bLeft = false;
#endif
#ifdef VIDOO_TAP
static void tapTouch(unsigned long ulData);
#else
static void swipeTouch(unsigned long ulData);
static void swipeLeftOrRight(int nX, int nY);
#endif
static void set_timer(void);
static int vidoots_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct input_dev *input_dev;
struct vidoo_ts_info *info;
struct device *dev;
struct device_node *dnode;
int ret = -EINVAL;
pr_info("%s\n", __func__);
info = kzalloc(sizeof(struct vidoo_ts_info), GFP_KERNEL);
input_dev = input_allocate_device();
if (!info || !input_dev) {
dev_err(&client->dev, "%s [ERROR]\n", __func__);
ret = -ENOMEM;
goto err_inputdev;
}
#ifdef CONFIG_OF
dev = &client->dev;
dnode = dev->of_node;
#endif
info->client = client;
info->input = input_dev;
g_input_dev = input_dev;
/*info->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
info->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
input_set_abs_params(info->input, ABS_X, 0, 0x5A0, 0, 0);
input_set_abs_params(info->input, ABS_Y, 0, 0xA00, 0, 0);*/
info->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) | BIT_MASK(EV_SYN);
info->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
__set_bit(INPUT_PROP_DIRECT, info->input->propbit);
input_set_abs_params(info->input, ABS_MT_POSITION_X, 0, 0x5A0, 0, 0);
input_set_abs_params(info->input, ABS_MT_POSITION_Y, 0, 0xA00, 0, 0);
input_set_abs_params(info->input, ABS_MT_WIDTH_MAJOR, 0, 0xff, 0, 0);//255
input_set_abs_params(info->input, ABS_MT_TOUCH_MAJOR, 0, 0xff, 0, 0);
input_set_abs_params(info->input, ABS_MT_TRACKING_ID, 0, 0xffff, 0, 0);
input_set_abs_params(info->input, ABS_MT_SLOT, 0, 9, 0, 0);
info->input->name = VIDOOTS_DEVICE_NAME;
info->input->dev.parent = &client->dev;
info->input->id.bustype = BUS_I2C;
info->input->id.vendor = 0xAABB;
info->input->id.product = 0xCCDD;
info->input->id.version = 0x1222;
input_set_drvdata(input_dev, info);
i2c_set_clientdata(client, info);
pr_info("register vidoo virtual touch: %s\n", VIDOOTS_DEVICE_NAME);
/* All went ok, so register to the input system */
ret = input_register_device(info->input);
if (ret < 0) {
dev_err(dev, "failed to register input device\n");
ret = -EIO;
goto err_inputdev;
}
/* BEGIN: test touch */
set_timer();
dev_info(&client->dev, "Sharpnow " VIDOOTS_DEVICE_NAME " Touchscreen is initialized successfully.\n");
return 0;
err_inputdev:
input_free_device(info->input);
return ret;
}
/**
* vidoots_remove - device core removal entry point
* @pdev: The device we are being removed from.
*
* Free up our state ready to be removed.
*/
static int vidoots_remove(struct i2c_client *client)
{
struct vidoo_ts_info *info = i2c_get_clientdata(client);
input_unregister_device(info->input);
kfree(info);
return 0;
}
/**
* Device tree match table
*/
#ifdef CONFIG_OF
static const struct of_device_id vidoots_match_table[] = {
{ .compatible = "sharpnow,vidoo_ts",},
{},
};
MODULE_DEVICE_TABLE(of, vidoots_match_table);
#endif
/**
* I2C Device ID
*/
static const struct i2c_device_id vidoots_id[] = {
{VIDOOTS_DEVICE_NAME, 0},
};
/**
* I2C driver info
*/
static struct i2c_driver vidoots_driver = {
.id_table = vidoots_id,
.probe = vidoots_probe,
.remove = vidoots_remove,
.driver = {
.name = VIDOOTS_DEVICE_NAME,
.owner = THIS_MODULE,
#ifdef CONFIG_OF
.of_match_table = vidoots_match_table,
#endif
},
};
#ifdef VIDOO_TAP
/*****************************************************************************
Prototype : tapTouch
Description : vidoo Tap func
Input : unsigned long ulData
Output : None
Return Value : static
Calls :
Called By :
History :
1.Date : 2017/1/17
Author : dk
Modification : Created function
*****************************************************************************/
static void tapTouch(/*unsigned long ulData*/)
{
struct input_dev *input_dev = g_input_dev;
int nX = 700;
int nY = 2300;
if(g_bHome)
{
input_report_key(input_dev, BTN_TOUCH, 1);// 1 down,0 up
input_report_abs(input_dev, ABS_MT_POSITION_X, nX);
input_report_abs(input_dev, ABS_MT_POSITION_Y, nY + 200);//go to home
input_sync(input_dev);
input_report_key(input_dev, BTN_TOUCH, 0);// 1 down,0 up
input_sync(input_dev);
pr_info("---report input event---x = %d,----y = %d\n", nX, nY);
g_bHome = false;
}
else
{
input_report_key(input_dev, BTN_TOUCH, 1);// 1 down,0 up
input_report_abs(input_dev, ABS_MT_POSITION_X, nX);
input_report_abs(input_dev, ABS_MT_POSITION_Y, nY);
input_sync(input_dev);
input_report_key(input_dev, BTN_TOUCH, 0);// 1 down,0 up
input_sync(input_dev);
g_bHome = true;
}
s_timer.expires = jiffies + 2*HZ;//2s do
s_timer.function = &tapTouch;//timer handler
add_timer(&s_timer);
}
#else
/*****************************************************************************
Prototype : swipeTouch
Description : vidoo touch swipe
Input : unsigned long ulData
Output : None
Return Value : static
Calls :
Called By :
History :
1.Date : 2017/1/17
Author : dk
Modification : Created function
exmaple:
input_report_key(input_dev, BTN_TOUCH, 1);// 1 down,0 up
input_report_abs(input_dev, ABS_MT_POSITION_X, nX);
input_report_abs(input_dev, ABS_MT_POSITION_Y, nY);
input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 1);
input_report_abs(input_dev, ABS_MT_WIDTH_MAJOR, 1);
input_report_abs(input_dev, ABS_MT_TRACKING_ID, 1);
input_sync(input_dev);
input_report_key(input_dev, BTN_TOUCH, 0);// 1 down,0 up
input_sync(input_dev);
*****************************************************************************/
static void swipeTouch(unsigned long ulData)
{
//struct input_dev *input_dev = g_input_dev;
int nX = 10;//700;//2300;
int nY = 600;//1400;//1200;
//slide to the left or right
swipeLeftOrRight(nX, nY);
s_timer.expires = jiffies + 3*HZ;
s_timer.function = &swipeTouch;
add_timer(&s_timer);
}
static int g_ntracking_id = 0;
static void swipeLeftOrRight(int nX, int nY)
{
struct input_dev *input_dev = g_input_dev;
int j = 0;
int nPrecision = (PERCENT)*(WIDTH)/100;
g_ntracking_id = g_ntracking_id + 1;
input_report_abs(input_dev, ABS_MT_TRACKING_ID, g_ntracking_id);
input_report_key(input_dev, BTN_TOUCH, 1);// 1 down,0 up
pr_info("---report input down\n");
for(j=0; j<100; j++)
{
input_report_abs(input_dev, ABS_MT_POSITION_X, nX);
input_report_abs(input_dev, ABS_MT_POSITION_Y, nY);
//input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR, 5);
//input_report_abs(input_dev, ABS_MT_WIDTH_MAJOR, 5);
//input_report_abs(input_dev, ABS_MT_PRESSURE, 5);
input_sync(input_dev);
if(((nX < WIDTH)&&(nX > 0)) && ((nY < HEIGHT)&&(nY > 0)))//1440*2560
{
(g_bLeft)?(nX = nX - nPrecision):(nX = nX + nPrecision);
//(g_bLeft)?(nY = nY - 10):(nY = nY + 1);
(g_bLeft)?(nY = nY - 10):(nY = nY + 10);
//nX = nX - 200;
//nY = nY - 60;
pr_info("---report input nX: %d, nY: %d, nPrecision:%d\n", nX, nY, nPrecision);
}
}
//(g_bLeft)?(g_bLeft = false):(g_bLeft = true);
input_report_abs(input_dev, ABS_MT_TRACKING_ID, 0xffffffff);
input_report_key(input_dev, BTN_TOUCH, 0);// 1 down,0 up
pr_info("---report input up,g_ntracking_id : %d\n", g_ntracking_id);
input_sync(input_dev);
//test
if(0/*(g_ntracking_id%3) == 0*/)
{
input_report_key(input_dev, BTN_TOUCH, 1);// 1 down,0 up
input_report_abs(input_dev, ABS_MT_POSITION_X, 700);
input_report_abs(input_dev, ABS_MT_POSITION_Y, 2300);//go to home
input_sync(input_dev);
input_report_key(input_dev, BTN_TOUCH, 0);// 1 down,0 up
input_sync(input_dev);
pr_info("-----------------clear view");
if(g_ntracking_id == 12)
g_ntracking_id = 0;
}
}
#endif
static void set_timer(void)
{
init_timer(&s_timer);
s_timer.expires = jiffies + 2*HZ;//2s do
#ifdef VIDOO_TAP
s_timer.function = &tapTouch;//timer handler
#else
s_timer.function = &swipeTouch;
#endif
add_timer(&s_timer);
}
static int __init vidoots_init(void)
{
printk(KERN_ERR "vidoots_init\n");
return i2c_add_driver(&vidoots_driver);
}
static void __exit vidoots_exit(void)
{
printk(KERN_ERR "vidoots_exit\n");
del_timer(&s_timer);/* test */
i2c_del_driver(&vidoots_driver);
}
module_init(vidoots_init);
module_exit(vidoots_exit);
MODULE_AUTHOR("Juven <dk@xx.com>");
MODULE_DESCRIPTION("vidoo Touchscreen driver");
MODULE_LICENSE("GPL v2");
Android 模拟触摸事件I2C driver demo
于 2018-08-06 16:55:31 首次发布