You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
6577 lines
176 KiB
6577 lines
176 KiB
/*
|
|
* Copyright (C) 2010,Imagis Technology Co. Ltd. All Rights Reserved.
|
|
*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
#include <linux/vmalloc.h>
|
|
|
|
#include "ist40xx.h"
|
|
#include "ist40xx_update.h"
|
|
#include "ist40xx_misc.h"
|
|
#include "ist40xx_cmcs.h"
|
|
|
|
#ifdef SEC_FACTORY_MODE
|
|
|
|
#if defined(CONFIG_SEC_SYSFS)
|
|
#include <linux/sec_sysfs.h>
|
|
#elif defined(CONFIG_DRV_SAMSUNG)
|
|
#endif
|
|
|
|
#define COMMAND_LENGTH (64)
|
|
#define FACTORY_BUF_SIZE PAGE_SIZE
|
|
#define BUILT_IN (0)
|
|
#define UMS (1)
|
|
|
|
#define TSP_CH_UNKNOWN (0)
|
|
#define TSP_CH_UNUSED (1)
|
|
#define TSP_CH_USED (2)
|
|
|
|
#define ORIGIN_ARRAY { LTR_TTB, TTB_LTR, RTL_TTB, TTB_RTL, \
|
|
LTR_BTT, BTT_LTR, RTL_TTB, BTT_RTL }
|
|
|
|
int ist40xx_origin_value[ORI_MAX] = ORIGIN_ARRAY;
|
|
|
|
u32 ist40xx_get_fw_ver(struct ist40xx_data *data)
|
|
{
|
|
u32 ver = 0;
|
|
int ret = 0;
|
|
|
|
ret = ist40xx_read_cmd(data, eHCOM_GET_VER_FW, &ver);
|
|
if (ret) {
|
|
ist40xx_reset(data, false);
|
|
ist40xx_start(data);
|
|
|
|
input_info(true, &data->client->dev, "%s: ret=%d\n", __func__, ret);
|
|
return ver;
|
|
}
|
|
|
|
tsp_debug("Reg addr: %x, ver: %x\n", eHCOM_GET_VER_FW, ver);
|
|
|
|
return ver;
|
|
}
|
|
|
|
u32 ist40xx_get_fw_chksum(struct ist40xx_data *data)
|
|
{
|
|
u32 chksum = 0;
|
|
int ret = 0;
|
|
|
|
ret = ist40xx_read_cmd(data, eHCOM_GET_CRC32, &chksum);
|
|
if (ret) {
|
|
ist40xx_reset(data, false);
|
|
ist40xx_start(data);
|
|
|
|
input_err(true, &data->client->dev, "%s: ret=%d\n", __func__, ret);
|
|
return 0;
|
|
}
|
|
|
|
tsp_debug("Reg addr: 0x%08x, chksum: %08x\n", eHCOM_GET_CRC32, chksum);
|
|
|
|
return chksum;
|
|
}
|
|
|
|
static void not_support_cmd(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
snprintf(buf, sizeof(buf), "NA");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void get_chip_vendor(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
snprintf(buf, sizeof(buf), "%s", TSP_CHIP_VENDOR);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)),
|
|
"IC_VENDOR");
|
|
}
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void get_chip_name(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
snprintf(buf, sizeof(buf), "%s", TSP_CHIP_NAME);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)),
|
|
"IC_NAME");
|
|
}
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void get_chip_id(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
snprintf(buf, sizeof(buf), "%#02x", data->chip_id);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
#include <linux/uaccess.h>
|
|
#define MAX_FW_PATH 255
|
|
static void fw_update(void *dev_data)
|
|
{
|
|
int ret;
|
|
char buf[16] = { 0 };
|
|
mm_segment_t old_fs = { 0 };
|
|
struct file *fp = NULL;
|
|
long fsize = 0, nread = 0;
|
|
char fw_path[MAX_FW_PATH + 1];
|
|
u8 *fwbuf = NULL;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
#if defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
|
|
if (sec->cmd_param[0] == UMS) {
|
|
input_err(true, &data->client->dev, "%s: user_ship, skip\n", __func__);
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s() now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
return;
|
|
}
|
|
|
|
switch (sec->cmd_param[0]) {
|
|
case BUILT_IN:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
ret = ist40xx_fw_recovery(data);
|
|
if (ret < 0)
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
break;
|
|
case UMS:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
fwbuf = vzalloc(IST40XX_ROM_TOTAL_SIZE + sizeof(struct ist40xx_tags));
|
|
if (!fwbuf) {
|
|
input_err(true, &data->client->dev,
|
|
"%s() failed to fwbuf allocate\n", __func__);
|
|
|
|
sec->cmd_state= SEC_CMD_STATUS_FAIL;
|
|
|
|
break;
|
|
}
|
|
|
|
old_fs = get_fs();
|
|
set_fs(get_ds());
|
|
|
|
snprintf(fw_path, MAX_FW_PATH, "/sdcard/Firmware/TSP/%s", IST40XX_FW_NAME);
|
|
fp = filp_open(fw_path, O_RDONLY, 0);
|
|
if (IS_ERR(fp)) {
|
|
input_err(true, &data->client->dev, "%s: file %s open error:%d\n",
|
|
__func__, fw_path, IS_ERR(fp));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
set_fs(old_fs);
|
|
|
|
break;
|
|
}
|
|
|
|
fsize = fp->f_path.dentry->d_inode->i_size;
|
|
if (fsize != data->fw.buf_size) {
|
|
input_err(true, &data->client->dev, "%s: invalid fw size!!\n",
|
|
__func__);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
set_fs(old_fs);
|
|
|
|
break;
|
|
}
|
|
|
|
nread = vfs_read(fp, (char __user *)fwbuf, fsize, &fp->f_pos);
|
|
if (nread != fsize) {
|
|
input_err(true, &data->client->dev, "%s: failed to read fw\n",
|
|
__func__);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
filp_close(fp, NULL);
|
|
set_fs(old_fs);
|
|
|
|
break;
|
|
}
|
|
|
|
filp_close(fp, current->files);
|
|
set_fs(old_fs);
|
|
|
|
input_info(true, &data->client->dev, "%s: ums fw is loaded!!\n",
|
|
__func__);
|
|
|
|
ret = ist40xx_get_update_info(data, fwbuf, fsize);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
break;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
ret = ist40xx_fw_update(data, fwbuf, fsize);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
mutex_unlock(&data->lock);
|
|
break;
|
|
}
|
|
ist40xx_print_info(data);
|
|
#ifdef TCLM_CONCEPT
|
|
sec_tclm_root_of_cal(data->tdata, CALPOSITION_TESTMODE);
|
|
|
|
ret = sec_execute_tclm_package(data->tdata, 0);
|
|
if (ret < 0)
|
|
input_err(true, &data->client->dev,
|
|
"%s: sec_execute_tclm_package fail\n", __func__);
|
|
|
|
sec_tclm_root_of_cal(data->tdata, CALPOSITION_NONE);
|
|
#else
|
|
ist40xx_calibrate(data, 1);
|
|
#endif
|
|
mutex_unlock(&data->lock);
|
|
ist40xx_start(data);
|
|
|
|
break;
|
|
|
|
default:
|
|
input_err(true, &data->client->dev, "%s() Invalid fw file type!\n",
|
|
__func__);
|
|
break;
|
|
}
|
|
|
|
if (fwbuf)
|
|
vfree(fwbuf);
|
|
|
|
if (sec->cmd_state == SEC_CMD_STATUS_OK)
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
else
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void get_fw_ver_bin(void *dev_data)
|
|
{
|
|
u32 ver = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->dt_data->bringup != 1) {
|
|
ver = ist40xx_parse_ver(data, FLAG_FW, data->fw.buf);
|
|
}
|
|
snprintf(buf, sizeof(buf), "IM%08X", ver);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)),
|
|
"FW_VER_BIN");
|
|
}
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void get_config_ver(void *dev_data)
|
|
{
|
|
char buf[255] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
snprintf(buf, sizeof(buf), "%s_%s", TSP_CHIP_VENDOR, TSP_CHIP_NAME);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void get_checksum_data(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
u32 chksum = 0;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_OFF)
|
|
chksum = ist40xx_get_fw_chksum(data);
|
|
|
|
if (chksum == 0) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: Failed get the checksum data \n", __func__);
|
|
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
return;
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "0x%06X", chksum);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void get_fw_ver_ic(void *dev_data)
|
|
{
|
|
u32 ver = 0;
|
|
char msg[8];
|
|
char buf[16] = { 0 };
|
|
char model[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_OFF) {
|
|
ver = ist40xx_get_fw_ver(data);
|
|
snprintf(buf, sizeof(buf), "IM%08X", ver);
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "IM%08X", data->fw.cur.fw_ver);
|
|
}
|
|
|
|
if (data->fw.cur.test_ver > 0) {
|
|
sprintf(msg, "(T%X)", data->fw.cur.test_ver);
|
|
strcat(buf, msg);
|
|
}
|
|
|
|
snprintf(model, sizeof(model), "IM%04X", data->fw.cur.fw_ver >> 16);
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)),
|
|
"FW_VER_IC");
|
|
sec_cmd_set_cmd_result_all(sec, model, strnlen(model, sizeof(model)),
|
|
"FW_MODEL");
|
|
}
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void dead_zone_enable(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
goto out;
|
|
}
|
|
|
|
switch (sec->cmd_param[0]) {
|
|
case 0:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Set Edge Mode\n",
|
|
__func__);
|
|
|
|
ist40xx_set_edge_mode(1);
|
|
|
|
break;
|
|
case 1:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Unset Edge Mode\n",
|
|
__func__);
|
|
|
|
ist40xx_set_edge_mode(0);
|
|
|
|
break;
|
|
default:
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_info(true, &data->client->dev, "%s: Invalid Argument\n",
|
|
__func__);
|
|
|
|
break;
|
|
}
|
|
|
|
out:
|
|
if (sec->cmd_state == SEC_CMD_STATUS_OK)
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
else
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void call_mode(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
goto out;
|
|
}
|
|
|
|
switch (sec->cmd_param[0]) {
|
|
case 0:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Unset Call Mode\n",
|
|
__func__);
|
|
|
|
ist40xx_set_call_mode(0);
|
|
|
|
break;
|
|
case 1:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Set Call Mode\n",
|
|
__func__);
|
|
|
|
ist40xx_set_call_mode(1);
|
|
|
|
break;
|
|
default:
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_info(true, &data->client->dev, "%s: Invalid Argument\n",
|
|
__func__);
|
|
|
|
break;
|
|
}
|
|
|
|
out:
|
|
if (sec->cmd_state == SEC_CMD_STATUS_OK)
|
|
snprintf(buf, sizeof(buf), "%s", "OK");
|
|
else
|
|
snprintf(buf, sizeof(buf), "%s", "NG");
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void glove_mode(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
goto out;
|
|
}
|
|
|
|
switch (sec->cmd_param[0]) {
|
|
case 0:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Unset Glove Mode\n",
|
|
__func__);
|
|
|
|
ist40xx_set_glove_mode(0);
|
|
|
|
break;
|
|
case 1:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Set Glove Mode\n",
|
|
__func__);
|
|
|
|
ist40xx_set_glove_mode(1);
|
|
|
|
break;
|
|
default:
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_info(true, &data->client->dev, "%s: Invalid Argument\n",
|
|
__func__);
|
|
|
|
break;
|
|
}
|
|
|
|
out:
|
|
if (sec->cmd_state == SEC_CMD_STATUS_OK)
|
|
snprintf(buf, sizeof(buf), "%s", "OK");
|
|
else
|
|
snprintf(buf, sizeof(buf), "%s", "NG");
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
/*
|
|
* index
|
|
* 0 : set edge handler
|
|
* 1 : portrait (normal) mode
|
|
* 2 : landscape mode
|
|
*
|
|
* data
|
|
* 0, X (direction), X (y start), X (y end)
|
|
* direction : 0 (off), 1 (left), 2 (right)
|
|
* ex) echo set_grip_data,0,2,600,900 > cmd
|
|
*
|
|
* 1, X (edge zone), X (dead zone up x), X (dead zone down x), X (dead zone y)
|
|
* ex) echo set_grip_data,1,200,10,50,1500 > cmd
|
|
*
|
|
* 2, 1 (landscape mode), X (edge zone), X (dead zone x), X (dead zone top y), X (dead zone bottom y)
|
|
* ex) echo set_grip_data,2,1,200,100,120,0 > cmd
|
|
*
|
|
* 2, 0 (landscape mode off)
|
|
* ex) echo set_grip_data,2,0 > cmd
|
|
*/
|
|
static void set_grip_data(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
int ret;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (sec->cmd_param[0] == 2) { // landscape mode
|
|
if (sec->cmd_param[1] == 0) { // normal mode
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev,
|
|
"%s: Unset Touchable Area\n", __func__);
|
|
|
|
ret = ist40xx_set_rejectzone_mode(0, 0, 0);
|
|
if (ret)
|
|
goto err_grip_data;
|
|
} else if (sec->cmd_param[1] == 1) {
|
|
input_info(true, &data->client->dev,
|
|
"%s: Set Touchable Area\n", __func__);
|
|
|
|
ret = ist40xx_set_rejectzone_mode(1, sec->cmd_param[4],
|
|
sec->cmd_param[5]);
|
|
if (ret)
|
|
goto err_grip_data;
|
|
} else {
|
|
input_info(true, &data->client->dev,
|
|
"%s: not support function\n", __func__);
|
|
}
|
|
} else {
|
|
input_info(true, &data->client->dev, "%s: not support function\n", __func__);
|
|
}
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
err_grip_data:
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void set_touchable_area(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
goto out;
|
|
}
|
|
|
|
switch (sec->cmd_param[0]) {
|
|
case 0:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Unset Touchable Area\n",
|
|
__func__);
|
|
|
|
ist40xx_set_touchable_mode(0);
|
|
|
|
break;
|
|
case 1:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Set Touchable Area\n",
|
|
__func__);
|
|
|
|
ist40xx_set_touchable_mode(1);
|
|
|
|
break;
|
|
default:
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_info(true, &data->client->dev, "%s: Invalid Argument\n",
|
|
__func__);
|
|
|
|
break;
|
|
}
|
|
|
|
out:
|
|
if (sec->cmd_state == SEC_CMD_STATUS_OK)
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
else
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
input_info(true, &data->client->dev, "%s() %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void spay_enable(void *dev_data)
|
|
{
|
|
int ret;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
switch (sec->cmd_param[0]) {
|
|
case 0:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Unset SPAY Mode\n",
|
|
__func__);
|
|
|
|
data->lpm_mode &= ~IST40XX_SPAY;
|
|
|
|
break;
|
|
case 1:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Set SPAY Mode\n",
|
|
__func__);
|
|
|
|
data->lpm_mode |= IST40XX_SPAY;
|
|
|
|
break;
|
|
default:
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_info(true, &data->client->dev, "%s: Invalid Argument\n",
|
|
__func__);
|
|
|
|
break;
|
|
}
|
|
|
|
if (data->status.sys_mode != STATE_POWER_OFF) {
|
|
mutex_lock(&data->aod_lock);
|
|
ret = ist40xx_write_sponge_reg(data, IST40XX_SPONGE_CTRL,
|
|
(u16*)&data->lpm_mode, 1, true);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: fail to write sponge reg\n", __func__);
|
|
mutex_unlock(&data->aod_lock);
|
|
goto err;
|
|
}
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_NOTIRY_G_REGMAP << 16) | IST40XX_ENABLE);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: fail to write notify packet.\n", __func__);
|
|
mutex_unlock(&data->aod_lock);
|
|
goto err;
|
|
}
|
|
mutex_unlock(&data->aod_lock);
|
|
}
|
|
|
|
err:
|
|
if (sec->cmd_state == SEC_CMD_STATUS_OK)
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
else
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void aot_enable(void *dev_data)
|
|
{
|
|
int ret;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
switch (sec->cmd_param[0]) {
|
|
case 0:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Unset AOT Mode\n",
|
|
__func__);
|
|
|
|
data->lpm_mode &= ~IST40XX_DOUBLETAP_WAKEUP;
|
|
|
|
break;
|
|
case 1:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Set AOT Mode\n",
|
|
__func__);
|
|
|
|
data->lpm_mode |= IST40XX_DOUBLETAP_WAKEUP;
|
|
|
|
break;
|
|
default:
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_info(true, &data->client->dev, "%s: Invalid Argument\n",
|
|
__func__);
|
|
|
|
break;
|
|
}
|
|
|
|
if (data->status.sys_mode != STATE_POWER_OFF) {
|
|
mutex_lock(&data->aod_lock);
|
|
ret = ist40xx_write_sponge_reg(data, IST40XX_SPONGE_CTRL,
|
|
(u16*)&data->lpm_mode, 1, true);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: fail to write sponge reg.\n", __func__);
|
|
mutex_unlock(&data->aod_lock);
|
|
goto err;
|
|
}
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_NOTIRY_G_REGMAP << 16) | IST40XX_ENABLE);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: fail to write notify packet.\n", __func__);
|
|
mutex_unlock(&data->aod_lock);
|
|
goto err;
|
|
}
|
|
mutex_unlock(&data->aod_lock);
|
|
}
|
|
|
|
err:
|
|
if (sec->cmd_state == SEC_CMD_STATUS_OK)
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
else
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void aod_enable(void *dev_data)
|
|
{
|
|
int ret;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
switch (sec->cmd_param[0]) {
|
|
case 0:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Unset AOD Mode\n",
|
|
__func__);
|
|
|
|
data->lpm_mode &= ~IST40XX_AOD;
|
|
|
|
break;
|
|
case 1:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Set AOD Mode\n",
|
|
__func__);
|
|
|
|
data->lpm_mode |= IST40XX_AOD;
|
|
|
|
break;
|
|
default:
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_info(true, &data->client->dev, "%s: Invalid Argument\n",
|
|
__func__);
|
|
|
|
break;
|
|
}
|
|
|
|
if (data->status.sys_mode != STATE_POWER_OFF) {
|
|
mutex_lock(&data->aod_lock);
|
|
ret = ist40xx_write_sponge_reg(data, IST40XX_SPONGE_CTRL,
|
|
(u16*)&data->lpm_mode, 1, true);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: fail to write sponge reg.\n", __func__);
|
|
mutex_unlock(&data->aod_lock);
|
|
goto err;
|
|
}
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_NOTIRY_G_REGMAP << 16) | IST40XX_ENABLE);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: fail to write notify packet.\n", __func__);
|
|
mutex_unlock(&data->aod_lock);
|
|
goto err;
|
|
}
|
|
mutex_unlock(&data->aod_lock);
|
|
}
|
|
|
|
err:
|
|
if (sec->cmd_state == SEC_CMD_STATUS_OK)
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
else
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void set_aod_rect(void *dev_data)
|
|
{
|
|
int i;
|
|
int ret;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
data->rect_data[i] = sec->cmd_param[i];
|
|
|
|
if (data->status.sys_mode == STATE_LPM) {
|
|
mutex_lock(&data->aod_lock);
|
|
ret = ist40xx_burst_write(data->client, IST40XX_HIB_SPONGE_RECT,
|
|
(u32 *)data->rect_data, 2);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: fail to write rect\n", __func__);
|
|
mutex_unlock(&data->aod_lock);
|
|
goto err_rect;
|
|
}
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_SET_AOD_RECT << 16) | (IST40XX_ENABLE & 0xFFFF));
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: fail to write rect notify.\n", __func__);
|
|
mutex_unlock(&data->aod_lock);
|
|
goto err_rect;
|
|
}
|
|
mutex_unlock(&data->aod_lock);
|
|
}
|
|
|
|
err_rect:
|
|
if (sec->cmd_state == SEC_CMD_STATUS_OK)
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
else
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void get_aod_rect(void *dev_data)
|
|
{
|
|
char buf[32] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
snprintf(buf, sizeof(buf), "%d,%d,%d,%d", data->rect_data[0],
|
|
data->rect_data[1], data->rect_data[2], data->rect_data[3]);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void singletap_enable(void *dev_data)
|
|
{
|
|
int ret;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
switch (sec->cmd_param[0]) {
|
|
case 0:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Unset SingleTap Mode\n",
|
|
__func__);
|
|
|
|
data->lpm_mode &= ~IST40XX_SINGLETAP;
|
|
|
|
break;
|
|
case 1:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Set SingleTap Mode\n",
|
|
__func__);
|
|
|
|
data->lpm_mode |= IST40XX_SINGLETAP;
|
|
|
|
break;
|
|
default:
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_info(true, &data->client->dev, "%s: Invalid Argument\n",
|
|
__func__);
|
|
|
|
break;
|
|
}
|
|
|
|
if (data->status.sys_mode != STATE_POWER_OFF) {
|
|
mutex_lock(&data->aod_lock);
|
|
ret = ist40xx_write_sponge_reg(data, IST40XX_SPONGE_CTRL,
|
|
(u16*)&data->lpm_mode, 1, true);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: fail to write sponge reg.\n", __func__);
|
|
mutex_unlock(&data->aod_lock);
|
|
goto err;
|
|
}
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_NOTIRY_G_REGMAP << 16) | IST40XX_ENABLE);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_info(true, &data->client->dev,
|
|
"%s: fail to write notify packet.\n", __func__);
|
|
mutex_unlock(&data->aod_lock);
|
|
goto err;
|
|
}
|
|
mutex_unlock(&data->aod_lock);
|
|
}
|
|
|
|
err:
|
|
if (sec->cmd_state == SEC_CMD_STATUS_OK)
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
else
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void fod_enable(void *dev_data)
|
|
{
|
|
int ret;
|
|
char buf[16] = { 0 };
|
|
u8 fod_property;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (!data->dt_data->support_fod) {
|
|
input_err(true, &data->client->dev, "%s not supported\n", __func__);
|
|
snprintf(buf, sizeof(buf), "%s", "NA");
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec_cmd_set_cmd_exit(sec);
|
|
return;
|
|
}
|
|
|
|
fod_property = !!sec->cmd_param[1];
|
|
|
|
mutex_lock(&data->aod_lock);
|
|
|
|
switch (sec->cmd_param[0]) {
|
|
case 0:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Unset FOD Mode\n",
|
|
__func__);
|
|
|
|
data->lpm_mode &= ~IST40XX_FOD;
|
|
data->fod_property = fod_property;
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_SET_FOD_DISABLE << 16) | data->fod_property);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: fail to write fod disable.\n", __func__);
|
|
goto err;
|
|
}
|
|
|
|
break;
|
|
case 1:
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: Set FOD Mode\n",
|
|
__func__);
|
|
|
|
data->lpm_mode |= IST40XX_FOD;
|
|
data->fod_property = fod_property;
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_SET_FOD_ENABLE << 16) | data->fod_property);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: fail to write fod enable.\n", __func__);
|
|
goto err;
|
|
}
|
|
|
|
break;
|
|
default:
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_info(true, &data->client->dev, "%s: Invalid Argument\n",
|
|
__func__);
|
|
|
|
break;
|
|
}
|
|
|
|
err:
|
|
mutex_unlock(&data->aod_lock);
|
|
if (sec->cmd_state == SEC_CMD_STATUS_OK)
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
else
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec_cmd_set_cmd_exit(sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void fod_lp_mode(void *dev_data)
|
|
{
|
|
char buf[32] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
data->fod_lp_mode = sec->cmd_param[0];
|
|
|
|
input_info(true, &data->client->dev, "%s: fod_lp_mode %d\n", __func__, data->fod_lp_mode);
|
|
|
|
snprintf(buf, sizeof(buf), "%s", "OK");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
sec_cmd_set_cmd_exit(sec);
|
|
}
|
|
|
|
static void get_threshold(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
snprintf(buf, sizeof(buf), "%d", tsp->threshold);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void get_scr_x_num(void *dev_data)
|
|
{
|
|
int val = -1;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->tsp_info.dir.swap_xy)
|
|
val = data->tsp_info.screen.tx;
|
|
else
|
|
val = data->tsp_info.screen.rx;
|
|
|
|
if (val >= 0) {
|
|
snprintf(buf, sizeof(buf), "%u", val);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
input_err(true, &data->client->dev, "%s: fail to read num of x (%d).\n",
|
|
__func__, val);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void get_scr_y_num(void *dev_data)
|
|
{
|
|
int val = -1;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->tsp_info.dir.swap_xy)
|
|
val = data->tsp_info.screen.rx;
|
|
else
|
|
val = data->tsp_info.screen.tx;
|
|
|
|
if (val >= 0) {
|
|
snprintf(buf, sizeof(buf), "%u", val);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
input_err(true, &data->client->dev, "%s: fail to read num of y (%d).\n",
|
|
__func__, val);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void get_all_x_num(void *dev_data)
|
|
{
|
|
int val = -1;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->tsp_info.dir.swap_xy)
|
|
val = data->tsp_info.ch_num.tx;
|
|
else
|
|
val = data->tsp_info.ch_num.rx;
|
|
|
|
if (val >= 0) {
|
|
snprintf(buf, sizeof(buf), "%u", val);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
input_err(true, &data->client->dev, "%s: fail to read num of x (%d).\n",
|
|
__func__, val);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void get_all_y_num(void *dev_data)
|
|
{
|
|
int val = -1;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->tsp_info.dir.swap_xy)
|
|
val = data->tsp_info.ch_num.rx;
|
|
else
|
|
val = data->tsp_info.ch_num.tx;
|
|
|
|
if (val >= 0) {
|
|
snprintf(buf, sizeof(buf), "%u", val);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
input_err(true, &data->client->dev, "%s: fail to read num of y (%d).\n",
|
|
__func__, val);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
int check_tsp_channel(struct ist40xx_data *data, int width, int height)
|
|
{
|
|
int node = -EPERM;
|
|
struct sec_cmd_data *sec = &data->sec;
|
|
|
|
if (data->tsp_info.dir.swap_xy) {
|
|
if ((sec->cmd_param[0] < 0) || (sec->cmd_param[0] >= height) ||
|
|
(sec->cmd_param[1] < 0) || (sec->cmd_param[1] >= width)) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: parameter error: %u,%u\n", __func__,
|
|
sec->cmd_param[0], sec->cmd_param[1]);
|
|
} else {
|
|
node = sec->cmd_param[1] + sec->cmd_param[0] * width;
|
|
input_info(true, &data->client->dev, "%s: node = %d\n",
|
|
__func__, node);
|
|
}
|
|
} else {
|
|
if ((sec->cmd_param[0] < 0) || (sec->cmd_param[0] >= width) ||
|
|
(sec->cmd_param[1] < 0) || (sec->cmd_param[1] >= height)) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: parameter error: %u,%u\n", __func__,
|
|
sec->cmd_param[0], sec->cmd_param[1]);
|
|
} else {
|
|
node = sec->cmd_param[0] + sec->cmd_param[1] * width;
|
|
input_info(true, &data->client->dev, "%s: node = %d\n",
|
|
__func__, node);
|
|
}
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
static u16 cal_cp_value[IST40XX_MAX_NODE_NUM];
|
|
static u16 cal_self_cp_value[IST40XX_MAX_SELF_NODE_NUM];
|
|
static u16 cal_prox_cp_value[IST40XX_MAX_SELF_NODE_NUM];
|
|
|
|
void get_cp_array(void *dev_data)
|
|
{
|
|
int i, ret;
|
|
int count = 0;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
char buff[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
ret = ist40xx_read_cp_node(data, &tsp->node, true);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
input_err(true, &data->client->dev, "%s: tsp cp read fail!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
ist40xx_parse_cp_node(data, &tsp->node, true);
|
|
|
|
ret = parse_cp_node(data, &tsp->node, cal_cp_value, cal_self_cp_value,
|
|
cal_prox_cp_value, true);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp cp parse fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
buf = kmalloc(IST40XX_MAX_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->ch_num.rx * tsp->ch_num.tx; i++) {
|
|
count += snprintf(msg, msg_len, "%d,", cal_cp_value[i]);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count - 1);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buff, sizeof(buff), "NG");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void get_self_cp_array(void *dev_data)
|
|
{
|
|
int i, ret;
|
|
int count = 0;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
char buff[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
ret = ist40xx_read_cp_node(data, &tsp->node, true);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
input_err(true, &data->client->dev, "%s: tsp self cp read fail!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
ist40xx_parse_cp_node(data, &tsp->node, true);
|
|
|
|
ret = parse_cp_node(data, &tsp->node, cal_cp_value, cal_self_cp_value,
|
|
cal_prox_cp_value, true);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp self cp parse fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
buf = kmalloc(IST40XX_MAX_SELF_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_SELF_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->ch_num.rx + tsp->ch_num.tx; i++) {
|
|
count += snprintf(msg, msg_len, "%d,", cal_self_cp_value[i]);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count - 1);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buff, sizeof(buff), "NG");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void get_prox_cp_array(void *dev_data)
|
|
{
|
|
int i, ret;
|
|
int count = 0;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
char buff[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
ret = ist40xx_read_cp_node(data, &tsp->node, true);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
input_err(true, &data->client->dev, "%s: tsp prox cp read fail!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
ist40xx_parse_cp_node(data, &tsp->node, true);
|
|
|
|
ret = parse_cp_node(data, &tsp->node, cal_cp_value, cal_self_cp_value,
|
|
cal_prox_cp_value, true);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp prox cp parse fail!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
buf = kmalloc(IST40XX_MAX_SELF_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_SELF_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->ch_num.rx + tsp->ch_num.tx; i++) {
|
|
count += snprintf(msg, msg_len, "%d,", cal_prox_cp_value[i]);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count - 1);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buff, sizeof(buff), "NG");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void run_miscalibration(void *dev_data)
|
|
{
|
|
int ret = 0;
|
|
int max_val = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is STATE_POWER_OFF!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_miscalibrate(data);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: miscalibration fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
max_val = data->status.miscalib_result;
|
|
if (max_val > SEC_MISCAL_SPEC)
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
else
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
snprintf(buf, sizeof(buf), "0,%d", max_val);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)),
|
|
"MIS_CAL");
|
|
}
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)),
|
|
"MIS_CAL");
|
|
}
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void run_miscalibration_all(void *dev_data)
|
|
{
|
|
int i, ret = 0;
|
|
int count = 0;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
char buff[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
struct TSP_NODE_BUF *node = &tsp->node;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is STATE_POWER_OFF!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ist40xx_delay(300);
|
|
|
|
ret = ist40xx_miscalibrate(data);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: miscalibration fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
buf = kmalloc(IST40XX_MAX_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->ch_num.rx + tsp->ch_num.tx; i++) {
|
|
count += snprintf(msg, msg_len, "%d,", node->miscal[i]);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count - 1);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buff, sizeof(buff), "NG");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
}
|
|
|
|
void get_miscalibration_value(void *dev_data)
|
|
{
|
|
int idx = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
struct TSP_NODE_BUF *node = &tsp->node;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
idx = check_tsp_channel(data, tsp->screen.rx, tsp->screen.tx);
|
|
if (idx < 0) { // Parameter parsing fail
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "%d", node->miscal[idx]);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
void get_mis_cal_info(void *dev_data)
|
|
{
|
|
int ret = 0;
|
|
int max_val = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is STATE_POWER_OFF!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_miscalibrate(data);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: miscalibration fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
max_val = data->status.miscalib_result;
|
|
if (max_val > SEC_MISCAL_SPEC)
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
else
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
snprintf(buf, sizeof(buf), "0,%d", max_val);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)),
|
|
"MIS_CAL");
|
|
}
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)),
|
|
"MIS_CAL");
|
|
}
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
static void check_connection(void *dev_data)
|
|
{
|
|
int ret;
|
|
u32 chk_value = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
ret = ist40xx_read_cmd(data, rSYS_CHIPID, &chk_value);
|
|
if (ret || (chk_value != data->chip_id)) {
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void run_prox_intensity_read_all(void *dev_data)
|
|
{
|
|
int ret = 0;
|
|
u32 sensitivity = 0;
|
|
char buf[SEC_CMD_STR_LEN] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_PROX_HQE_EN << 16) | IST40XX_ENABLE);
|
|
if (ret) {
|
|
input_info(true, &data->client->dev, "%s Failed Write the Prox HQE Enable\n", __func__);
|
|
snprintf(buf, sizeof(buf), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_read_reg(data->client, IST40XX_HIB_PROX_SENSITI,
|
|
&sensitivity);
|
|
if (ret) {
|
|
input_info(true, &data->client->dev, "%s Failed get the touch status data\n", __func__);
|
|
snprintf(buf, sizeof(buf), "%s", "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "SUM_X:%d SUM_Y:%d THD_X:%d THD_Y:%d", (sensitivity >> 16) & 0xFFFF,
|
|
sensitivity & 0xFFFF, tsp->prox_tx_threshold, tsp->prox_rx_threshold);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
out:
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
#define FPCB_NOISE_FRAME_CNT 30
|
|
#define GROUP_CH_CNT 9
|
|
static void get_fpcb_noise(void *dev_data)
|
|
{
|
|
int i, w, h, ret = 0;
|
|
int idx = 0;
|
|
u32 result_sum = 0;
|
|
u32 max_peak = 0;
|
|
u32 addr;
|
|
u32 *cdc = NULL;
|
|
s16 diff;
|
|
s16 max_diff = 0;
|
|
s16 min_diff = 0;
|
|
s16 *sum = NULL;
|
|
s16 peak = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
|
snprintf(buf, sizeof(buf), "0,%d", data->fpcb_noise_max_sum);
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)), "JITTER");
|
|
input_info(true, &data->client->dev, "%s: fpcb_noise_max_sum %d\n", __func__, data->fpcb_noise_max_sum);
|
|
return;
|
|
}
|
|
|
|
data->ignore_delay = true;
|
|
|
|
cdc = kmalloc(tsp->node.len * sizeof(u32), GFP_KERNEL);
|
|
if (!cdc) {
|
|
input_info(true, &data->client->dev, "%s couldn't allocate cdc memory\n", __func__);
|
|
goto err;
|
|
}
|
|
|
|
sum = kmalloc(tsp->ch_num.tx * sizeof(s16), GFP_KERNEL);
|
|
if (!sum) {
|
|
input_info(true, &data->client->dev, "%s couldn't allocate sum memory\n", __func__);
|
|
kfree(cdc);
|
|
goto err;
|
|
}
|
|
|
|
memset(sum, 0, tsp->ch_num.tx * sizeof(s16));
|
|
|
|
for (i = 0; i < FPCB_NOISE_FRAME_CNT; i++) {
|
|
ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_FW_HOLD << 16) | (IST40XX_ENABLE & 0xFFFF));
|
|
ist40xx_delay(20);
|
|
|
|
// Read CDC Data
|
|
for (h = 0; h < tsp->ch_num.tx; h++) {
|
|
idx = h * tsp->ch_num.rx + tsp->ch_num.rx - GROUP_CH_CNT;
|
|
addr = IST40XX_DA_ADDR(data->cdc_addr) + (IST40XX_ADDR_LEN * idx);
|
|
ret = ist40xx_burst_read(data->client, addr, cdc + idx,
|
|
GROUP_CH_CNT, true);
|
|
if (ret) {
|
|
input_info(true, &data->client->dev, "%s: read fail\n", __func__);
|
|
kfree(sum);
|
|
kfree(cdc);
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_FW_HOLD << 16) | (IST40XX_DISABLE & 0xFFFF));
|
|
ist40xx_delay(20);
|
|
|
|
peak = 0;
|
|
for (h = 0; h < tsp->ch_num.tx; h++) {
|
|
for (w = (tsp->ch_num.rx - GROUP_CH_CNT); w < tsp->ch_num.rx; w++) {
|
|
idx = h * tsp->ch_num.rx + w;
|
|
diff = (cdc[idx] & 0xFFF) - ((cdc[idx] >> 16) & 0xFFF);
|
|
if (w == (tsp->ch_num.rx - GROUP_CH_CNT)) {
|
|
max_diff = diff;
|
|
min_diff = diff;
|
|
} else if (diff > max_diff) {
|
|
max_diff = diff;
|
|
} else if (diff < min_diff) {
|
|
min_diff = diff;
|
|
}
|
|
}
|
|
peak = max_diff - min_diff;
|
|
sum[h] += peak;
|
|
|
|
if (peak > max_peak)
|
|
max_peak = peak;
|
|
}
|
|
}
|
|
|
|
for (h = 0; h < tsp->ch_num.tx; h++)
|
|
result_sum += (sum[h] / FPCB_NOISE_FRAME_CNT);
|
|
|
|
data->fpcb_noise_max_sum = result_sum;
|
|
|
|
kfree(sum);
|
|
kfree(cdc);
|
|
err:
|
|
data->ignore_delay = false;
|
|
input_info(true, &data->client->dev, "%s: result_sum %d max_peak %d\n", __func__, result_sum, max_peak);
|
|
}
|
|
|
|
static u16 node_value[IST40XX_MAX_NODE_NUM];
|
|
static u16 self_node_value[IST40XX_MAX_SELF_NODE_NUM];
|
|
static u16 prox_node_value[IST40XX_MAX_SELF_NODE_NUM];
|
|
|
|
void get_cdc_array(void *dev_data)
|
|
{
|
|
int i, ret;
|
|
int count = 0;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
u8 flag = NODE_FLAG_CDC;
|
|
char buff[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
ret = ist40xx_read_touch_node(data, flag, &tsp->node);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
input_err(true, &data->client->dev, "%s() tsp node read fail!\n", __func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
ist40xx_parse_touch_node(data, &tsp->node);
|
|
|
|
ret = parse_tsp_node(data, flag, &tsp->node, node_value, self_node_value,
|
|
prox_node_value);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp node parse fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
buf = kmalloc(IST40XX_MAX_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->ch_num.rx * tsp->ch_num.tx; i++) {
|
|
count += snprintf(msg, msg_len, "%d,", node_value[i]);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count -1);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buff, sizeof(buff), "NG");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void get_self_cdc_array(void *dev_data)
|
|
{
|
|
int i, ret;
|
|
int count = 0;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
u8 flag = NODE_FLAG_CDC;
|
|
char buff[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
ret = ist40xx_read_touch_node(data, flag, &tsp->node);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
input_err(true, &data->client->dev, "%s: tsp self cdc read fail!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
ist40xx_parse_touch_node(data, &tsp->node);
|
|
|
|
ret = parse_tsp_node(data, flag, &tsp->node, node_value, self_node_value,
|
|
prox_node_value);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp self cdc parse fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
buf = kmalloc(IST40XX_MAX_SELF_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_SELF_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->ch_num.rx + tsp->ch_num.tx; i++) {
|
|
count += snprintf(msg, msg_len, "%d,", self_node_value[i]);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count - 1);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buff, sizeof(buff), "NG");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void get_prox_cdc_array(void *dev_data)
|
|
{
|
|
int i, ret;
|
|
int count = 0;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
u8 flag = NODE_FLAG_CDC;
|
|
char buff[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
ret = ist40xx_read_touch_node(data, flag, &tsp->node);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
input_err(true, &data->client->dev, "%s: tsp prox cdc read fail!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
ist40xx_parse_touch_node(data, &tsp->node);
|
|
|
|
ret = parse_tsp_node(data, flag, &tsp->node, node_value, self_node_value,
|
|
prox_node_value);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp prox cdc parse fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
buf = kmalloc(IST40XX_MAX_SELF_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_SELF_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->ch_num.rx + tsp->ch_num.tx; i++) {
|
|
count += snprintf(msg, msg_len, "%d,", prox_node_value[i]);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count - 1);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buff, sizeof(buff), "NG");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void run_cdc_read(void *dev_data)
|
|
{
|
|
int i;
|
|
int ret = 0;
|
|
int min_val = 0, max_val = 0;
|
|
char buf[16] = { 0 };
|
|
u8 flag = NODE_FLAG_CDC;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_read_touch_node(data, flag, &tsp->node);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s() tsp node read fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ist40xx_parse_touch_node(data, &tsp->node);
|
|
|
|
ret = parse_tsp_node(data, flag, &tsp->node, node_value, self_node_value,
|
|
prox_node_value);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp node parse fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
min_val = max_val = node_value[0];
|
|
|
|
for (i = 0; i < tsp->screen.rx * tsp->screen.tx; i++) {
|
|
max_val = max(max_val, (int)node_value[i]);
|
|
min_val = min(min_val, (int)node_value[i]);
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "%d,%d", min_val, max_val);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)), "CR");
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)), "CR");
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void run_cdc_read_all(void *dev_data)
|
|
{
|
|
int i;
|
|
int ret = 0;
|
|
int count = 0;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
u8 flag = NODE_FLAG_CDC;
|
|
char buff[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_read_touch_node(data, flag, &tsp->node);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s() tsp node read fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ist40xx_parse_touch_node(data, &tsp->node);
|
|
|
|
ret = parse_tsp_node(data, flag, &tsp->node, node_value, self_node_value,
|
|
prox_node_value);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp node parse fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
buf = kmalloc(IST40XX_MAX_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->screen.rx * tsp->screen.tx; i++) {
|
|
count += snprintf(msg, msg_len, "%d,", node_value[i]);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count - 1);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buff, sizeof(buff), "NG");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void run_self_cdc_read(void *dev_data)
|
|
{
|
|
int i;
|
|
int ret = 0;
|
|
int min_val, max_val;
|
|
int min_val_tx, max_val_tx;
|
|
int min_val_rx, max_val_rx;
|
|
char buf[16] = { 0 };
|
|
char buf_onecmd_1[16] = { 0 };
|
|
char buf_onecmd_2[16] = { 0 };
|
|
u8 flag = NODE_FLAG_CDC;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_SET_TIME_ACTIVE << 16) | 30000);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: write active time fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_SET_TIME_IDLE << 16) | 30000);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: write idle time fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ist40xx_delay(200);
|
|
|
|
ret = ist40xx_read_touch_node(data, flag, &tsp->node);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp node read fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_SET_TIME_ACTIVE << 16) | 0xFFFF);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: write active time fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_SET_TIME_IDLE << 16) | 0xFFFF);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: write idle time fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ist40xx_parse_touch_node(data, &tsp->node);
|
|
|
|
ret = parse_tsp_node(data, flag, &tsp->node, node_value, self_node_value,
|
|
prox_node_value);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp node parse fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
min_val = max_val = self_node_value[0];
|
|
|
|
for (i = 0; i < tsp->ch_num.rx + tsp->ch_num.tx; i++) {
|
|
max_val = max(max_val, (int)self_node_value[i]);
|
|
min_val = min(min_val, (int)self_node_value[i]);
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "%d,%d", min_val, max_val);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
|
min_val_tx = max_val_tx = self_node_value[0];
|
|
|
|
for (i = 1; i < tsp->ch_num.tx; i++) {
|
|
min_val_tx = min(min_val_tx, (int)self_node_value[i]);
|
|
max_val_tx = max(max_val_tx, (int)self_node_value[i]);
|
|
}
|
|
|
|
min_val_rx = max_val_rx = self_node_value[tsp->ch_num.tx];
|
|
|
|
for (i = 1; i < tsp->ch_num.rx; i++) {
|
|
min_val_rx = min(min_val_rx,
|
|
(int)self_node_value[i + tsp->ch_num.tx]);
|
|
max_val_rx = max(max_val_rx,
|
|
(int)self_node_value[i + tsp->ch_num.tx]);
|
|
}
|
|
|
|
snprintf(buf_onecmd_1, sizeof(buf_onecmd_1), "%d,%d", min_val_tx,
|
|
max_val_tx);
|
|
snprintf(buf_onecmd_2, sizeof(buf_onecmd_2), "%d,%d", min_val_rx,
|
|
max_val_rx);
|
|
|
|
sec_cmd_set_cmd_result_all(sec, buf_onecmd_1,
|
|
strnlen(buf_onecmd_1, sizeof(buf_onecmd_1)),
|
|
"SELF_CR_X");
|
|
sec_cmd_set_cmd_result_all(sec, buf_onecmd_2,
|
|
strnlen(buf_onecmd_2, sizeof(buf_onecmd_2)),
|
|
"SELF_CR_Y");
|
|
}
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)),
|
|
"SELF_CR_X");
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)),
|
|
"SELF_CR_Y");
|
|
}
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void run_self_cdc_read_all(void *dev_data)
|
|
{
|
|
int i;
|
|
int ret = 0;
|
|
int count = 0;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
u8 flag = NODE_FLAG_CDC;
|
|
char buff[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_SET_TIME_ACTIVE << 16) | 30000);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: write active time fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_SET_TIME_IDLE << 16) | 30000);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: write idle time fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ist40xx_delay(200);
|
|
|
|
ret = ist40xx_read_touch_node(data, flag, &tsp->node);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp node read fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_SET_TIME_ACTIVE << 16) | 0xFFFF);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: write active time fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_write_cmd(data, IST40XX_HIB_CMD,
|
|
(eHCOM_SET_TIME_IDLE << 16) | 0xFFFF);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: write idle time fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ist40xx_parse_touch_node(data, &tsp->node);
|
|
|
|
ret = parse_tsp_node(data, flag, &tsp->node, node_value, self_node_value,
|
|
prox_node_value);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp node parse fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
buf = kmalloc(IST40XX_MAX_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->ch_num.tx + tsp->ch_num.rx; i++) {
|
|
count += snprintf(msg, msg_len, "%d,", self_node_value[i]);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count - 1);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buff, sizeof(buff), "NG");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void run_prox_cdc_read(void *dev_data)
|
|
{
|
|
int i;
|
|
int ret = 0;
|
|
int min_val, max_val;
|
|
int min_val_tx, max_val_tx;
|
|
int min_val_rx, max_val_rx;
|
|
char buf[16] = { 0 };
|
|
char buf_onecmd_1[16] = { 0 };
|
|
char buf_onecmd_2[16] = { 0 };
|
|
u8 flag = NODE_FLAG_CDC;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_read_touch_node(data, flag, &tsp->node);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp node read fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ist40xx_parse_touch_node(data, &tsp->node);
|
|
|
|
ret = parse_tsp_node(data, flag, &tsp->node, node_value, self_node_value,
|
|
prox_node_value);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp node parse fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
min_val = max_val = prox_node_value[0];
|
|
|
|
for (i = 0; i < tsp->ch_num.rx + tsp->ch_num.tx; i++) {
|
|
max_val = max(max_val, (int)prox_node_value[i]);
|
|
min_val = min(min_val, (int)prox_node_value[i]);
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "%d,%d", min_val, max_val);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
|
min_val_tx = max_val_tx = prox_node_value[0];
|
|
|
|
for (i = 1; i < tsp->ch_num.tx; i++) {
|
|
min_val_tx = min(min_val_tx, (int)prox_node_value[i]);
|
|
max_val_tx = max(max_val_tx, (int)prox_node_value[i]);
|
|
}
|
|
|
|
min_val_rx = max_val_rx = prox_node_value[tsp->ch_num.tx];
|
|
|
|
for (i = 1; i < tsp->ch_num.rx; i++) {
|
|
min_val_rx = min(min_val_rx,
|
|
(int)prox_node_value[i + tsp->ch_num.tx]);
|
|
max_val_rx = max(max_val_rx,
|
|
(int)prox_node_value[i + tsp->ch_num.tx]);
|
|
}
|
|
|
|
snprintf(buf_onecmd_1, sizeof(buf_onecmd_1), "%d,%d", min_val_tx,
|
|
max_val_tx);
|
|
snprintf(buf_onecmd_2, sizeof(buf_onecmd_2), "%d,%d", min_val_rx,
|
|
max_val_rx);
|
|
sec_cmd_set_cmd_result_all(sec, buf_onecmd_1,
|
|
strnlen(buf_onecmd_1, sizeof(buf_onecmd_1)),
|
|
"PROXI_CR_X");
|
|
sec_cmd_set_cmd_result_all(sec, buf_onecmd_2,
|
|
strnlen(buf_onecmd_2, sizeof(buf_onecmd_2)),
|
|
"PROXI_CR_Y");
|
|
}
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s() %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)),
|
|
"PROXI_CR_X");
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)),
|
|
"PROXI_CR_Y");
|
|
}
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void get_cdc_value(void *dev_data)
|
|
{
|
|
int idx = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
idx = check_tsp_channel(data, tsp->screen.rx, tsp->screen.tx);
|
|
if (idx < 0) { // Parameter parsing fail
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "%d", node_value[idx]);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
void get_self_cdc_value(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if ((sec->cmd_param[0] < 0) ||
|
|
(sec->cmd_param[0] >= (tsp->ch_num.rx + tsp->ch_num.tx))) {
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "%d", self_node_value[sec->cmd_param[0]]);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
void get_prox_cdc_value(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if ((sec->cmd_param[0] < 0) ||
|
|
(sec->cmd_param[0] >= (tsp->ch_num.rx + tsp->ch_num.tx))) {
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "%d", prox_node_value[sec->cmd_param[0]]);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
void get_rx_self_cdc_value(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if ((sec->cmd_param[1] < 0) || (sec->cmd_param[1] >= (tsp->ch_num.rx))) {
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "%d",
|
|
self_node_value[sec->cmd_param[1] + tsp->ch_num.tx]);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
void get_tx_self_cdc_value(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if ((sec->cmd_param[0] < 0) || (sec->cmd_param[0] >= (tsp->ch_num.tx))) {
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "%d", self_node_value[sec->cmd_param[0]]);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
void get_rx_prox_cdc_value(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if ((sec->cmd_param[1] < 0) || (sec->cmd_param[1] >= (tsp->ch_num.rx))) {
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "%d",
|
|
prox_node_value[sec->cmd_param[1] + tsp->ch_num.tx]);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
void get_tx_prox_cdc_value(void *dev_data)
|
|
{
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if ((sec->cmd_param[0] < 0) || (sec->cmd_param[0] >= (tsp->ch_num.tx))) {
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "%d", prox_node_value[sec->cmd_param[0]]);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
void run_cs_raw_read_all(void *dev_data)
|
|
{
|
|
int i, j, idx, ret;
|
|
int count = 0;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
u8 flag = NODE_FLAG_CDC;
|
|
char buff[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
ret = ist40xx_read_touch_node(data, flag, &tsp->node);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
input_err(true, &data->client->dev, "%s: tsp node read fail!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
ist40xx_parse_touch_node(data, &tsp->node);
|
|
|
|
ret = parse_tsp_node(data, flag, &tsp->node, node_value, self_node_value,
|
|
prox_node_value);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp node parse fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
buf = kmalloc(IST40XX_MAX_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->ch_num.tx; i++) {
|
|
for (j = 0; j < tsp->ch_num.rx; j++) {
|
|
idx = i * tsp->ch_num.rx + j;
|
|
count += snprintf(msg, msg_len, "%d,", node_value[idx]);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count - 1);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buff, sizeof(buff), "NG");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void run_cs_delta_read_all(void *dev_data)
|
|
{
|
|
int i, j, idx, ret;
|
|
int count = 0;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
u8 flag = NODE_FLAG_CDC;
|
|
char buff[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
ret = ist40xx_read_touch_node(data, flag, &tsp->node);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
input_err(true, &data->client->dev, "%s: tsp node read fail!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
ist40xx_parse_touch_node(data, &tsp->node);
|
|
|
|
ret = parse_tsp_node(data, flag, &tsp->node, node_value, self_node_value,
|
|
prox_node_value);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: tsp node parse fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
buf = kmalloc(IST40XX_MAX_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->ch_num.tx; i++) {
|
|
for (j = 0; j < tsp->ch_num.rx; j++) {
|
|
idx = i * tsp->ch_num.rx + j;
|
|
count += snprintf(msg, msg_len, "%d,",
|
|
node_value[idx] - tsp->baseline);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count - 1);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buff, sizeof(buff), "NG");
|
|
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
#define MAX_DCM_DEFAULT 500
|
|
void get_max_dcm(void *dev_data)
|
|
{
|
|
int ret = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
u32 max_dcm = 0;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_read_cmd(data, eHCOM_GET_MAX_DCM, &max_dcm);
|
|
if (ret) {
|
|
ist40xx_reset(data, false);
|
|
ist40xx_start(data);
|
|
max_dcm = 0;
|
|
}
|
|
|
|
out:
|
|
if (max_dcm == 0)
|
|
max_dcm = MAX_DCM_DEFAULT;
|
|
|
|
snprintf(buf, sizeof(buf), "%d", max_dcm);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
extern u8 *ts_cmcs_bin;
|
|
extern u32 ts_cmcs_bin_size;
|
|
extern CMCS_BUF *cmcs_buf;
|
|
static int tx_cm_gap_value[IST40XX_MAX_NODE_NUM];
|
|
static int rx_cm_gap_value[IST40XX_MAX_NODE_NUM];
|
|
|
|
int get_read_all_data(struct ist40xx_data *data, u8 flag)
|
|
{
|
|
int ii;
|
|
int count = 0;
|
|
int type;
|
|
char *buffer;
|
|
char *temp;
|
|
int ret;
|
|
u32 cmcs_flag = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)&data->sec;
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
if (flag == TEST_CM_ALL_DATA)
|
|
cmcs_flag = CMCS_FLAG_CM;
|
|
else if ((flag == TEST_SLOPE0_ALL_DATA) || (flag == TEST_SLOPE1_ALL_DATA))
|
|
cmcs_flag = CMCS_FLAG_CM | CMCS_FLAG_SLOPE;
|
|
else if (flag == TEST_CS_ALL_DATA)
|
|
cmcs_flag = CMCS_FLAG_CS;
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
ret = ist40xx_cmcs_test(data, cmcs_flag);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
input_err(true, &data->client->dev, "%s: tsp cmcs test fail!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
buffer = kzalloc(IST40XX_MAX_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buffer) {
|
|
input_err(true, &data->client->dev, "%s: failed to buffer alloc\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
temp = kzalloc(10, GFP_KERNEL);
|
|
if (!temp) {
|
|
input_err(true, &data->client->dev, "%s: failed to temp alloc\n",
|
|
__func__);
|
|
goto alloc_out;
|
|
}
|
|
|
|
for (ii = 0; ii < tsp->ch_num.rx * tsp->ch_num.tx; ii++) {
|
|
type = check_tsp_type(data, ii / tsp->ch_num.rx, ii % tsp->ch_num.rx);
|
|
if ((type == TSP_CH_UNKNOWN) || (type == TSP_CH_UNUSED)) {
|
|
count += snprintf(temp, 10, "%d,", 0);
|
|
} else {
|
|
switch (flag) {
|
|
case TEST_CM_ALL_DATA:
|
|
count += snprintf(temp, 10, "%d,", cmcs_buf->cm[ii]);
|
|
break;
|
|
case TEST_SLOPE0_ALL_DATA:
|
|
count += snprintf(temp, 10, "%d,", cmcs_buf->slope0[ii]);
|
|
break;
|
|
case TEST_SLOPE1_ALL_DATA:
|
|
count += snprintf(temp, 10, "%d,", cmcs_buf->slope1[ii]);
|
|
break;
|
|
case TEST_CS_ALL_DATA:
|
|
count += snprintf(temp, 10, "%d,", cmcs_buf->cs[ii]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
strncat(buffer, temp, 10);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buffer, count - 1);
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buffer,
|
|
strnlen(buffer, sizeof(buffer)) - 1);
|
|
|
|
kfree(buffer);
|
|
kfree(temp);
|
|
|
|
return 0;
|
|
|
|
alloc_out:
|
|
kfree(buffer);
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
return -1;
|
|
}
|
|
|
|
void get_cm_all_data(void *dev_data)
|
|
{
|
|
int ret;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
ret = get_read_all_data(data, TEST_CM_ALL_DATA);
|
|
if (ret < 0)
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
else
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
void run_cm_read_all(void *dev_data)
|
|
{
|
|
int ret;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_get_cmcs_info(ts_cmcs_bin, ts_cmcs_bin_size);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: get cmcs info read fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = get_read_all_data(data, TEST_CM_ALL_DATA);
|
|
if (ret < 0)
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
else
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void get_slope0_all_data(void *dev_data)
|
|
{
|
|
int ret;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
ret = get_read_all_data(data, TEST_SLOPE0_ALL_DATA);
|
|
if (ret < 0)
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
else
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
void get_slope1_all_data(void *dev_data)
|
|
{
|
|
int ret;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
ret = get_read_all_data(data, TEST_SLOPE1_ALL_DATA);
|
|
if (ret < 0)
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
else
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
void get_cs_all_data(void *dev_data)
|
|
{
|
|
int ret;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
ret = get_read_all_data(data, TEST_CS_ALL_DATA);
|
|
if (ret < 0)
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
else
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
void run_cm_test(void *dev_data)
|
|
{
|
|
int i, j;
|
|
int ret = 0;
|
|
char buf[16] = { 0 };
|
|
int type, idx;
|
|
int next_idx;
|
|
int last_col;
|
|
int min_val, max_val;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_get_cmcs_info(ts_cmcs_bin, ts_cmcs_bin_size);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: get cmcs info read fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
ret = ist40xx_cmcs_test(data, CMCS_FLAG_CM);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
input_err(true, &data->client->dev, "%s: tsp cmcs test fail!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
/* tx gap = abs(x-y)/x * 100 with x=Rx0,Tx0, y=Rx0,Tx1, ...*/
|
|
for (i = 0; i < tsp->ch_num.tx - 1; i++) {
|
|
for (j = 0; j < tsp->ch_num.rx; j++) {
|
|
idx = i * tsp->ch_num.rx + j;
|
|
next_idx = idx + tsp->ch_num.rx;
|
|
|
|
if (cmcs_buf->cm[idx]) {
|
|
tx_cm_gap_value[idx] = 100 -
|
|
DIV_ROUND_CLOSEST(100 *
|
|
min(cmcs_buf->cm[idx], cmcs_buf->cm[next_idx]),
|
|
max(cmcs_buf->cm[idx], cmcs_buf->cm[next_idx]));
|
|
} else {
|
|
tx_cm_gap_value[idx] = 9999; /* the value is out of spec */
|
|
}
|
|
}
|
|
}
|
|
/*rx gap = abs(x-y)/x * 100 with x=Rx0,Tx0, y=Rx1,Tx0, ... */
|
|
last_col = tsp->ch_num.rx - 1;
|
|
for (i = 0; i < tsp->ch_num.tx; i++) {
|
|
for (j = 0; j < tsp->ch_num.rx; j++) {
|
|
idx = i * tsp->ch_num.rx + j;
|
|
if ((idx % tsp->ch_num.rx) == last_col)
|
|
continue;
|
|
|
|
next_idx = idx + 1;
|
|
|
|
if (cmcs_buf->cm[idx]) {
|
|
rx_cm_gap_value[idx] = 100 -
|
|
DIV_ROUND_CLOSEST(100 *
|
|
min(cmcs_buf->cm[idx], cmcs_buf->cm[next_idx]),
|
|
max(cmcs_buf->cm[idx], cmcs_buf->cm[next_idx]));
|
|
} else {
|
|
rx_cm_gap_value[idx] = 9999; /* the value is out of spec */
|
|
}
|
|
}
|
|
}
|
|
|
|
min_val = max_val = cmcs_buf->cm[0];
|
|
for (i = 0; i < tsp->ch_num.tx; i++) {
|
|
for (j = 0; j < tsp->ch_num.rx; j++) {
|
|
idx = (i * tsp->ch_num.rx) + j;
|
|
|
|
type = check_tsp_type(data, i, j);
|
|
if (type == TSP_CH_USED) {
|
|
max_val = max(max_val, (int)cmcs_buf->cm[idx]);
|
|
min_val = min(min_val, (int)cmcs_buf->cm[idx]);
|
|
}
|
|
}
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "%d,%d,%d", min_val, max_val, max_val - min_val);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)), "CM");
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)), "CM");
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void get_cm_value(void *dev_data)
|
|
{
|
|
int idx = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
idx = check_tsp_channel(data, tsp->ch_num.rx, tsp->ch_num.tx);
|
|
if (idx < 0) { // Parameter parsing fail
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "%d", cmcs_buf->cm[idx]);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
void get_cm_maxgap_value(void *dev_data)
|
|
{
|
|
int i, j;
|
|
int idx;
|
|
int last_col;
|
|
int max_cm_gap_tx;
|
|
int max_cm_gap_rx;
|
|
char buf[16] = { 0 };
|
|
char buf_onecmd[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
max_cm_gap_tx = tx_cm_gap_value[0];
|
|
|
|
for (i = 0; i < tsp->ch_num.tx - 1; i++) {
|
|
for (j = 0; j < tsp->ch_num.rx; j++) {
|
|
idx = i * tsp->ch_num.rx + j;
|
|
max_cm_gap_tx = max(max_cm_gap_tx, tx_cm_gap_value[idx]);
|
|
}
|
|
}
|
|
|
|
max_cm_gap_rx = rx_cm_gap_value[0];
|
|
last_col = tsp->ch_num.rx - 1;
|
|
|
|
for (i = 0; i < tsp->ch_num.tx; i++) {
|
|
for (j = 0; j < tsp->ch_num.rx; j++) {
|
|
idx = i * tsp->ch_num.rx + j;
|
|
if ((idx % tsp->ch_num.rx) == last_col)
|
|
continue;
|
|
|
|
max_cm_gap_rx = max(max_cm_gap_rx, rx_cm_gap_value[idx]);
|
|
}
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "%d,%d", max_cm_gap_tx, max_cm_gap_rx);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
|
|
snprintf(buf_onecmd, sizeof(buf_onecmd), "0,%d",
|
|
max(max_cm_gap_rx, max_cm_gap_tx));
|
|
sec_cmd_set_cmd_result_all(sec, buf_onecmd,
|
|
strnlen(buf_onecmd, sizeof(buf_onecmd)),
|
|
"CM_GAP");
|
|
}
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
#define CMD_RESULT_WORD_LEN 10
|
|
void get_cm_maxgap_all(void *dev_data)
|
|
{
|
|
char temp[CMD_RESULT_WORD_LEN] = { 0 };
|
|
char *buf = NULL;
|
|
int total_node, ii;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
total_node = tsp->ch_num.rx * tsp->ch_num.tx;
|
|
buf = kzalloc(total_node * CMD_RESULT_WORD_LEN, GFP_KERNEL);
|
|
if (!buf)
|
|
return;
|
|
|
|
for (ii = 0; ii < total_node; ii++) {
|
|
snprintf(temp, CMD_RESULT_WORD_LEN, "%d,", max(tx_cm_gap_value[ii],
|
|
rx_cm_gap_value[ii]));
|
|
strncat(buf, temp, CMD_RESULT_WORD_LEN);
|
|
memset(temp, 0x00, CMD_RESULT_WORD_LEN);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf,
|
|
total_node * CMD_RESULT_WORD_LEN));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
kfree(buf);
|
|
}
|
|
|
|
void get_tx_cm_gap_value(void *dev_data)
|
|
{
|
|
int idx = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
idx = check_tsp_channel(data, tsp->ch_num.rx, tsp->ch_num.tx);
|
|
if (idx < 0) { // Parameter parsing fail
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "%d", tx_cm_gap_value[idx]);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
void get_rx_cm_gap_value(void *dev_data)
|
|
{
|
|
int idx = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
idx = check_tsp_channel(data, tsp->ch_num.rx, tsp->ch_num.tx);
|
|
if (idx < 0) { // Parameter parsing fail
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "%d", rx_cm_gap_value[idx]);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
void run_cmjit_test(void *dev_data)
|
|
{
|
|
int i, j;
|
|
int ret = 0;
|
|
char buf[16] = { 0 };
|
|
int type, idx;
|
|
int min_val, max_val;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_get_cmcs_info(ts_cmcs_bin, ts_cmcs_bin_size);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: get cmcs info read fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
ret = ist40xx_cmcs_test(data, CMCS_FLAG_CMJIT);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
input_err(true, &data->client->dev, "%s: tsp cmcs test fail!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
min_val = max_val = cmcs_buf->cm_jit[0];
|
|
|
|
for (i = 0; i < tsp->ch_num.tx; i++) {
|
|
for (j = 0; j < tsp->ch_num.rx; j++) {
|
|
idx = (i * tsp->ch_num.rx) + j;
|
|
type = check_tsp_type(data, i, j);
|
|
|
|
if (type == TSP_CH_USED) {
|
|
max_val = max(max_val, (int)cmcs_buf->cm_jit[idx]);
|
|
min_val = min(min_val, (int)cmcs_buf->cm_jit[idx]);
|
|
}
|
|
}
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "%d,%d", min_val, max_val);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void get_cmjit_value(void *dev_data)
|
|
{
|
|
int idx = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
idx = check_tsp_channel(data, tsp->ch_num.rx, tsp->ch_num.tx);
|
|
if (idx < 0) { // Parameter parsing fail
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
} else {
|
|
snprintf(buf, sizeof(buf), "%d", cmcs_buf->cm_jit[idx]);
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
void run_cmcs_test(void *dev_data)
|
|
{
|
|
int ret = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_get_cmcs_info(ts_cmcs_bin, ts_cmcs_bin_size);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: get cmcs info read fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
ret = ist40xx_cmcs_test(data, CMCS_FLAG_CM);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
input_err(true, &data->client->dev, "%s: tsp cmcs test fail!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
snprintf(buf, sizeof(buf), "%s", "OK");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void get_cm_array(void *dev_data)
|
|
{
|
|
int i;
|
|
int count = 0;
|
|
int type;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
buf = kmalloc(IST40XX_MAX_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: couldn't allocate memory\n", __func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->ch_num.rx * tsp->ch_num.tx; i++) {
|
|
type = check_tsp_type(data, i / tsp->ch_num.rx, i % tsp->ch_num.rx);
|
|
if ((type == TSP_CH_UNKNOWN) || (type == TSP_CH_UNUSED))
|
|
count += snprintf(msg, msg_len, "%d,", 0);
|
|
else
|
|
count += snprintf(msg, msg_len, "%d,", cmcs_buf->cm[i]);
|
|
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void get_slope0_array(void *dev_data)
|
|
{
|
|
int i;
|
|
int count = 0;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
buf = kmalloc(IST40XX_MAX_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->ch_num.rx * tsp->ch_num.tx; i++) {
|
|
count += snprintf(msg, msg_len, "%d,", cmcs_buf->slope0[i]);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count - 1);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void get_slope1_array(void *dev_data)
|
|
{
|
|
int i;
|
|
int count = 0;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
buf = kmalloc(IST40XX_MAX_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->ch_num.rx * tsp->ch_num.tx; i++) {
|
|
count += snprintf(msg, msg_len, "%d,", cmcs_buf->slope1[i]);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count - 1);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void get_cs_array(void *dev_data)
|
|
{
|
|
int i;
|
|
int count = 0;
|
|
int type;
|
|
char *buf;
|
|
const int msg_len = 16;
|
|
char msg[msg_len];
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
buf = kmalloc(IST40XX_MAX_NODE_NUM * 5, GFP_KERNEL);
|
|
if (!buf) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0, IST40XX_MAX_NODE_NUM * 5);
|
|
|
|
for (i = 0; i < tsp->ch_num.rx * tsp->ch_num.tx; i++) {
|
|
type = check_tsp_type(data, i / tsp->ch_num.rx, i % tsp->ch_num.rx);
|
|
if ((type == TSP_CH_UNKNOWN) || (type == TSP_CH_UNUSED))
|
|
count += snprintf(msg, msg_len, "%d,", 0);
|
|
else
|
|
count += snprintf(msg, msg_len, "%d,", cmcs_buf->cs[i]);
|
|
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, count - 1);
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf, count - 1);
|
|
|
|
kfree(buf);
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void check_fail_channel(struct ist40xx_data *data, u32 *tx_result,
|
|
u32 *rx_result, char *buf)
|
|
{
|
|
int i;
|
|
char msg[128] = { 0 };
|
|
char fail_buf[256] = { 0 };
|
|
int count = 0;
|
|
int fail_cnt = 0;
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
count = sprintf(msg, "(");
|
|
strcat(fail_buf, msg);
|
|
|
|
for (i = 0; i < tsp->ch_num.tx; i++) {
|
|
if (fail_cnt >= 5)
|
|
break;
|
|
|
|
if (i < 32) {
|
|
if ((tx_result[0] >> i) & 0x1) {
|
|
count += sprintf(msg, "TX%d,", i);
|
|
strcat(fail_buf, msg);
|
|
fail_cnt++;
|
|
}
|
|
} else {
|
|
if ((tx_result[1] >> (i - 32)) & 0x1) {
|
|
count += sprintf(msg, "TX%d,", i);
|
|
strcat(fail_buf, msg);
|
|
fail_cnt++;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < tsp->ch_num.rx; i++) {
|
|
if (fail_cnt >= 5)
|
|
break;
|
|
|
|
if (i < 32) {
|
|
if ((rx_result[0] >> i) & 0x1) {
|
|
count += sprintf(msg, "RX%d,", i);
|
|
strcat(fail_buf, msg);
|
|
fail_cnt++;
|
|
}
|
|
} else {
|
|
if ((rx_result[1] >> (i - 32)) & 0x1) {
|
|
count += sprintf(msg, "RX%d,", i);
|
|
strcat(fail_buf, msg);
|
|
fail_cnt++;
|
|
}
|
|
}
|
|
}
|
|
|
|
strncat(buf, fail_buf, strlen(fail_buf) - 1);
|
|
|
|
sprintf(msg, ")");
|
|
strcat(buf, msg);
|
|
}
|
|
|
|
void run_cmcs_full_test(void *dev_data)
|
|
{
|
|
int ret = 0;
|
|
bool cm_result, cs_result, micro_cm_result, old_cmd = 0;
|
|
char msg[128] = { 0 };
|
|
char fail_msg[256] = { 0 };
|
|
char buf[256] = { 0 };
|
|
char test[32];
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev, "%s: couldn't allocate memory\n",
|
|
__func__);
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
goto out;
|
|
}
|
|
|
|
snprintf(test, sizeof(test), "%d", sec->cmd_param[0]);
|
|
|
|
memset(msg, 0, sizeof(msg));
|
|
|
|
if (sec->cmd_param[0] == 3) {
|
|
/* 3 : bridge short, micro short */
|
|
sprintf(msg, "NA");
|
|
strcat(buf, msg);
|
|
goto na;
|
|
}
|
|
|
|
if (sec->cmd_param[0] == 1 && sec->cmd_param[1] == 1) {
|
|
ret = ist40xx_get_cmcs_info(ts_cmcs_bin, ts_cmcs_bin_size);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: get cmcs info read fail!\n",
|
|
__func__);
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
goto out;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
ret = ist40xx_cmcs_test(data,
|
|
CMCS_FLAG_CM | CMCS_FLAG_SLOPE | CMCS_FLAG_CS);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
input_err(true, &data->client->dev, "%s: tsp cmcs test fail!\n",
|
|
__func__);
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
goto out;
|
|
}
|
|
|
|
mutex_unlock(&data->lock);
|
|
}
|
|
|
|
/* CM result */
|
|
if (cmcs_buf->cm_result == 1) {
|
|
cm_result = 1;
|
|
input_err(true, &data->client->dev, "CM result: fail\n");
|
|
} else {
|
|
cm_result = 0;
|
|
input_err(true, &data->client->dev, "CM result: pass\n");
|
|
}
|
|
|
|
/* CS result */
|
|
if (cmcs_buf->cs_result == 1) {
|
|
cs_result = 1;
|
|
input_err(true, &data->client->dev, "CS result: fail\n");
|
|
} else {
|
|
cs_result = 0;
|
|
input_err(true, &data->client->dev, "CS result: pass\n");
|
|
}
|
|
|
|
/* Micro cm result */
|
|
if ((cmcs_buf->cm_result == 0) && (cmcs_buf->slope_result == 1)) {
|
|
micro_cm_result = 1;
|
|
input_err(true, &data->client->dev, "Micro CM result: fail\n");
|
|
} else {
|
|
micro_cm_result = 0;
|
|
input_err(true, &data->client->dev, "Micro CM result: pass\n");
|
|
}
|
|
|
|
memset(fail_msg, 0, sizeof(fail_msg));
|
|
|
|
if (sec->cmd_param[0] == 1 && sec->cmd_param[1] == 1) {
|
|
/* 1,1 : open */
|
|
if (cm_result) {
|
|
check_fail_channel(data, cmcs_buf->cm_tx_result,
|
|
cmcs_buf->cm_rx_result, fail_msg);
|
|
sprintf(msg, "OPEN:%s", fail_msg);
|
|
strcat(buf, msg);
|
|
goto out;
|
|
} else {
|
|
sprintf(msg, "OPEN:OK");
|
|
strcat(buf, msg);
|
|
}
|
|
} else if (sec->cmd_param[0] == 1 && sec->cmd_param[1] == 2) {
|
|
/* 1,2 : short */
|
|
if (cs_result) {
|
|
check_fail_channel(data, cmcs_buf->cs_tx_result,
|
|
cmcs_buf->cs_rx_result, fail_msg);
|
|
sprintf(msg, "SHORT:%s", fail_msg);
|
|
strcat(buf, msg);
|
|
goto out;
|
|
} else {
|
|
sprintf(msg, "SHORT:OK");
|
|
strcat(buf, msg);
|
|
}
|
|
} else if (sec->cmd_param[0] == 2) {
|
|
/* 2 : micro open, crack */
|
|
if (micro_cm_result) {
|
|
check_fail_channel(data, cmcs_buf->cm_slope_result,
|
|
cmcs_buf->cm_slope_result, fail_msg);
|
|
sprintf(msg, "CRACK:%s", fail_msg);
|
|
strcat(buf, msg);
|
|
goto out;
|
|
} else {
|
|
sprintf(msg, "CRACK:OK");
|
|
strcat(buf, msg);
|
|
}
|
|
} else if (sec->cmd_param[0] == 1 && sec->cmd_param[1] == 0) {
|
|
/* 1,0 : old command, return CONT */
|
|
sprintf(msg, "CONT");
|
|
strcat(buf, msg);
|
|
} else {
|
|
/* 0 or else : old command */
|
|
old_cmd = true;
|
|
if (cm_result) {
|
|
check_fail_channel(data, cmcs_buf->cm_tx_result,
|
|
cmcs_buf->cm_rx_result, fail_msg);
|
|
sprintf(msg, "FAIL%s;", fail_msg);
|
|
} else {
|
|
sprintf(msg, "PASS;");
|
|
}
|
|
strcat(buf, msg);
|
|
|
|
memset(fail_msg, 0, sizeof(fail_msg));
|
|
if (cs_result) {
|
|
check_fail_channel(data, cmcs_buf->cs_tx_result,
|
|
cmcs_buf->cs_rx_result, fail_msg);
|
|
sprintf(msg, "FAIL%s;", fail_msg);
|
|
} else {
|
|
sprintf(msg, "PASS;");
|
|
}
|
|
strcat(buf, msg);
|
|
|
|
memset(fail_msg, 0, sizeof(fail_msg));
|
|
if (micro_cm_result) {
|
|
check_fail_channel(data, cmcs_buf->slope_tx_result,
|
|
cmcs_buf->slope_rx_result, fail_msg);
|
|
sprintf(msg, "FAIL;%s", fail_msg);
|
|
} else {
|
|
sprintf(msg, "PASS;");
|
|
}
|
|
strcat(buf, msg);
|
|
|
|
sprintf(msg, "NA");
|
|
strcat(buf, msg);
|
|
|
|
|
|
if (strnstr(msg, "T", sizeof(msg)))
|
|
data->ito_test[3] |= 0x10;
|
|
if (strnstr(msg, "R", sizeof(msg)))
|
|
data->ito_test[3] |= 0x20;
|
|
if (cs_result)
|
|
data->ito_test[3] |= 0x0F;
|
|
}
|
|
|
|
na:
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
if (sec->cmd_param[0] == 3) {
|
|
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
|
|
}
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
|
|
if (old_cmd ||cm_result || cs_result || micro_cm_result)
|
|
sec_cmd_send_event_to_user(sec, test, "RESULT=FAIL");
|
|
else
|
|
sec_cmd_send_event_to_user(sec, test, "RESULT=PASS");
|
|
|
|
return;
|
|
|
|
out:
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
|
|
sec_cmd_send_event_to_user(sec, test, "RESULT=FAIL");
|
|
}
|
|
|
|
void run_cr_variance_read(void *dev_data)
|
|
{
|
|
int ret = 0;
|
|
char buf[64] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
memset(cmcs_buf->cr_variance, 0, sizeof(cmcs_buf->cr_variance));
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_get_cmcs_info(ts_cmcs_bin, ts_cmcs_bin_size);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: get cmcs info read fail!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
|
|
ret = ist40xx_cmcs_test(data, CMCS_FLAG_CRJIT2);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
input_err(true, &data->client->dev, "%s: tsp cmcs test fail!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
/* check spec (temp) */
|
|
if ((cmcs_buf->cr_variance2[0] > 10000) || (cmcs_buf->cr_variance2[1] > 10000) ||
|
|
(cmcs_buf->cr_variance2[2] > 10000)) {
|
|
input_info(true, &data->client->dev, "%s: spec fail\n", __func__);
|
|
goto out;
|
|
}
|
|
|
|
// Result : Variance, MaxSum, MaxPeak
|
|
snprintf(buf, sizeof(buf), "OK,%d,%d,%d", cmcs_buf->cr_variance2[0],
|
|
cmcs_buf->cr_variance2[1], cmcs_buf->cr_variance2[2]);
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG,%d,%d,%d", cmcs_buf->cr_variance2[0],
|
|
cmcs_buf->cr_variance2[1], cmcs_buf->cr_variance2[2]);
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
int ist40xx_execute_force_calibration(struct i2c_client *client, int cal_mode)
|
|
{
|
|
struct ist40xx_data *data = i2c_get_clientdata(client);
|
|
int ret = -ENOEXEC;
|
|
int wait_cnt = 1;
|
|
|
|
input_info(true, &data->client->dev, "*** Force Auto Calibrate %ds ***\n",
|
|
CALIB_WAIT_TIME / 10);
|
|
|
|
data->status.calib = 1;
|
|
ist40xx_disable_irq(data);
|
|
while (1) {
|
|
ret = ist40xx_cmd_calibrate(data);
|
|
if (ret)
|
|
continue;
|
|
|
|
ist40xx_enable_irq(data);
|
|
ret = ist40xx_calib_wait(data);
|
|
if (!ret)
|
|
break;
|
|
|
|
ist40xx_disable_irq(data);
|
|
|
|
if (--wait_cnt == 0)
|
|
break;
|
|
|
|
ist40xx_reset(data, false);
|
|
}
|
|
|
|
ist40xx_disable_irq(data);
|
|
ist40xx_reset(data, false);
|
|
data->status.calib = 0;
|
|
ist40xx_enable_irq(data);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void run_force_calibration(void *dev_data)
|
|
{
|
|
int ret = 0;
|
|
char buf[16] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
if (data->touch_pressed_num != 0) {
|
|
input_err(true, &data->client->dev, "%s: return (finger cnt %d)\n",
|
|
__func__, data->touch_pressed_num);
|
|
|
|
goto out;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
ist40xx_reset(data, false);
|
|
|
|
ret = ist40xx_execute_force_calibration(data->client, 0);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
snprintf(buf, sizeof(buf), "%s", "NG");
|
|
} else {
|
|
#ifdef TCLM_CONCEPT
|
|
/* devide tclm case */
|
|
sec_tclm_case(data->tdata, sec->cmd_param[0]);
|
|
|
|
input_info(true, &data->client->dev, "%s: param, %d, %c, %d\n",
|
|
__func__, sec->cmd_param[0], sec->cmd_param[0],
|
|
data->tdata->root_of_calibration);
|
|
|
|
ret = sec_execute_tclm_package(data->tdata, 1);
|
|
if (ret < 0) {
|
|
input_info(true, &data->client->dev,
|
|
"%s: sec_execute_tclm_package\n", __func__);
|
|
}
|
|
|
|
sec_tclm_root_of_cal(data->tdata, CALPOSITION_NONE);
|
|
#endif
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
snprintf(buf, sizeof(buf), "%s", "OK");
|
|
}
|
|
|
|
ist40xx_start(data);
|
|
|
|
mutex_unlock(&data->lock);
|
|
|
|
data->tdata->external_factory = false;
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
|
|
if (data->dt_data->enable_fpcb_noise_test) {
|
|
ist40xx_delay(300);
|
|
get_fpcb_noise(sec);
|
|
}
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "%s", "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
void get_force_calibration(void *dev_data)
|
|
{
|
|
int ret = 0;
|
|
char buf[16] = { 0 };
|
|
u32 calib_msg;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
|
|
goto err;
|
|
}
|
|
|
|
ret = ist40xx_read_cmd(data, eHCOM_GET_CAL_RESULT_S, &calib_msg);
|
|
if (ret) {
|
|
mutex_lock(&data->lock);
|
|
ist40xx_reset(data, false);
|
|
ist40xx_start(data);
|
|
mutex_unlock(&data->lock);
|
|
|
|
snprintf(buf, sizeof(buf), "%s", "NG");
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev, "Error Read SLF Calibration Result\n");
|
|
|
|
goto err;
|
|
}
|
|
|
|
if (((calib_msg & CALIB_MSG_MASK) != CALIB_MSG_VALID) ||
|
|
(CALIB_TO_STATUS(calib_msg) != 0)) {
|
|
snprintf(buf, sizeof(buf), "%s", "NG");
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
goto err;
|
|
}
|
|
|
|
ret = ist40xx_read_cmd(data, eHCOM_GET_CAL_RESULT_M, &calib_msg);
|
|
if (ret) {
|
|
mutex_lock(&data->lock);
|
|
ist40xx_reset(data, false);
|
|
ist40xx_start(data);
|
|
mutex_unlock(&data->lock);
|
|
|
|
snprintf(buf, sizeof(buf), "%s", "NG");
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev, "Error Read MTL Calibration Result\n");
|
|
|
|
goto err;
|
|
}
|
|
|
|
if (((calib_msg & CALIB_MSG_MASK) != CALIB_MSG_VALID) ||
|
|
(CALIB_TO_STATUS(calib_msg) != 0)) {
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
goto err;
|
|
}
|
|
|
|
ret = ist40xx_read_cmd(data, eHCOM_GET_CAL_RESULT_P, &calib_msg);
|
|
if (ret) {
|
|
mutex_lock(&data->lock);
|
|
ist40xx_reset(data, false);
|
|
ist40xx_start(data);
|
|
mutex_unlock(&data->lock);
|
|
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev, "Error Read PROX Calibration Result\n");
|
|
|
|
goto err;
|
|
}
|
|
|
|
if (((calib_msg & CALIB_MSG_MASK) != CALIB_MSG_VALID) ||
|
|
(CALIB_TO_STATUS(calib_msg) != 0)) {
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
|
|
goto err;
|
|
}
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
err:
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
#ifdef TCLM_CONCEPT
|
|
static void set_external_factory(void *dev_data)
|
|
{
|
|
char buf[22] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
data->tdata->external_factory = true;
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s\n", __func__, buf);
|
|
}
|
|
|
|
int ist40xx_tclm_data_read(struct i2c_client *client, int address)
|
|
{
|
|
int i, ret = 0;
|
|
u32 fw_ver = 0;
|
|
u32 nbuff[IST40XX_NVM_OFFSET_LENGTH];
|
|
struct ist40xx_data *data = i2c_get_clientdata(client);
|
|
|
|
switch (address) {
|
|
case SEC_TCLM_NVM_OFFSET_IC_FIRMWARE_VER:
|
|
fw_ver = ist40xx_get_fw_ver(data);
|
|
/*need check 16 or 32 bits*/
|
|
return (fw_ver & 0xFFFF);
|
|
|
|
case SEC_TCLM_NVM_ALL_DATA:
|
|
ret = ist40xx_read_sec_info(data, IST40XX_NVM_OFFSET_FAC_RESULT, nbuff,
|
|
IST40XX_NVM_OFFSET_LENGTH);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: [ERROR] read_tsp_nvm_data ret:%d\n",
|
|
__func__, ret);
|
|
return -1;
|
|
}
|
|
|
|
data->test_result.data[0] =
|
|
(u8)(nbuff[IST40XX_NVM_OFFSET_FAC_RESULT] & 0xFF);
|
|
data->disassemble_count = nbuff[IST40XX_NVM_OFFSET_DISASSEMBLE_COUNT];
|
|
data->tdata->nvdata.cal_count =
|
|
(u8)(nbuff[IST40XX_NVM_OFFSET_CAL_COUNT] & 0xFF);
|
|
data->tdata->nvdata.tune_fix_ver =
|
|
(u16)(nbuff[IST40XX_NVM_OFFSET_TUNE_VERSION] & 0xFFFF);
|
|
data->tdata->nvdata.cal_position =
|
|
(u8)(nbuff[IST40XX_NVM_OFFSET_CAL_POSITION] & 0xFF);
|
|
data->tdata->nvdata.cal_pos_hist_cnt =
|
|
(u8)(nbuff[IST40XX_NVM_OFFSET_HISTORY_QUEUE_COUNT] & 0xFF);
|
|
data->tdata->nvdata.cal_pos_hist_lastp =
|
|
(u8)(nbuff[IST40XX_NVM_OFFSET_HISTORY_QUEUE_LASTP] & 0xFF);
|
|
|
|
for (i = IST40XX_NVM_OFFSET_HISTORY_QUEUE_ZERO; i < IST40XX_NVM_OFFSET_LENGTH; i++) {
|
|
data->tdata->nvdata.cal_pos_hist_queue[2 * (i - IST40XX_NVM_OFFSET_HISTORY_QUEUE_ZERO)] = (u8)((nbuff[i] & 0xFFFF) >> 8);
|
|
data->tdata->nvdata.cal_pos_hist_queue[2 * (i - IST40XX_NVM_OFFSET_HISTORY_QUEUE_ZERO) + 1] = (u8)(nbuff[i] & 0xFF);
|
|
}
|
|
|
|
input_info(true, &data->client->dev, "%s: %d %X %x %d %d\n",
|
|
__func__, data->tdata->nvdata.cal_count,
|
|
data->tdata->nvdata.tune_fix_ver,
|
|
data->tdata->nvdata.cal_position,
|
|
data->tdata->nvdata.cal_pos_hist_cnt,
|
|
data->tdata->nvdata.cal_pos_hist_lastp);
|
|
|
|
return ret;
|
|
default:
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
int ist40xx_tclm_data_write(struct i2c_client *client, int address)
|
|
{
|
|
int i, ret = 1;
|
|
u32 nbuff[IST40XX_NVM_OFFSET_LENGTH];
|
|
struct ist40xx_data *data = i2c_get_clientdata(client);
|
|
|
|
input_info(true, &data->client->dev,
|
|
"%s: write SEC_TCLM_NVM_ALL_DATA: %d %X %x %d %d\n", __func__,
|
|
data->tdata->nvdata.cal_count, data->tdata->nvdata.tune_fix_ver,
|
|
data->tdata->nvdata.cal_position,
|
|
data->tdata->nvdata.cal_pos_hist_cnt,
|
|
data->tdata->nvdata.cal_pos_hist_lastp);
|
|
|
|
memset(nbuff, 0x00, IST40XX_NVM_OFFSET_LENGTH);
|
|
|
|
nbuff[IST40XX_NVM_OFFSET_FAC_RESULT] = (u32)data->test_result.data[0];
|
|
nbuff[IST40XX_NVM_OFFSET_DISASSEMBLE_COUNT] = data->disassemble_count;
|
|
nbuff[IST40XX_NVM_OFFSET_CAL_COUNT] = (u32)data->tdata->nvdata.cal_count;
|
|
nbuff[IST40XX_NVM_OFFSET_TUNE_VERSION] =
|
|
(u32)data->tdata->nvdata.tune_fix_ver;
|
|
nbuff[IST40XX_NVM_OFFSET_CAL_POSITION] =
|
|
(u32)data->tdata->nvdata.cal_position;
|
|
nbuff[IST40XX_NVM_OFFSET_HISTORY_QUEUE_COUNT] =
|
|
(u32)data->tdata->nvdata.cal_pos_hist_cnt;
|
|
nbuff[IST40XX_NVM_OFFSET_HISTORY_QUEUE_LASTP] =
|
|
(u32)data->tdata->nvdata.cal_pos_hist_lastp;
|
|
|
|
for (i = IST40XX_NVM_OFFSET_HISTORY_QUEUE_ZERO; i < IST40XX_NVM_OFFSET_LENGTH; i++) {
|
|
nbuff[i] = (u32)((data->tdata->nvdata.cal_pos_hist_queue[2 * (i - IST40XX_NVM_OFFSET_HISTORY_QUEUE_ZERO)] << 8) |
|
|
(data->tdata->nvdata.cal_pos_hist_queue[2 * (i - IST40XX_NVM_OFFSET_HISTORY_QUEUE_ZERO) + 1]));
|
|
}
|
|
|
|
ret = ist40xx_write_sec_info(data, IST40XX_NVM_OFFSET_FAC_RESULT, nbuff,
|
|
IST40XX_NVM_OFFSET_LENGTH);
|
|
if (ret) {
|
|
input_err(true, &data->client->dev, "%s: [ERROR] set_tsp_nvm_data ret:%d\n",
|
|
__func__, ret);
|
|
return -1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void get_pat_information(void *dev_data)
|
|
{
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
char buf[50] = { 0 };
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
snprintf(buf, sizeof(buf), "C%02XT%04X.%4s%s%c%d%c%d%c%d",
|
|
data->tdata->nvdata.cal_count, data->tdata->nvdata.tune_fix_ver,
|
|
data->tdata->tclm_string[data->tdata->nvdata.cal_position].f_name,
|
|
(data->tdata->tclm_level == TCLM_LEVEL_LOCKDOWN) ? ".L " : " ",
|
|
data->tdata->cal_pos_hist_last3[0], data->tdata->cal_pos_hist_last3[1],
|
|
data->tdata->cal_pos_hist_last3[2], data->tdata->cal_pos_hist_last3[3],
|
|
data->tdata->cal_pos_hist_last3[4], data->tdata->cal_pos_hist_last3[5]);
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
/* FACTORY TEST RESULT SAVING FUNCTION
|
|
* bit 3 ~ 0 : OCTA Assy
|
|
* bit 7 ~ 4 : OCTA module
|
|
* param[0] : OCTA module(1) / OCTA Assy(2)
|
|
* param[1] : TEST NONE(0) / TEST FAIL(1) / TEST PASS(2) : 2 bit
|
|
*/
|
|
static void get_tsp_test_result(void *dev_data)
|
|
{
|
|
u32 *buf32;
|
|
int ret;
|
|
int len = 1; //1~32
|
|
char buf[50] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
if (ist40xx_intr_wait(data, 30) < 0) {
|
|
input_err(true, &data->client->dev,"%s: intr wait fail", __func__);
|
|
goto out;
|
|
}
|
|
|
|
buf32 = kzalloc(len * sizeof(u32), GFP_KERNEL);
|
|
if (!buf32) {
|
|
input_err(true, &data->client->dev, "%s: failed to allocate\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_read_sec_info(data, IST40XX_NVM_OFFSET_FAC_RESULT, buf32,
|
|
len);
|
|
if (ret) {
|
|
kfree(buf32);
|
|
input_err(true, &data->client->dev, "%s: sec info read fail\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
input_info(true, &data->client->dev, "%s: [%2d]:%08X\n", __func__, len,
|
|
buf32[0]);
|
|
|
|
data->test_result.data[0] = buf32[0] & 0xff;
|
|
kfree(buf32);
|
|
|
|
input_info(true, &data->client->dev, "%s: %X", __func__,
|
|
data->test_result.data[0]);
|
|
|
|
if (data->test_result.data[0] == 0xFF) {
|
|
input_info(true, &data->client->dev,
|
|
"%s: clear factory_result as zero\n", __func__);
|
|
data->test_result.data[0] = 0;
|
|
}
|
|
|
|
snprintf(buf, sizeof(buf), "M:%s, M:%d, A:%s, A:%d",
|
|
data->test_result.module_result == 0 ? "NONE" :
|
|
data->test_result.module_result == 1 ? "FAIL" : "PASS",
|
|
data->test_result.module_count,
|
|
data->test_result.assy_result == 0 ? "NONE" :
|
|
data->test_result.assy_result == 1 ? "FAIL" : "PASS",
|
|
data->test_result.assy_count);
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s() %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
static void set_tsp_test_result(void *dev_data)
|
|
{
|
|
int ret;
|
|
char buf[16] = { 0 };
|
|
u32 *buf32;
|
|
u32 temp = 0;
|
|
int len = 1; //1~32
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
if (ist40xx_intr_wait(data, 30) < 0) {
|
|
input_err(true, &data->client->dev, "%s: intr wait fail", __func__);
|
|
goto out;
|
|
}
|
|
|
|
buf32 = kzalloc(len * sizeof(u32), GFP_KERNEL);
|
|
if (!buf32) {
|
|
input_err(true, &data->client->dev, "%s: failed to allocate\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_read_sec_info(data, IST40XX_NVM_OFFSET_FAC_RESULT, buf32,
|
|
len);
|
|
if (ret) {
|
|
kfree(buf32);
|
|
input_err(true, &data->client->dev, "%s: sec info read fail\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
input_info(true, &data->client->dev, "%s: [%2d]:%08X\n", __func__, len,
|
|
buf32[0]);
|
|
|
|
data->test_result.data[0] = buf32[0] & 0xff;
|
|
kfree(buf32);
|
|
|
|
input_info(true, &data->client->dev, "%s: %X", __func__,
|
|
data->test_result.data[0]);
|
|
|
|
if (data->test_result.data[0] == 0xFF) {
|
|
input_info(true, &data->client->dev, "%s: clear factory_result as zero\n",
|
|
__func__);
|
|
data->test_result.data[0] = 0;
|
|
}
|
|
|
|
if (sec->cmd_param[0] == TEST_OCTA_ASSAY) {
|
|
data->test_result.assy_result = sec->cmd_param[1];
|
|
if (data->test_result.assy_count < 3)
|
|
data->test_result.assy_count++;
|
|
} else if (sec->cmd_param[0] == TEST_OCTA_MODULE) {
|
|
data->test_result.module_result = sec->cmd_param[1];
|
|
if (data->test_result.module_count < 3)
|
|
data->test_result.module_count++;
|
|
}
|
|
|
|
input_info(true, &data->client->dev, "%s: [0x%X] M:%s, M:%d, A:%s, A:%d\n",
|
|
__func__, data->test_result.data[0],
|
|
data->test_result.module_result == 0 ? "NONE" :
|
|
data->test_result.module_result == 1 ? "FAIL" : "PASS",
|
|
data->test_result.module_count,
|
|
data->test_result.assy_result == 0 ? "NONE" :
|
|
data->test_result.assy_result == 1 ? "FAIL" : "PASS",
|
|
data->test_result.assy_count);
|
|
|
|
temp = data->test_result.data[0];
|
|
ist40xx_write_sec_info(data, IST40XX_NVM_OFFSET_FAC_RESULT, &temp, 1);
|
|
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s() %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP
|
|
void ist40xx_read_sec_info_all(void *dev_data)
|
|
{
|
|
int ret = 0;
|
|
char buf[16] = { 0 };
|
|
u32 *buf32;
|
|
int len = 32; //4~32 (0~32)
|
|
int i;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode == STATE_POWER_OFF) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
if (ist40xx_intr_wait(data, 30) < 0) {
|
|
input_err(true, &data->client->dev, "%s: intr wait fail", __func__);
|
|
goto out;
|
|
}
|
|
|
|
buf32 = kzalloc(len * sizeof(u32), GFP_KERNEL);
|
|
if (!buf32) {
|
|
input_err(true, &data->client->dev, "%s: failed to allocate\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ret = ist40xx_read_sec_info(data, 0, buf32, len);
|
|
if (ret) {
|
|
kfree(buf32);
|
|
input_err(true, &data->client->dev, "%s: sec info read fail\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
for (i = (len - 1); i > 0; i -= 4) {
|
|
input_info(true, &data->client->dev, "%s: [%2d]:%08X %08X %08X %08X\n",
|
|
__func__, i, buf32[i], buf32[i - 1], buf32[i - 2], buf32[i - 3]);
|
|
}
|
|
|
|
kfree(buf32);
|
|
|
|
snprintf(buf, sizeof(buf), "%s", "OK");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
#endif
|
|
|
|
static void increase_disassemble_count(void *dev_data)
|
|
{
|
|
int ret;
|
|
char buf[16] = { 0 };
|
|
u32 buf32[1] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode == STATE_POWER_OFF) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
ist40xx_read_sec_info(data, IST40XX_NVM_OFFSET_DISASSEMBLE_COUNT, buf32, 1);
|
|
|
|
input_info(true, &data->client->dev, "%s: disassemble count is #1 %d\n",
|
|
__func__, buf32[0]);
|
|
|
|
if ((buf32[0] & 0xff) == 0xFF)
|
|
buf32[0] = 0;
|
|
|
|
if (buf32[0] < 0xFE)
|
|
buf32[0]++;
|
|
|
|
data->disassemble_count = buf32[0];
|
|
|
|
ret = ist40xx_write_sec_info(data, IST40XX_NVM_OFFSET_DISASSEMBLE_COUNT,
|
|
buf32, 1);
|
|
if (ret < 0) {
|
|
input_err(true, &data->client->dev, "%s: nvm write failed. ret: %d\n",
|
|
__func__, ret);
|
|
goto out;
|
|
}
|
|
|
|
ist40xx_delay(20);
|
|
|
|
ist40xx_read_sec_info(data, IST40XX_NVM_OFFSET_DISASSEMBLE_COUNT, buf32, 1);
|
|
input_info(true, &data->client->dev, "%s: check disassemble count: %d\n",
|
|
__func__, buf32[0]);
|
|
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
|
|
static void get_disassemble_count(void *dev_data)
|
|
{
|
|
u32 buf32;
|
|
char buf[SEC_CMD_STR_LEN] = { 0 };
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode == STATE_POWER_OFF) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto out;
|
|
}
|
|
|
|
memset(buf, 0x00, SEC_CMD_STR_LEN);
|
|
|
|
ist40xx_read_sec_info(data, IST40XX_NVM_OFFSET_DISASSEMBLE_COUNT, &buf32,
|
|
1);
|
|
if ((buf32 & 0xff) == 0xFF) {
|
|
buf32 = 0;
|
|
ist40xx_write_sec_info(data, IST40XX_NVM_OFFSET_DISASSEMBLE_COUNT,
|
|
&buf32, 1);
|
|
}
|
|
|
|
data->disassemble_count = buf32;
|
|
|
|
input_info(true, &data->client->dev, "%s: read disassemble count: %d\n",
|
|
__func__, buf32 & 0xff);
|
|
|
|
snprintf(buf, sizeof(buf), "%d", buf32 & 0xff);
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
|
|
return;
|
|
|
|
out:
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
}
|
|
#endif
|
|
|
|
static void check_ic_mode(void *dev_data)
|
|
{
|
|
int ret = 0;
|
|
char buf[16] = { 0 };
|
|
u32 status = 0;
|
|
u8 mode = TOUCH_STATUS_NORMAL_MODE;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode == STATE_POWER_ON) {
|
|
ret = ist40xx_read_reg(data->client, IST40XX_HIB_TOUCH_STATUS, &status);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: Failed get the touch status data\n", __func__);
|
|
} else {
|
|
if ((status & TOUCH_STATUS_MASK) == TOUCH_STATUS_MAGIC) {
|
|
if (GET_NOISE_MODE(status))
|
|
mode |= TOUCH_STATUS_NOISE_MODE;
|
|
|
|
if (GET_WET_MODE(status))
|
|
mode |= TOUCH_STATUS_WET_MODE;
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
} else {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: invalid touch status \n", __func__);
|
|
}
|
|
}
|
|
} else {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
}
|
|
|
|
if (sec->cmd_state == SEC_CMD_STATUS_OK)
|
|
snprintf(buf, sizeof(buf), "%d", mode);
|
|
else
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void get_wet_mode(void *dev_data)
|
|
{
|
|
int ret = 0;
|
|
char buf[16] = { 0 };
|
|
u32 status = 0;
|
|
u8 mode = TOUCH_STATUS_NORMAL_MODE;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode == STATE_POWER_ON) {
|
|
ret = ist40xx_read_reg(data->client, IST40XX_HIB_TOUCH_STATUS,
|
|
&status);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: Failed get the touch status data \n", __func__);
|
|
} else {
|
|
if ((status & TOUCH_STATUS_MASK) == TOUCH_STATUS_MAGIC) {
|
|
if (GET_WET_MODE(status))
|
|
mode = true;
|
|
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
} else {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s() invalid touch status \n", __func__);
|
|
}
|
|
}
|
|
} else {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
}
|
|
|
|
if (sec->cmd_state == SEC_CMD_STATUS_OK)
|
|
snprintf(buf, sizeof(buf), "%d", mode);
|
|
else
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
|
|
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
|
|
sec_cmd_set_cmd_result_all(sec, buf, strnlen(buf, sizeof(buf)),
|
|
"WET_MODE");
|
|
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
static void run_fw_integrity(void *dev_data)
|
|
{
|
|
int ret = 0;
|
|
char buf[16] = { 0 };
|
|
u32 integrity = 0;
|
|
u32 chksum = 0;
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec_cmd_set_default_result(sec);
|
|
|
|
if (data->status.sys_mode == STATE_POWER_ON) {
|
|
ist40xx_reset(data, false);
|
|
|
|
ret = ist40xx_read_cmd(data, eHCOM_GET_FW_INTEGRITY, &integrity);
|
|
if (ret) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: Failed get the fw integrity \n", __func__);
|
|
} else {
|
|
if (integrity == IST40XX_EXCEPT_INTEGRITY) {
|
|
chksum = ist40xx_get_fw_chksum(data);
|
|
if (chksum == 0) {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: Failed get the checksum data\n",
|
|
__func__);
|
|
} else {
|
|
sec->cmd_state = SEC_CMD_STATUS_OK;
|
|
}
|
|
} else {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: FW is broken \n", __func__);
|
|
}
|
|
}
|
|
|
|
ist40xx_start(data);
|
|
} else {
|
|
sec->cmd_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
}
|
|
|
|
if (sec->cmd_state == SEC_CMD_STATUS_OK) {
|
|
snprintf(buf, sizeof(buf), "OK");
|
|
input_err(true, &data->client->dev,
|
|
"%s: chksum %08x\n", __func__, chksum);
|
|
} else
|
|
snprintf(buf, sizeof(buf), "NG");
|
|
|
|
sec_cmd_set_cmd_result(sec, buf, strnlen(buf, sizeof(buf)));
|
|
input_info(true, &data->client->dev, "%s: %s(%d)\n", __func__, buf,
|
|
(int)strnlen(buf, sizeof(buf)));
|
|
}
|
|
|
|
/* sysfs: /sys/class/sec/tsp/close_tsp_test */
|
|
static ssize_t show_close_tsp_test(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return snprintf(buf, FACTORY_BUF_SIZE, "%u\n", 0);
|
|
}
|
|
|
|
static void factory_cmd_result_all(void *dev_data)
|
|
{
|
|
struct sec_cmd_data *sec = (struct sec_cmd_data *)dev_data;
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
sec->item_count = 0;
|
|
memset(sec->cmd_result_all, 0x00, SEC_CMD_RESULT_STR_LEN);
|
|
|
|
if (data->status.sys_mode != STATE_POWER_ON) {
|
|
sec->cmd_all_factory_state = SEC_CMD_STATUS_FAIL;
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
|
|
goto out;
|
|
}
|
|
|
|
sec->cmd_all_factory_state = SEC_CMD_STATUS_RUNNING;
|
|
|
|
get_chip_vendor(sec);
|
|
get_chip_name(sec);
|
|
get_fw_ver_bin(sec);
|
|
get_fw_ver_ic(sec);
|
|
|
|
ist40xx_delay(300); /* need Stabilize time after reset(cal) */
|
|
|
|
run_cdc_read(sec); /*run_reference_read*/
|
|
run_self_cdc_read(sec); /*run_self_reference_read*/
|
|
run_prox_cdc_read(sec);
|
|
get_wet_mode(sec);
|
|
run_cm_test(sec);
|
|
get_cm_maxgap_value(sec);
|
|
run_miscalibration(sec);
|
|
if (data->dt_data->enable_fpcb_noise_test) {
|
|
get_fpcb_noise(sec);
|
|
}
|
|
|
|
sec->cmd_all_factory_state = SEC_CMD_STATUS_OK;
|
|
out:
|
|
input_err(true, &data->client->dev, "%s: %d%s\n", __func__, sec->item_count,
|
|
sec->cmd_result_all);
|
|
}
|
|
|
|
struct sec_cmd sec_cmds[] = {
|
|
{SEC_CMD("get_chip_vendor", get_chip_vendor),},
|
|
{SEC_CMD("get_chip_name", get_chip_name),},
|
|
{SEC_CMD("get_chip_id", get_chip_id),},
|
|
{SEC_CMD("fw_update", fw_update),},
|
|
{SEC_CMD("get_fw_ver_bin", get_fw_ver_bin),},
|
|
{SEC_CMD("get_fw_ver_ic", get_fw_ver_ic),},
|
|
{SEC_CMD("get_threshold", get_threshold),},
|
|
{SEC_CMD("get_checksum_data", get_checksum_data),},
|
|
{SEC_CMD("get_x_num", get_scr_x_num),},
|
|
{SEC_CMD("get_y_num", get_scr_y_num),},
|
|
{SEC_CMD("get_all_x_num", get_all_x_num),},
|
|
{SEC_CMD("get_all_y_num", get_all_y_num),},
|
|
{SEC_CMD("dead_zone_enable", dead_zone_enable),},
|
|
{SEC_CMD("clear_cover_mode", not_support_cmd),},
|
|
{SEC_CMD("call_mode", call_mode),},
|
|
{SEC_CMD("glove_mode", glove_mode),},
|
|
{SEC_CMD("set_grip_data", set_grip_data),},
|
|
{SEC_CMD("set_touchable_area", set_touchable_area),},
|
|
{SEC_CMD("hover_enable", not_support_cmd),},
|
|
{SEC_CMD("spay_enable", spay_enable),},
|
|
{SEC_CMD("aot_enable", aot_enable),},
|
|
{SEC_CMD("aod_enable", aod_enable),},
|
|
{SEC_CMD("set_aod_rect", set_aod_rect),},
|
|
{SEC_CMD("get_aod_rect", get_aod_rect),},
|
|
{SEC_CMD("singletap_enable", singletap_enable),},
|
|
{SEC_CMD("fod_enable", fod_enable),},
|
|
{SEC_CMD_H("fod_lp_mode", fod_lp_mode),},
|
|
{SEC_CMD("get_cp_array", get_cp_array),},
|
|
{SEC_CMD("get_self_cp_array", get_self_cp_array),},
|
|
{SEC_CMD("get_prox_cp_array", get_prox_cp_array),},
|
|
{SEC_CMD("run_reference_read", run_cdc_read),},
|
|
{SEC_CMD("get_reference", get_cdc_value),},
|
|
{SEC_CMD("run_self_reference_read", run_self_cdc_read),},
|
|
{SEC_CMD("run_prox_reference_read", run_prox_cdc_read),},
|
|
{SEC_CMD("get_self_reference", get_self_cdc_value),},
|
|
{SEC_CMD("get_prox_reference", get_prox_cdc_value),},
|
|
{SEC_CMD("get_rx_self_reference", get_rx_self_cdc_value),},
|
|
{SEC_CMD("get_tx_self_reference", get_tx_self_cdc_value),},
|
|
{SEC_CMD("get_rx_prox_reference", get_rx_prox_cdc_value),},
|
|
{SEC_CMD("get_tx_prox_reference", get_tx_prox_cdc_value),},
|
|
{SEC_CMD("run_cdc_read", run_cdc_read),},
|
|
{SEC_CMD("run_cdc_read_all", run_cdc_read_all),},
|
|
{SEC_CMD("run_self_cdc_read", run_self_cdc_read),},
|
|
{SEC_CMD("run_self_cdc_read_all", run_self_cdc_read_all),},
|
|
{SEC_CMD("run_prox_cdc_read", run_prox_cdc_read),},
|
|
{SEC_CMD("get_cdc_value", get_cdc_value),},
|
|
{SEC_CMD("get_self_cdc_value", get_self_cdc_value),},
|
|
{SEC_CMD("get_prox_cdc_value", get_prox_cdc_value),},
|
|
{SEC_CMD("get_cdc_all_data", get_cdc_array),},
|
|
{SEC_CMD("get_self_cdc_all_data", get_self_cdc_array),},
|
|
{SEC_CMD("get_prox_cdc_all_data", get_prox_cdc_array),},
|
|
{SEC_CMD("get_cdc_array", get_cdc_array),},
|
|
{SEC_CMD("get_self_cdc_array", get_self_cdc_array),},
|
|
{SEC_CMD("get_prox_cdc_array", get_prox_cdc_array),},
|
|
{SEC_CMD("run_cs_raw_read_all", run_cs_raw_read_all), },
|
|
{SEC_CMD("run_cs_delta_read_all", run_cs_delta_read_all), },
|
|
{SEC_CMD("get_max_dcm", get_max_dcm), },
|
|
{SEC_CMD("get_cm_all_data", get_cm_all_data),},
|
|
{SEC_CMD("run_cm_read_all", run_cm_read_all),},
|
|
{SEC_CMD("get_slope0_all_data", get_slope0_all_data),},
|
|
{SEC_CMD("get_slope1_all_data", get_slope1_all_data),},
|
|
{SEC_CMD("get_cs_all_data", get_cs_all_data),},
|
|
{SEC_CMD("run_cm_test", run_cm_test),},
|
|
{SEC_CMD("get_cm_value", get_cm_value),},
|
|
{SEC_CMD("get_cm_maxgap_value", get_cm_maxgap_value),},
|
|
{SEC_CMD("get_cm_maxgap_all", get_cm_maxgap_all),},
|
|
{SEC_CMD("run_cm_maxgap_read_all", get_cm_maxgap_all),},
|
|
{SEC_CMD("get_tx_cm_gap_value", get_tx_cm_gap_value),},
|
|
{SEC_CMD("get_rx_cm_gap_value", get_rx_cm_gap_value),},
|
|
{SEC_CMD("run_jitter_read", run_cmjit_test),},
|
|
{SEC_CMD("get_jitter", get_cmjit_value),},
|
|
{SEC_CMD("run_cmcs_test", run_cmcs_test),},
|
|
{SEC_CMD("get_cm_array", get_cm_array),},
|
|
{SEC_CMD("get_slope0_array", get_slope0_array),},
|
|
{SEC_CMD("get_slope1_array", get_slope1_array),},
|
|
{SEC_CMD("get_cs_array", get_cs_array),},
|
|
{SEC_CMD("get_cs0_array", get_cs_array),},
|
|
{SEC_CMD("get_cs1_array", get_cs_array),},
|
|
{SEC_CMD("run_cmcs_full_test", run_cmcs_full_test),},
|
|
{SEC_CMD("run_trx_short_test", run_cmcs_full_test),},
|
|
{SEC_CMD("get_config_ver", get_config_ver),},
|
|
{SEC_CMD("run_force_calibration", run_force_calibration),},
|
|
{SEC_CMD("get_force_calibration", get_force_calibration),},
|
|
{SEC_CMD("run_mis_cal_read", run_miscalibration),},
|
|
{SEC_CMD("run_mis_cal_read_all", run_miscalibration_all),},
|
|
{SEC_CMD("get_mis_cal", get_miscalibration_value),},
|
|
{SEC_CMD("get_mis_cal_info", get_mis_cal_info), },
|
|
{SEC_CMD("check_connection", check_connection),},
|
|
{SEC_CMD("run_prox_intensity_read_all", run_prox_intensity_read_all),},
|
|
{SEC_CMD("run_cr_variance_read", run_cr_variance_read),},
|
|
#ifdef TCLM_CONCEPT
|
|
{SEC_CMD("set_external_factory", set_external_factory),},
|
|
{SEC_CMD("get_pat_information", get_pat_information),},
|
|
{SEC_CMD("get_tsp_test_result", get_tsp_test_result),},
|
|
{SEC_CMD("set_tsp_test_result", set_tsp_test_result),},
|
|
#ifndef CONFIG_SAMSUNG_PRODUCT_SHIP
|
|
{SEC_CMD("ium_read", ist40xx_read_sec_info_all),},
|
|
#endif
|
|
{SEC_CMD("increase_disassemble_count", increase_disassemble_count),},
|
|
{SEC_CMD("get_disassemble_count", get_disassemble_count),},
|
|
#endif
|
|
{SEC_CMD("check_ic_mode", check_ic_mode),},
|
|
{SEC_CMD("get_wet_mode", get_wet_mode),},
|
|
{SEC_CMD("get_crc_check", run_fw_integrity),},
|
|
{SEC_CMD("get_fw_integrity", get_checksum_data),},
|
|
{SEC_CMD("factory_cmd_result_all", factory_cmd_result_all),},
|
|
{SEC_CMD("not_support_cmd", not_support_cmd),},
|
|
};
|
|
|
|
static ssize_t get_lp_dump(struct device *dev, struct device_attribute *attr,
|
|
char *buf)
|
|
{
|
|
int i, ret;
|
|
u8 string_data[12] = {0, };
|
|
u16 current_index;
|
|
u8 dump_format, dump_num;
|
|
u16 dump_start, dump_end;
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
if (data->status.sys_mode == STATE_POWER_OFF) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
return snprintf(buf, PAGE_SIZE, "TSP turned off");
|
|
}
|
|
|
|
ist40xx_disable_irq(data);
|
|
|
|
ist40xx_cmd_hold(data, IST40XX_ENABLE);
|
|
|
|
ret = ist40xx_burst_read(data->client,
|
|
IST40XX_SPONGE_REG_BASE + IST40XX_SPONGE_LP_DUMP, (u32*)string_data,
|
|
1, true);
|
|
if (ret < 0) {
|
|
input_err(true, &data->client->dev, "%s: Failed to read rect\n",
|
|
__func__);
|
|
snprintf(buf, PAGE_SIZE, "NG, Failed to read rect");
|
|
|
|
goto out;
|
|
}
|
|
|
|
dump_format = string_data[0];
|
|
dump_num = string_data[1];
|
|
dump_start = IST40XX_SPONGE_LP_DUMP + 4;
|
|
dump_end = dump_start + (dump_format * (dump_num - 1));
|
|
|
|
current_index = (string_data[3] & 0xFF) << 8 | (string_data[2] & 0xFF);
|
|
if (current_index > dump_end || current_index < dump_start) {
|
|
input_err(true, &data->client->dev, "Failed to Sponge LP log %d\n",
|
|
current_index);
|
|
snprintf(buf, PAGE_SIZE, "NG, Failed to Sponge LP log, current_index=%d",
|
|
current_index);
|
|
|
|
goto out;
|
|
}
|
|
|
|
input_info(true, &data->client->dev,
|
|
"%s: DEBUG fmt=%d, num=%d, start=%d, end=%d, current_index=%d\n",
|
|
__func__, dump_format, dump_num, dump_start, dump_end,
|
|
current_index);
|
|
|
|
for (i = (dump_num - 1); i >= 0; i--) {
|
|
u16 data0, data1, data2, data3, data4;
|
|
const int msg_len = 128;
|
|
char buff[msg_len] = {0, };
|
|
u16 string_addr;
|
|
u16 offset = 0;
|
|
|
|
string_addr = current_index - (dump_format * i);
|
|
if (current_index < (dump_format * i))
|
|
string_addr += (dump_format * dump_num);
|
|
|
|
if (string_addr < dump_start)
|
|
string_addr += (dump_format * dump_num);
|
|
|
|
if (dump_format == 8) {
|
|
ret = ist40xx_burst_read(data->client,
|
|
IST40XX_SPONGE_REG_BASE + string_addr, (u32*)string_data,
|
|
dump_format / IST40XX_DATA_LEN, true);
|
|
if (ret < 0) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: Failed to read rect\n", __func__);
|
|
snprintf(buf, PAGE_SIZE, "NG, Failed to read rect, addr=%d",
|
|
string_addr);
|
|
|
|
goto out;
|
|
}
|
|
|
|
data0 = (string_data[1] & 0xFF) << 8 | (string_data[0] & 0xFF);
|
|
data1 = (string_data[3] & 0xFF) << 8 | (string_data[2] & 0xFF);
|
|
data2 = (string_data[5] & 0xFF) << 8 | (string_data[4] & 0xFF);
|
|
data3 = (string_data[7] & 0xFF) << 8 | (string_data[6] & 0xFF);
|
|
|
|
if (data0 || data1 || data2 || data3) {
|
|
snprintf(buff, msg_len, "%d: %04x%04x%04x%04x\n",
|
|
string_addr, data0, data1, data2, data3);
|
|
strncat(buf, buff, msg_len);
|
|
}
|
|
} else {
|
|
if (string_addr % IST40XX_ADDR_LEN)
|
|
offset = 2;
|
|
|
|
ret = ist40xx_burst_read(data->client,
|
|
IST40XX_SPONGE_REG_BASE + string_addr - offset,
|
|
(u32*)string_data, (dump_format / IST40XX_DATA_LEN) + 1,
|
|
true);
|
|
if (ret < 0) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: Failed to read rect\n", __func__);
|
|
snprintf(buf, PAGE_SIZE, "NG, Failed to read rect, addr=%d",
|
|
string_addr);
|
|
|
|
goto out;
|
|
}
|
|
|
|
data0 = (string_data[1 + offset] & 0xFF) << 8 |
|
|
(string_data[0 + offset] & 0xFF);
|
|
data1 = (string_data[3 + offset] & 0xFF) << 8 |
|
|
(string_data[2 + offset] & 0xFF);
|
|
data2 = (string_data[5 + offset] & 0xFF) << 8 |
|
|
(string_data[4 + offset] & 0xFF);
|
|
data3 = (string_data[7 + offset] & 0xFF) << 8 |
|
|
(string_data[6 + offset] & 0xFF);
|
|
data4 = (string_data[9 + offset] & 0xFF) << 8 |
|
|
(string_data[8 + offset] & 0xFF);
|
|
|
|
if (data0 || data1 || data2 || data3 || data4) {
|
|
snprintf(buff, msg_len, "%d: %04x%04x%04x%04x%04x\n",
|
|
string_addr, data0, data1, data2, data3, data4);
|
|
strncat(buf, buff, msg_len);
|
|
}
|
|
}
|
|
}
|
|
|
|
out:
|
|
ist40xx_cmd_hold(data, IST40XX_DISABLE);
|
|
ist40xx_enable_irq(data);
|
|
|
|
return strlen(buf);
|
|
}
|
|
|
|
static ssize_t scrub_position_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
char buff[256] = { 0 };
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
input_info(true, &data->client->dev, "%s() scrub_id: %d, X:%d, Y:%d \n",
|
|
__func__, data->scrub_id, data->scrub_x, data->scrub_y);
|
|
|
|
snprintf(buff, sizeof(buff), "%d %d %d", data->scrub_id, data->scrub_x,
|
|
data->scrub_y);
|
|
|
|
data->scrub_id = 0;
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%s", buff);
|
|
}
|
|
|
|
static ssize_t read_ito_check_show(struct device *dev,
|
|
struct device_attribute *devattr, char *buf)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %02X%02X%02X%02X\n", __func__,
|
|
data->ito_test[0], data->ito_test[1], data->ito_test[2],
|
|
data->ito_test[3]);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%02X%02X%02X%02X", data->ito_test[0],
|
|
data->ito_test[1], data->ito_test[2], data->ito_test[3]);
|
|
}
|
|
|
|
static ssize_t read_raw_check_show(struct device *dev,
|
|
struct device_attribute *devattr, char *buf)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
input_info(true, &data->client->dev, "%s\n", __func__);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "OK");
|
|
}
|
|
|
|
static ssize_t read_multi_count_show(struct device *dev,
|
|
struct device_attribute *devattr, char *buf)
|
|
{
|
|
char buffer[256] = { 0 };
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
input_err(true, &data->client->dev, "%s: %d\n", __func__, data->multi_count);
|
|
snprintf(buffer, sizeof(buffer), "%d", data->multi_count);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%s\n", buffer);
|
|
}
|
|
|
|
static ssize_t clear_multi_count_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
data->multi_count = 0;
|
|
|
|
input_info(true, &data->client->dev, "%s: clear\n", __func__);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t read_wet_mode_show(struct device *dev,
|
|
struct device_attribute *devattr, char *buf)
|
|
{
|
|
char buffer[256] = { 0 };
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %d\n", __func__,
|
|
data->wet_count);
|
|
snprintf(buffer, sizeof(buffer), "%d", data->wet_count);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%s\n", buffer);
|
|
}
|
|
|
|
static ssize_t clear_wet_mode_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
data->wet_count = 0;
|
|
|
|
input_info(true, &data->client->dev, "%s: clear\n", __func__);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t read_comm_err_count_show(struct device *dev,
|
|
struct device_attribute *devattr, char *buf)
|
|
{
|
|
char buffer[256] = { 0 };
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %d\n", __func__,
|
|
data->comm_err_count);
|
|
snprintf(buffer, sizeof(buffer), "%d", data->comm_err_count);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%s\n", buffer);
|
|
}
|
|
|
|
static ssize_t clear_comm_err_count_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
data->comm_err_count = 0;
|
|
|
|
input_info(true, &data->client->dev, "%s: clear\n", __func__);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t read_module_id_show(struct device *dev,
|
|
struct device_attribute *devattr, char *buf)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
#ifdef TCLM_CONCEPT
|
|
input_info(true, &data->client->dev, "%s: IM%04X%02X%02X%02X\n", __func__,
|
|
(data->fw.cur.fw_ver & 0xffff), data->test_result.data[0],
|
|
data->tdata->nvdata.cal_count,
|
|
(data->tdata->nvdata.tune_fix_ver & 0xff));
|
|
|
|
return snprintf(buf, PAGE_SIZE, "IM%04X%02X%02X%02X",
|
|
(data->fw.cur.fw_ver & 0xffff), data->test_result.data[0],
|
|
data->tdata->nvdata.cal_count,
|
|
(data->tdata->nvdata.tune_fix_ver & 0xff));
|
|
#else
|
|
input_info(true, &data->client->dev, "%s: IM%04X\n", __func__,
|
|
(data->fw.cur.fw_ver & 0xffff));
|
|
|
|
return snprintf(buf, PAGE_SIZE, "IM%04X", (data->fw.cur.fw_ver & 0xffff));
|
|
#endif
|
|
}
|
|
|
|
static ssize_t read_checksum_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %d\n", __func__,
|
|
data->checksum_result);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d", data->checksum_result);
|
|
}
|
|
|
|
static ssize_t clear_checksum_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
data->checksum_result = 0;
|
|
|
|
input_info(true, &data->client->dev, "%s: clear\n", __func__);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t read_all_touch_count_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: touch:%d, aod:%d, spay:%d\n",
|
|
__func__, data->all_finger_count, data->all_aod_tsp_count,
|
|
data->all_spay_count);
|
|
|
|
return snprintf(buf, PAGE_SIZE,
|
|
"\"TTCN\":\"%d\",\"TACN\":\"%d\",\"TSCN\":\"%d\"",
|
|
data->all_finger_count, data->all_aod_tsp_count,
|
|
data->all_spay_count);
|
|
}
|
|
|
|
static ssize_t clear_all_touch_count_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
data->all_aod_tsp_count = 0;
|
|
data->all_spay_count = 0;
|
|
data->all_singletap_count = 0;
|
|
|
|
input_info(true, &data->client->dev, "%s: clear\n", __func__);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t read_vendor_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE, "%s", TSP_CHIP_VENDOR);
|
|
}
|
|
|
|
static ssize_t sensitivity_mode_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
int mode;
|
|
|
|
if (kstrtoint(buf, 10, &mode) < 0) {
|
|
input_err(true, &data->client->dev, "%s: kstrtoint fail\n", __func__);
|
|
return count;
|
|
}
|
|
|
|
if ((mode != 0) && (mode != 1)) // enable/disable
|
|
return count;
|
|
|
|
ist40xx_set_sensitivity_mode(mode);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t sensitivity_mode_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
u32 result[5] = { 0, };
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
if (data->status.sys_mode == STATE_POWER_OFF) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: now sys_mode status is not STATE_POWER_ON!\n",
|
|
__func__);
|
|
goto end;
|
|
}
|
|
|
|
if (data->noise_mode & (1 << NOISE_MODE_SENSITIVITY))
|
|
ist40xx_burst_read(data->client, IST40XX_HIB_INTR_MSG, result, 5, true);
|
|
|
|
end:
|
|
return snprintf(buf, PAGE_SIZE, "%d,%d,%d,%d,%d", result[0], result[1],
|
|
result[2], result[3], result[4]);
|
|
}
|
|
|
|
static ssize_t ear_detect_enable_store(struct device *dev,
|
|
struct device_attribute *attr, const char *buf, size_t count)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
int mode;
|
|
|
|
if (kstrtoint(buf, 10, &mode) < 0) {
|
|
input_err(true, &data->client->dev, "%s: kstrtoint fail\n", __func__);
|
|
return count;
|
|
}
|
|
|
|
if ((mode != 0) && (mode != 1))
|
|
return count;
|
|
|
|
ist40xx_set_call_mode(mode);
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t ear_detect_enable_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %d\n",
|
|
__func__, data->noise_mode >> NOISE_MODE_CALL);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d", data->noise_mode >> NOISE_MODE_CALL);
|
|
}
|
|
|
|
static ssize_t prox_power_off_store(struct device *dev,
|
|
struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
int mode;
|
|
|
|
if (kstrtoint(buf, 10, &mode) < 0) {
|
|
input_err(true, &data->client->dev, "%s: kstrtoint fail\n", __func__);
|
|
return count;
|
|
}
|
|
|
|
if ((mode != 0) && (mode != 1))
|
|
return count;
|
|
|
|
input_info(true, &data->client->dev, "%s: enable:%d\n", __func__, mode);
|
|
data->prox_power_off = mode;
|
|
|
|
return count;
|
|
}
|
|
|
|
static ssize_t prox_power_off_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
input_info(true, &data->client->dev, "%s: %d\n", __func__, data->prox_power_off);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d", data->prox_power_off);
|
|
}
|
|
|
|
static ssize_t read_support_feature(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
u32 feature = 0;
|
|
|
|
if (data->dt_data->enable_settings_aot )
|
|
feature |= INPUT_FEATURE_ENABLE_SETTINGS_AOT;
|
|
|
|
input_info(true, &data->client->dev, "%s: %d%s\n", __func__, feature,
|
|
feature & INPUT_FEATURE_ENABLE_SETTINGS_AOT ? " aot" : "");
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d", feature);
|
|
}
|
|
|
|
static ssize_t fod_info_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
if (!data->dt_data->support_fod) {
|
|
input_err(true, &data->client->dev, "%s: fod is not supported\n", __func__);
|
|
return snprintf(buf, sizeof(buf), "NG");
|
|
}
|
|
|
|
input_info(true, &data->client->dev, "%s: tx:%d, rx:%d, size:%d\n",
|
|
__func__, data->fod_tx, data->fod_rx, data->fod_vi_size);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d,%d,%d", data->fod_tx, data->fod_rx, data->fod_vi_size);
|
|
}
|
|
|
|
static ssize_t fod_position_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
u32 addr;
|
|
u8 fodvi_position[28] = { 0, };
|
|
char buff[3] = { 0 };
|
|
int i;
|
|
struct sec_cmd_data *sec = dev_get_drvdata(dev);
|
|
struct ist40xx_data *data = container_of(sec, struct ist40xx_data, sec);
|
|
|
|
if (data->status.sys_mode == STATE_POWER_OFF) {
|
|
input_err(true, &data->client->dev, "%s: error currently power off\n", __func__);
|
|
return snprintf(buf, sizeof(buf), "NG");
|
|
}
|
|
|
|
if (!data->dt_data->support_fod) {
|
|
input_err(true, &data->client->dev, "%s: fod is not supported\n", __func__);
|
|
return snprintf(buf, sizeof(buf), "NG");
|
|
}
|
|
|
|
if (!data->fod_vi_size) {
|
|
input_err(true, &data->client->dev, "%s: not read fod_info yet\n", __func__);
|
|
return snprintf(buf, sizeof(buf), "NG");
|
|
}
|
|
|
|
if (data->status.sys_mode == STATE_LPM)
|
|
addr = IST40XX_SPONGE_L_FODVI_BASE + IST40XX_SPONGE_FODVI_POSITION;
|
|
else
|
|
addr = IST40XX_SPONGE_N_FODVI_BASE + IST40XX_SPONGE_FODVI_POSITION;
|
|
|
|
ist40xx_burst_read(data->client, addr, (u32 *)fodvi_position, 7, true);
|
|
|
|
for (i = 0; i < data->fod_vi_size; i++) {
|
|
snprintf(buff, 3, "%02X", fodvi_position[i]);
|
|
strlcat(buf, buff, SEC_CMD_BUF_SIZE);
|
|
}
|
|
|
|
return strlen(buf);
|
|
}
|
|
|
|
/* sysfs - tsp */
|
|
static DEVICE_ATTR(close_tsp_test, S_IRUGO, show_close_tsp_test, NULL);
|
|
static DEVICE_ATTR(scrub_pos, S_IRUGO, scrub_position_show, NULL);
|
|
/* BiG data */
|
|
static DEVICE_ATTR(ito_check, S_IRUGO, read_ito_check_show, NULL);
|
|
static DEVICE_ATTR(raw_check, S_IRUGO, read_raw_check_show, NULL);
|
|
static DEVICE_ATTR(multi_count, S_IRUGO | S_IWUSR | S_IWGRP,
|
|
read_multi_count_show, clear_multi_count_store);
|
|
static DEVICE_ATTR(wet_mode, S_IRUGO | S_IWUSR | S_IWGRP, read_wet_mode_show,
|
|
clear_wet_mode_store);
|
|
static DEVICE_ATTR(comm_err_count, S_IRUGO | S_IWUSR | S_IWGRP,
|
|
read_comm_err_count_show, clear_comm_err_count_store);
|
|
static DEVICE_ATTR(checksum, S_IRUGO | S_IWUSR | S_IWGRP, read_checksum_show,
|
|
clear_checksum_store);
|
|
static DEVICE_ATTR(all_touch_count, S_IRUGO | S_IWUSR | S_IWGRP,
|
|
read_all_touch_count_show, clear_all_touch_count_store);
|
|
static DEVICE_ATTR(module_id, S_IRUGO, read_module_id_show, NULL);
|
|
static DEVICE_ATTR(vendor, S_IRUGO, read_vendor_show, NULL);
|
|
static DEVICE_ATTR(get_lp_dump, S_IRUGO, get_lp_dump, NULL);
|
|
static DEVICE_ATTR(sensitivity_mode, S_IRUGO | S_IWUSR | S_IWGRP,
|
|
sensitivity_mode_show, sensitivity_mode_store);
|
|
static DEVICE_ATTR(ear_detect_enable, S_IRUGO | S_IWUSR | S_IWGRP,
|
|
ear_detect_enable_show, ear_detect_enable_store);
|
|
static DEVICE_ATTR(prox_power_off, S_IRUGO | S_IWUSR | S_IWGRP,
|
|
prox_power_off_show, prox_power_off_store);
|
|
static DEVICE_ATTR(support_feature, S_IRUGO, read_support_feature, NULL);
|
|
static DEVICE_ATTR(fod_info, S_IRUGO, fod_info_show, NULL);
|
|
static DEVICE_ATTR(fod_pos, S_IRUGO, fod_position_show, NULL);
|
|
|
|
static struct attribute *sec_touch_factory_attributes[] = {
|
|
&dev_attr_close_tsp_test.attr,
|
|
&dev_attr_scrub_pos.attr,
|
|
&dev_attr_ito_check.attr,
|
|
&dev_attr_raw_check.attr,
|
|
&dev_attr_multi_count.attr,
|
|
&dev_attr_wet_mode.attr,
|
|
&dev_attr_comm_err_count.attr,
|
|
&dev_attr_checksum.attr,
|
|
&dev_attr_all_touch_count.attr,
|
|
&dev_attr_module_id.attr,
|
|
&dev_attr_vendor.attr,
|
|
&dev_attr_get_lp_dump.attr,
|
|
&dev_attr_sensitivity_mode.attr,
|
|
&dev_attr_ear_detect_enable.attr,
|
|
&dev_attr_prox_power_off.attr,
|
|
&dev_attr_support_feature.attr,
|
|
&dev_attr_fod_info.attr,
|
|
&dev_attr_fod_pos.attr,
|
|
NULL,
|
|
};
|
|
|
|
static struct attribute_group sec_touch_factory_attr_group = {
|
|
.attrs = sec_touch_factory_attributes,
|
|
};
|
|
|
|
#if defined(CONFIG_INPUT_SEC_SECURE_TOUCH)
|
|
static ssize_t ist40xx_secure_touch_enable_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct ist40xx_data *data = dev_get_drvdata(dev);
|
|
|
|
return scnprintf(buf, PAGE_SIZE, "%d", atomic_read(&data->st_enabled));
|
|
}
|
|
|
|
/*
|
|
* Accept only "0" and "1" valid values.
|
|
* "0" will reset the st_enabled flag, then wake up the reading process.
|
|
* The bus driver is notified via pm_runtime that it is not required to stay
|
|
* awake anymore.
|
|
* It will also make sure the queue of events is emptied in the controller,
|
|
* in case a touch happened in between the secure touch being disabled and
|
|
* the local ISR being ungated.
|
|
* "1" will set the st_enabled flag and clear the st_pending_irqs flag.
|
|
* The bus driver is requested via pm_runtime to stay awake.
|
|
*/
|
|
static ssize_t ist40xx_secure_touch_enable_store(struct device *dev,
|
|
struct device_attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
struct ist40xx_data *data = dev_get_drvdata(dev);
|
|
unsigned long value;
|
|
int err = 0;
|
|
|
|
if (count > 2) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: cmd length is over (%s,%d)!!\n",
|
|
__func__, buf, (int)strlen(buf));
|
|
return -EINVAL;
|
|
}
|
|
|
|
err = kstrtoul(buf, 10, &value);
|
|
if (err != 0) {
|
|
input_err(true, &data->client->dev, "%s: failed to read:%d\n",
|
|
__func__, err);
|
|
return err;
|
|
}
|
|
|
|
err = count;
|
|
|
|
switch (value) {
|
|
case 0:
|
|
if (atomic_read(&data->st_enabled) == 0) {
|
|
input_err(true, &data->client->dev, "%s: secure_touch is not enabled, pending:%d\n",
|
|
__func__, atomic_read(&data->st_pending_irqs));
|
|
break;
|
|
}
|
|
|
|
pm_runtime_put_sync(data->client->adapter->dev.parent);
|
|
|
|
atomic_set(&data->st_enabled, 0);
|
|
|
|
sysfs_notify(&data->input_dev->dev.kobj, NULL, "secure_touch");
|
|
|
|
ist40xx_delay(10);
|
|
|
|
ist40xx_irq_thread(data->client->irq, data);
|
|
|
|
complete(&data->st_powerdown);
|
|
complete(&data->st_interrupt);
|
|
|
|
input_info(true, &data->client->dev, "%s: secure_touch is disabled\n", __func__);
|
|
|
|
#ifdef IST40XX_NOISE_MODE
|
|
schedule_delayed_work(&data->work_noise_protect, 0);
|
|
#endif
|
|
#if defined(CONFIG_TRUSTONIC_TRUSTED_UI_QC)
|
|
complete(&data->st_irq_received);
|
|
#endif
|
|
break;
|
|
|
|
case 1:
|
|
// if (data->reset_is_on_going) {
|
|
// input_err(true, &info->client->dev, "%s: reset is on goning becuse i2c fail\n",
|
|
// __func__);
|
|
// return -EBUSY;
|
|
// }
|
|
|
|
if (atomic_read(&data->st_enabled)) {
|
|
input_err(true, &data->client->dev, "%s: secure_touch is already enabled, pending:%d\n",
|
|
__func__, atomic_read(&data->st_pending_irqs));
|
|
err = -EBUSY;
|
|
break;
|
|
}
|
|
|
|
#ifdef IST40XX_NOISE_MODE
|
|
cancel_delayed_work_sync(&data->work_noise_protect);
|
|
#endif
|
|
|
|
/* synchronize_irq -> disable_irq + enable_irq
|
|
* concern about timing issue.
|
|
*/
|
|
ist40xx_disable_irq(data);
|
|
/* Release All Finger */
|
|
/* TODO */
|
|
if (pm_runtime_get_sync(data->client->adapter->dev.parent) < 0) {
|
|
input_err(true, &data->client->dev, "%s: pm_runtime_get failed\n", __func__);
|
|
err = -EIO;
|
|
ist40xx_enable_irq(data);
|
|
break;
|
|
}
|
|
|
|
reinit_completion(&data->st_powerdown);
|
|
reinit_completion(&data->st_interrupt);
|
|
#if defined(CONFIG_TRUSTONIC_TRUSTED_UI_QC)
|
|
reinit_completion(&data->st_irq_received);
|
|
#endif
|
|
atomic_set(&data->st_enabled, 1);
|
|
atomic_set(&data->st_pending_irqs, 0);
|
|
|
|
ist40xx_enable_irq(data);
|
|
|
|
input_info(true, &data->client->dev, "%s: secure_touch is enabled\n", __func__);
|
|
|
|
break;
|
|
|
|
default:
|
|
input_err(true, &data->client->dev, "%s: unsupported value: %lu\n", __func__, value);
|
|
err = -EINVAL;
|
|
break;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
#if defined(CONFIG_TRUSTONIC_TRUSTED_UI_QC)
|
|
static int secure_get_irq(struct device *dev)
|
|
{
|
|
struct ist40xx_data *data = dev_get_drvdata(dev);
|
|
int val = 0;
|
|
|
|
input_err(true, &data->client->dev, "%s: enter\n", __func__);
|
|
if (atomic_read(&data->st_enabled) == 0) {
|
|
input_err(true, &data->client->dev, "%s: disabled\n", __func__);
|
|
return -EBADF;
|
|
}
|
|
|
|
if (atomic_cmpxchg(&data->st_pending_irqs, -1, 0) == -1) {
|
|
input_err(true, &data->client->dev, "%s: pending irq -1\n", __func__);
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (atomic_cmpxchg(&data->st_pending_irqs, 1, 0) == 1)
|
|
val = 1;
|
|
|
|
input_err(true, &data->client->dev, "%s: pending irq is %d\n",
|
|
__func__, atomic_read(&data->st_pending_irqs));
|
|
|
|
complete(&data->st_interrupt);
|
|
|
|
return val;
|
|
}
|
|
#endif
|
|
|
|
static ssize_t ist40xx_secure_touch_show(struct device *dev,
|
|
struct device_attribute *attr, char *buf)
|
|
{
|
|
struct ist40xx_data *data = dev_get_drvdata(dev);
|
|
int val = 0;
|
|
|
|
if (atomic_read(&data->st_enabled) == 0) {
|
|
input_err(true, &data->client->dev, "%s: secure_touch is not enabled, st_pending_irqs: %d\n",
|
|
__func__, atomic_read(&data->st_pending_irqs));
|
|
return -EBADF;
|
|
}
|
|
|
|
if (atomic_cmpxchg(&data->st_pending_irqs, -1, 0) == -1) {
|
|
input_err(true, &data->client->dev, "%s: st_pending_irqs: %d\n",
|
|
__func__, atomic_read(&data->st_pending_irqs));
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (atomic_cmpxchg(&data->st_pending_irqs, 1, 0) == 1) {
|
|
val = 1;
|
|
input_info(true, &data->client->dev, "%s: st_pending_irqs: %d, val: %d\n",
|
|
__func__, atomic_read(&data->st_pending_irqs), val);
|
|
}
|
|
|
|
complete(&data->st_interrupt);
|
|
|
|
return scnprintf(buf, PAGE_SIZE, "%u", val);
|
|
}
|
|
|
|
static void ist40xx_secure_touch_init(struct ist40xx_data *data)
|
|
{
|
|
init_completion(&data->st_powerdown);
|
|
init_completion(&data->st_interrupt);
|
|
#if defined(CONFIG_TRUSTONIC_TRUSTED_UI_QC)
|
|
init_completion(&data->st_irq_received);
|
|
#endif
|
|
#if defined(CONFIG_TRUSTONIC_TRUSTED_UI_QC)
|
|
register_tui_hal_ts(&data->input_dev->dev, &data->st_enabled,
|
|
&data->st_irq_received, secure_get_irq,
|
|
ist40xx_secure_touch_enable_store);
|
|
#endif
|
|
}
|
|
|
|
void ist40xx_secure_touch_stop(struct ist40xx_data *data, int blocking)
|
|
{
|
|
if (atomic_read(&data->st_enabled)) {
|
|
atomic_set(&data->st_pending_irqs, -1);
|
|
sysfs_notify(&data->input_dev->dev.kobj, NULL, "secure_touch");
|
|
if (blocking)
|
|
wait_for_completion_interruptible(&data->st_powerdown);
|
|
}
|
|
}
|
|
|
|
irqreturn_t ist40xx_filter_interrupt(struct ist40xx_data *data)
|
|
{
|
|
if (atomic_read(&data->st_enabled)) {
|
|
if (atomic_cmpxchg(&data->st_pending_irqs, 0, 1) == 0) {
|
|
sysfs_notify(&data->input_dev->dev.kobj, NULL, "secure_touch");
|
|
} else {
|
|
input_info(true, &data->client->dev, "%s: st_pending_irqs: %d\n",
|
|
__func__, atomic_read(&data->st_pending_irqs));
|
|
}
|
|
return IRQ_HANDLED;
|
|
}
|
|
return IRQ_NONE;
|
|
}
|
|
|
|
static struct device_attribute secure_attrs[] = {
|
|
__ATTR(secure_touch_enable, (0664),
|
|
ist40xx_secure_touch_enable_show,
|
|
ist40xx_secure_touch_enable_store),
|
|
__ATTR(secure_touch, (0444),
|
|
ist40xx_secure_touch_show,
|
|
NULL),
|
|
};
|
|
#endif
|
|
|
|
int run_debug_for_dump(struct ist40xx_data *data)
|
|
{
|
|
int ret;
|
|
int i;
|
|
u32 addr = IST40XX_DA_ADDR(data->algo_addr);
|
|
u32 size = data->algo_size;
|
|
u32 Scancount = 0;
|
|
u32 *buf32;
|
|
|
|
if (!addr) {
|
|
addr = IST40XX_ALGORITHM_ADDR;
|
|
size = 1024;
|
|
}
|
|
|
|
input_raw_info(true, &data->client->dev, "----- scancount value -----:\n");
|
|
ist40xx_read_reg(data->client, IST40XX_HIB_TOUCH_STATUS, &Scancount);
|
|
input_raw_info(true, &data->client->dev, "ScanCount(0) : %08X\n", Scancount);
|
|
ist40xx_delay(100);
|
|
ist40xx_read_reg(data->client, IST40XX_HIB_TOUCH_STATUS, &Scancount);
|
|
input_raw_info(true, &data->client->dev, "ScanCount(1) : %08X\n", Scancount);
|
|
ist40xx_delay(100);
|
|
ist40xx_read_reg(data->client, IST40XX_HIB_TOUCH_STATUS, &Scancount);
|
|
input_raw_info(true, &data->client->dev, "ScanCount(2) : %08X\n", Scancount);
|
|
|
|
data->status.event_mode = false;
|
|
ist40xx_cmd_hold(data, IST40XX_ENABLE);
|
|
buf32 = kzalloc(size * sizeof(u32), GFP_KERNEL);
|
|
ret = ist40xx_burst_read(data->client, addr, buf32, size, true);
|
|
if (ret) {
|
|
data->status.event_mode = true;
|
|
ist40xx_reset(data, false);
|
|
ist40xx_start(data);
|
|
kfree(buf32);
|
|
return ret;
|
|
}
|
|
ist40xx_cmd_hold(data, IST40XX_DISABLE);
|
|
|
|
input_raw_info(true, &data->client->dev, "----- debug value -----:\n");
|
|
for (i = 0; i < (size / IST40XX_DATA_LEN); i++)
|
|
input_raw_info(true, &data->client->dev, "%08X %08X %08X %08X\n", buf32[i * 4], buf32[i * 4 + 1],
|
|
buf32[i * 4 + 2], buf32[i * 4 + 3]);
|
|
|
|
data->status.event_mode = true;
|
|
kfree(buf32);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int run_cp_for_dump(struct ist40xx_data *data)
|
|
{
|
|
int ret;
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
mutex_lock(&data->lock);
|
|
ret = ist40xx_read_cp_node(data, &tsp->node, false);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
tsp_err("MemX cp read fail\n");
|
|
return ret;
|
|
}
|
|
|
|
ist40xx_parse_cp_node(data, &tsp->node, false);
|
|
|
|
ret = ist40xx_read_cp_node(data, &tsp->node, true);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
tsp_err("Info cp read fail\n");
|
|
return ret;
|
|
}
|
|
mutex_unlock(&data->lock);
|
|
|
|
ist40xx_parse_cp_node(data, &tsp->node, true);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void dump_self_prox_log(struct ist40xx_data *data, int type)
|
|
{
|
|
int ii, jj;
|
|
int val = 0;
|
|
const int msg_len = 128;
|
|
char msg[msg_len];
|
|
char *buf = NULL;
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
struct TSP_NODE_BUF *node = &tsp->node;
|
|
|
|
buf = kzalloc(2048, GFP_KERNEL);
|
|
if (buf == NULL)
|
|
return;
|
|
buf[0] = '\0';
|
|
|
|
if (tsp->dir.swap_xy) {
|
|
for (ii = tsp->ch_num.rx - 1; ii >= 0; ii--) {
|
|
for (jj = tsp->ch_num.tx - 1; jj >= 0; jj--) {
|
|
if (type == LOG_MEMX_CP)
|
|
val = node->memx_cp[jj * tsp->ch_num.rx + ii];
|
|
else if (type == LOG_ROM_CP)
|
|
val = node->rom_cp[jj * tsp->ch_num.rx + ii];
|
|
else if (type == LOG_CDC)
|
|
val = node->cdc[jj * tsp->ch_num.rx + ii];
|
|
else if (type == LOG_BASE)
|
|
val = node->base[jj * tsp->ch_num.rx + ii];
|
|
snprintf(msg, msg_len, "%4d ", val);
|
|
strncat(buf, msg, msg_len);
|
|
if (jj == 0) {
|
|
if (type == LOG_MEMX_CP)
|
|
val = node->memx_self_cp[tsp->ch_num.tx + ii];
|
|
else if (type == LOG_ROM_CP)
|
|
val = node->rom_self_cp[tsp->ch_num.tx + ii];
|
|
else if (type == LOG_CDC)
|
|
val = node->self_cdc[tsp->ch_num.tx + ii];
|
|
else if (type == LOG_BASE)
|
|
val = node->self_base[tsp->ch_num.tx + ii];
|
|
snprintf(msg, msg_len, " %4d ", val);
|
|
strncat(buf, msg, msg_len);
|
|
if (type == LOG_MEMX_CP)
|
|
val = node->memx_prox_cp[tsp->ch_num.tx + ii];
|
|
else if (type == LOG_ROM_CP)
|
|
val = node->rom_prox_cp[tsp->ch_num.tx + ii];
|
|
else if (type == LOG_CDC)
|
|
val = node->prox_cdc[tsp->ch_num.tx + ii];
|
|
else if (type == LOG_BASE)
|
|
val = node->prox_base[tsp->ch_num.tx + ii];
|
|
snprintf(msg, msg_len, "%4d ", val);
|
|
strncat(buf, msg, msg_len);
|
|
snprintf(msg, msg_len, " | Rx%02d", ii);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
}
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
|
|
if (ii == 0) {
|
|
input_raw_info(true, &data->client->dev, "\n");
|
|
buf[0] = '\0';
|
|
for (jj = tsp->ch_num.tx - 1; jj >= 0; jj--) {
|
|
if (type == LOG_MEMX_CP)
|
|
val = node->memx_self_cp[jj];
|
|
else if (type == LOG_ROM_CP)
|
|
val = node->rom_self_cp[jj];
|
|
else if (type == LOG_CDC)
|
|
val = node->self_cdc[jj];
|
|
else if (type == LOG_BASE)
|
|
val = node->self_base[jj];
|
|
snprintf(msg, msg_len, "%4d ", val);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
|
|
buf[0] = '\0';
|
|
for (jj = tsp->ch_num.tx - 1; jj >= 0; jj--) {
|
|
if (type == LOG_MEMX_CP)
|
|
val = node->memx_prox_cp[jj];
|
|
else if (type == LOG_ROM_CP)
|
|
val = node->rom_prox_cp[jj];
|
|
else if (type == LOG_CDC)
|
|
val = node->prox_cdc[jj];
|
|
else if (type == LOG_BASE)
|
|
val = node->prox_base[jj];
|
|
snprintf(msg, msg_len, "%4d ", val);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
|
|
buf[0] = '\0';
|
|
for (jj = tsp->ch_num.tx + 2; jj >= 0; jj--) {
|
|
snprintf(msg, msg_len, "-----");
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
|
|
buf[0] = '\0';
|
|
for (jj = tsp->ch_num.tx - 1; jj >= 0 ; jj--) {
|
|
snprintf(msg, msg_len, " %02d ", jj);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
snprintf(msg, msg_len, " | Tx");
|
|
strncat(buf, msg, msg_len);
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
}
|
|
buf[0] = '\0';
|
|
}
|
|
} else {
|
|
for (ii = tsp->ch_num.tx - 1; ii >= 0; ii--) {
|
|
for (jj = tsp->ch_num.rx - 1; jj >= 0; jj--) {
|
|
if (type == LOG_MEMX_CP)
|
|
val = node->memx_cp[ii * tsp->ch_num.rx + ii];
|
|
else if (type == LOG_ROM_CP)
|
|
val = node->rom_cp[ii * tsp->ch_num.rx + jj];
|
|
else if (type == LOG_CDC)
|
|
val = node->cdc[ii * tsp->ch_num.rx + jj];
|
|
else if (type == LOG_BASE)
|
|
val = node->base[ii * tsp->ch_num.rx + jj];
|
|
snprintf(msg, msg_len, "%4d ", val);
|
|
strncat(buf, msg, msg_len);
|
|
if (jj == 0) {
|
|
if (type == LOG_MEMX_CP)
|
|
val = node->memx_self_cp[ii];
|
|
else if (type == LOG_ROM_CP)
|
|
val = node->rom_self_cp[ii];
|
|
else if (type == LOG_CDC)
|
|
val = node->self_cdc[ii];
|
|
else if (type == LOG_BASE)
|
|
val = node->self_base[ii];
|
|
snprintf(msg, msg_len, " %4d ", val);
|
|
strncat(buf, msg, msg_len);
|
|
if (type == LOG_MEMX_CP)
|
|
val = node->memx_prox_cp[ii];
|
|
else if (type == LOG_ROM_CP)
|
|
val = node->rom_prox_cp[ii];
|
|
else if (type == LOG_CDC)
|
|
val = node->prox_cdc[ii];
|
|
else if (type == LOG_BASE)
|
|
val = node->prox_base[ii];
|
|
snprintf(msg, msg_len, "%4d ", val);
|
|
strncat(buf, msg, msg_len);
|
|
|
|
snprintf(msg, msg_len, " | Tx%02d", ii);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
}
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
|
|
if (ii == 0) {
|
|
input_raw_info(true, &data->client->dev, "\n");
|
|
buf[0] = '\0';
|
|
for (jj = tsp->ch_num.rx - 1; jj >= 0; jj--) {
|
|
if (type == LOG_MEMX_CP)
|
|
val = node->memx_self_cp[tsp->ch_num.tx + jj];
|
|
else if (type == LOG_ROM_CP)
|
|
val = node->rom_self_cp[tsp->ch_num.tx + jj];
|
|
else if (type == LOG_CDC)
|
|
val = node->self_cdc[tsp->ch_num.tx + jj];
|
|
else if (type == LOG_BASE)
|
|
val = node->self_base[jj];
|
|
snprintf(msg, msg_len, "%4d ", val);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
|
|
buf[0] = '\0';
|
|
for (jj = tsp->ch_num.rx - 1; jj >= 0; jj--) {
|
|
if (type == LOG_MEMX_CP)
|
|
val = node->memx_prox_cp[tsp->ch_num.tx + jj];
|
|
else if (type == LOG_ROM_CP)
|
|
val = node->rom_prox_cp[tsp->ch_num.tx + jj];
|
|
else if (type == LOG_CDC)
|
|
val = node->prox_cdc[tsp->ch_num.tx + jj];
|
|
else if (type == LOG_BASE)
|
|
val = node->prox_base[jj];
|
|
snprintf(msg, msg_len, "%4d ", val);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
|
|
buf[0] = '\0';
|
|
for (jj = tsp->ch_num.rx + 2; jj >= 0; jj--) {
|
|
snprintf(msg, msg_len, "-----");
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
|
|
buf[0] = '\0';
|
|
for (jj = tsp->ch_num.rx - 1; jj >= 0 ; jj--) {
|
|
snprintf(msg, msg_len, " %02d ", jj);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
snprintf(msg, msg_len, " | Rx");
|
|
strncat(buf, msg, msg_len);
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
}
|
|
buf[0] = '\0';
|
|
}
|
|
}
|
|
kfree(buf);
|
|
}
|
|
|
|
void dump_log(struct ist40xx_data *data, int type)
|
|
{
|
|
int ii, jj;
|
|
int val = 0;
|
|
const int msg_len = 128;
|
|
char msg[msg_len];
|
|
char *buf = NULL;
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
struct TSP_NODE_BUF *node = &tsp->node;
|
|
|
|
buf = kzalloc(2048, GFP_KERNEL);
|
|
if (buf == NULL)
|
|
return;
|
|
buf[0] = '\0';
|
|
|
|
if (tsp->dir.swap_xy) {
|
|
for (ii = tsp->ch_num.rx - 1; ii >= 0; ii--) {
|
|
for (jj = tsp->ch_num.tx - 1; jj >= 0; jj--) {
|
|
if (type == LOG_LOFS)
|
|
val = node->lofs[jj * tsp->ch_num.rx + ii];
|
|
else if (type == LOG_CM)
|
|
val = cmcs_buf->cm[jj * tsp->ch_num.rx + ii];
|
|
else if (type == LOG_GAP)
|
|
val = cmcs_buf->slope[jj * tsp->ch_num.rx + ii];
|
|
else if (type == LOG_CS)
|
|
val = cmcs_buf->cs[jj * tsp->ch_num.rx + ii];
|
|
else if (type == LOG_MISCAL)
|
|
val = node->miscal[jj * tsp->ch_num.rx + ii];
|
|
snprintf(msg, msg_len, "%4d ", val);
|
|
strncat(buf, msg, msg_len);
|
|
if (jj == 0) {
|
|
snprintf(msg, msg_len, " | Rx%02d", ii);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
}
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
if (ii == 0) {
|
|
buf[0] = '\0';
|
|
for (jj = tsp->ch_num.tx - 1; jj >= 0; jj--) {
|
|
snprintf(msg, msg_len, "-----");
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
|
|
buf[0] = '\0';
|
|
for (jj = tsp->ch_num.tx - 1; jj >= 0 ; jj--) {
|
|
snprintf(msg, msg_len, " %02d ", jj);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
snprintf(msg, msg_len, " | Tx");
|
|
strncat(buf, msg, msg_len);
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
}
|
|
buf[0] = '\0';
|
|
}
|
|
} else {
|
|
for (ii = tsp->ch_num.tx - 1; ii >= 0; ii--) {
|
|
for (jj = tsp->ch_num.rx - 1; jj >= 0; jj--) {
|
|
if (type == LOG_LOFS)
|
|
val = node->lofs[ii * tsp->ch_num.rx + jj];
|
|
else if (type == LOG_CM)
|
|
val = cmcs_buf->cm[ii * tsp->ch_num.rx + jj];
|
|
else if (type == LOG_GAP)
|
|
val = cmcs_buf->slope[ii * tsp->ch_num.rx + jj];
|
|
else if (type == LOG_CS)
|
|
val = cmcs_buf->cs[ii * tsp->ch_num.rx + jj];
|
|
else if (type == LOG_MISCAL)
|
|
val = node->miscal[ii * tsp->ch_num.rx + jj];
|
|
snprintf(msg, msg_len, "%4d ", val);
|
|
strncat(buf, msg, msg_len);
|
|
if (jj == 0) {
|
|
snprintf(msg, msg_len, " | Tx%02d", ii);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
}
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
if (ii == 0) {
|
|
buf[0] = '\0';
|
|
for (jj = tsp->ch_num.rx - 1; jj >= 0; jj--) {
|
|
snprintf(msg, msg_len, "-----");
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
|
|
buf[0] = '\0';
|
|
for (jj = tsp->ch_num.rx - 1; jj >= 0 ; jj--) {
|
|
snprintf(msg, msg_len, " %02d ", jj);
|
|
strncat(buf, msg, msg_len);
|
|
}
|
|
snprintf(msg, msg_len, " | Rx");
|
|
strncat(buf, msg, msg_len);
|
|
input_raw_info(true, &data->client->dev, "%s\n", buf);
|
|
}
|
|
buf[0] = '\0';
|
|
}
|
|
}
|
|
|
|
kfree(buf);
|
|
}
|
|
|
|
int run_node_for_dump(struct ist40xx_data *data)
|
|
{
|
|
int ret;
|
|
int pre_mode = 0;
|
|
u8 flag = NODE_FLAG_CDC | NODE_FLAG_BASE | NODE_FLAG_LOFS;
|
|
TSP_INFO *tsp = &data->tsp_info;
|
|
|
|
pre_mode = (data->noise_mode >> NOISE_MODE_CALL) & 1;
|
|
ist40xx_set_call_mode(1);
|
|
ist40xx_delay(300);
|
|
|
|
mutex_lock(&data->lock);
|
|
ret = ist40xx_read_touch_node(data, flag, &tsp->node);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
ist40xx_set_call_mode(pre_mode);
|
|
tsp_err("node frame read fail\n");
|
|
return ret;
|
|
}
|
|
mutex_unlock(&data->lock);
|
|
ist40xx_set_call_mode(pre_mode);
|
|
|
|
ist40xx_parse_touch_node(data, &tsp->node);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void dump_node_log(struct ist40xx_data *data)
|
|
{
|
|
input_raw_info(true, &data->client->dev, "----- cdc value -----:\n");
|
|
dump_self_prox_log(data, LOG_CDC);
|
|
|
|
input_raw_info(true, &data->client->dev, "----- base value -----:\n");
|
|
dump_self_prox_log(data, LOG_BASE);
|
|
|
|
input_raw_info(true, &data->client->dev, "----- lofs value -----:\n");
|
|
dump_log(data, LOG_LOFS);
|
|
}
|
|
|
|
int run_cmcs_for_dump(struct ist40xx_data *data)
|
|
{
|
|
int ret;
|
|
|
|
ret = ist40xx_get_cmcs_info(ts_cmcs_bin, ts_cmcs_bin_size);
|
|
if (ret) {
|
|
tsp_err("%s() get cmcs info read fail!\n", __func__);
|
|
return ret;
|
|
}
|
|
|
|
mutex_lock(&data->lock);
|
|
ret = ist40xx_cmcs_test(data,
|
|
CMCS_FLAG_CM | CMCS_FLAG_SLOPE | CMCS_FLAG_CS);
|
|
if (ret) {
|
|
mutex_unlock(&data->lock);
|
|
tsp_err( "%s() cmcs test fail!\n", __func__);
|
|
return ret;
|
|
}
|
|
mutex_unlock(&data->lock);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void dump_cmcs_log(struct ist40xx_data *data)
|
|
{
|
|
bool cm_result, cs_result, gap_result;
|
|
|
|
input_raw_info(true, &data->client->dev, "----- cm value -----:\n");
|
|
dump_log(data, LOG_CM);
|
|
|
|
if (cmcs_buf->cm_result == 0) {
|
|
cm_result = 0;
|
|
input_raw_info(true, &data->client->dev, "### CM result: pass ###\n");
|
|
} else {
|
|
cm_result = 1;
|
|
input_raw_info(true, &data->client->dev, "### CM result: fail ###\n");
|
|
}
|
|
|
|
input_raw_info(true, &data->client->dev, "----- gap value -----:\n");
|
|
dump_log(data, LOG_GAP);
|
|
|
|
if (cmcs_buf->slope_result == 0) {
|
|
gap_result = 0;
|
|
tsp_err( "### GAP result: pass ###\n");
|
|
} else {
|
|
gap_result = 1;
|
|
tsp_err( "### GAP result: fail ###\n");
|
|
}
|
|
|
|
input_raw_info(true, &data->client->dev, "----- cs value -----:\n");
|
|
dump_log(data, LOG_CS);
|
|
|
|
/* CS result */
|
|
if (cmcs_buf->cs_result == 0) {
|
|
cs_result = 0;
|
|
input_raw_info(true, &data->client->dev, "### CS result: pass ###\n");
|
|
} else {
|
|
cs_result = 1;
|
|
input_raw_info(true, &data->client->dev, "### CS result: fail ###\n");
|
|
}
|
|
}
|
|
|
|
void dump_miscal_log(struct ist40xx_data *data)
|
|
{
|
|
dump_log(data, LOG_MISCAL);
|
|
/*for max miscal_value */
|
|
input_raw_info(true, &data->client->dev, "### miscal_value - Max: %d ###\n", data->status.miscalib_result);
|
|
|
|
}
|
|
|
|
void ist40xx_display_booting_dump_log(struct ist40xx_data *data)
|
|
{
|
|
int ret;
|
|
|
|
input_raw_info(true, &data->client->dev, "*** TSP Dump CMCS Value ***\n");
|
|
ret = run_cmcs_for_dump(data);
|
|
if (ret) {
|
|
input_raw_info(true, &data->client->dev, "TSP Dump CMCS FAILED\n");
|
|
return;
|
|
}
|
|
dump_cmcs_log(data);
|
|
|
|
ret = ist40xx_miscalibrate(data);
|
|
if (ret) {
|
|
input_raw_info(true, &data->client->dev, "TSP Dump Miscal FAILED\n");
|
|
return;
|
|
}
|
|
input_raw_info(true, &data->client->dev, "*** TSP Dump Miscal Value ***\n");
|
|
dump_miscal_log(data);
|
|
}
|
|
|
|
void ist40xx_display_key_dump_log(struct ist40xx_data *data)
|
|
{
|
|
int ret;
|
|
|
|
ret = run_debug_for_dump(data);
|
|
if (ret) {
|
|
input_raw_info(true, &data->client->dev, "TSP Dump Debug FAILED\n");
|
|
return;
|
|
}
|
|
|
|
ret = run_node_for_dump(data);
|
|
if (ret) {
|
|
input_raw_info(true, &data->client->dev, "TSP Dump Node FAILED\n");
|
|
return;
|
|
}
|
|
|
|
input_raw_info(true, &data->client->dev, "----- cdc value -----:\n");
|
|
dump_self_prox_log(data, LOG_CDC);
|
|
|
|
input_raw_info(true, &data->client->dev, "----- base value -----:\n");
|
|
dump_self_prox_log(data, LOG_BASE);
|
|
|
|
input_raw_info(true, &data->client->dev, "----- lofs value -----:\n");
|
|
dump_log(data, LOG_LOFS);
|
|
|
|
ret = run_cp_for_dump(data);
|
|
if (ret) {
|
|
input_raw_info(true, &data->client->dev, "TSP Dump CP FAILED\n");
|
|
return;
|
|
}
|
|
|
|
input_raw_info(true, &data->client->dev, "----- MemX cp value -----:\n");
|
|
dump_self_prox_log(data, LOG_MEMX_CP);
|
|
|
|
input_raw_info(true, &data->client->dev, "----- Info cp value -----:\n");
|
|
dump_self_prox_log(data, LOG_ROM_CP);
|
|
|
|
ret = run_cmcs_for_dump(data);
|
|
if (ret) {
|
|
input_raw_info(true, &data->client->dev, "TSP Dump CMCS FAILED\n");
|
|
return;
|
|
}
|
|
dump_cmcs_log(data);
|
|
|
|
ret = ist40xx_miscalibrate(data);
|
|
if (ret) {
|
|
input_raw_info(true, &data->client->dev, "TSP Dump Miscal FAILED\n");
|
|
return;
|
|
}
|
|
input_raw_info(true, &data->client->dev, "*** TSP Dump Miscal Value ***\n");
|
|
dump_miscal_log(data);
|
|
|
|
}
|
|
|
|
int sec_touch_sysfs(struct ist40xx_data *data)
|
|
{
|
|
int ret;
|
|
#if defined(CONFIG_INPUT_SEC_SECURE_TOUCH)
|
|
int i;
|
|
#endif
|
|
|
|
/* /sys/class/sec/tsp */
|
|
ret = sec_cmd_init(&data->sec, sec_cmds,
|
|
ARRAY_SIZE(sec_cmds), SEC_CLASS_DEVT_TSP);
|
|
if (ret < 0) {
|
|
input_err(true, &data->client->dev, "%s: Failure in sec_cmd_init\n",
|
|
__func__);
|
|
return ret;
|
|
}
|
|
|
|
ret = sysfs_create_link(&data->sec.fac_dev->kobj,
|
|
&data->input_dev->dev.kobj, "input");
|
|
if (ret < 0) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: Failed to create input symbolic link\n", __func__);
|
|
goto err_sec_fac_dev_link;
|
|
}
|
|
|
|
/* /sys/class/sec/tsp/... */
|
|
if (sysfs_create_group(&data->sec.fac_dev->kobj,
|
|
&sec_touch_factory_attr_group)) {
|
|
input_err(true, &data->client->dev, "%s: Failed to create sysfs group(%s)!\n",
|
|
__func__, SEC_CLASS_DEV_NAME_TSP);
|
|
goto err_sec_fac_dev_attr;
|
|
}
|
|
|
|
#if defined(CONFIG_INPUT_SEC_SECURE_TOUCH)
|
|
for (i = 0; i < (int)ARRAY_SIZE(secure_attrs); i++) {
|
|
ret = sysfs_create_file(&data->input_dev->dev.kobj,
|
|
&secure_attrs[i].attr);
|
|
if (ret < 0) {
|
|
input_err(true, &data->client->dev,
|
|
"%s: Failed to create sysfs attributes\n",
|
|
__func__);
|
|
}
|
|
}
|
|
|
|
ist40xx_secure_touch_init(data);
|
|
#endif
|
|
return 0;
|
|
|
|
err_sec_fac_dev_attr:
|
|
sysfs_remove_link(&data->sec.fac_dev->kobj, "input");
|
|
err_sec_fac_dev_link:
|
|
sec_cmd_exit(&data->sec, SEC_CLASS_DEVT_TSP);
|
|
|
|
return -ENODEV;
|
|
}
|
|
|
|
EXPORT_SYMBOL(sec_touch_sysfs);
|
|
|
|
void sec_touch_sysfs_remove(struct ist40xx_data *data)
|
|
{
|
|
#if defined(CONFIG_INPUT_SEC_SECURE_TOUCH)
|
|
int i;
|
|
|
|
for (i = 0; i < (int)ARRAY_SIZE(secure_attrs); i++)
|
|
sysfs_remove_file(&data->input_dev->dev.kobj, &secure_attrs[i].attr);
|
|
#endif
|
|
|
|
sysfs_remove_group(&data->sec.fac_dev->kobj, &sec_touch_factory_attr_group);
|
|
sysfs_remove_link(&data->sec.fac_dev->kobj, "input");
|
|
sec_cmd_exit(&data->sec, SEC_CLASS_DEVT_TSP);
|
|
}
|
|
|
|
EXPORT_SYMBOL(sec_touch_sysfs_remove);
|
|
#endif
|
|
|