383 lines
12 KiB
C
383 lines
12 KiB
C
/*
|
|
*
|
|
* FocalTech ftxxxx TouchScreen driver.
|
|
*
|
|
* Copyright (c) 2012-2018, 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_ex_mode.c
|
|
*
|
|
* Author: Focaltech Driver Team
|
|
*
|
|
* Created: 2016-08-31
|
|
*
|
|
* Abstract:
|
|
*
|
|
* Reference:
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
* 1.Included header files
|
|
*****************************************************************************/
|
|
#include "focaltech_core.h"
|
|
|
|
/*****************************************************************************
|
|
* 2.Private constant and macro definitions using #define
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
* 3.Private enumerations, structures and unions using typedef
|
|
*****************************************************************************/
|
|
struct fts_mode_flag {
|
|
int fts_glove_mode_flag;
|
|
int fts_cover_mode_flag;
|
|
int fts_charger_mode_flag;
|
|
};
|
|
|
|
struct fts_mode_flag g_fts_mode_flag;
|
|
|
|
/*****************************************************************************
|
|
* 4.Static variables
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
* 5.Global variable or extern global variabls/functions
|
|
*****************************************************************************/
|
|
int fts_enter_glove_mode(struct i2c_client *client, int mode );
|
|
int fts_enter_cover_mode(struct i2c_client *client, int mode );
|
|
int fts_enter_charger_mode(struct i2c_client *client, int mode );
|
|
|
|
/*****************************************************************************
|
|
* 6.Static function prototypes
|
|
*******************************************************************************/
|
|
|
|
#if FTS_GLOVE_EN
|
|
static ssize_t fts_touch_glove_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
int count;
|
|
u8 val;
|
|
struct input_dev *input_dev = fts_data->input_dev;
|
|
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
|
|
|
|
mutex_lock(&input_dev->mutex);
|
|
fts_i2c_read_reg(client, FTS_REG_GLOVE_MODE_EN, &val);
|
|
count = snprintf(buf, PAGE_SIZE, "Glove Mode: %s\n", g_fts_mode_flag.fts_glove_mode_flag ? "On" : "Off");
|
|
count += snprintf(buf + count, PAGE_SIZE, "Glove Reg(0xC0) = %d\n", val);
|
|
mutex_unlock(&input_dev->mutex);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t fts_touch_glove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
int ret;
|
|
struct fts_ts_data *ts_data = fts_data;
|
|
struct i2c_client *client;
|
|
|
|
|
|
client = ts_data->client;
|
|
if (FTS_SYSFS_ECHO_ON(buf)) {
|
|
if (!g_fts_mode_flag.fts_glove_mode_flag) {
|
|
FTS_INFO("[Mode]enter glove mode");
|
|
ret = fts_enter_glove_mode(client, true);
|
|
if (ret >= 0) {
|
|
g_fts_mode_flag.fts_glove_mode_flag = true;
|
|
}
|
|
}
|
|
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
|
|
if (g_fts_mode_flag.fts_glove_mode_flag) {
|
|
FTS_INFO("[Mode]exit glove mode");
|
|
ret = fts_enter_glove_mode(client, false);
|
|
if (ret >= 0) {
|
|
g_fts_mode_flag.fts_glove_mode_flag = false;
|
|
}
|
|
}
|
|
}
|
|
FTS_INFO("[Mode]glove mode status: %d", g_fts_mode_flag.fts_glove_mode_flag);
|
|
return count;
|
|
}
|
|
|
|
/************************************************************************
|
|
* Name: fts_enter_glove_mode
|
|
* Brief: change glove mode
|
|
* Input: glove mode
|
|
* Output: no
|
|
* Return: success >=0, otherwise failed
|
|
***********************************************************************/
|
|
int fts_enter_glove_mode( struct i2c_client *client, int mode)
|
|
{
|
|
int ret = 0;
|
|
static u8 buf_addr[2] = { 0 };
|
|
static u8 buf_value[2] = { 0 };
|
|
buf_addr[0] = FTS_REG_GLOVE_MODE_EN; /* glove control */
|
|
|
|
if (mode)
|
|
buf_value[0] = 0x01;
|
|
else
|
|
buf_value[0] = 0x00;
|
|
|
|
ret = fts_i2c_write_reg( client, buf_addr[0], buf_value[0]);
|
|
if (ret < 0) {
|
|
FTS_ERROR("[Mode]fts_enter_glove_mode write value fail");
|
|
}
|
|
|
|
return ret ;
|
|
|
|
}
|
|
|
|
/* read and write glove mode
|
|
* read example: cat fts_touch_glove_mode---read glove mode
|
|
* write example:echo 01 > fts_touch_glove_mode ---write glove mode to 01
|
|
*
|
|
*/
|
|
static DEVICE_ATTR (fts_glove_mode, S_IRUGO | S_IWUSR, fts_touch_glove_show, fts_touch_glove_store);
|
|
|
|
#endif
|
|
|
|
#if FTS_COVER_EN
|
|
static ssize_t fts_touch_cover_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
int count;
|
|
u8 val;
|
|
struct input_dev *input_dev = fts_data->input_dev;
|
|
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
|
|
|
|
mutex_lock(&input_dev->mutex);
|
|
fts_i2c_read_reg(client, FTS_REG_COVER_MODE_EN, &val);
|
|
count = snprintf(buf, PAGE_SIZE, "Cover Mode: %s\n", g_fts_mode_flag.fts_cover_mode_flag ? "On" : "Off");
|
|
count += snprintf(buf + count, PAGE_SIZE, "Cover Reg(0xC1) = %d\n", val);
|
|
mutex_unlock(&input_dev->mutex);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t fts_touch_cover_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
int ret;
|
|
struct fts_ts_data *ts_data = fts_data;
|
|
struct i2c_client *client;
|
|
|
|
client = ts_data->client;
|
|
if (FTS_SYSFS_ECHO_ON(buf)) {
|
|
if (!g_fts_mode_flag.fts_cover_mode_flag) {
|
|
FTS_INFO("[Mode]enter cover mode");
|
|
ret = fts_enter_cover_mode(client, true);
|
|
if (ret >= 0) {
|
|
g_fts_mode_flag.fts_cover_mode_flag = true;
|
|
}
|
|
}
|
|
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
|
|
if (g_fts_mode_flag.fts_cover_mode_flag) {
|
|
FTS_INFO("[Mode]exit cover mode");
|
|
ret = fts_enter_cover_mode(client, false);
|
|
if (ret >= 0) {
|
|
g_fts_mode_flag.fts_cover_mode_flag = false;
|
|
}
|
|
}
|
|
}
|
|
FTS_INFO("[Mode]cover mode status: %d", g_fts_mode_flag.fts_cover_mode_flag);
|
|
return count;
|
|
}
|
|
|
|
/************************************************************************
|
|
* Name: fts_enter_cover_mode
|
|
* Brief: change cover mode
|
|
* Input: cover mode
|
|
* Output: no
|
|
* Return: success >=0, otherwise failed
|
|
***********************************************************************/
|
|
int fts_enter_cover_mode( struct i2c_client *client, int mode)
|
|
{
|
|
int ret = 0;
|
|
static u8 buf_addr[2] = { 0 };
|
|
static u8 buf_value[2] = { 0 };
|
|
buf_addr[0] = FTS_REG_COVER_MODE_EN; /* cover control */
|
|
|
|
if (mode)
|
|
buf_value[0] = 0x01;
|
|
else
|
|
buf_value[0] = 0x00;
|
|
|
|
ret = fts_i2c_write_reg( client, buf_addr[0], buf_value[0]);
|
|
if (ret < 0) {
|
|
FTS_ERROR("[Mode] fts_enter_cover_mode write value fail \n");
|
|
}
|
|
|
|
return ret ;
|
|
|
|
}
|
|
|
|
/* read and write cover mode
|
|
* read example: cat fts_touch_cover_mode---read cover mode
|
|
* write example:echo 01 > fts_touch_cover_mode ---write cover mode to 01
|
|
*
|
|
*/
|
|
static DEVICE_ATTR (fts_cover_mode, S_IRUGO | S_IWUSR, fts_touch_cover_show, fts_touch_cover_store);
|
|
|
|
#endif
|
|
|
|
#if FTS_CHARGER_EN
|
|
static ssize_t fts_touch_charger_show(struct device *dev, struct device_attribute *attr, char *buf)
|
|
{
|
|
int count;
|
|
u8 val;
|
|
struct input_dev *input_dev = fts_data->input_dev;
|
|
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
|
|
|
|
mutex_lock(&input_dev->mutex);
|
|
fts_i2c_read_reg(client, FTS_REG_CHARGER_MODE_EN, &val);
|
|
count = snprintf(buf, PAGE_SIZE, "Charge Mode: %s\n", g_fts_mode_flag.fts_charger_mode_flag ? "On" : "Off");
|
|
count += snprintf(buf + count, PAGE_SIZE, "Charge Reg(0x8B) = %d\n", val);
|
|
mutex_unlock(&input_dev->mutex);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t fts_touch_charger_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
int ret;
|
|
struct fts_ts_data *ts_data = fts_data;
|
|
struct i2c_client *client;
|
|
|
|
client = ts_data->client;
|
|
|
|
if (FTS_SYSFS_ECHO_ON(buf)) {
|
|
if (!g_fts_mode_flag.fts_charger_mode_flag) {
|
|
FTS_INFO("[Mode]enter charger mode");
|
|
ret = fts_enter_charger_mode(client, true);
|
|
if (ret >= 0) {
|
|
g_fts_mode_flag.fts_charger_mode_flag = true;
|
|
}
|
|
}
|
|
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
|
|
if (g_fts_mode_flag.fts_charger_mode_flag) {
|
|
FTS_INFO("[Mode]exit charger mode");
|
|
ret = fts_enter_charger_mode(client, false);
|
|
if (ret >= 0) {
|
|
g_fts_mode_flag.fts_charger_mode_flag = false;
|
|
}
|
|
}
|
|
}
|
|
FTS_INFO("[Mode]charger mode status: %d", g_fts_mode_flag.fts_charger_mode_flag);
|
|
return count;
|
|
}
|
|
|
|
/************************************************************************
|
|
* Name: fts_enter_charger_mode
|
|
* Brief: change charger mode
|
|
* Input: charger mode
|
|
* Output: no
|
|
* Return: success >=0, otherwise failed
|
|
***********************************************************************/
|
|
int fts_enter_charger_mode(struct i2c_client *client, int mode)
|
|
{
|
|
int ret = 0;
|
|
static u8 buf_addr[2] = { 0 };
|
|
static u8 buf_value[2] = { 0 };
|
|
buf_addr[0] = FTS_REG_CHARGER_MODE_EN; /* charger control */
|
|
|
|
if (mode)
|
|
buf_value[0] = 0x01;
|
|
else
|
|
buf_value[0] = 0x00;
|
|
|
|
ret = fts_i2c_write_reg( client, buf_addr[0], buf_value[0]);
|
|
if (ret < 0) {
|
|
FTS_DEBUG("[Mode]fts_enter_charger_mode write value fail");
|
|
}
|
|
|
|
return ret ;
|
|
|
|
}
|
|
|
|
/* read and write charger mode
|
|
* read example: cat fts_touch_charger_mode---read charger mode
|
|
* write example:echo 01 > fts_touch_charger_mode ---write charger mode to 01
|
|
*
|
|
*/
|
|
static DEVICE_ATTR (fts_charger_mode, S_IRUGO | S_IWUSR, fts_touch_charger_show, fts_touch_charger_store);
|
|
|
|
#endif
|
|
|
|
static struct attribute *fts_touch_mode_attrs[] = {
|
|
#if FTS_GLOVE_EN
|
|
&dev_attr_fts_glove_mode.attr,
|
|
#endif
|
|
|
|
#if FTS_COVER_EN
|
|
&dev_attr_fts_cover_mode.attr,
|
|
#endif
|
|
|
|
#if FTS_CHARGER_EN
|
|
&dev_attr_fts_charger_mode.attr,
|
|
#endif
|
|
|
|
NULL,
|
|
};
|
|
|
|
static struct attribute_group fts_touch_mode_group = {
|
|
.attrs = fts_touch_mode_attrs,
|
|
};
|
|
|
|
int fts_ex_mode_init(struct i2c_client *client)
|
|
{
|
|
int err = 0;
|
|
|
|
g_fts_mode_flag.fts_glove_mode_flag = false;
|
|
g_fts_mode_flag.fts_cover_mode_flag = false;
|
|
g_fts_mode_flag.fts_charger_mode_flag = false;
|
|
|
|
err = sysfs_create_group(&client->dev.kobj, &fts_touch_mode_group);
|
|
if (0 != err) {
|
|
FTS_ERROR("[Mode]create sysfs failed.");
|
|
sysfs_remove_group(&client->dev.kobj, &fts_touch_mode_group);
|
|
return -EIO;
|
|
} else {
|
|
FTS_DEBUG("[Mode]create sysfs succeeded");
|
|
}
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
int fts_ex_mode_exit(struct i2c_client *client)
|
|
{
|
|
sysfs_remove_group(&client->dev.kobj, &fts_touch_mode_group);
|
|
return 0;
|
|
}
|
|
|
|
int fts_ex_mode_recovery(struct i2c_client *client)
|
|
{
|
|
int ret = 0;
|
|
#if FTS_GLOVE_EN
|
|
if (g_fts_mode_flag.fts_glove_mode_flag)
|
|
ret = fts_enter_glove_mode(client, true);
|
|
#endif
|
|
|
|
#if FTS_COVER_EN
|
|
if (g_fts_mode_flag.fts_cover_mode_flag)
|
|
ret = fts_enter_cover_mode(client, true);
|
|
#endif
|
|
|
|
#if FTS_CHARGER_EN
|
|
if (g_fts_mode_flag.fts_charger_mode_flag)
|
|
ret = fts_enter_charger_mode(client, true);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|