blob: 9faabb8681bb79317aec54aed1b4d7d8160d578b [file] [log] [blame]
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2010-2016, Focaltech Ltd. All rights reserved.
*
* 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.
*
*/
/*****************************************************************************
*
* File Name: focaltech_gestrue.c
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-08
*
* Abstract:
*
* Reference:
*
*****************************************************************************/
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "focaltech_core.h"
#if FTS_GESTURE_EN
/******************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define KEY_GESTURE_U KEY_U
#define KEY_GESTURE_UP KEY_UP
#define KEY_GESTURE_DOWN KEY_DOWN
#define KEY_GESTURE_LEFT KEY_LEFT
#define KEY_GESTURE_RIGHT KEY_RIGHT
#define KEY_GESTURE_O KEY_O
#define KEY_GESTURE_E KEY_E
#define KEY_GESTURE_M KEY_M
#define KEY_GESTURE_L KEY_L
#define KEY_GESTURE_W KEY_W
#define KEY_GESTURE_S KEY_S
#define KEY_GESTURE_V KEY_V
#define KEY_GESTURE_C KEY_C
#define KEY_GESTURE_Z KEY_Z
#define GESTURE_LEFT 0x20
#define GESTURE_RIGHT 0x21
#define GESTURE_UP 0x22
#define GESTURE_DOWN 0x23
#define GESTURE_DOUBLECLICK 0x24
#define GESTURE_O 0x30
#define GESTURE_W 0x31
#define GESTURE_M 0x32
#define GESTURE_E 0x33
#define GESTURE_L 0x44
#define GESTURE_S 0x46
#define GESTURE_V 0x54
#define GESTURE_Z 0x41
#define GESTURE_C 0x34
#define FTS_GESTRUE_POINTS 255
#define FTS_GESTRUE_POINTS_HEADER 8
#define FTS_GESTURE_OUTPUT_ADRESS 0xD3
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
struct fts_gesture_st {
u8 header[FTS_GESTRUE_POINTS_HEADER];
u16 coordinate_x[FTS_GESTRUE_POINTS];
u16 coordinate_y[FTS_GESTRUE_POINTS];
u8 mode;
u8 active;
};
/*****************************************************************************
* Static variables
*****************************************************************************/
static struct fts_gesture_st fts_gesture_data;
extern struct fts_ts_data *fts_wq_data;
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
static ssize_t fts_gesture_show(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t fts_gesture_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count);
static ssize_t fts_gesture_buf_show(struct device *dev,
struct device_attribute *attr, char *buf);
static ssize_t fts_gesture_buf_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count);
/* sysfs gesture node
* read example: cat fts_gesture_mode ---read gesture mode
* write example:echo 01 > fts_gesture_mode ---write gesture mode to 01
*
*/
static DEVICE_ATTR(fts_gesture_mode, S_IRUGO | S_IWUSR, fts_gesture_show,
fts_gesture_store);
/*
* read example: cat fts_gesture_buf ---read gesture buf
*/
static DEVICE_ATTR(fts_gesture_buf, S_IRUGO | S_IWUSR, fts_gesture_buf_show,
fts_gesture_buf_store);
static struct attribute *fts_gesture_mode_attrs[] = {
&dev_attr_fts_gesture_mode.attr,
&dev_attr_fts_gesture_buf.attr,
NULL,
};
static struct attribute_group fts_gesture_group = {
.attrs = fts_gesture_mode_attrs,
};
/************************************************************************
* Name: fts_gesture_show
* Brief: no
* Input: device, device attribute, char buf
* Output: no
* Return:
***********************************************************************/
static ssize_t fts_gesture_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int count;
u8 val;
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
mutex_lock(&fts_input_dev->mutex);
fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &val);
count =
sprintf(buf, "Gesture Mode: %s\n",
fts_gesture_data.mode ? "On" : "Off");
count += sprintf(buf + count, "Reg(0xD0) = %d\n", val);
mutex_unlock(&fts_input_dev->mutex);
return count;
}
/************************************************************************
* Name: fts_gesture_store
* Brief: no
* Input: device, device attribute, char buf, char count
* Output: no
* Return:
***********************************************************************/
static ssize_t fts_gesture_store(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t count)
{
mutex_lock(&fts_input_dev->mutex);
if (FTS_SYSFS_ECHO_ON(buf)) {
FTS_INFO("[GESTURE]enable gesture");
fts_gesture_data.mode = ENABLE;
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
FTS_INFO("[GESTURE]disable gesture");
fts_gesture_data.mode = DISABLE;
}
mutex_unlock(&fts_input_dev->mutex);
return count;
}
/************************************************************************
* Name: fts_gesture_buf_show
* Brief: no
* Input: device, device attribute, char buf
* Output: no
* Return:
***********************************************************************/
static ssize_t fts_gesture_buf_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int count;
int i = 0;
mutex_lock(&fts_input_dev->mutex);
count =
snprintf(buf, PAGE_SIZE, "Gesture ID: 0x%x\n",
fts_gesture_data.header[0]);
count +=
snprintf(buf + count, PAGE_SIZE, "Gesture PointNum: %d\n",
fts_gesture_data.header[1]);
count += snprintf(buf + count, PAGE_SIZE, "Gesture Point Buf:\n");
for (i = 0; i < fts_gesture_data.header[1]; i++) {
count +=
snprintf(buf + count, PAGE_SIZE, "%3d(%4d,%4d) ", i,
fts_gesture_data.coordinate_x[i],
fts_gesture_data.coordinate_y[i]);
if ((i + 1) % 4 == 0)
count += snprintf(buf + count, PAGE_SIZE, "\n");
}
count += snprintf(buf + count, PAGE_SIZE, "\n");
mutex_unlock(&fts_input_dev->mutex);
return count;
}
/************************************************************************
* Name: fts_gesture_buf_store
* Brief: no
* Input: device, device attribute, char buf, char count
* Output: no
* Return:
***********************************************************************/
static ssize_t fts_gesture_buf_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
/* place holder for future use */
return -EPERM;
}
/*****************************************************************************
* Name: fts_create_gesture_sysfs
* Brief:
* Input:
* Output: None
* Return: 0-success or error
*****************************************************************************/
int fts_create_gesture_sysfs(struct i2c_client *client)
{
int ret = 0;
ret = sysfs_create_group(&client->dev.kobj, &fts_gesture_group);
if (ret != 0) {
FTS_ERROR
("[GESTURE]fts_gesture_mode_group(sysfs) create failed!");
sysfs_remove_group(&client->dev.kobj, &fts_gesture_group);
return ret;
}
return 0;
}
/*****************************************************************************
* Name: fts_gesture_recovery
* Brief: recovery gesture state when reset
* Input:
* Output: None
* Return:
*****************************************************************************/
void fts_gesture_recovery(struct i2c_client *client)
{
if (fts_gesture_data.mode && fts_gesture_data.active) {
fts_i2c_write_reg(client, 0xD1, 0xff);
fts_i2c_write_reg(client, 0xD2, 0xff);
fts_i2c_write_reg(client, 0xD5, 0xff);
fts_i2c_write_reg(client, 0xD6, 0xff);
fts_i2c_write_reg(client, 0xD7, 0xff);
fts_i2c_write_reg(client, 0xD8, 0xff);
fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, ENABLE);
}
}
/*****************************************************************************
* Name: fts_gesture_init
* Brief:
* Input:
* Output: None
* Return: None
*****************************************************************************/
int fts_gesture_init(struct input_dev *input_dev, struct i2c_client *client)
{
FTS_FUNC_ENTER();
input_set_capability(input_dev, EV_KEY, KEY_POWER);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_U);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_UP);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_DOWN);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_LEFT);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_RIGHT);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_O);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_E);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_M);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_L);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_W);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_S);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_V);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_Z);
input_set_capability(input_dev, EV_KEY, KEY_GESTURE_C);
__set_bit(KEY_GESTURE_RIGHT, input_dev->keybit);
__set_bit(KEY_GESTURE_LEFT, input_dev->keybit);
__set_bit(KEY_GESTURE_UP, input_dev->keybit);
__set_bit(KEY_GESTURE_DOWN, input_dev->keybit);
__set_bit(KEY_GESTURE_U, input_dev->keybit);
__set_bit(KEY_GESTURE_O, input_dev->keybit);
__set_bit(KEY_GESTURE_E, input_dev->keybit);
__set_bit(KEY_GESTURE_M, input_dev->keybit);
__set_bit(KEY_GESTURE_W, input_dev->keybit);
__set_bit(KEY_GESTURE_L, input_dev->keybit);
__set_bit(KEY_GESTURE_S, input_dev->keybit);
__set_bit(KEY_GESTURE_V, input_dev->keybit);
__set_bit(KEY_GESTURE_C, input_dev->keybit);
__set_bit(KEY_GESTURE_Z, input_dev->keybit);
fts_create_gesture_sysfs(client);
fts_gesture_data.mode = 0;
fts_gesture_data.active = 0;
FTS_FUNC_EXIT();
return 0;
}
/************************************************************************
* Name: fts_gesture_exit
* Brief: remove sys
* Input: i2c info
* Output: no
* Return: no
***********************************************************************/
int fts_gesture_exit(struct i2c_client *client)
{
sysfs_remove_group(&client->dev.kobj, &fts_gesture_group);
return 0;
}
/*****************************************************************************
* Name: fts_check_gesture
* Brief:
* Input:
* Output: None
* Return: None
*****************************************************************************/
static void fts_check_gesture(struct input_dev *input_dev, int gesture_id)
{
char *envp[2];
int gesture;
FTS_FUNC_ENTER();
switch (gesture_id) {
case GESTURE_LEFT:
envp[0] = "GESTURE=LEFT";
gesture = KEY_GESTURE_LEFT;
break;
case GESTURE_RIGHT:
envp[0] = "GESTURE=RIGHT";
gesture = KEY_GESTURE_RIGHT;
break;
case GESTURE_UP:
envp[0] = "GESTURE=UP";
gesture = KEY_GESTURE_UP;
break;
case GESTURE_DOWN:
envp[0] = "GESTURE=DOWN";
gesture = KEY_GESTURE_DOWN;
break;
case GESTURE_DOUBLECLICK:
envp[0] = "GESTURE=DOUBLE_CLICK";
gesture = KEY_POWER;
break;
case GESTURE_O:
envp[0] = "GESTURE=O";
gesture = KEY_GESTURE_O;
break;
case GESTURE_W:
envp[0] = "GESTURE=W";
gesture = KEY_GESTURE_W;
break;
case GESTURE_M:
envp[0] = "GESTURE=M";
gesture = KEY_GESTURE_M;
break;
case GESTURE_E:
envp[0] = "GESTURE=E";
gesture = KEY_GESTURE_E;
break;
case GESTURE_L:
envp[0] = "GESTURE=L";
gesture = KEY_GESTURE_L;
break;
case GESTURE_S:
envp[0] = "GESTURE=S";
gesture = KEY_GESTURE_S;
break;
case GESTURE_V:
envp[0] = "GESTURE=V";
gesture = KEY_GESTURE_V;
break;
case GESTURE_Z:
envp[0] = "GESTURE=Z";
gesture = KEY_GESTURE_Z;
break;
case GESTURE_C:
envp[0] = "GESTURE=C";
gesture = KEY_GESTURE_C;
break;
default:
envp[0] = "GESTURE=NONE";
gesture = -1;
break;
}
FTS_DEBUG("envp[0]: %s", envp[0]);
/* report event key */
/*if (gesture != -1)
{
input_report_key(input_dev, gesture, 1);
input_sync(input_dev);
input_report_key(input_dev, gesture, 0);
input_sync(input_dev);
} */
envp[1] = NULL;
kobject_uevent_env(&fts_wq_data->client->dev.kobj, KOBJ_CHANGE, envp);
sysfs_notify(&fts_wq_data->client->dev.kobj, NULL, "GESTURE_ID");
FTS_FUNC_EXIT();
}
/************************************************************************
* Name: fts_gesture_readdata
* Brief: read data from TP register
* Input: no
* Output: no
* Return: fail <0
***********************************************************************/
static int fts_gesture_read_buffer(struct i2c_client *client, u8 *buf,
int read_bytes)
{
int remain_bytes;
int ret;
int i;
if (read_bytes <= I2C_BUFFER_LENGTH_MAXINUM) {
ret = fts_i2c_read(client, buf, 1, buf, read_bytes);
} else {
ret =
fts_i2c_read(client, buf, 1, buf,
I2C_BUFFER_LENGTH_MAXINUM);
remain_bytes = read_bytes - I2C_BUFFER_LENGTH_MAXINUM;
for (i = 1; remain_bytes > 0; i++) {
if (remain_bytes <= I2C_BUFFER_LENGTH_MAXINUM)
ret =
fts_i2c_read(client, buf, 0,
buf +
I2C_BUFFER_LENGTH_MAXINUM * i,
remain_bytes);
else
ret =
fts_i2c_read(client, buf, 0,
buf +
I2C_BUFFER_LENGTH_MAXINUM * i,
I2C_BUFFER_LENGTH_MAXINUM);
remain_bytes -= I2C_BUFFER_LENGTH_MAXINUM;
}
}
return ret;
}
/************************************************************************
* Name: fts_gesture_readdata
* Brief: read data from TP register
* Input: no
* Output: no
* Return: fail <0
***********************************************************************/
int fts_gesture_readdata(struct i2c_client *client)
{
u8 buf[FTS_GESTRUE_POINTS * 4] = { 0 };
int ret = -1;
int i = 0;
int gestrue_id = 0;
int read_bytes = 0;
u8 pointnum;
FTS_FUNC_ENTER();
/* init variable before read gesture point */
memset(fts_gesture_data.header, 0, FTS_GESTRUE_POINTS_HEADER);
memset(fts_gesture_data.coordinate_x, 0,
FTS_GESTRUE_POINTS * sizeof(u16));
memset(fts_gesture_data.coordinate_y, 0,
FTS_GESTRUE_POINTS * sizeof(u16));
buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
ret = fts_i2c_read(client, buf, 1, buf, FTS_GESTRUE_POINTS_HEADER);
if (ret < 0) {
FTS_ERROR("[GESTURE]Read gesture header data failed!!");
FTS_FUNC_EXIT();
return ret;
}
/* FW recognize gesture */
if (chip_types.chip_idh == 0x54 || chip_types.chip_idh == 0x58
|| chip_types.chip_idh == 0x86 || chip_types.chip_idh == 0x87
|| chip_types.chip_idh == 0x64) {
memcpy(fts_gesture_data.header, buf, FTS_GESTRUE_POINTS_HEADER);
gestrue_id = buf[0];
pointnum = buf[1];
read_bytes = ((int)pointnum) * 4 + 2;
buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
FTS_DEBUG("[GESTURE]PointNum=%d", pointnum);
ret = fts_gesture_read_buffer(client, buf, read_bytes);
if (ret < 0) {
FTS_ERROR("[GESTURE]Read gesture touch data failed!!");
FTS_FUNC_EXIT();
return ret;
}
fts_check_gesture(fts_input_dev, gestrue_id);
for (i = 0; i < pointnum; i++) {
fts_gesture_data.coordinate_x[i] =
(((s16) buf[0 + (4 * i + 2)]) & 0x0F) << 8 |
(((s16) buf[1 + (4 * i + 2)]) & 0xFF);
fts_gesture_data.coordinate_y[i] =
(((s16) buf[2 + (4 * i + 2)]) & 0x0F) << 8 |
(((s16) buf[3 + (4 * i + 2)]) & 0xFF);
}
FTS_FUNC_EXIT();
return 0;
}
/* other IC's gestrue in driver */
if (0x24 == buf[0]) {
gestrue_id = 0x24;
fts_check_gesture(fts_input_dev, gestrue_id);
FTS_DEBUG("[GESTURE]%d check_gesture gestrue_id", gestrue_id);
FTS_FUNC_EXIT();
return -1;
}
/* Host Driver recognize gesture */
pointnum = buf[1];
read_bytes = ((int)pointnum) * 4 + 2;
buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
ret = fts_gesture_read_buffer(client, buf, read_bytes);
if (ret < 0) {
FTS_ERROR ("[GESTURE]Driver recognize gesture -"
"Read gesture touch data failed!!");
FTS_FUNC_EXIT();
return ret;
}
/*
* Host Driver recognize gesture, need gesture lib.a
* Not use now for compatibility
gestrue_id = fetch_object_sample(buf, pointnum);
*/
gestrue_id = 0x24;
fts_check_gesture(fts_input_dev, gestrue_id);
FTS_DEBUG("[GESTURE]%d read gestrue_id", gestrue_id);
for (i = 0; i < pointnum; i++) {
fts_gesture_data.coordinate_x[i] =
(((s16) buf[0 + (4 * i + 8)]) & 0x0F) << 8 |
(((s16) buf[1 + (4 * i + 8)]) & 0xFF);
fts_gesture_data.coordinate_y[i] =
(((s16) buf[2 + (4 * i + 8)]) & 0x0F) << 8 |
(((s16) buf[3 + (4 * i + 8)]) & 0xFF);
}
FTS_FUNC_EXIT();
return -1;
}
/*****************************************************************************
* Name: fts_gesture_suspend
* Brief:
* Input:
* Output: None
* Return: None
*****************************************************************************/
int fts_gesture_suspend(struct i2c_client *i2c_client)
{
int i;
u8 state;
FTS_FUNC_ENTER();
/* gesture not enable, return immediately */
if (fts_gesture_data.mode == 0) {
FTS_DEBUG("gesture is disabled");
FTS_FUNC_EXIT();
return -1;
}
for (i = 0; i < 5; i++) {
fts_i2c_write_reg(i2c_client, 0xd1, 0xff);
fts_i2c_write_reg(i2c_client, 0xd2, 0xff);
fts_i2c_write_reg(i2c_client, 0xd5, 0xff);
fts_i2c_write_reg(i2c_client, 0xd6, 0xff);
fts_i2c_write_reg(i2c_client, 0xd7, 0xff);
fts_i2c_write_reg(i2c_client, 0xd8, 0xff);
fts_i2c_write_reg(i2c_client, FTS_REG_GESTURE_EN, 0x01);
msleep(1);
fts_i2c_read_reg(i2c_client, FTS_REG_GESTURE_EN, &state);
if (state == 1)
break;
}
if (i >= 5) {
FTS_ERROR("[GESTURE]Enter into gesture(suspend) failed!\n");
FTS_FUNC_EXIT();
return -1;
}
fts_gesture_data.active = 1;
FTS_DEBUG("[GESTURE]Enter into gesture(suspend) successfully!");
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Name: fts_gesture_resume
* Brief:
* Input:
* Output: None
* Return: None
*****************************************************************************/
int fts_gesture_resume(struct i2c_client *client)
{
int i;
u8 state;
FTS_FUNC_ENTER();
/* gesture not enable, return immediately */
if (fts_gesture_data.mode == 0) {
FTS_DEBUG("gesture is disabled");
FTS_FUNC_EXIT();
return -1;
}
fts_gesture_data.active = 0;
for (i = 0; i < 5; i++) {
fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, 0x00);
msleep(1);
fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &state);
if (state == 0)
break;
}
if (i >= 5)
FTS_ERROR("[GESTURE]Clear gesture(resume) failed!\n");
FTS_FUNC_EXIT();
return 0;
}
#endif