diff options
Diffstat (limited to 'drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c')
-rw-r--r-- | drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c | 652 |
1 files changed, 652 insertions, 0 deletions
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c b/drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c new file mode 100644 index 000000000000..9faabb8681bb --- /dev/null +++ b/drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c @@ -0,0 +1,652 @@ +/* + * + * 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 |