blob: 78229dec4eb71fbc94b3af774a847626f88ba1b8 [file] [log] [blame]
#ifdef SEC_TSP_FACTORY_TEST
#define BUFFER_MAX ((256 * 1024) - 16)
#define READ_CHUNK_SIZE 128 // (2 * 1024) - 16
enum {
TYPE_RAW_DATA = 0,
TYPE_FILTERED_DATA = 2,
TYPE_STRENGTH_DATA = 4,
TYPE_BASELINE_DATA = 6
};
enum {
BUILT_IN = 0,
UMS,
};
#ifdef FTS_SUPPORT_TOUCH_KEY
enum {
TYPE_TOUCHKEY_RAW = 0x34,
TYPE_TOUCHKEY_STRENGTH = 0x36,
};
#endif
#define FTS_FLASH_DATA_OFFSET_BASE 16
enum fts_nvm_data_type { /* Write Command */
FTS_NVM_OFFSET_FAC_RESULT = 1,
FTS_NVM_OFFSET_CAL_COUNT,
FTS_NVM_OFFSET_DISASSEMBLE_COUNT,
FTS_NVM_OFFSET_TUNE_VERSION,
FTS_NVM_OFFSET_CAL_POSITION,
FTS_NVM_OFFSET_HISTORY_QUEUE_COUNT,
FTS_NVM_OFFSET_HISTORY_QUEUE_LASTP,
FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO,
FTS_NVM_OFFSET_TCLM_TEST_LEVEL,
FTS_NVM_OFFSET_TCLM_TEST_AFE_BASE,
FTS_NVM_OFFSET_PRESSURE_BASE_CAL_COUNT,
FTS_NVM_OFFSET_PRESSURE_DELTA_CAL_COUNT,
FTS_NVM_OFFSET_PRESSURE_INDEX,
};
struct fts_nvm_data_map {
int type;
int offset;
int length;
};
#define NVM_CMD(mtype, moffset, mlength) .type = mtype, .offset = moffset, .length = mlength
/* This Flash Meory Map is FIXED by STM firmware
* Do not change MAP.
*/
struct fts_nvm_data_map nvm_data[] = {
{NVM_CMD(0, 0x00, 0),},
{NVM_CMD(FTS_NVM_OFFSET_FAC_RESULT, 0x00, 1),}, /* SEC */
{NVM_CMD(FTS_NVM_OFFSET_CAL_COUNT, 0x01, 1),}, /* SEC */
{NVM_CMD(FTS_NVM_OFFSET_DISASSEMBLE_COUNT, 0x02, 1),}, /* SEC */
{NVM_CMD(FTS_NVM_OFFSET_TUNE_VERSION, 0x03, 2),}, /* SEC */
{NVM_CMD(FTS_NVM_OFFSET_CAL_POSITION, 0x05, 1),}, /* SEC */
{NVM_CMD(FTS_NVM_OFFSET_HISTORY_QUEUE_COUNT, 0x06, 1),}, /* SEC */
{NVM_CMD(FTS_NVM_OFFSET_HISTORY_QUEUE_LASTP, 0x07, 1),}, /* SEC */
{NVM_CMD(FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO, 0x08, 20),}, /* SEC */
{NVM_CMD(FTS_NVM_OFFSET_TCLM_TEST_LEVEL, 0x1E, 1),}, /* SEC */
{NVM_CMD(FTS_NVM_OFFSET_TCLM_TEST_AFE_BASE, 0x1F, 2),}, /* SEC */
{NVM_CMD(FTS_NVM_OFFSET_PRESSURE_BASE_CAL_COUNT, 0x23, 1),}, /* SEC */
{NVM_CMD(FTS_NVM_OFFSET_PRESSURE_DELTA_CAL_COUNT, 0x24, 1),}, /* SEC */
{NVM_CMD(FTS_NVM_OFFSET_PRESSURE_INDEX, 0x25, 1),}, /* SEC */
};
#define FTS_NVM_OFFSET_ALL 28
#define FTS_NVM_OFFSET_TCLM_TEST_SIZE 3
#define FTS_OFFSET_TCLM_TEST_LEVEL 0
#define FTS_OFFSET_TCLM_TEST_AFE_BASE 1
static void fw_update(void *device_data);
static void get_fw_ver_bin(void *device_data);
static void get_fw_ver_ic(void *device_data);
static void get_config_ver(void *device_data);
static void get_threshold(void *device_data);
static void module_off_master(void *device_data);
static void module_on_master(void *device_data);
static void get_chip_vendor(void *device_data);
static void get_chip_name(void *device_data);
static void get_mis_cal_info(void *device_data);
static void get_wet_mode(void *device_data);
static void get_x_num(void *device_data);
static void get_y_num(void *device_data);
static void get_checksum_data(void *device_data);
static void run_reference_read(void *device_data);
static void get_reference(void *device_data);
static void run_rawcap_read(void *device_data);
static void run_rawcap_read_all(void *device_data);
static void get_rawcap(void *device_data);
static void run_delta_read(void *device_data);
static void get_delta(void *device_data);
#ifdef TCLM_CONCEPT
static void get_pat_information(void *device_data);
static void set_external_factory(void *device_data);
#endif
#ifdef FTS_SUPPORT_HOVER
static void run_abscap_read(void *device_data);
static void run_absdelta_read(void *device_data);
#endif
static void run_ix_data_read(void *device_data);
static void run_ix_data_read_all(void *device_data);
static void run_self_raw_read(void *device_data);
static void run_self_raw_read_all(void *device_data);
static void run_trx_short_test(void *device_data);
static void check_connection(void *device_data);
static void get_cx_data(void *device_data);
static void run_cx_data_read(void *device_data);
static void get_cx_all_data(void *device_data);
static void get_strength_all_data(void *device_data);
#ifdef FTS_SUPPORT_TOUCH_KEY
static void run_key_cx_data_read(void *device_data);
#endif
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
static void run_force_pressure_calibration(void *device_data);
static void set_pressure_test_mode(void *device_data);
static void run_pressure_strength_read_all(void *device_data);
static void run_pressure_rawdata_read_all(void *device_data);
static void run_pressure_ix_data_read_all(void *device_data);
static void set_pressure_strength(void *device_data);
static void set_pressure_rawdata(void *device_data);
static void set_pressure_data_index(void *device_data);
static void get_pressure_strength(void *device_data);
static void get_pressure_rawdata(void *device_data);
static void get_pressure_data_index(void *device_data);
static void set_pressure_strength_clear(void *device_data);
static void get_pressure_threshold(void *device_data);
static void set_pressure_user_level(void *device_data);
static void get_pressure_user_level(void *device_data);
#endif
static void set_tsp_test_result(void *device_data);
static void get_tsp_test_result(void *device_data);
static void increase_disassemble_count(void *device_data);
static void get_disassemble_count(void *device_data);
#ifdef FTS_SUPPORT_HOVER
static void hover_enable(void *device_data);
/* static void hover_no_sleep_enable(void *device_data); */
#endif
#ifdef CONFIG_GLOVE_TOUCH
static void glove_mode(void *device_data);
static void get_glove_sensitivity(void *device_data);
static void fast_glove_mode(void *device_data);
#endif
static void clear_cover_mode(void *device_data);
static void report_rate(void *device_data);
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
static void interrupt_control(void *device_data);
#endif
static void set_wirelesscharger_mode(void *device_data);
static void set_grip_data(void *device_data);
static void set_dead_zone(void *device_data);
static void dead_zone_enable(void *device_data);
static void drawing_test_enable(void *device_data);
static void spay_enable(void *device_data);
static void aod_enable(void *device_data);
static void set_aod_rect(void *device_data);
static void get_aod_rect(void *device_data);
static void dex_enable(void *device_data);
static void brush_enable(void *device_data);
static void set_touchable_area(void *device_data);
static void delay(void *device_data);
static void debug(void *device_data);
static void factory_cmd_result_all(void *device_data);
static void run_force_calibration(void *device_data);
static void set_factory_level(void *device_data);
static void not_support_cmd(void *device_data);
static ssize_t fts_scrub_position(struct device *dev,
struct device_attribute *attr, char *buf);
#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
extern int tui_force_close(uint32_t arg);
extern void tui_cover_mode_set(bool arg);
#endif
struct sec_cmd ft_commands[] = {
{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_config_ver", get_config_ver),},
{SEC_CMD("get_threshold", get_threshold),},
{SEC_CMD("module_off_master", module_off_master),},
{SEC_CMD("module_on_master", module_on_master),},
{SEC_CMD("module_off_slave", not_support_cmd),},
{SEC_CMD("module_on_slave", not_support_cmd),},
{SEC_CMD("get_chip_vendor", get_chip_vendor),},
{SEC_CMD("get_chip_name", get_chip_name),},
{SEC_CMD("get_mis_cal_info", get_mis_cal_info),},
{SEC_CMD("get_wet_mode", get_wet_mode),},
{SEC_CMD("get_module_vendor", not_support_cmd),},
{SEC_CMD("get_x_num", get_x_num),},
{SEC_CMD("get_y_num", get_y_num),},
{SEC_CMD("get_checksum_data", get_checksum_data),},
{SEC_CMD("run_reference_read", run_reference_read),},
{SEC_CMD("get_reference", get_reference),},
{SEC_CMD("run_rawcap_read", run_rawcap_read),},
{SEC_CMD("run_rawcap_read_all", run_rawcap_read_all),},
{SEC_CMD("get_rawcap", get_rawcap),},
{SEC_CMD("run_delta_read", run_delta_read),},
{SEC_CMD("get_delta", get_delta),},
#ifdef TCLM_CONCEPT
{SEC_CMD("get_pat_information", get_pat_information),},
{SEC_CMD("set_external_factory", set_external_factory),},
#endif
#ifdef FTS_SUPPORT_HOVER
{SEC_CMD("run_abscap_read" , run_abscap_read),},
{SEC_CMD("run_absdelta_read", run_absdelta_read),},
#endif
{SEC_CMD("run_ix_data_read", run_ix_data_read),},
{SEC_CMD("run_ix_data_read_all", run_ix_data_read_all),},
{SEC_CMD("run_self_raw_read", run_self_raw_read),},
{SEC_CMD("run_self_raw_read_all", run_self_raw_read_all),},
{SEC_CMD("run_trx_short_test", run_trx_short_test),},
{SEC_CMD("check_connection", check_connection),},
{SEC_CMD("get_cx_data", get_cx_data),},
{SEC_CMD("run_cx_data_read", run_cx_data_read),},
{SEC_CMD("run_cx_data_read_all", get_cx_all_data),},
{SEC_CMD("get_cx_all_data", get_cx_all_data),},
{SEC_CMD("get_strength_all_data", get_strength_all_data),},
#ifdef FTS_SUPPORT_TOUCH_KEY
{SEC_CMD("run_key_cx_data_read", run_key_cx_data_read),},
#endif
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
{SEC_CMD("run_force_pressure_calibration", run_force_pressure_calibration),},
{SEC_CMD("set_pressure_test_mode", set_pressure_test_mode),},
{SEC_CMD("run_pressure_strength_read_all", run_pressure_strength_read_all),},
{SEC_CMD("run_pressure_rawdata_read_all", run_pressure_rawdata_read_all),},
{SEC_CMD("run_pressure_ix_data_read_all", run_pressure_ix_data_read_all),},
{SEC_CMD("set_pressure_strength", set_pressure_strength),},
{SEC_CMD("set_pressure_rawdata", set_pressure_rawdata),},
{SEC_CMD("set_pressure_data_index", set_pressure_data_index),},
{SEC_CMD("get_pressure_strength", get_pressure_strength),},
{SEC_CMD("get_pressure_rawdata", get_pressure_rawdata),},
{SEC_CMD("get_pressure_data_index", get_pressure_data_index),},
{SEC_CMD("set_pressure_strength_clear", set_pressure_strength_clear),},
{SEC_CMD("get_pressure_threshold", get_pressure_threshold),},
{SEC_CMD("set_pressure_user_level", set_pressure_user_level),},
{SEC_CMD("get_pressure_user_level", get_pressure_user_level),},
#endif
{SEC_CMD("set_tsp_test_result", set_tsp_test_result),},
{SEC_CMD("get_tsp_test_result", get_tsp_test_result),},
{SEC_CMD("increase_disassemble_count", increase_disassemble_count),},
{SEC_CMD("get_disassemble_count", get_disassemble_count),},
#ifdef FTS_SUPPORT_HOVER
{SEC_CMD("hover_enable", hover_enable),},
#endif
#ifdef CONFIG_GLOVE_TOUCH
{SEC_CMD("glove_mode", glove_mode),},
{SEC_CMD("get_glove_sensitivity", get_glove_sensitivity),},
{SEC_CMD("fast_glove_mode", fast_glove_mode),},
#endif
{SEC_CMD("clear_cover_mode", clear_cover_mode),},
{SEC_CMD("report_rate", report_rate),},
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
{SEC_CMD("interrupt_control", interrupt_control),},
#endif
{SEC_CMD("set_wirelesscharger_mode", set_wirelesscharger_mode),},
{SEC_CMD("set_grip_data", set_grip_data),},
{SEC_CMD("set_dead_zone", set_dead_zone),},
{SEC_CMD("dead_zone_enable", dead_zone_enable),},
{SEC_CMD("drawing_test_enable", drawing_test_enable),},
{SEC_CMD("spay_enable", spay_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("dex_enable", dex_enable),},
{SEC_CMD("brush_enable", brush_enable),},
{SEC_CMD("set_touchable_area", set_touchable_area),},
{SEC_CMD("delay", delay),},
{SEC_CMD("debug", debug),},
{SEC_CMD("factory_cmd_result_all", factory_cmd_result_all),},
{SEC_CMD("run_force_calibration", run_force_calibration),},
{SEC_CMD("set_factory_level", set_factory_level),},
{SEC_CMD("not_support_cmd", not_support_cmd),},
};
static ssize_t read_ito_check_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
input_info(true, &info->client->dev, "%s: %02X%02X%02X%02X\n", __func__,
info->ito_test[0], info->ito_test[1],
info->ito_test[2], info->ito_test[3]);
return snprintf(buf, SEC_CMD_BUF_SIZE, "%02X%02X%02X%02X",
info->ito_test[0], info->ito_test[1],
info->ito_test[2], info->ito_test[3]);
}
static ssize_t read_raw_check_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
int ii, ret = 0;
char *buffer = NULL;
char temp[10] = { 0 };
buffer = kzalloc(info->SenseChannelLength * info->ForceChannelLength * 6, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
for (ii = 0; ii < (info->SenseChannelLength * info->ForceChannelLength - 1); ii++) {
snprintf(temp, 6, "%d ", info->pFrame[ii]);
strncat(buffer, temp, 6);
memset(temp, 0x00, 10);
}
snprintf(temp, 6, "%d", info->pFrame[ii]);
strncat(buffer, temp, 6);
ret = snprintf(buf, info->SenseChannelLength * info->ForceChannelLength * 6, buffer);
kfree(buffer);
return ret;
}
static ssize_t read_multi_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
input_info(true, &info->client->dev, "%s: %d\n", __func__, info->multi_count);
return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", info->multi_count);
}
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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
info->multi_count = 0;
input_info(true, &info->client->dev, "%s: clear\n", __func__);
return count;
}
static ssize_t read_wet_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
input_info(true, &info->client->dev, "%s: %d\n", __func__, info->wet_count);
return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", info->wet_count);
}
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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
info->wet_count = 0;
info->dive_count= 0;
input_info(true, &info->client->dev, "%s: clear\n", __func__);
return count;
}
static ssize_t read_comm_err_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
input_info(true, &info->client->dev, "%s: %d\n", __func__, info->comm_err_count);
return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", info->comm_err_count);
}
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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
info->comm_err_count = 0;
input_info(true, &info->client->dev, "%s: clear\n", __func__);
return count;
}
static ssize_t read_module_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
return snprintf(buf, SEC_CMD_BUF_SIZE, "ST%02X%04X%02X%c%01X",
info->panel_revision, info->fw_main_version_of_ic,
info->test_result.data[0],
info->tdata->tclm_string[info->tdata->nvdata.cal_position].s_name,
info->tdata->nvdata.cal_count & 0xF);
}
static ssize_t read_vendor_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
unsigned char buffer[10] = { 0 };
snprintf(buffer, 9, info->board->firmware_name + 8);
return snprintf(buf, SEC_CMD_BUF_SIZE, "STM_%s", buffer);
}
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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
input_info(true, &info->client->dev, "%s: crc fail count in NV: %d\n", __func__, info->nv_crc_fail_count);
return snprintf(buf, SEC_CMD_BUF_SIZE, "%d", info->nv_crc_fail_count);
}
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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
// info->checksum_result = 0;
input_info(true, &info->client->dev, "%s:nothing\n", __func__);
return count;
}
static ssize_t clear_holding_time_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
info->time_longest = 0;
input_info(true, &info->client->dev, "%s: clear\n", __func__);
return count;
}
static ssize_t read_holding_time_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
input_info(true, &info->client->dev, "%s: %ld\n", __func__,
info->time_longest);
return snprintf(buf, SEC_CMD_BUF_SIZE, "%ld", info->time_longest);
}
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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
input_info(true, &info->client->dev, "%s: touch:%d, force:%d, aod:%d, spay:%d\n", __func__,
info->all_finger_count, info->all_force_count,
info->all_aod_tap_count, info->all_spay_count);
return snprintf(buf, SEC_CMD_BUF_SIZE,
"\"TTCN\":\"%d\",\"TFCN\":\"%d\",\"TACN\":\"%d\",\"TSCN\":\"%d\"",
info->all_finger_count, info->all_force_count,
info->all_aod_tap_count, info->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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
info->all_force_count = 0;
info->all_aod_tap_count = 0;
info->all_spay_count = 0;
input_info(true, &info->client->dev, "%s: clear\n", __func__);
return count;
}
static ssize_t read_z_value_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
input_info(true, &info->client->dev, "%s: max:%d, min:%d, sum:%d\n", __func__,
info->max_z_value, info->min_z_value,
info->sum_z_value);
if (info->all_finger_count > 0)
return snprintf(buf, SEC_CMD_BUF_SIZE,
"\"TMXZ\":\"%d\",\"TMNZ\":\"%d\",\"TAVZ\":\"%d\"",
info->max_z_value, info->min_z_value,
info->sum_z_value / info->all_finger_count);
else
return snprintf(buf, SEC_CMD_BUF_SIZE,
"\"TMXZ\":\"%d\",\"TMNZ\":\"%d\"",
info->max_z_value, info->min_z_value);
}
static ssize_t clear_z_value_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
info->max_z_value= 0;
info->min_z_value= 0xFFFFFFFF;
info->sum_z_value= 0;
info->all_finger_count = 0;
input_info(true, &info->client->dev, "%s: clear\n", __func__);
return count;
}
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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
unsigned char wbuf[3] = { 0 };
unsigned long value = 0;
int ret = 0;
if (count > 2)
return -EINVAL;
ret = kstrtoul(buf, 10, &value);
if (ret != 0)
return ret;
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
return -EPERM;
}
wbuf[0] = 0xC7;
wbuf[1] = 0x03;
if (value)
wbuf[2] = 0x01; /* enable */
else
wbuf[2] = 0x00; /* disable */
ret = fts_write_reg(info, &wbuf[0], 3);
if (ret < 0) {
input_err(true, &info->client->dev,
"%s: write failed. ret: %d\n", __func__, ret);
return ret;
}
fts_delay(30);
input_info(true, &info->client->dev, "%s: %d\n", __func__, value);
return count;
}
static ssize_t sensitivity_mode_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
u8 rbuf[11] = { 0 };
u8 reg_read[3] = { 0xD0, 0x00, 0x9E };
int ret, i;
s16 value[5];
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
return -EPERM;
}
ret = info->fts_read_reg(info, &reg_read[0], 3, &rbuf[0], 3);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: read failed ret = %d\n", __func__, ret);
return ret;
}
reg_read[1] = rbuf[2];
reg_read[2] = rbuf[1];
ret = info->fts_read_reg(info, &reg_read[0], 3, &rbuf[0], 11);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: read failed ret = %d\n", __func__, ret);
return ret;
}
for (i = 0; i < 5; i++)
value[i] = rbuf[i * 2 + 1] + (rbuf[i * 2 + 2] << 8);
input_info(true, &info->client->dev, "%s: %d,%d,%d,%d,%d\n", __func__,
value[0], value[1], value[2], value[3], value[4]);
return snprintf(buf, SEC_CMD_BUF_SIZE, "%d,%d,%d,%d,%d",
value[0], value[1], value[2], value[3], value[4]);
}
static ssize_t pressure_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[256] = { 0 };
if (info->lowpower_flag & FTS_MODE_PRESSURE)
snprintf(buff, sizeof(buff), "1");
else
snprintf(buff, sizeof(buff), "0");
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
return snprintf(buf, SEC_CMD_BUF_SIZE, "%s\n", buff);
}
static ssize_t pressure_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 fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
int ret;
unsigned long value = 0;
#ifdef FTS_SUPPORT_STRINGLIB
unsigned short addr = FTS_CMD_STRING_ACCESS;
#endif
if (count > 2)
return -EINVAL;
ret = kstrtoul(buf, 10, &value);
if (ret != 0)
return ret;
if (value == 1) {
info->lowpower_flag |= FTS_MODE_PRESSURE;
} else {
info->lowpower_flag &= ~FTS_MODE_PRESSURE;
}
#ifdef FTS_SUPPORT_STRINGLIB
ret = info->fts_write_to_string(info, &addr, &info->lowpower_flag, sizeof(info->lowpower_flag));
if (ret < 0)
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
#endif
input_info(true, &info->client->dev, "%s: %d\n", __func__, value);
return count;
}
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(module_id, S_IRUGO, read_module_id_show, NULL);
static DEVICE_ATTR(vendor, S_IRUGO, read_vendor_show, NULL);
static DEVICE_ATTR(checksum, S_IRUGO | S_IWUSR | S_IWGRP, read_checksum_show, clear_checksum_store);
static DEVICE_ATTR(holding_time, S_IRUGO | S_IWUSR | S_IWGRP, read_holding_time_show, clear_holding_time_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(z_value, S_IRUGO | S_IWUSR | S_IWGRP, read_z_value_show, clear_z_value_store);
static DEVICE_ATTR(sensitivity_mode, S_IRUGO | S_IWUSR | S_IWGRP, sensitivity_mode_show, sensitivity_mode_store);
static DEVICE_ATTR(scrub_pos, S_IRUGO, fts_scrub_position, NULL);
static DEVICE_ATTR(pressure_enable, S_IRUGO | S_IWUSR | S_IWGRP, pressure_enable_show, pressure_enable_store);
static struct attribute *sec_touch_facotry_attributes[] = {
&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_module_id.attr,
&dev_attr_vendor.attr,
&dev_attr_checksum.attr,
&dev_attr_holding_time.attr,
&dev_attr_all_touch_count.attr,
&dev_attr_z_value.attr,
&dev_attr_sensitivity_mode.attr,
&dev_attr_pressure_enable.attr,
NULL,
};
static struct attribute_group sec_touch_factory_attr_group = {
.attrs = sec_touch_facotry_attributes,
};
static int fts_check_index(struct fts_ts_info *info)
{
struct sec_cmd_data *sec = &info->sec;
char buff[SEC_CMD_STR_LEN] = { 0 };
int node;
if (sec->cmd_param[0] < 0
|| sec->cmd_param[0] >= info->SenseChannelLength
|| sec->cmd_param[1] < 0
|| sec->cmd_param[1] >= info->ForceChannelLength) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
input_err(true, &info->client->dev, "%s: parameter error: %u,%u\n",
__func__, sec->cmd_param[0], sec->cmd_param[1]);
node = -1;
return node;
}
node = sec->cmd_param[1] * info->SenseChannelLength + sec->cmd_param[0];
/* input_info(true, &info->client->dev, "%s: node = %d\n", __func__, node); */
return node;
}
static ssize_t fts_scrub_position(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sec_cmd_data *sec = dev_get_drvdata(dev);
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
input_info(true, &info->client->dev, "%s: %d %d %d\n",
__func__, info->scrub_id, info->scrub_x, info->scrub_y);
snprintf(buff, sizeof(buff), "%d %d %d", info->scrub_id, info->scrub_x, info->scrub_y);
info->scrub_x = 0;
info->scrub_y = 0;
return snprintf(buf, SEC_CMD_BUF_SIZE, "%s\n", buff);
}
#if 0 //def CONFIG_TRUSTONIC_TRUSTED_UI
static void tui_mode_cmd(struct fts_ts_info *info)
{
struct sec_cmd_data *sec = &info->sec;
char buff[16] = "TUImode:FAIL";
sec_cmd_set_default_result(sec);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#endif
static void not_support_cmd(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[16] = { 0 };
sec_cmd_set_default_result(sec);
snprintf(buff, sizeof(buff), "%s", "NA");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void fw_update(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[64] = { 0 };
int retval = 0;
sec_cmd_set_default_result(sec);
#if defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
if (sec->cmd_param[0] == 1) {
snprintf(buff, sizeof(buff), "%s", "OK");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: user_ship, success [%d]\n", __func__, retval);
return;
}
#endif
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
retval = fts_fw_update_on_hidden_menu(info, sec->cmd_param[0]);
if (retval < 0) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
input_err(true, &info->client->dev, "%s: failed [%d]\n", __func__, retval);
} else {
snprintf(buff, sizeof(buff), "%s", "OK");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: success [%d]\n", __func__, retval);
}
return;
}
static int fts_get_channel_info(struct fts_ts_info *info) // Need to change function for sysinfo
{
int rc = -1;
unsigned char data[FTS_EVENT_SIZE] = { 0 };
memset(data, 0x0, FTS_EVENT_SIZE);
fts_interrupt_set(info, INT_DISABLE);
fts_command(info, FLUSHBUFFER);
fts_release_all_finger(info);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_release_all_key(info);
#endif
// Read Sense Channel
rc = info->fts_get_sysinfo_data(info, FTS_SI_SENSE_CH_LENGTH, 3, data);
if (rc <= 0) {
info->SenseChannelLength = 0;
input_err(true, info->dev, "%s: Get channel info Read Fail!! [Data : %2X]\n", __func__, data[0]);
return rc;
}
info->SenseChannelLength = data[0];
// Read Force Channel
rc = info->fts_get_sysinfo_data(info, FTS_SI_FORCE_CH_LENGTH, 3, data);
if (rc <= 0) {
info->ForceChannelLength = 0;
input_err(true, info->dev, "%s: Get channel info Read Fail!! [Data : %2X]\n", __func__, data[0]);
return rc;
}
info->ForceChannelLength = data[0];
fts_interrupt_set(info, INT_ENABLE);
return rc;
}
void fts_print_frame(struct fts_ts_info *info, short *min, short *max)
{
int i = 0;
int j = 0;
unsigned char *pStr = NULL;
unsigned char pTmp[16] = { 0 };
pStr = kzalloc(6 * (info->SenseChannelLength + 1), GFP_KERNEL);
if (pStr == NULL) {
input_err(true, &info->client->dev, "%s: pStr kzalloc failed\n", __func__);
return;
}
snprintf(pTmp, 4, " ");
strncat(pStr, pTmp, 4);
for (i = 0; i < info->SenseChannelLength; i++) {
snprintf(pTmp, 6, "Rx%02d ", i);
strncat(pStr, pTmp, 6);
}
input_raw_info(true, &info->client->dev, "%s\n", pStr);
memset(pStr, 0x0, 6 * (info->SenseChannelLength + 1));
snprintf(pTmp, 2, " +");
strncat(pStr, pTmp, 2);
for (i = 0; i < info->SenseChannelLength; i++) {
snprintf(pTmp, 6, "------");
strncat(pStr, pTmp, 6);
}
input_raw_info(true, &info->client->dev, "%s\n", pStr);
for (i = 0; i < info->ForceChannelLength; i++) {
memset(pStr, 0x0, 6 * (info->SenseChannelLength + 1));
snprintf(pTmp, 7, "Tx%02d | ", i);
strncat(pStr, pTmp, 7);
for (j = 0; j < info->SenseChannelLength; j++) {
snprintf(pTmp, 6, "%5d ", info->pFrame[(i * info->SenseChannelLength) + j]);
if (i > 0) {
if (info->pFrame[(i * info->SenseChannelLength) + j] < *min)
*min = info->pFrame[(i * info->SenseChannelLength) + j];
if (info->pFrame[(i * info->SenseChannelLength) + j] > *max)
*max = info->pFrame[(i * info->SenseChannelLength) + j];
}
strncat(pStr, pTmp, 6);
}
input_raw_info(true, &info->client->dev, "%s\n", pStr);
}
kfree(pStr);
}
int fts_read_frame(struct fts_ts_info *info, unsigned char type, short *min,
short *max)
{
unsigned char pFrameAddress[8] =
{ 0xD0, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00 };
unsigned int FrameAddress = 0;
unsigned int writeAddr = 0;
unsigned int start_addr = 0;
unsigned int end_addr = 0;
unsigned int totalbytes = 0;
unsigned int remained = 0;
unsigned int readbytes = 0xFF;
unsigned int dataposition = 0;
unsigned char *pRead = NULL;
int rc = 0;
int ret = 0;
int i = 0;
pRead = kzalloc(BUFFER_MAX, GFP_KERNEL);
if (pRead == NULL) {
input_err(true, &info->client->dev, "%s: pRead kzalloc failed\n", __func__);
rc = 1;
goto ErrorExit;
}
pFrameAddress[2] = type;
totalbytes = info->SenseChannelLength * info->ForceChannelLength * 2;
ret = fts_read_reg(info, &pFrameAddress[0], 3, pRead, pFrameAddress[3]);
if (ret >= 0) {
FrameAddress = pRead[1] + (pRead[2] << 8);
start_addr = FrameAddress+info->SenseChannelLength * 2;
end_addr = start_addr + totalbytes;
} else {
input_err(true, &info->client->dev, "%s: read failed rc = %d\n", __func__, ret);
rc = 2;
goto ErrorExit;
}
#ifdef DEBUG_MSG
input_info(true, &info->client->dev, "%s: FrameAddress = %X\n", __func__, FrameAddress);
input_info(true, &info->client->dev, "%s: start_addr = %X, end_addr = %X\n", __func__, start_addr, end_addr);
#endif
remained = totalbytes;
for (writeAddr = start_addr; writeAddr < end_addr; writeAddr += READ_CHUNK_SIZE) {
pFrameAddress[1] = (writeAddr >> 8) & 0xFF;
pFrameAddress[2] = writeAddr & 0xFF;
if (remained >= READ_CHUNK_SIZE)
readbytes = READ_CHUNK_SIZE;
else
readbytes = remained;
memset(pRead, 0x0, readbytes);
#ifdef DEBUG_MSG
input_info(true, &info->client->dev, "%s: %02X%02X%02X readbytes=%d\n", __func__,
pFrameAddress[0], pFrameAddress[1],
pFrameAddress[2], readbytes);
#endif
fts_read_reg(info, &pFrameAddress[0], 3, pRead, readbytes + 1);
remained -= readbytes;
for (i = 1; i < (readbytes+1); i += 2) {
info->pFrame[dataposition++] =
pRead[i] + (pRead[i + 1] << 8);
}
}
kfree(pRead);
#ifdef DEBUG_MSG
input_info(true, &info->client->dev,
"%s: writeAddr = %X, start_addr = %X, end_addr = %X\n", __func__,
writeAddr, start_addr, end_addr);
#endif
switch (type) {
case TYPE_RAW_DATA:
input_raw_info(true, &info->client->dev, "%s: [Raw Data : 0x%X%X]\n", __func__, pFrameAddress[0],
FrameAddress);
break;
case TYPE_FILTERED_DATA:
input_raw_info(true, &info->client->dev, "%s: [Filtered Data : 0x%X%X]\n", __func__,
pFrameAddress[0], FrameAddress);
break;
case TYPE_STRENGTH_DATA:
input_raw_info(true, &info->client->dev, "%s: [Strength Data : 0x%X%X]\n", __func__,
pFrameAddress[0], FrameAddress);
break;
case TYPE_BASELINE_DATA:
input_raw_info(true, &info->client->dev, "%s: [Baseline Data : 0x%X%X]\n", __func__,
pFrameAddress[0], FrameAddress);
break;
}
fts_print_frame(info, min, max);
ErrorExit:
return rc;
}
void fts_get_sec_ito_test_result(struct fts_ts_info *info)
{
struct sec_cmd_data *sec = &info->sec;
struct fts_sec_panel_test_result result[10];
u8 regAdd[3] = { 0 };
u8 regAddData[3] = { 0 };
u8 data[sizeof(struct fts_sec_panel_test_result) * 10 + 3] = { 0 };
int ret, i, max_count = 0;
u8 length = sizeof(data);
u8 buff[100] = { 0 };
u8 pos_buf[6] = { 0 };
u8 doffset = 1;
regAdd[0] = 0xB8;
regAdd[1] = 0x00;
regAdd[2] = 0x20;
ret = info->fts_write_reg(info, regAdd, 3);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: failed to write request cmd, %d\n", __func__, ret);
goto done;
}
fts_delay(10);
regAdd[0] = 0xD0;
regAdd[1] = 0x00;
regAdd[2] = 0x50;
ret = info->fts_read_reg(info, regAdd, 3, regAddData, 3);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: failed to read data, %d\n", __func__, ret);
goto done;
}
regAdd[1] = regAddData[2];
regAdd[2] = regAddData[1];
ret = info->fts_read_reg(info, regAdd, 3, data, length);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: failed to read data, %d\n", __func__, ret);
goto done;
}
memcpy(result, &data[2 + doffset], length - (2 + doffset));
memset(info->ito_result, 0x00, FTS_ITO_RESULT_PRINT_SIZE);
snprintf(buff, sizeof(buff), "%s: test count - sub:%d, main:%d\n", __func__, data[0 + doffset], data[1 + doffset]);
input_info(true, &info->client->dev, "%s", buff);
strncat(info->ito_result, buff, sizeof(buff));
snprintf(buff, sizeof(buff), "ITO: / TX_GAP_MAX / RX_GAP_MAX\n");
input_info(true, &info->client->dev, "%s", buff);
strncat(info->ito_result, buff, sizeof(buff));
for (i = 0; i < 10; i++) {
switch (result[i].flag) {
case OFFSET_FAC_SUB:
snprintf(pos_buf, sizeof(pos_buf), "SUB ");
break;
case OFFSET_FAC_MAIN:
snprintf(pos_buf, sizeof(pos_buf), "MAIN");
break;
case OFFSET_FAC_NOSAVE:
default:
snprintf(pos_buf, sizeof(pos_buf), "NONE");
break;
}
snprintf(buff, sizeof(buff), "ITO: [%3d] %d-%s / Tx%02d,Rx%02d: %3d / Tx%02d,Rx%02d: %3d\n",
result[i].num_of_test, result[i].flag, pos_buf,
result[i].tx_of_txmax_gap, result[i].rx_of_txmax_gap,
result[i].max_of_tx_gap,
result[i].tx_of_rxmax_gap, result[i].rx_of_rxmax_gap,
result[i].max_of_rx_gap);
input_info(true, &info->client->dev, "%s", buff);
strncat(info->ito_result, buff, sizeof(buff));
/* when count is over 200, it restart from 1 */
if (result[i].num_of_test > result[max_count].num_of_test + 100)
continue;
if (result[i].num_of_test > result[max_count].num_of_test)
max_count = i;
if (result[i].num_of_test == 1 && result[max_count].num_of_test == 200)
max_count = i;
}
input_info(true, &info->client->dev, "%s: latest test is %d\n",
__func__, result[max_count].num_of_test);
done:
if (sec->cmd_all_factory_state != SEC_CMD_STATUS_RUNNING)
return;
if (ret < 0) {
snprintf(buff, sizeof(buff), "NG");
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CH_OPEN/SHORT_TEST_X");
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CH_OPEN/SHORT_TEST_Y");
} else {
snprintf(buff, sizeof(buff), "0,%d", result[max_count].max_of_rx_gap);
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CH_OPEN/SHORT_TEST_X");
snprintf(buff, sizeof(buff), "0,%d", result[max_count].max_of_tx_gap);
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CH_OPEN/SHORT_TEST_Y");
}
}
int fts_set_sec_ito_test_result(struct fts_ts_info *info)
{
struct sec_cmd_data *sec = &info->sec;
u8 regAdd[3] = { 0 };
int ret = -EINVAL;
u8 buff[10] = { 0 };
if (!info->factory_position) {
input_err(true, &info->client->dev, "%s: not save, factory level = %d\n",
__func__, info->factory_position);
goto out;
}
fts_systemreset(info, 10);
fts_command(info, 0xA5); // HF ITO test
ret = fts_fw_wait_for_specific_event(info, EVENTID_STATUS_EVENT, 0x20, 0x00);
if(ret < 0) {
input_err(true, &info->client->dev, "%s: failed HF ito test , %d\n", __func__, ret);
goto out;
}
regAdd[0] = 0xC7;
regAdd[1] = 0x06;
regAdd[2] = info->factory_position;
ret = info->fts_write_reg(info, regAdd, 3);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: failed to write fac position, %d\n", __func__, ret);
goto out;
}
fts_delay(10);
fts_command(info, FTS_CMD_SAVE_CX_TUNING);
fts_delay(230);
fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE);
input_info(true, &info->client->dev, "%s: position %d result is saved\n", __func__, info->factory_position);
return 0;
out:
if (sec->cmd_all_factory_state != SEC_CMD_STATUS_RUNNING)
return ret;
snprintf(buff, sizeof(buff), "NG");
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CH_OPEN/SHORT_TEST_X");
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CH_OPEN/SHORT_TEST_Y");
return ret;
}
void fts_checking_miscal(struct fts_ts_info *info, int testmode)
{
u8 regAdd[4] = { 0 };
u8 data[3] = { 0 };
u16 jitter_avg = 0, miscal_thd = 0;
int ret, diff_sum = 0, i;
short min = 0x7FFF;
short max = 0x8000;
info->miscal_result = MISCAL_PASS;
if (testmode == SAVE_MISCAL_REF_RAW) {
/* store miscal ref raw data after CX2=0 : in autotune */
fts_read_frame(info, TYPE_RAW_DATA, &min, &max);
memcpy(&info->miscal_ref_raw[0], &info->pFrame[0],
info->ForceChannelLength * info->SenseChannelLength * sizeof(short));
input_info(true, &info->client->dev, "%s: miscal ref raw data is saved\n", __func__);
return;
} else if (testmode != OPEN_SHORT_CRACK_TEST) {
return;
}
/* checking miscal ref raw is saved or not */
for (i = 0; i < info->ForceChannelLength * info->SenseChannelLength; i++) {
if (info->miscal_ref_raw[i] != 0)
break;
}
if (i == info->ForceChannelLength * info->SenseChannelLength) {
input_info(true, &info->client->dev,
"%s: miscal ref raw data is not saved\n", __func__);
return;
}
info->miscal_result = MISCAL_FAIL;
/* get the raw data after CX2=0 : in selftest */
fts_read_frame(info, TYPE_RAW_DATA, &min, &max);
regAdd[0] = 0xD0;
regAdd[1] = 0x00;
regAdd[2] = 0x98;
ret = info->fts_read_reg(info, regAdd, 3, data, 3);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: failed to read jitter avg\n", __func__);
return;
}
jitter_avg = data[2] << 8 | data[1];
regAdd[0] = 0xD0;
regAdd[1] = 0x00;
regAdd[2] = 0x9A;
ret = info->fts_read_reg(info, regAdd, 3, data, 3);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: failed to read miscal threshold\n", __func__);
return;
}
miscal_thd = data[2] << 8 | data[1];
/* compare raw data between autotune and selftest */
for (i = 0; i < info->ForceChannelLength * info->SenseChannelLength; i++) {
short node_diff = abs(info->miscal_ref_raw[i] - info->pFrame[i]);
if (node_diff > jitter_avg)
diff_sum += node_diff - jitter_avg;
}
if (diff_sum < miscal_thd)
info->miscal_result = MISCAL_PASS;
input_info(true, &info->client->dev, "%s: jitter avg:%d, threshold:%d, diff sum:%d, miscal:%s\n",
__func__, jitter_avg, miscal_thd, diff_sum,
info->miscal_result == MISCAL_PASS ? "PASS" : "FAIL");
}
int fts_panel_ito_test(struct fts_ts_info *info, int testmode)
{
unsigned char cmd = READ_ONE_EVENT;
unsigned char data[FTS_EVENT_SIZE];
u8 regAdd[4] = { 0 };
u8 regAddOff[4] = { 0 };
int retry = 0;
int result = -1;
fts_systemreset(info, 10);
disable_irq(info->irq);
fts_interrupt_set(info, INT_DISABLE);
fts_command(info, FLUSHBUFFER);
fts_release_all_finger(info);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_release_all_key(info);
#endif
switch(testmode) {
case OPEN_TEST: /* connection test */
case SAVE_MISCAL_REF_RAW:
fts_command(info, 0xA6);
break;
case OPEN_SHORT_CRACK_TEST:
default:
fts_command(info, 0xA7); /* ITO test command */
break;
}
fts_delay(200);
memset(data, 0x0, FTS_EVENT_SIZE);
while (fts_read_reg(info, &cmd, 1, (unsigned char *)data, FTS_EVENT_SIZE)) {
if ((data[0] == 0x0F) && (data[1] == 0x05)) {
info->ito_test[0] = 0x0;
info->ito_test[1] = 0x0;
info->ito_test[2] = data[2];
info->ito_test[3] = data[3];
switch (data[2]) {
case 0x00 :
result = 0;
break;
case 0x01 :
input_info(true, &info->client->dev, "%s: Force channel [%d] open\n", __func__,
data[3]);
break;
case 0x02 :
input_info(true, &info->client->dev, "%s: Sense channel [%d] open\n", __func__,
data[3]);
break;
case 0x03 :
input_info(true, &info->client->dev, "%s: Force channel [%d] short to GND\n", __func__,
data[3]);
break;
case 0x04 :
input_info(true, &info->client->dev, "%s: Sense channel [%d] short to GND\n", __func__,
data[3]);
break;
case 0x05 :
input_info(true, &info->client->dev, "%s: Force channel [%d] short to VDD\n", __func__,
data[3]);
break;
case 0x06 :
input_info(true, &info->client->dev, "%s: Sense channel [%d] short to VDD\n", __func__,
data[3]);
break;
case 0x07 :
input_info(true, &info->client->dev, "%s: Force channel [%d] short to force\n", __func__,
data[3]);
break;
case 0x08 :
input_info(true, &info->client->dev, "%s: Sennse channel [%d] short to sense\n", __func__,
data[3]);
break;
default:
break;
}
}else if ((data[0] == 0x16) && (data[1] == 0xA6)) {
if(testmode == OPEN_TEST) {
regAdd[0] = 0xD0;
regAdd[1] = 0x00;
regAdd[2] = 0x9C;
fts_read_reg(info, regAdd, 3, regAddOff, 3);
fts_delay(10);
regAdd[1] = regAddOff[2];
regAdd[2] = regAddOff[1];
fts_read_reg(info, regAdd, 3, data, 3);
if((data[1] & 0xff) == 0x0) {
result = 0;
input_info(true, &info->client->dev, "%s: Connection Checking success \n", __func__);
} else {
result = -1;
input_info(true, &info->client->dev, "%s: Connection Checking fail \n", __func__);
}
}
break;
}
if (retry++ > 30) {
input_err(true, &info->client->dev, "%s: Time over - wait for result of ITO test\n", __func__);
break;
}
fts_delay(10);
}
if (info->board->item_version > 1) {
if (fts_set_sec_ito_test_result(info) >= 0)
fts_get_sec_ito_test_result(info);
}
if((testmode == OPEN_SHORT_CRACK_TEST) || (info->factory_position != 0)) {
fts_systemreset(info, 10);
fts_command(info, 0xA6);
fts_fw_wait_for_specific_event(info, EVENTID_STATUS_EVENT, 0xA6, 0x00);
}
fts_checking_miscal(info, testmode);
fts_systemreset(info, 10);
#ifdef FTS_SUPPORT_NOISE_PARAM
fts_set_noise_param(info);
#endif
fts_command(info, FLUSHBUFFER);
fts_delay(10);
fts_command(info, SENSEON);
fts_fw_wait_for_event (info, STATUS_EVENT_FORCE_CAL_DONE_D3);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_command(info, FTS_CMD_KEY_SENSE_ON);
#endif
#ifdef FTS_SUPPORT_HOVER
if (info->hover_enabled)
fts_command(info, FTS_CMD_HOVER_ON);
#endif
if (info->flip_enable) {
fts_set_cover_type(info, true);
}
#ifdef CONFIG_GLOVE_TOUCH
else {
if (info->glove_enabled)
fts_command(info, FTS_CMD_GLOVE_ON);
}
#endif
#ifdef FTS_SUPPORT_TA_MODE
if (info->TA_Pluged)
fts_command(info, FTS_CMD_CHARGER_PLUGGED);
#endif
info->touch_count = 0;
fts_interrupt_set(info, INT_ENABLE);
enable_irq(info->irq);
return result;
}
static void get_fw_ver_bin(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[16] = { 0 };
sec_cmd_set_default_result(sec);
snprintf(buff, sizeof(buff), "ST%02X%04X",
info->panel_revision,
info->fw_main_version_of_bin);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "FW_VER_BIN");
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_fw_ver_ic(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[16] = { 0 };
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "FW_VER_IC");
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
disable_irq(info->irq);
fts_get_version_info(info);
enable_irq(info->irq);
snprintf(buff, sizeof(buff), "ST%02X%04X",
info->panel_revision,
info->fw_main_version_of_ic);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "FW_VER_IC");
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_config_ver(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[20] = { 0 };
snprintf(buff, sizeof(buff), "%s_ST_%04X",
info->board->model_name ?: info->board->project_name ?: "STM",
info->config_version_of_ic);
sec_cmd_set_default_result(sec);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_threshold(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
unsigned char buff[16] = { 0 };
unsigned char data[5] = { 0 };
unsigned short finger_threshold = 0;
int rc;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
sec->cmd_state = SEC_CMD_STATUS_RUNNING;
rc = info->fts_get_sysinfo_data(info, FTS_SI_FINGER_THRESHOLD, 4, data);
if (rc <= 0) {
input_err(true, info->dev, "%s: Get threshold Read Fail!! [Data : %2X%2X]\n", __func__, data[0], data[1]);
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
finger_threshold = (unsigned short)(data[0] + (data[1] << 8));
snprintf(buff, sizeof(buff), "%d", finger_threshold);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void module_off_master(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[3] = { 0 };
int ret = 0;
ret = fts_stop_device(info, false);
if (ret == 0)
snprintf(buff, sizeof(buff), "%s", "OK");
else
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_default_result(sec);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (strncmp(buff, "OK", 2) == 0)
sec->cmd_state = SEC_CMD_STATUS_OK;
else
sec->cmd_state = SEC_CMD_STATUS_FAIL;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void module_on_master(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[3] = { 0 };
int ret = 0;
ret = fts_start_device(info);
if (info->input_dev->disabled)
fts_stop_device(info, info->lowpower_flag);
if (ret == 0)
snprintf(buff, sizeof(buff), "%s", "OK");
else
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_default_result(sec);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (strncmp(buff, "OK", 2) == 0)
sec->cmd_state = SEC_CMD_STATUS_OK;
else
sec->cmd_state = SEC_CMD_STATUS_FAIL;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_chip_vendor(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[16] = { 0 };
strncpy(buff, "STM", sizeof(buff));
sec_cmd_set_default_result(sec);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "IC_VENDOR");
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_chip_name(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[16] = { 0 };
memcpy(buff, info->firmware_name + 8, 9);
sec_cmd_set_default_result(sec);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "IC_NAME");
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_mis_cal_info(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
snprintf(buff, sizeof(buff), "%d", info->miscal_result);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "MIS_CAL");
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
return;
}
static void get_wet_mode(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char regAdd[3] = { 0 };
unsigned char data[2] = { 0 };
int ret;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
regAdd[0] = 0xD0;
regAdd[1] = 0x00;
regAdd[2] = 0x66;
ret = fts_read_reg(info, regAdd, 3, data, 2);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: [ERROR] failed to read\n", __func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
input_err(true, &info->client->dev, "%s: %02X, %02X\n", __func__, data[0], data[1]);
snprintf(buff, sizeof(buff), "%d", data[1]);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_x_num(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[16] = { 0 };
sec_cmd_set_default_result(sec);
snprintf(buff, sizeof(buff), "%d", info->SenseChannelLength);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_y_num(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[16] = { 0 };
sec_cmd_set_default_result(sec);
snprintf(buff, sizeof(buff), "%d", info->ForceChannelLength);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_checksum_data(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[16] = { 0 };
int rc;
unsigned char data[6] = { 0 };
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
rc = fts_systemreset(info, 10);
if (rc != FTS_NOT_ERROR) {
snprintf(buff, sizeof(buff), "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
} else {
fts_reinit(info);
fts_interrupt_set(info, INT_DISABLE);
rc = info->fts_get_sysinfo_data(info, FTS_SI_CONFIG_CHECKSUM, 5, data);
if (rc <= 0) {
input_err(true, info->dev, "%s: Get checksum data Read Fail!! [Data : %2X%2X%2X%2X]\n", __func__, data[1], data[0], data[3], data[2]);
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
fts_interrupt_set(info, INT_ENABLE);
snprintf(buff, sizeof(buff), "%02X%02X%02X%02X", data[1], data[0], data[3], data[2]);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
}
static void run_reference_read(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
short min = 0x7FFF;
short max = 0x8000;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
fts_read_frame(info, TYPE_BASELINE_DATA, &min, &max);
snprintf(buff, sizeof(buff), "%d,%d", min, max);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_reference(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
short val = 0;
int node = 0;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
node = fts_check_index(info);
if (node < 0)
return;
val = info->pFrame[node];
snprintf(buff, sizeof(buff), "%d", val);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void run_rawcap_read(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
short min = 0x7FFF;
short max = 0x8000;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "RAW_DATA");
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
fts_read_frame(info, TYPE_FILTERED_DATA, &min, &max);
snprintf(buff, sizeof(buff), "%d,%d", min, max);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "RAW_DATA");
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void run_rawcap_read_all(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
short min = 0x7FFF;
short max = 0x8000;
char *all_strbuff;
int i, j;
sec_cmd_set_default_result(sec);
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
all_strbuff = kzalloc(info->ForceChannelLength * info->SenseChannelLength * 7 + 1, GFP_KERNEL);
if (!all_strbuff) {
input_err(true, &info->client->dev, "%s: alloc failed\n", __func__);
snprintf(buff, sizeof(buff), "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
fts_read_frame(info, TYPE_FILTERED_DATA, &min, &max);
for (j = 0; j < info->ForceChannelLength; j++) {
for (i = 0; i < info->SenseChannelLength; i++) {
snprintf(buff, sizeof(buff), "%d,", info->pFrame[j * info->SenseChannelLength + i]);
strncat(all_strbuff, buff, sizeof(buff));
}
}
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, all_strbuff, strlen(all_strbuff));
input_info(true, &info->client->dev, "%s: %ld\n", __func__, strlen(all_strbuff));
kfree(all_strbuff);
}
static void get_rawcap(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
short val = 0;
int node = 0;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
node = fts_check_index(info);
if (node < 0)
return;
val = info->pFrame[node];
snprintf(buff, sizeof(buff), "%d", val);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void run_delta_read(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
short min = 0x7FFF;
short max = 0x8000;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
fts_read_frame(info, TYPE_STRENGTH_DATA, &min, &max);
snprintf(buff, sizeof(buff), "%d,%d", min, max);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_strength_all_data(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
short min = 0x7FFF;
short max = 0x8000;
char all_strbuff[(info->ForceChannelLength)*(info->SenseChannelLength)*5];
int i, j;
memset(all_strbuff,0,sizeof(char)*((info->ForceChannelLength)*(info->SenseChannelLength)*5)); //size 5 ex(1125,)
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
fts_read_frame(info, TYPE_STRENGTH_DATA, &min, &max);
for (i = 0; i < info->ForceChannelLength; i++) {
for (j = 0; j < info->SenseChannelLength; j++) {
snprintf(buff, sizeof(buff), "%d,", info->pFrame[(i * info->SenseChannelLength) + j]);
strncat(all_strbuff, buff, sizeof(buff));
}
}
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, all_strbuff, strnlen(all_strbuff, sizeof(all_strbuff)));
input_info(true, &info->client->dev, "%s: %ld (%ld)\n", __func__, strnlen(all_strbuff, sizeof(all_strbuff)),sizeof(all_strbuff));
}
static void get_delta(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
short val = 0;
int node = 0;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
node = fts_check_index(info);
if (node < 0)
return;
val = info->pFrame[node];
snprintf(buff, sizeof(buff), "%d", val);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#ifdef TCLM_CONCEPT
static void get_pat_information(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[50] = { 0 };
sec_cmd_set_default_result(sec);
/* fixed tune version will be saved at excute autotune */
snprintf(buff, sizeof(buff), "C%02XT%04X.%4s%s%c%d%c%d%c%d",
info->tdata->nvdata.cal_count, info->tdata->nvdata.tune_fix_ver,
info->tdata->tclm_string[info->tdata->nvdata.cal_position].f_name,
(info->tdata->tclm_level == TCLM_LEVEL_LOCKDOWN) ? ".L " : " ",
info->tdata->cal_pos_hist_last3[0], info->tdata->cal_pos_hist_last3[1],
info->tdata->cal_pos_hist_last3[2], info->tdata->cal_pos_hist_last3[3],
info->tdata->cal_pos_hist_last3[4], info->tdata->cal_pos_hist_last3[5]);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void set_external_factory(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
info->tdata->external_factory = true;
snprintf(buff, sizeof(buff), "OK");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#endif
#ifdef FTS_SUPPORT_HOVER
void fts_read_self_frame(struct fts_ts_info *info, unsigned short oAddr)
{
struct sec_cmd_data *sec = &info->sec;
char buff[66] = {0, };
short *data = 0;
char temp[9] = {0, };
char temp2[512] = {0, };
int i;
int rc;
int retry=1;
unsigned char regAdd[6] = {0xD0, 0x00, 0x00, 0xD0, 0x00, 0x00};
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
if (!info->hover_enabled) {
input_err(true, &info->client->dev, "%s: [ERROR] Hover is disabled\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP Hover disabled");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
while (!info->hover_ready) {
if (retry++ > 500) {
input_err(true, &info->client->dev, "%s: Timeout - Abs Raw Data Ready Event\n",
__func__);
break;
}
fts_delay(10);
}
regAdd[1] = (oAddr >> 8) & 0xff;
regAdd[2] = oAddr & 0xff;
rc = info->fts_read_reg(info, &regAdd[0], 3, (unsigned char *)&buff[0], 5);
if (rc <= 0) {
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
input_info(true, &info->client->dev, "%s: Force Address : %02x%02x\n",
__func__, buff[2], buff[1]);
input_info(true, &info->client->dev, "%s: Sense Address : %02x%02x\n",
__func__, buff[4], buff[3]);
regAdd[1] = buff[4];
regAdd[2] = buff[3];
regAdd[4] = buff[2];
regAdd[5] = buff[1];
rc = info->fts_read_reg(info, &regAdd[0], 3,
(unsigned char *)&buff[0],
info->SenseChannelLength * 2 + 1);
if (rc <= 0) {
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
data = (short *)&buff[1];
memset(temp, 0x00, ARRAY_SIZE(temp));
memset(temp2, 0x00, ARRAY_SIZE(temp2));
for (i = 0; i < info->SenseChannelLength; i++) {
input_info(true, &info->client->dev,
"%s: Rx [%d] = %d\n", __func__, i, *data);
snprintf(temp, sizeof(temp), "%d,", *data);
strncat(temp2, temp, 9);
data++;
}
rc = info->fts_read_reg(info, &regAdd[3], 3,
(unsigned char *)&buff[0],
info->ForceChannelLength * 2 + 1);
if (rc <= 0) {
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
data = (short *)&buff[1];
for (i = 0; i < info->ForceChannelLength; i++) {
input_info(true, &info->client->dev,
"%s: Tx [%d] = %d\n", __func__, i, *data);
snprintf(temp, sizeof(temp), "%d,", *data);
strncat(temp2, temp, 9);
data++;
}
sec_cmd_set_cmd_result(sec, temp2, strnlen(temp2, sizeof(temp2)));
sec->cmd_state = SEC_CMD_STATUS_OK;
}
static void run_abscap_read(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
sec_cmd_set_default_result(sec);
fts_read_self_frame(info, 0x000E);
}
static void run_absdelta_read(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
sec_cmd_set_default_result(sec);
fts_read_self_frame(info, 0x0012);
}
#endif
#define FTS_WATER_SELF_RAW_ADDR 0x1A
static void fts_read_ix_data(struct fts_ts_info *info, bool allnode)
{
struct sec_cmd_data *sec = &info->sec;
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned short max_tx_ix_sum = 0;
unsigned short min_tx_ix_sum = 0xFFFF;
unsigned short max_rx_ix_sum = 0;
unsigned short min_rx_ix_sum = 0xFFFF;
unsigned char tx_ix2[info->ForceChannelLength + 4];
unsigned char rx_ix2[info->SenseChannelLength + 4];
unsigned char regAdd[FTS_EVENT_SIZE];
unsigned short tx_ix1 = 0, rx_ix1 = 0;
unsigned short force_ix_data[info->ForceChannelLength * 2 + 1];
unsigned short sense_ix_data[info->SenseChannelLength * 2 + 1];
int buff_size,j;
char *mbuff = NULL;
int num,n,a,fzero;
char cnum;
int i = 0;
int comp_header_addr, comp_start_tx_addr, comp_start_rx_addr;
unsigned int rx_num, tx_num;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "IX_DATA");
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
disable_irq(info->irq);
fts_interrupt_set(info, INT_DISABLE);
fts_command(info, SENSEOFF);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey) {
fts_command(info, FTS_CMD_KEY_SENSE_OFF);
}
#endif
fts_command(info, FLUSHBUFFER); // Clear FIFO
fts_delay(50);
fts_release_all_finger(info);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_release_all_key(info);
#endif
/* Request compensation data */
regAdd[0] = 0xB8;
regAdd[1] = 0x20; // SELF IX
regAdd[2] = 0x00;
fts_write_reg(info, &regAdd[0], 3);
fts_fw_wait_for_specific_event(info, EVENTID_STATUS_REQUEST_COMP, 0x20, 0x00);
/* Read an address of compensation data */
regAdd[0] = 0xD0;
regAdd[1] = 0x00;
regAdd[2] = FTS_SI_COMPENSATION_OFFSET_ADDR;
fts_read_reg(info, regAdd, 3, &buff[0], 4);
comp_header_addr = buff[1] + (buff[2] << 8);
/* Read header of compensation area */
regAdd[0] = 0xD0;
regAdd[1] = (comp_header_addr >> 8) & 0xFF;
regAdd[2] = comp_header_addr & 0xFF;
fts_read_reg(info, regAdd, 3, &buff[0], 16 + 1);
tx_num = buff[5];
rx_num = buff[6];
tx_ix1 = (short) buff[10] * FTS_SEC_IX1_TX_MULTIPLIER; // Self TX Ix1
rx_ix1 = (short) buff[11] * FTS_SEC_IX1_RX_MULTIPLIER; // Self RX Ix1
comp_start_tx_addr = comp_header_addr + 0x10;
comp_start_rx_addr = comp_start_tx_addr + tx_num;
memset(tx_ix2, 0x0, tx_num);
memset(rx_ix2, 0x0, rx_num);
/* Read Self TX Ix2 */
regAdd[0] = 0xD0;
regAdd[1] = (comp_start_tx_addr >> 8) & 0xFF;
regAdd[2] = comp_start_tx_addr & 0xFF;
fts_read_reg(info, regAdd, 3, &tx_ix2[0], tx_num + 1);
/* Read Self RX Ix2 */
regAdd[0] = 0xD0;
regAdd[1] = (comp_start_rx_addr >> 8) & 0xFF;
regAdd[2] = comp_start_rx_addr & 0xFF;
fts_read_reg(info, regAdd, 3, &rx_ix2[0], rx_num + 1);
for(i = 0; i < info->ForceChannelLength; i++) {
force_ix_data[i] = tx_ix1 + (tx_ix2[i + 1] * 2);
if(max_tx_ix_sum < force_ix_data[i])
max_tx_ix_sum = force_ix_data[i];
if(min_tx_ix_sum > force_ix_data[i])
min_tx_ix_sum = force_ix_data[i];
}
for(i = 0; i < info->SenseChannelLength; i++) {
sense_ix_data[i] = rx_ix1 + rx_ix2[i + 1];
if(max_rx_ix_sum < sense_ix_data[i])
max_rx_ix_sum = sense_ix_data[i];
if(min_rx_ix_sum > sense_ix_data[i])
min_rx_ix_sum = sense_ix_data[i];
}
input_info(true, &info->client->dev, "%s: MIN_TX_IX_SUM : %d MAX_TX_IX_SUM : %d\n",
__func__, min_tx_ix_sum, max_tx_ix_sum );
input_info(true, &info->client->dev, "%s: MIN_RX_IX_SUM : %d MAX_RX_IX_SUM : %d\n",
__func__, min_rx_ix_sum, max_rx_ix_sum );
fts_systemreset(info, 10);
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
fts_fw_wait_for_event (info, STATUS_EVENT_FORCE_CAL_DONE_D3);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_command(info, FTS_CMD_KEY_SENSE_ON);
#endif
enable_irq(info->irq);
fts_interrupt_set(info, INT_ENABLE);
if (allnode == true) {
buff_size = (info->ForceChannelLength + info->SenseChannelLength + 2) * 5;
mbuff = kzalloc(buff_size, GFP_KERNEL);
}
if (mbuff != NULL) {
char *pBuf = mbuff;
for (i = 0; i < info->ForceChannelLength; i++) {
num = force_ix_data[i];
n = 100000;
fzero = 0;
for (j = 5; j > 0; j--) {
n = n / 10;
a = num / n;
if (a)
fzero = 1;
cnum = a + '0';
num = num - a*n;
if (fzero)
*pBuf++ = cnum;
}
if (!fzero)
*pBuf++ = '0';
*pBuf++ = ',';
input_info(true, &info->client->dev, "Force[%d] %d\n", i, force_ix_data[i]);
}
for (i = 0; i < info->SenseChannelLength; i++) {
num = sense_ix_data[i];
n = 100000;
fzero = 0;
for (j = 5; j > 0; j--) {
n = n / 10;
a = num / n;
if (a)
fzero = 1;
cnum = a + '0';
num = num - a * n;
if (fzero)
*pBuf++ = cnum;
}
if (!fzero)
*pBuf++ = '0';
if (i < (info->SenseChannelLength - 1))
*pBuf++ = ',';
input_info(true, &info->client->dev, "Sense[%d] %d\n", i, sense_ix_data[i]);
}
sec_cmd_set_cmd_result(sec, mbuff, buff_size);
sec->cmd_state = SEC_CMD_STATUS_OK;
kfree(mbuff);
} else {
if (allnode == true) {
snprintf(buff, sizeof(buff), "%s", "kzalloc failed");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
snprintf(buff, sizeof(buff), "%d,%d,%d,%d", min_tx_ix_sum, max_tx_ix_sum, min_rx_ix_sum, max_rx_ix_sum);
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
char ret_buff[SEC_CMD_STR_LEN] = { 0 };
snprintf(ret_buff, sizeof(ret_buff), "%d,%d", min_rx_ix_sum, max_rx_ix_sum);
sec_cmd_set_cmd_result_all(sec, ret_buff, strnlen(ret_buff, sizeof(ret_buff)), "IX_DATA_X");
snprintf(ret_buff, sizeof(ret_buff), "%d,%d", min_tx_ix_sum, max_tx_ix_sum);
sec_cmd_set_cmd_result_all(sec, ret_buff, strnlen(ret_buff, sizeof(ret_buff)), "IX_DATA_Y");
}
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
}
static void run_ix_data_read(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
sec_cmd_set_default_result(sec);
fts_read_ix_data(info, false);
}
static void run_ix_data_read_all(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
sec_cmd_set_default_result(sec);
fts_read_ix_data(info, true);
}
static void fts_read_self_raw_frame(struct fts_ts_info *info, unsigned short oAddr, bool allnode)
{
struct sec_cmd_data *sec = &info->sec;
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char D0_offset = 1;
unsigned char regAdd[3] = {0xD0, 0x00, 0x00};
unsigned char ReadData[(info->ForceChannelLength + info->SenseChannelLength) * 2 + 1];
unsigned short self_force_raw_data[info->ForceChannelLength * 2 + 1];
unsigned short self_sense_raw_data[info->SenseChannelLength * 2 + 1];
unsigned int FrameAddress = 0;
unsigned char count=0;
int buff_size,i,j;
char *mbuff = NULL;
int num,n,a,fzero;
char cnum;
unsigned short min_tx_self_raw_data = 0xFFFF;
unsigned short max_tx_self_raw_data = 0;
unsigned short min_rx_self_raw_data = 0xFFFF;
unsigned short max_rx_self_raw_data = 0;
unsigned char cmd[4] = {0xC7, 0x00, FTS_CFG_APWR, 0x00}; // Don't enter to IDLE
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "RAW_DATA");
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
fts_systemreset(info, 60);
// Don't enter to IDLE mode
fts_write_reg(info, &cmd[0], 4);
fts_delay(20);
fts_command(info, FLUSHBUFFER); // Clear FIFO
fts_delay(20);
// Auto-Tune
fts_command(info, CX_TUNNING);
msleep(300);
fts_fw_wait_for_event_D3(info, STATUS_EVENT_MUTUAL_AUTOTUNE_DONE, 0x00);
fts_command(info, SELF_AUTO_TUNE);
msleep(300);
fts_fw_wait_for_event_D3(info, STATUS_EVENT_SELF_AUTOTUNE_DONE_D3, 0x00);
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
fts_delay(150);
fts_command(info, SENSEOFF);
fts_delay(100);
disable_irq(info->irq);
fts_interrupt_set(info, INT_DISABLE);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey) {
fts_command(info, FTS_CMD_KEY_SENSE_OFF);
}
#endif
fts_release_all_finger(info);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_release_all_key(info);
#endif
regAdd[1] = 0x00;
regAdd[2] = oAddr;
fts_read_reg(info, regAdd, 3, &ReadData[0], 4);
FrameAddress = ReadData[D0_offset] + (ReadData[D0_offset + 1] << 8); // D1 : DOFFSET = 0, D2 : DOFFSET : 1
regAdd[1] = (FrameAddress >> 8) & 0xFF;
regAdd[2] = FrameAddress & 0xFF;
fts_read_reg(info, regAdd, 3, &ReadData[0], info->ForceChannelLength * 2 + 1);
for(count = 0; count < info->ForceChannelLength; count++) {
self_force_raw_data[count] = ReadData[count*2+D0_offset] + (ReadData[count*2+D0_offset+1]<<8);
if(max_tx_self_raw_data < self_force_raw_data[count])
max_tx_self_raw_data = self_force_raw_data[count];
if(min_tx_self_raw_data > self_force_raw_data[count])
min_tx_self_raw_data = self_force_raw_data[count];
}
regAdd[1] = 0x00;
regAdd[2] = oAddr + 2;
fts_read_reg(info, regAdd, 3, &ReadData[0], 4);
FrameAddress = ReadData[D0_offset] + (ReadData[D0_offset + 1] << 8); // D1 : DOFFSET = 0, D2 : DOFFSET : 1
regAdd[1] = (FrameAddress >> 8) & 0xFF;
regAdd[2] = FrameAddress & 0xFF;
fts_read_reg(info, regAdd, 3, &ReadData[0], info->SenseChannelLength * 2 + 1);
for(count = 0; count < info->SenseChannelLength; count++) {
self_sense_raw_data[count] = ReadData[count*2+D0_offset] + (ReadData[count*2+D0_offset+1]<<8);
if(max_rx_self_raw_data < self_sense_raw_data[count])
max_rx_self_raw_data = self_sense_raw_data[count];
if(min_rx_self_raw_data > self_sense_raw_data[count])
min_rx_self_raw_data = self_sense_raw_data[count];
}
input_info(true, &info->client->dev, "%s: MIN_TX_SELF_RAW: %d MAX_TX_SELF_RAW : %d\n",
__func__, min_tx_self_raw_data, max_tx_self_raw_data );
input_info(true, &info->client->dev, "%s: MIN_RX_SELF_RAW : %d MIN_RX_SELF_RAW : %d\n",
__func__, min_rx_self_raw_data, max_rx_self_raw_data );
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
fts_delay(50);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_command(info, FTS_CMD_KEY_SENSE_ON);
#endif
enable_irq(info->irq);
fts_interrupt_set(info, INT_ENABLE);
if (allnode == true) {
buff_size = (info->ForceChannelLength + info->SenseChannelLength + 2) * 7;
mbuff = kzalloc(buff_size, GFP_KERNEL);
}
if (mbuff != NULL) {
char *pBuf = mbuff;
for (i = 0; i < info->ForceChannelLength; i++) {
num = self_force_raw_data[i];
n = 100000;
fzero = 0;
for (j = 5; j > 0; j--) {
n = n / 10;
a = num / n;
if (a)
fzero = 1;
cnum = a + '0';
num = num - a * n;
if (fzero)
*pBuf++ = cnum;
}
if (!fzero)
*pBuf++ = '0';
*pBuf++ = ',';
input_info(true, &info->client->dev, "Force[%d] %d\n", i, self_force_raw_data[i]);
}
for (i = 0; i < info->SenseChannelLength; i++) {
num = self_sense_raw_data[i];
n = 100000;
fzero = 0;
for (j = 5; j > 0; j--) {
n = n / 10;
a = num / n;
if (a)
fzero = 1;
cnum = a + '0';
num = num - a * n;
if (fzero)
*pBuf++ = cnum;
}
if (!fzero)
*pBuf++ = '0';
if (i < (info->SenseChannelLength - 1))
*pBuf++ = ',';
input_info(true, &info->client->dev, "Sense[%d] %d\n", i, self_sense_raw_data[i]);
}
sec_cmd_set_cmd_result(sec, mbuff, buff_size);
sec->cmd_state = SEC_CMD_STATUS_OK;
kfree(mbuff);
} else {
if (allnode == true) {
snprintf(buff, sizeof(buff), "%s", "kzalloc failed");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
snprintf(buff, sizeof(buff), "%d,%d,%d,%d", min_tx_self_raw_data, max_tx_self_raw_data, min_rx_self_raw_data, max_rx_self_raw_data);
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
char ret_buff[SEC_CMD_STR_LEN] = { 0 };
snprintf(ret_buff, sizeof(ret_buff), "%d,%d", (s16)min_rx_self_raw_data, (s16)max_rx_self_raw_data);
sec_cmd_set_cmd_result_all(sec, ret_buff, strnlen(ret_buff, sizeof(ret_buff)), "SELF_RAW_DATA_X");
snprintf(ret_buff, sizeof(ret_buff), "%d,%d", (s16)min_tx_self_raw_data, (s16)max_tx_self_raw_data);
sec_cmd_set_cmd_result_all(sec, ret_buff, strnlen(ret_buff, sizeof(ret_buff)), "SELF_RAW_DATA_Y");
}
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
}
static void run_self_raw_read(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
sec_cmd_set_default_result(sec);
fts_read_self_raw_frame(info, FTS_WATER_SELF_RAW_ADDR,false);
}
static void run_self_raw_read_all(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
sec_cmd_set_default_result(sec);
fts_read_self_raw_frame(info, FTS_WATER_SELF_RAW_ADDR,true);
}
static void run_trx_short_test(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
int ret = 0;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
ret = fts_panel_ito_test(info, OPEN_SHORT_CRACK_TEST);
if (ret == 0)
snprintf(buff, sizeof(buff), "%s", "OK");
else
snprintf(buff, sizeof(buff), "%s", "FAIL");
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void check_connection(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
int ret = 0;
sec_cmd_set_default_result(sec);
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
ret = fts_panel_ito_test(info, OPEN_TEST);
if (ret == 0)
snprintf(buff, sizeof(buff), "OK");
else
snprintf(buff, sizeof(buff), "NG");
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#define FTS_MAX_TX_LENGTH 44
#define FTS_MAX_RX_LENGTH 64
#define FTS_CX2_READ_LENGTH 4
#define FTS_CX2_ADDR_OFFSET 3
#define FTS_CX2_TX_START 0
static void get_cx_data(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
short val = 0;
int node = 0;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
node = fts_check_index(info);
if (node < 0)
return;
if (info->cx_data)
val = info->cx_data[node];
snprintf(buff, sizeof(buff), "%d", val);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
/* input_info(true, &info->client->dev, "%s: %s\n", __func__, buff); */
}
static void run_cx_data_read(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char ReadData[info->ForceChannelLength][info->SenseChannelLength + FTS_CX2_READ_LENGTH];
unsigned char regAdd[8];
unsigned int addr, rx_num, tx_num;
unsigned char cx1;
unsigned char cx_min = 255, cx_max = 0;
int i, j;
unsigned char *pStr = NULL;
unsigned char pTmp[16] = { 0 };
int ret;
int comp_header_addr, comp_start_addr;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CX_DATA");
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
pStr = kzalloc(4 * (info->SenseChannelLength + 1), GFP_KERNEL);
if (pStr == NULL) {
input_err(true, &info->client->dev, "%s: pStr kzalloc failed\n", __func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CX_DATA");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
input_info(true, &info->client->dev, "%s: start\n", __func__);
disable_irq(info->irq);
ret = fts_interrupt_set(info, INT_DISABLE);
if (ret <= 0) {
input_err(true, &info->client->dev,
"%s: failed to set of interrupt(%d)\n",
__func__, INT_DISABLE);
goto out;
}
ret = fts_command(info, SENSEOFF);
if (ret <= 0) {
input_err(true, &info->client->dev,
"%s: failed to send cmd(%d)\n",
__func__, SENSEOFF);
goto out;
}
fts_delay(50);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey) {
ret = fts_command(info, FTS_CMD_KEY_SENSE_OFF); // Key Sensor OFF
if (ret <= 0) {
input_err(true, &info->client->dev,
"%s: failed to send cmd(%d)\n",
__func__, FTS_CMD_KEY_SENSE_OFF);
goto out;
}
}
#endif
ret = fts_command(info, FLUSHBUFFER);
if (ret <= 0) {
input_err(true, &info->client->dev,
"%s: failed to send cmd(%d)\n",
__func__, FLUSHBUFFER);
goto out;
}
fts_delay(50);
fts_release_all_finger(info);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_release_all_key(info);
#endif
/* Request compensation data */
regAdd[0] = 0xB8;
regAdd[1] = 0x04; // MUTUAL CX
regAdd[2] = 0x00;
ret = fts_write_reg(info, &regAdd[0], 3);
if (ret <= 0) {
input_err(true, &info->client->dev,
"%s: failed to write reg\n", __func__);
goto out;
}
ret = fts_fw_wait_for_specific_event(info, EVENTID_STATUS_REQUEST_COMP, regAdd[1], regAdd[2]);
if (ret) {
input_err(true, &info->client->dev,
"%s: failed to wait for specific event\n",
__func__);
goto out;
}
/* Read an address of compensation data */
regAdd[0] = 0xD0;
regAdd[1] = 0x00;
regAdd[2] = FTS_SI_COMPENSATION_OFFSET_ADDR;
ret = fts_read_reg(info, regAdd, 3, &buff[0], 4);
if (ret <= 0) {
input_err(true, &info->client->dev,
"%s: failed to read reg\n", __func__);
goto out;
}
comp_header_addr = buff[1] + (buff[2] << 8);
/* Read header of compensation area */
regAdd[0] = 0xD0;
regAdd[1] = (comp_header_addr >> 8) & 0xFF;
regAdd[2] = comp_header_addr & 0xFF;
ret = fts_read_reg(info, regAdd, 3, &buff[0], 16 + 1);
if (ret <= 0) {
input_err(true, &info->client->dev,
"%s: failed to read reg\n", __func__);
goto out;
}
tx_num = buff[5];
rx_num = buff[6];
cx1 = buff[10] * 8;
comp_start_addr = comp_header_addr + 0x10;
/* Read compensation data */
for (j = 0; j < tx_num; j++) {
memset(&ReadData[j], 0x0, (rx_num + 1));
memset(pStr, 0x0, 4 * (rx_num + 1));
snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", j);
strncat(pStr, pTmp, 4 * rx_num);
addr = comp_start_addr + (rx_num * j);
regAdd[0] = 0xD0;
regAdd[1] = (addr >> 8) & 0xFF;
regAdd[2] = addr & 0xFF;
ret = fts_read_reg(info, regAdd, 3, &ReadData[j][0], rx_num + 1);
if (ret <= 0) {
input_err(true, &info->client->dev,
"%s: failed to read reg\n", __func__);
goto out;
}
for (i = 0; i < rx_num; i++) {
snprintf(pTmp, sizeof(pTmp), "%3d", ReadData[j][i + 1]);
strncat(pStr, pTmp, 4 * rx_num);
}
input_raw_info(true, &info->client->dev, "%s\n", pStr);
}
if (info->cx_data) {
for (j = 0; j < tx_num; j++) {
for(i = 0; i < rx_num; i++) {
info->cx_data[(j * rx_num) + i] = ReadData[j][i + 1] + cx1;
cx_min = min(cx_min, info->cx_data[(j * rx_num) + i]);
cx_max = max(cx_max, info->cx_data[(j * rx_num) + i]);
}
}
}
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey) {
fts_command(info, FTS_CMD_KEY_SENSE_ON);
}
#endif
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
fts_command(info, SENSEON);
fts_interrupt_set(info, INT_ENABLE);
kfree(pStr);
enable_irq(info->irq);
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
char ret_buff[SEC_CMD_STR_LEN] = { 0 };
snprintf(ret_buff, sizeof(ret_buff), "%d,%d", (s16)cx_min, (s16)cx_max);
sec_cmd_set_cmd_result_all(sec, ret_buff, strnlen(ret_buff, sizeof(ret_buff)), "CX_DATA");
}
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
return;
out:
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey) {
fts_command(info, FTS_CMD_KEY_SENSE_ON);
}
#endif
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
fts_command(info, SENSEON);
fts_interrupt_set(info, INT_ENABLE);
kfree(pStr);
enable_irq(info->irq);
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING)
sec_cmd_set_cmd_result_all(sec, buff, strnlen(buff, sizeof(buff)), "CX_DATA");
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_cx_all_data(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char ReadData[info->ForceChannelLength][info->SenseChannelLength + FTS_CX2_READ_LENGTH];
unsigned char regAdd[8];
unsigned int addr, rx_num, tx_num;
unsigned char cx1;
int i, j;
unsigned char *pStr = NULL;
unsigned char pTmp[16] = { 0 };
char all_strbuff[(info->ForceChannelLength)*(info->SenseChannelLength)*3];
int comp_header_addr, comp_start_addr;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
input_info(true, &info->client->dev, "%s: start\n", __func__);
pStr = kzalloc(4 * (info->SenseChannelLength + 1), GFP_KERNEL);
if (pStr == NULL) {
input_err(true, &info->client->dev, "%s: pStr kzalloc failed\n", __func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
fts_command(info, SENSEOFF);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey) {
fts_command(info, FTS_CMD_KEY_SENSE_OFF); // Key Sensor OFF
}
#endif
disable_irq(info->irq);
fts_command(info, FLUSHBUFFER);
fts_delay(50);
fts_release_all_finger(info);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_release_all_key(info);
#endif
tx_num = info->ForceChannelLength;
rx_num = info->SenseChannelLength;
memset(all_strbuff, 0, sizeof(char) * (tx_num*rx_num*3)); //size 3 ex(45,)
/* Request compensation data */
regAdd[0] = 0xB8;
regAdd[1] = 0x04; // MUTUAL CX
regAdd[2] = 0x00;
fts_write_reg(info, &regAdd[0], 3);
fts_fw_wait_for_specific_event(info, EVENTID_STATUS_REQUEST_COMP, regAdd[1], regAdd[2]);
/* Read an address of compensation data */
regAdd[0] = 0xD0;
regAdd[1] = 0x00;
regAdd[2] = FTS_SI_COMPENSATION_OFFSET_ADDR;
fts_read_reg(info, regAdd, 3, &buff[0], 4);
comp_header_addr = buff[1] + (buff[2] << 8);
/* Read header of compensation area */
regAdd[0] = 0xD0;
regAdd[1] = (comp_header_addr >> 8) & 0xFF;
regAdd[2] = comp_header_addr & 0xFF;
fts_read_reg(info, regAdd, 3, &buff[0], 16 + 1);
tx_num = buff[5];
rx_num = buff[6];
cx1 = buff[10] * 8;
comp_start_addr = comp_header_addr + 0x10;
/* Read compensation data */
for (j = 0; j < tx_num; j++) {
memset(&ReadData[j], 0x0, (rx_num + 1));
memset(pStr, 0x0, 4 * (rx_num + 1));
snprintf(pTmp, sizeof(pTmp), "Tx%02d | ", j);
strncat(pStr, pTmp, 4 * rx_num);
addr = comp_start_addr + (rx_num * j);
regAdd[0] = 0xD0;
regAdd[1] = (addr >> 8) & 0xFF;
regAdd[2] = addr & 0xFF;
fts_read_reg(info, regAdd, 3, &ReadData[j][0], rx_num + 1);
for (i = 0; i < rx_num; i++) {
snprintf(pTmp, sizeof(pTmp), "%3d", ReadData[j][i + 1]);
strncat(pStr, pTmp, 4 * rx_num);
}
input_info(true, &info->client->dev, "%s\n", pStr);
}
if (info->cx_data) {
for (j = 0; j < tx_num; j++) {
for(i = 0; i < rx_num; i++){
info->cx_data[(j * rx_num) + i] = ReadData[j][i + 1] + cx1;
snprintf(buff, sizeof(buff), "%d,", ReadData[j][i + 1] + cx1);
strncat(all_strbuff, buff, sizeof(buff));
}
}
}
kfree(pStr);
enable_irq(info->irq);
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey) {
fts_command(info, FTS_CMD_KEY_SENSE_ON);
}
#endif
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, all_strbuff, strnlen(all_strbuff, sizeof(all_strbuff)));
input_info(true, &info->client->dev, "%s: %ld (%ld)\n", __func__, strnlen(all_strbuff, sizeof(all_strbuff)),sizeof(all_strbuff));
}
static void get_cx_gap_data(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
int rx_max = 0, tx_max = 0, ii;
for (ii = 0; ii < (info->SenseChannelLength * info->ForceChannelLength); ii++) {
/* rx(x) gap max */
if ((ii + 1) % (info->SenseChannelLength) != 0)
rx_max = max(rx_max, (int)abs(info->cx_data[ii + 1] - info->cx_data[ii]));
/* tx(y) gap max */
if (ii < (info->ForceChannelLength - 1) * info->SenseChannelLength)
tx_max = max(tx_max, (int)abs(info->cx_data[ii + info->SenseChannelLength] - info->cx_data[ii]));
}
input_raw_info(true, &info->client->dev, "%s: rx max:%d, tx max:%d\n", __func__, rx_max, tx_max);
if (sec->cmd_all_factory_state == SEC_CMD_STATUS_RUNNING) {
snprintf(buff, sizeof(buff), "%d,%d", 0, rx_max);
sec_cmd_set_cmd_result_all(sec, buff, SEC_CMD_STR_LEN, "CX_DATA_GAP_X");
snprintf(buff, sizeof(buff), "%d,%d", 0, tx_max);
sec_cmd_set_cmd_result_all(sec, buff, SEC_CMD_STR_LEN, "CX_DATA_GAP_Y");
}
}
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
int fts_read_pressure_data(struct fts_ts_info *info)
{
unsigned char pressure_reg[3] = {0, };
unsigned char buf[32] = {0, };
short value[10] = {0, };
int rtn, i = 0;
int pressure_sensor_value = 0;
pressure_reg[0] = 0xD0;
pressure_reg[1] = 0x00;
pressure_reg[2] = FTS_SI_PRESSURE_STRENGTH_ADDR;
rtn = fts_read_reg(info, pressure_reg, 3, &buf[0], 4);
if (rtn <= 0) {
input_err(true, &info->client->dev, "%s: Pressure read failed rc = %d\n", __func__, rtn);
return rtn;
} else {
pressure_reg[1] = buf[2];
pressure_reg[2] = buf[1];
}
rtn = fts_read_reg(info, pressure_reg, 3, &buf[0], PRESSURE_SENSOR_COUNT * 2 + 1);
if (rtn <= 0) {
input_err(true, &info->client->dev, "%s: Pressure read failed rc = %d\n", __func__, rtn);
return rtn;
} else {
for (i = 0; i < PRESSURE_SENSOR_COUNT; i++) {
value[i] = buf[i * 2 + 1] + (buf[i * 2 + 1 + 1] << 8);
pressure_sensor_value += value[i];
}
}
if (info->debug_string & 0x2)
input_info(true, &info->client->dev, "%s: %d %d %d %d %d %d %d %d %d %d %d\n", __func__,
value[0], value[1], value[2], value[3], value[4],
value[5], value[6], value[7], value[8], value[9],
pressure_sensor_value);
return pressure_sensor_value;
}
#endif
#ifdef FTS_SUPPORT_TOUCH_KEY
#define USE_KEY_NUM 2
static void run_key_cx_data_read(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char key_cx2_data[2], key_cx1_data, total_cx_data[USE_KEY_NUM];
unsigned char ReadData[USE_KEY_NUM * FTS_CX2_READ_LENGTH];
unsigned char regAdd[8];
unsigned int addr;
int /*tx_num, */rx_num, DOFFSET = 1;
int comp_start_addr, comp_header_addr;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
disable_irq(info->irq);
/* Request compensation data */
regAdd[0] = 0xB8;
regAdd[1] = 0x10; // For button
regAdd[2] = 0x00;
fts_write_reg(info, &regAdd[0], 3);
fts_fw_wait_for_specific_event(info, EVENTID_STATUS_REQUEST_COMP, regAdd[1], 0x00);
/* Read an address of compensation data */
regAdd[0] = 0xD0;
regAdd[1] = 0x00;
regAdd[2] = FTS_SI_COMPENSATION_OFFSET_ADDR;
fts_read_reg(info, regAdd, 3, &buff[0], 4);
comp_header_addr = buff[0 + DOFFSET] + (buff[1 + DOFFSET] << 8);
/* Read header of compensation area */
regAdd[0] = 0xD0;
regAdd[1] = (comp_header_addr >> 8) & 0xFF;
regAdd[2] = comp_header_addr & 0xFF;
fts_read_reg(info, regAdd, 3, &buff[0], 16 + DOFFSET);
/*tx_num = buff[4 + DOFFSET];*/
rx_num = buff[5 + DOFFSET];
key_cx1_data = buff[9 + DOFFSET];
comp_start_addr = comp_header_addr + 0x10;
memset(&ReadData[0], 0x0, rx_num);
/* Read compensation data */
addr = comp_start_addr;
regAdd[0] = 0xD0;
regAdd[1] = (addr >> 8) & 0xFF;
regAdd[2] = addr & 0xFF;
fts_read_reg(info, regAdd, 3, &ReadData[0], rx_num + DOFFSET);
key_cx2_data[0] = ReadData[0 + DOFFSET];
key_cx2_data[1] = ReadData[1 + DOFFSET];
total_cx_data[0] = key_cx1_data * 2 + key_cx2_data[0];
total_cx_data[1] = key_cx1_data * 2 + key_cx2_data[1];
//snprintf(buff, sizeof(buff), "%s", "OK");
snprintf(buff, sizeof(buff), "%d,%d,%d,%d", key_cx2_data[0], key_cx2_data[1], total_cx_data[0], total_cx_data[1]);
enable_irq(info->irq);
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#endif
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
static void run_force_pressure_calibration(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = {0};
#ifdef FTS_SUPPORT_STRINGLIB
unsigned short addr = FTS_CMD_STRING_ACCESS;
int ret;
#endif
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
if (info->touch_count > 0) {
snprintf(buff, sizeof(buff), "%s", "NG_FINGER_ON");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
goto out_force_pressure_cal;
}
disable_irq(info->irq);
fts_interrupt_set(info, INT_DISABLE);
fts_command(info, FTS_CMD_PRESSURE_SENSE_OFF);
info->fts_systemreset(info, 30);
fts_command(info, PRESSURE_AUTO_TUNE);
fts_delay(300);
fts_fw_wait_for_event_D3(info, STATUS_EVENT_SELF_AUTOTUNE_DONE_D3, 0x00);
fts_command(info, FTS_CMD_SAVE_CX_TUNING);
fts_delay(230);
fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE);
info->fts_systemreset(info, 30);
fts_command(info, SENSEON);
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
fts_fw_wait_for_event (info, STATUS_EVENT_FORCE_CAL_DONE_D3);
fts_interrupt_set(info, INT_ENABLE);
enable_irq(info->irq);
#ifdef FTS_SUPPORT_STRINGLIB
ret = info->fts_write_to_string(info, &addr, &info->lowpower_flag, sizeof(info->lowpower_flag));
if (ret < 0)
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
#endif
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
out_force_pressure_cal:
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
/*
* index is 0 : cleared, do not calibrated
* index is 1 : Ass'y
* index is 2 : Rear
* index is 3 : BackGlass
*/
static void set_pressure_test_mode(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char regAdd[4] = {0xC7, 0x03, 0x00, 0x00};
int ret = 0;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_info(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
regAdd[3] = sec->cmd_param[0];
ret = fts_write_reg(info, regAdd, 4);
if (ret < 0) {
snprintf(buff, sizeof(buff), "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
}
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void run_pressure_strength_read_all(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char regAddr[3] = {0xD0, 0x00, FTS_SI_PRESSURE_STRENGTH_ADDR};
unsigned char data[PRESSURE_SENSOR_COUNT * 2 + 1];
int ret, i;
short value[3] = { 0 };
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
memset(data, 3, PRESSURE_SENSOR_COUNT * 2 + 1);
ret = fts_read_reg(info, regAddr, 3, data, 4);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: [ERROR] failed to read pressure strength addr\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
regAddr[1] = data[2];
regAddr[2] = data[1];
memset(data, 0x00, PRESSURE_SENSOR_COUNT * 2 + 1);
ret = fts_read_reg(info, regAddr, 3, data, PRESSURE_SENSOR_COUNT * 2 + 1);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: [ERROR] failed to read pressure strength\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
input_err(true, &info->client->dev, "%s: [3] %02X, %02X, %02X, %02X, %02X, %02X, %02X\n",
__func__, data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
for (i = 0; i < PRESSURE_SENSOR_COUNT; i++)
value[i] = (short)(data[i * 2 + 1] | (data[i * 2 + 1 + 1] << 8));
snprintf(buff, sizeof(buff), "%d,%d,%d", value[0], value[1], value[2]);
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void run_pressure_rawdata_read_all(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char regAddr[3] = {0xD0, 0x00, 0x00};
unsigned char data[PRESSURE_SENSOR_COUNT * 2 + 1];
int ret, i;
short value[3] = { 0 };
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
memset(data, 3, PRESSURE_SENSOR_COUNT * 2 + 1);
ret = info->fts_get_sysinfo_data(info, FTS_SI_PRESSURE_FILTERED_RAW_ADDR, 3, data);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: [ERROR] failed to read pressure rawdata addr\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
regAddr[1] = data[1];
regAddr[2] = data[0];
memset(data, 0x00, PRESSURE_SENSOR_COUNT * 2 + 1);
ret = fts_read_reg(info, regAddr, 3, data, PRESSURE_SENSOR_COUNT * 2 + 1);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: [ERROR] failed to read pressure rawdata\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
input_err(true, &info->client->dev, "%s: [3] %02X, %02X, %02X, %02X, %02X, %02X, %02X\n",
__func__, data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
for (i = 0; i < PRESSURE_SENSOR_COUNT; i++)
value[i] = (short)(data[i * 2 + 1] | (data[i * 2 + 1 + 1] << 8));
snprintf(buff, sizeof(buff), "%d,%d,%d", value[0], value[1], value[2]);
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#define FTS_PRESSURE_IX1 10
#define FTS_PRESSIRE_IX2 17
static void run_pressure_ix_data_read_all(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char regAdd[3] = {0xB8, 0x00, 0x02};
unsigned char data[32];
int ret, i;
int value[3] = { 0 };
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
disable_irq(info->irq);
fts_interrupt_set(info, INT_DISABLE);
fts_command(info, SENSEOFF);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_command(info, FTS_CMD_KEY_SENSE_OFF);
#endif
fts_command(info, FLUSHBUFFER);
fts_delay(50);
fts_release_all_finger(info);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_release_all_key(info);
#endif
ret = fts_write_reg(info, regAdd, 3);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: [ERROR] failed to write pressure ix\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
fts_fw_wait_for_specific_event(info, EVENTID_STATUS_REQUEST_COMP, regAdd[1], regAdd[2]);
memset(data, 0x00, 32);
ret = info->fts_get_sysinfo_data(info, FTS_SI_COMPENSATION_OFFSET_ADDR, 7, data);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: [ERROR] failed to read ix offset addr\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
input_info(true, &info->client->dev, "%s: [0] 0x%02X, [0x%02X, 0x%02X], 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
__func__, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
regAdd[0] = 0xD0;
regAdd[1] = data[1];
regAdd[2] = data[0];
memset(data, 0x00, 32);
ret = fts_read_reg(info, &regAdd[0], 3, data, 32);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: [ERROR] failed to read ix\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
for (i = 0; i < 4; i++)
input_info(true, &info->client->dev, "%s: [%d] 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
__func__, i, data[i * 8 + 0], data[i * 8 + 1], data[i * 8 + 2], data[i * 8 + 3],
data[i * 8 + 4], data[i * 8 + 5], data[i * 8 + 6], data[i * 8 + 7]);
for (i = 0; i < PRESSURE_SENSOR_COUNT; i++)
value[i] = ((data[FTS_PRESSURE_IX1] * 2) + data[FTS_PRESSIRE_IX2 + i]);
snprintf(buff, sizeof(buff), "%d,%d,%d", value[0], value[1], value[2]);
enable_irq(info->irq);
fts_interrupt_set(info, INT_ENABLE);
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_command(info, FTS_CMD_KEY_SENSE_ON);
#endif
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void set_pressure_strength(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char strength[12] = { 0 };
int ret, index;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
input_info(true, &info->client->dev, "%s: [index:%d], [1: %d], [2:%d], [3:%d]\n",
__func__, sec->cmd_param[0], sec->cmd_param[1], sec->cmd_param[2], sec->cmd_param[3]);
if ((sec->cmd_param[0] < 1) || (sec->cmd_param[0] > 4)) {
input_err(true, &info->client->dev, "%s: wrong index.\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "WRONG INDEX");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
index = sec->cmd_param[0];
strength[0] = 0xC7;
strength[1] = 0x03;
strength[2] = 0x02;
strength[3] = (char)index;
strength[4] = (char)(sec->cmd_param[1] & 0xFF);
strength[5] = (char)(sec->cmd_param[1] >> 8);
strength[6] = (char)(sec->cmd_param[2] & 0xFF);
strength[7] = (char)(sec->cmd_param[2] >> 8);
strength[8] = (char)(sec->cmd_param[3] & 0xFF);
strength[9] = (char)(sec->cmd_param[3] >> 8);
strength[10] = 0x00;
strength[11] = 0x00;
fts_command(info, SENSEOFF);
fts_delay(50);
fts_command(info, FLUSHBUFFER);
fts_interrupt_set(info, INT_DISABLE);
fts_release_all_finger(info);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_release_all_key(info);
#endif
ret = fts_write_reg(info, strength, 12);
if (ret <= 0) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
fts_command(info, FTS_CMD_SAVE_CX_TUNING);
fts_delay(230);
fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE);
fts_command(info, FLUSHBUFFER);
fts_delay(10);
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
fts_interrupt_set(info, INT_ENABLE);
return;
}
fts_command(info, FTS_CMD_SAVE_CX_TUNING);
fts_delay(230);
fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE);
fts_command(info, FLUSHBUFFER);
fts_delay(10);
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
fts_interrupt_set(info, INT_ENABLE);
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void set_pressure_rawdata(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char rawdata[12] = { 0 };
int ret, index;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
input_info(true, &info->client->dev, "%s: [index:%d], [1: %d], [2:%d], [3:%d]\n",
__func__, sec->cmd_param[0], sec->cmd_param[1], sec->cmd_param[2], sec->cmd_param[3]);
if ((sec->cmd_param[0] < 1) || (sec->cmd_param[0] > 4)) {
input_err(true, &info->client->dev, "%s: wrong index.\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "WRONG INDEX");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
index = sec->cmd_param[0];
rawdata[0] = 0xC7;
rawdata[1] = 0x03;
rawdata[2] = 0x03;
rawdata[3] = (char)index;
rawdata[4] = (char)(sec->cmd_param[1] & 0xFF);
rawdata[5] = (char)(sec->cmd_param[1] >> 8);
rawdata[6] = (char)(sec->cmd_param[2] & 0xFF);
rawdata[7] = (char)(sec->cmd_param[2] >> 8);
rawdata[8] = (char)(sec->cmd_param[3] & 0xFF);
rawdata[9] = (char)(sec->cmd_param[3] >> 8);
rawdata[10] = 0x00;
rawdata[11] = 0x00;
fts_command(info, SENSEOFF);
fts_delay(50);
fts_command(info, FLUSHBUFFER);
fts_interrupt_set(info, INT_DISABLE);
fts_release_all_finger(info);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_release_all_key(info);
#endif
ret = fts_write_reg(info, rawdata, 12);
if (ret <= 0) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
fts_command(info, FTS_CMD_SAVE_CX_TUNING);
fts_delay(230);
fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE);
fts_command(info, FLUSHBUFFER);
fts_delay(10);
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
fts_interrupt_set(info, INT_ENABLE);
return;
}
fts_command(info, FTS_CMD_SAVE_CX_TUNING);
fts_delay(230);
fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE);
fts_command(info, FLUSHBUFFER);
fts_delay(10);
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
fts_interrupt_set(info, INT_ENABLE);
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void set_pressure_data_index(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char data[12] = { 0 };
int ret, index;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
input_info(true, &info->client->dev, "%s: %d\n",
__func__, sec->cmd_param[0]);
if ((sec->cmd_param[0] < 0) || (sec->cmd_param[0] > 4)) {
input_err(true, &info->client->dev, "%s: wrong index.\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "WRONG INDEX");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
if (sec->cmd_param[0] == 0)
input_info(true, &info->client->dev, "%s: disable calibrated strength\n", __func__);
index = sec->cmd_param[0];
data[0] = 0xC7;
data[1] = 0x03;
data[2] = 0x01;
data[3] = (char)index;
fts_command(info, SENSEOFF);
fts_delay(50);
fts_command(info, FLUSHBUFFER);
fts_interrupt_set(info, INT_DISABLE);
fts_release_all_finger(info);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_release_all_key(info);
#endif
ret = fts_write_reg(info, data, 4);
if (ret <= 0) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
if (index != 0x00) {
fts_command(info, FTS_CMD_SAVE_CX_TUNING);
fts_delay(230);
fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE);
}
fts_command(info, FLUSHBUFFER);
fts_delay(10);
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
fts_interrupt_set(info, INT_ENABLE);
return;
}
if (index != 0x00) {
fts_command(info, FTS_CMD_SAVE_CX_TUNING);
fts_delay(230);
fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE);
}
fts_command(info, FLUSHBUFFER);
fts_delay(10);
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
fts_interrupt_set(info, INT_ENABLE);
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_pressure_strength(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char *data = NULL;
short strength[3] = { 0 };
int ret, index;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
input_info(true, &info->client->dev, "%s: index: %d\n",
__func__, sec->cmd_param[0]);
if ((sec->cmd_param[0] < 1) || (sec->cmd_param[0] > 4)) {
input_err(true, &info->client->dev, "%s: wrong index.\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "WRONG INDEX");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
index = sec->cmd_param[0] - 1;
data = kzalloc(nvm_data[PRESSURE_STRENGTH].length, GFP_KERNEL);
if (!data) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
input_err(true, &info->client->dev, "%s: failed to alloc mem\n",
__func__);
return;
}
ret = get_nvm_data(info, PRESSURE_STRENGTH, data);
if (ret <= 0) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
kfree(data);
return;
}
if ((data[index * 8 + 6] == 0xFF) && (data[index * 8 + 7] == 0xFF)) {
input_info(true, &info->client->dev, "%s: flash is initailized, clear\n", __func__);
memset(&data[index * 8], 0x00, 8);
}
strength[0] = (short)(data[index * 8 + 0] | ((data[index * 8 + 1] << 8) & 0xFF00));
strength[1] = (short)(data[index * 8 + 2] | ((data[index * 8 + 3] << 8) & 0xFF00));
strength[2] = (short)(data[index * 8 + 4] | ((data[index * 8 + 5] << 8) & 0xFF00));
snprintf(buff, sizeof(buff), "%d,%d,%d", strength[0], strength[1], strength[2]);
kfree(data);
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_pressure_rawdata(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char *data = NULL;
short rawdata[3] = { 0 };
int ret, index;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
input_info(true, &info->client->dev, "%s: index: %d\n",
__func__, sec->cmd_param[0]);
if ((sec->cmd_param[0] < 1) || (sec->cmd_param[0] > 4)) {
input_err(true, &info->client->dev, "%s: wrong index.\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "WRONG INDEX");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
index = sec->cmd_param[0] - 1;
data = kzalloc(nvm_data[PRESSURE_RAWDATA].length, GFP_KERNEL);
if (!data) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
input_err(true, &info->client->dev, "%s: failed to alloc mem\n",
__func__);
return;
}
ret = get_nvm_data(info, PRESSURE_RAWDATA, data);
if (ret <= 0) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
kfree(data);
return;
}
if ((data[index * 8 + 6] == 0xFF) && (data[index * 8 + 7] == 0xFF)) {
input_info(true, &info->client->dev, "%s: flash is initailized, clear\n", __func__);
memset(&data[index * 8], 0x00, 8);
}
rawdata[0] = (short)(data[index * 8 + 0] | ((data[index * 8 + 1] << 8) & 0xFF00));
rawdata[1] = (short)(data[index * 8 + 2] | ((data[index * 8 + 3] << 8) & 0xFF00));
rawdata[2] = (short)(data[index * 8 + 4] | ((data[index * 8 + 5] << 8) & 0xFF00));
snprintf(buff, sizeof(buff), "%d,%d,%d", rawdata[0], rawdata[1], rawdata[2]);
kfree(data);
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_pressure_data_index(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char *data = NULL;
int ret;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
input_info(true, &info->client->dev, "%s: index: %d\n",
__func__, sec->cmd_param[0]);
data = kzalloc(nvm_data[GROUP_INDEX].length, GFP_KERNEL);
if (!data) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
input_err(true, &info->client->dev, "%s: failed to alloc mem\n",
__func__);
return;
}
ret = get_nvm_data(info, GROUP_INDEX, data);
if (ret <= 0) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
kfree(data);
return;
}
if (data[0] == 0xFF) {
input_info(true, &info->client->dev, "%s: flash is initailized, clear\n", __func__);
memset(&data[0], 0x00, 1);
}
snprintf(buff, sizeof(buff), "%d", data[0]);
kfree(data);
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void set_pressure_strength_clear(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char data[12] = { 0 };
int ret;
int ii = 0;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
fts_command(info, SENSEOFF);
fts_delay(50);
fts_command(info, FLUSHBUFFER);
fts_interrupt_set(info, INT_DISABLE);
fts_release_all_finger(info);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_release_all_key(info);
#endif
for (ii = 1; ii < 4; ii++) {
data[0] = 0xC7;
data[1] = 0x03;
data[2] = 0x02;
data[3] = ii;
ret = fts_write_reg(info, data, 12);
if (ret <= 0) {
goto err_write_reg;
}
}
input_info(true, &info->client->dev, "%s: clear strength\n", __func__);
for (ii = 1; ii < 4; ii++) {
data[0] = 0xC7;
data[1] = 0x03;
data[2] = 0x03;
data[3] = ii;
ret = fts_write_reg(info, data, 12);
if (ret <= 0) {
goto err_write_reg;
}
}
input_info(true, &info->client->dev, "%s: clear rawdata\n", __func__);
data[0] = 0xC7;
data[1] = 0x03;
data[2] = 0x01;
data[3] = 0;
ret = fts_write_reg(info, data, 4);
if (ret <= 0) {
goto err_write_reg;
}
input_info(true, &info->client->dev, "%s: clear group index\n", __func__);
fts_command(info, FTS_CMD_SAVE_CX_TUNING);
fts_delay(230);
fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE);
fts_command(info, FLUSHBUFFER);
fts_delay(10);
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
fts_interrupt_set(info, INT_ENABLE);
snprintf(buff, sizeof(buff), "%s", "OK");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
return;
err_write_reg:
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
fts_command(info, FTS_CMD_SAVE_CX_TUNING);
fts_delay(230);
fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE);
fts_command(info, FLUSHBUFFER);
fts_delay(10);
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
fts_interrupt_set(info, INT_ENABLE);
return;
}
static void get_pressure_threshold(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char data[3] = { 0 };
int ret;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
ret = info->fts_get_sysinfo_data(info, FTS_SI_PRESSURE_THRESHOLD, 3, data);
if (ret <= 0)
input_err(true, info->dev, "%s: failed to read pressure threshold\n", __func__);
snprintf(buff, sizeof(buff), "%d", ((data[2] << 8) + data[1]));
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
/* low level is more sensitivity, except level-0(value 0) */
static void set_pressure_user_level(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char data[1] = { 0 };
unsigned short addr;
int ret;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
if ((sec->cmd_param[0] < 1) || (sec->cmd_param[0] > 5)) {
input_err(true, &info->client->dev, "%s: wrong index.\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "WRONG INDEX");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
addr = FTS_CMD_STRING_ACCESS + FTS_CMD_OFFSET_PRESSURE_LEVEL;
data[0] = sec->cmd_param[0];
ret = info->fts_write_to_string(info, &addr, data, 1);
if (ret <= 0)
goto out_set_user_level;
ret = info->fts_read_from_string(info, &addr, data, 1);
if (ret <= 0)
goto out_set_user_level;
input_info(true, &info->client->dev, "%s: set user level: %d\n", __func__, data[0]);
info->pressure_user_level = data[0];
fts_delay(20);
addr = FTS_CMD_STRING_ACCESS + FTS_CMD_OFFSET_PRESSURE_THD_HIGH;
data[0] = 0;
ret = info->fts_read_from_string(info, &addr, data, 1);
if (ret <= 0)
goto out_set_user_level;
input_info(true, &info->client->dev, "%s: HIGH THD: %d\n", __func__, data[0]);
addr = FTS_CMD_STRING_ACCESS + FTS_CMD_OFFSET_PRESSURE_THD_LOW;
data[0] = 0;
ret = info->fts_read_from_string(info, &addr, data, 1);
if (ret <= 0)
goto out_set_user_level;
input_info(true, &info->client->dev, "%s: HIGH LOW: %d\n", __func__, data[0]);
snprintf(buff, sizeof(buff), "OK");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
return;
out_set_user_level:
snprintf(buff, sizeof(buff), "FAIL");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_pressure_user_level(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char data[1] = { 0 };
unsigned short addr;
int ret;
sec_cmd_set_default_result(sec);
data[0] = sec->cmd_param[0];
addr = FTS_CMD_STRING_ACCESS + FTS_CMD_OFFSET_PRESSURE_LEVEL;
ret = info->fts_write_to_string(info, &addr, data, 1);
if (ret <= 0)
goto out_get_user_level;
ret = info->fts_read_from_string(info, &addr, data, 1);
if (ret <= 0)
goto out_get_user_level;
input_info(true, &info->client->dev, "%s: set user level: %d\n", __func__, data[0]);
info->pressure_user_level = data[0];
snprintf(buff, sizeof(buff), "%d", info->pressure_user_level);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
return;
out_get_user_level:
snprintf(buff, sizeof(buff), "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#endif
static void factory_cmd_result_all(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[16] = { 0 };
memset(sec->cmd_result_all, 0x00, SEC_CMD_RESULT_STR_LEN);
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
sec->cmd_all_factory_state = SEC_CMD_STATUS_FAIL;
goto out;
}
sec->cmd_all_factory_state = SEC_CMD_STATUS_RUNNING;
snprintf(buff, sizeof(buff), "%d", info->board->item_version);
sec_cmd_set_cmd_result_all(sec, buff, sizeof(buff), "ITEM_VERSION");
get_chip_vendor(sec);
get_chip_name(sec);
get_fw_ver_bin(sec);
get_fw_ver_ic(sec);
/* mis cal check */
fts_panel_ito_test(info, OPEN_SHORT_CRACK_TEST);
info->fts_command(info, SENSEOFF);
fts_delay(50);
fts_interrupt_set(info, INT_DISABLE);
info->fts_command(info, CX_TUNNING);
fts_delay(300);
fts_fw_wait_for_event_D3(info, STATUS_EVENT_MUTUAL_AUTOTUNE_DONE, 0x00);
info->fts_command(info, SELF_AUTO_TUNE);
fts_delay(300);
fts_fw_wait_for_event_D3(info, STATUS_EVENT_SELF_AUTOTUNE_DONE_D3, 0x00);
fts_delay(50);
fts_command(info, SENSEON);
fts_fw_wait_for_event (info, STATUS_EVENT_FORCE_CAL_DONE_D3);
run_rawcap_read(sec);
run_self_raw_read(sec);
run_cx_data_read(sec);
get_cx_gap_data(sec);
run_ix_data_read(sec);
get_mis_cal_info(sec);
sec->cmd_all_factory_state = SEC_CMD_STATUS_OK;
out:
input_info(true, &info->client->dev, "%s: %s\n", __func__, sec->cmd_result_all);
}
static void set_factory_level(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
if (info->fts_power_state == FTS_POWER_STATE_POWERDOWN) {
input_err(true, &info->client->dev, "%s: Touch is stopped!\n", __func__);
goto NG;
}
if (sec->cmd_param[0] < OFFSET_FAC_SUB || sec->cmd_param[0] > OFFSET_FAC_MAIN) {
input_err(true, &info->client->dev,
"%s: cmd data is abnormal, %d\n", __func__, sec->cmd_param[0]);
goto NG;
}
info->factory_position = sec->cmd_param[0];
input_info(true, &info->client->dev, "%s: %d\n", __func__, info->factory_position);
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
return;
NG:
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
}
int fts_get_tsp_test_result(struct fts_ts_info *info)
{
unsigned char *data = NULL;
int ret;
data = kzalloc(nvm_data[FTS_NVM_OFFSET_FAC_RESULT].length, GFP_KERNEL);
if (!data) {
input_err(true, &info->client->dev, "%s: failed to alloc mem\n",
__func__);
return -ENOMEM;
}
ret = get_nvm_data(info, FTS_NVM_OFFSET_FAC_RESULT, data);
if (ret <= 0) {
input_err(true, &info->client->dev,
"%s: get failed. ret: %d\n", __func__, ret);
goto err_read;
}
if (data[0] == 0xFF)
data[0] = 0;
if (data[1] == 0xFF)
data[1] = 0;
info->test_result.data[0] = data[0];
info->disassemble_count = data[1];
err_read:
kfree(data);
return ret;
}
EXPORT_SYMBOL(fts_get_tsp_test_result);
static void get_tsp_test_result(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
int ret;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
ret = fts_get_tsp_test_result(info);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: failed to get result\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
snprintf(buff, sizeof(buff), "M:%s, M:%d, A:%s, A:%d",
info->test_result.module_result == 0 ? "NONE" :
info->test_result.module_result == 1 ? "FAIL" :
info->test_result.module_result == 2 ? "PASS" : "A",
info->test_result.module_count,
info->test_result.assy_result == 0 ? "NONE" :
info->test_result.assy_result == 1 ? "FAIL" :
info->test_result.assy_result == 2 ? "PASS" : "A",
info->test_result.assy_count);
sec_cmd_set_cmd_result(sec, buff, strlen(buff));
sec->cmd_state = SEC_CMD_STATUS_OK;
}
}
/* 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 int fts_set_tsp_test_result(struct fts_ts_info *info)
{
unsigned char *data = NULL;
int ret;
input_info(true, &info->client->dev, "%s: [0x%X] M:%s, M:%d, A:%s, A:%d\n",
__func__, info->test_result.data[0],
info->test_result.module_result == 0 ? "NONE" :
info->test_result.module_result == 1 ? "FAIL" :
info->test_result.module_result == 2 ? "PASS" : "A",
info->test_result.module_count,
info->test_result.assy_result == 0 ? "NONE" :
info->test_result.assy_result == 1 ? "FAIL" :
info->test_result.assy_result == 2 ? "PASS" : "A",
info->test_result.assy_count);
data = kzalloc(nvm_data[FTS_NVM_OFFSET_FAC_RESULT].length, GFP_KERNEL);
if (!data) {
input_err(true, &info->client->dev, "%s: failed to alloc mem\n",
__func__);
return -ENOMEM;
}
data[0] = info->test_result.data[0];
data[1] = info->disassemble_count;
ret = set_nvm_data(info, FTS_NVM_OFFSET_FAC_RESULT, data);
if (ret <= 0)
input_err(true, &info->client->dev,
"%s: set failed. ret: %d\n", __func__, ret);
kfree(data);
return ret;
}
static void set_tsp_test_result(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
int ret;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
ret = fts_get_tsp_test_result(info);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: [ERROR] failed to get_tsp_test_result\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
sec->cmd_state = SEC_CMD_STATUS_RUNNING;
if (info->test_result.data[0] == 0xFF) {
input_info(true, &info->client->dev,
"%s: clear factory_result as zero\n",
__func__);
info->test_result.data[0] = 0;
}
if (sec->cmd_param[0] == TEST_OCTA_ASSAY) {
info->test_result.assy_result = sec->cmd_param[1];
if (info->test_result.assy_count < 3)
info->test_result.assy_count++;
} else if (sec->cmd_param[0] == TEST_OCTA_MODULE) {
info->test_result.module_result = sec->cmd_param[1];
if (info->test_result.module_count < 3)
info->test_result.module_count++;
}
ret = fts_set_tsp_test_result(info);
if (ret < 0) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void increase_disassemble_count(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
int ret;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
ret = fts_get_tsp_test_result(info);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: [ERROR] failed to get_tsp_test_result\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
return;
}
sec->cmd_state = SEC_CMD_STATUS_RUNNING;
if (info->disassemble_count < 0xFE)
info->disassemble_count++;
ret = fts_set_tsp_test_result(info);
if (ret < 0) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_disassemble_count(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
int ret;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
ret = fts_get_tsp_test_result(info);
if (ret < 0) {
input_err(true, &info->client->dev, "%s: failed to get result\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
snprintf(buff, sizeof(buff), "%d", info->disassemble_count);
sec_cmd_set_cmd_result(sec, buff, strlen(buff));
sec->cmd_state = SEC_CMD_STATUS_OK;
}
}
int fts_get_tsp_flash_data(struct fts_ts_info *info, int offset, unsigned char cnt, unsigned char* buf)
{
unsigned char regAdd[3] = {0xB8, 0x00, 0x08};
unsigned char data[255] = { 0 };
unsigned short offset_addr;
int ret;
ret = fts_write_reg(info, &regAdd[0], 3);
if (ret <= 0) {
input_err(true, &info->client->dev,
"%s: failed. ret: %d\n", __func__, ret);
return -EINVAL;
}
ret = info->fts_get_sysinfo_data(info, FTS_SI_COMPENSATION_OFFSET_ADDR, 4, data);
if (ret < 0) {
input_err(true, &info->client->dev,
"%s: failed. ret: %d\n", __func__, ret);
return -EINVAL;
}
offset_addr = data[0] + (data[1] << 8);
regAdd[0] = 0xD0;
regAdd[1] = (offset_addr >> 8) & 0xFF;
regAdd[2] = (offset_addr & 0xFF) + offset;
ret = fts_read_reg(info, &regAdd[0], 3, (unsigned char *)buf, cnt + 1);
if (ret <= 0) {
input_err(true, &info->client->dev, "%s: failed. ret: %d\n",
__func__, ret);
return ret;
}
return 0;
}
int set_nvm_data_by_size(struct fts_ts_info *info, u8 offset, int length, u8 *buf)
{
u8 regAdd[256] = { 0 };
u8 remaining, index, sendinglength;
const u8 max_write_size = 11; // Total write size 15 bytes [Command(4byte) + User data(11bytes)]
int ret;
fts_command(info, SENSEOFF);
fts_delay(50);
fts_command(info, FLUSHBUFFER);
fts_interrupt_set(info, INT_DISABLE);
fts_release_all_finger(info);
remaining = length;
index = 0;
sendinglength = 0;
while (remaining) {
regAdd[0] = 0xC7;
regAdd[1] = 0x02;
regAdd[2] = offset + index;
// write data up to 11 bytes available
if (remaining < max_write_size) {
regAdd[3] = remaining;
memcpy(&regAdd[4], &buf[index], remaining);
sendinglength = remaining;
} else {
regAdd[3] = max_write_size;
memcpy(&regAdd[4], &buf[index], max_write_size);
index += max_write_size;
sendinglength = max_write_size;
}
ret = fts_write_reg(info, &regAdd[0], sendinglength + 4);
if (ret < 0) {
input_err(true, &info->client->dev,
"%s: failed. ret: %d\n", __func__, ret);
return ret;
}
remaining -= sendinglength;
}
fts_command(info, FTS_CMD_SAVE_CX_TUNING);
fts_delay(230);
fts_fw_wait_for_event(info, STATUS_EVENT_FLASH_WRITE_CXTUNE_VALUE);
fts_command(info, FLUSHBUFFER);
fts_delay(10);
fts_command(info, SENSEON);
fts_interrupt_set(info, INT_ENABLE);
return ret;
}
int set_nvm_data(struct fts_ts_info *info, u8 type, u8 *buf)
{
return set_nvm_data_by_size(info, nvm_data[type].offset, nvm_data[type].length, buf);
}
int get_nvm_data_by_size(struct fts_ts_info *info, u8 offset, int length, u8 *nvdata)
{
u8 regAdd[3] = {0};
u8 data[128 + 1] = { 0 };
u8 r_data[8] = { 0 };
int ret;
fts_command(info, SENSEOFF);
fts_delay(50);
fts_command(info, FLUSHBUFFER);
fts_interrupt_set(info, INT_DISABLE);
fts_release_all_finger(info);
// Request SEC factory debug data from flash
regAdd[0] = 0xB8;
regAdd[1] = 0x00;
regAdd[2] = 0x10;
ret = fts_write_reg(info, &regAdd[0], 3);
if (ret < 0) {
input_err(true, &info->client->dev,
"%s: failed. ret: %d\n", __func__, ret);
goto err_mode;
}
fts_delay(50);
fts_interrupt_set(info, INT_ENABLE);
ret = info->fts_get_sysinfo_data(info, FTS_SI_COMPENSATION_OFFSET_ADDR, 7, r_data);
if (ret < 0) {
input_err(true, &info->client->dev,
"%s: get failed. ret: %d\n", __func__, ret);
goto err_mode;
}
input_info(true, &info->client->dev, "%s: 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
__func__, r_data[0], r_data[1], r_data[2], r_data[3], r_data[4], r_data[5], r_data[6], r_data[7]);
regAdd[0] = 0xD0;
regAdd[1] = r_data[1];
regAdd[2] = r_data[0] + offset;
ret = fts_read_reg(info, &regAdd[0], 3, data, length + 1);
if (ret < 0) {
input_err(true, &info->client->dev,
"%s: read failed. ret: %d\n", __func__, ret);
goto err_mode;
}
memcpy(nvdata, &data[1], length);
err_mode:
fts_command(info, FLUSHBUFFER);
fts_delay(10);
fts_command(info, SENSEON);
fts_interrupt_set(info, INT_ENABLE);
return ret;
}
int get_nvm_data(struct fts_ts_info *info, int type, u8 *nvdata)
{
int size = sizeof(nvm_data) / sizeof(struct fts_nvm_data_map);
if (type >= size)
return -EINVAL;
return get_nvm_data_by_size(info, nvm_data[type].offset, nvm_data[type].length, nvdata);
}
#ifdef TCLM_CONCEPT
int sec_tclm_data_read(struct i2c_client *client, int address)
{
struct fts_ts_info *info = i2c_get_clientdata(client);
int ret = 0;
int i = 0;
u8 nbuff[FTS_NVM_OFFSET_ALL];
switch (address) {
case SEC_TCLM_NVM_OFFSET_IC_FIRMWARE_VER:
ret = info->fts_get_version_info(info);
return info->fw_main_version_of_ic;
case SEC_TCLM_NVM_ALL_DATA:
ret = get_nvm_data_by_size(info, nvm_data[FTS_NVM_OFFSET_FAC_RESULT].offset,
FTS_NVM_OFFSET_ALL, nbuff);
if (ret < 0)
return ret;
info->tdata->nvdata.cal_count = nbuff[nvm_data[FTS_NVM_OFFSET_CAL_COUNT].offset];
info->tdata->nvdata.tune_fix_ver = (nbuff[nvm_data[FTS_NVM_OFFSET_TUNE_VERSION].offset] << 8) |
nbuff[nvm_data[FTS_NVM_OFFSET_TUNE_VERSION].offset + 1];
info->tdata->nvdata.cal_position = nbuff[nvm_data[FTS_NVM_OFFSET_CAL_POSITION].offset];
info->tdata->nvdata.cal_pos_hist_cnt = nbuff[nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_COUNT].offset];
info->tdata->nvdata.cal_pos_hist_lastp = nbuff[nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_LASTP].offset];
for (i = nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].offset;
i < nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].offset +
nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].length; i++)
info->tdata->nvdata.cal_pos_hist_queue[i - nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].offset] = nbuff[i];
info->fac_nv = nbuff[nvm_data[FTS_NVM_OFFSET_FAC_RESULT].offset];
info->disassemble_count = nbuff[nvm_data[FTS_NVM_OFFSET_DISASSEMBLE_COUNT].offset];
return ret;
default:
return ret;
}
}
int sec_tclm_data_write(struct i2c_client *client)
{
struct fts_ts_info *info = i2c_get_clientdata(client);
int ret = 1;
int i = 0;
u8 nbuff[FTS_NVM_OFFSET_ALL];
memset(nbuff, 0x00, FTS_NVM_OFFSET_ALL);
nbuff[nvm_data[FTS_NVM_OFFSET_FAC_RESULT].offset] = info->fac_nv;
nbuff[nvm_data[FTS_NVM_OFFSET_DISASSEMBLE_COUNT].offset] = info->disassemble_count;
nbuff[nvm_data[FTS_NVM_OFFSET_CAL_COUNT].offset] = info->tdata->nvdata.cal_count;
nbuff[nvm_data[FTS_NVM_OFFSET_TUNE_VERSION].offset] = (u8)(info->tdata->nvdata.tune_fix_ver >> 8);
nbuff[nvm_data[FTS_NVM_OFFSET_TUNE_VERSION].offset + 1] = (u8)(0xff & info->tdata->nvdata.tune_fix_ver);
nbuff[nvm_data[FTS_NVM_OFFSET_CAL_POSITION].offset] = info->tdata->nvdata.cal_position;
nbuff[nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_COUNT].offset] = info->tdata->nvdata.cal_pos_hist_cnt;
nbuff[nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_LASTP].offset] = info->tdata->nvdata.cal_pos_hist_lastp;
for (i = nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].offset;
i < nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].offset +
nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].length; i++)
nbuff[i] = info->tdata->nvdata.cal_pos_hist_queue[i - nvm_data[FTS_NVM_OFFSET_HISTORY_QUEUE_ZERO].offset];
ret = set_nvm_data_by_size(info, nvm_data[FTS_NVM_OFFSET_FAC_RESULT].offset, FTS_NVM_OFFSET_ALL, nbuff);
return ret;
}
#endif
#ifdef FTS_SUPPORT_HOVER
static void hover_enable(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
if (info->touch_stopped || !(info->reinit_done) || (info->fts_power_state != FTS_POWER_STATE_ACTIVE)) {
input_err(true, &info->client->dev,
"%s: [ERROR] Touch is stopped:%d, reinit_done:%d, power_state:%d\n",
__func__, info->touch_stopped, info->reinit_done, info->fts_power_state);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
if(sec->cmd_param[0]==1){
info->retry_hover_enable_after_wakeup = 1;
input_info(true, &info->client->dev, "%s: retry_hover_on_after_wakeup\n", __func__);
}
goto out;
}
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
int enables;
enables = sec->cmd_param[0];
if (enables == info->hover_enabled) {
input_dbg(true, &info->client->dev,
"%s: Skip duplicate command. Hover is already %s.\n",
__func__, info->hover_enabled ? "enabled" : "disabled");
} else {
if (enables) {
unsigned char regAdd[4] = {0xB0, 0x01, 0x29, 0x41};
unsigned char Dly_regAdd[4] = {0xB0, 0x01, 0x72, 0x04};
fts_write_reg(info, &Dly_regAdd[0], 4);
fts_write_reg(info, &regAdd[0], 4);
fts_command(info, FTS_CMD_HOVER_ON);
info->hover_enabled = true;
info->hover_ready = false;
} else {
unsigned char Dly_regAdd[4] = {0xB0, 0x01, 0x72, 0x08};
fts_write_reg(info, &Dly_regAdd[0], 4);
fts_command(info, FTS_CMD_HOVER_OFF);
info->hover_enabled = false;
info->hover_ready = false;
}
}
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_WAITING;
out:
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
/* static void hover_no_sleep_enable(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
unsigned char regAdd[4] = {0xB0, 0x01, 0x18, 0x00};
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
if (sec->cmd_param[0]) {
regAdd[3]=0x0F;
} else {
regAdd[3]=0x08;
}
fts_write_reg(info, &regAdd[0], 4);
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
} */
#endif
#ifdef CONFIG_GLOVE_TOUCH
static void glove_mode(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
info->glove_enabled = sec->cmd_param[0];
if (!info->touch_stopped && info->reinit_done) {
if (info->glove_enabled)
fts_command(info, FTS_CMD_GLOVE_ON);
else
fts_command(info, FTS_CMD_GLOVE_OFF);
}
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_WAITING;
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void get_glove_sensitivity(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
unsigned char cmd[4] =
{ 0xB2, 0x01, 0xC6, 0x02 };
int timeout=0;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
char buff[SEC_CMD_STR_LEN] = { 0 };
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
return;
}
fts_write_reg(info, &cmd[0], 4);
sec->cmd_state = SEC_CMD_STATUS_RUNNING;
while (sec->cmd_state == SEC_CMD_STATUS_RUNNING) {
if (timeout++>30) {
sec->cmd_state = SEC_CMD_STATUS_FAIL;
break;
}
msleep(10);
}
}
static void fast_glove_mode(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
info->fast_glove_enabled = sec->cmd_param[0];
if (!info->touch_stopped && info->reinit_done) {
if (info->fast_glove_enabled)
fts_command(info, FTS_CMD_SET_FAST_GLOVE_MODE);
else
fts_command(info, FTS_CMD_SET_NOR_GLOVE_MODE);
}
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_WAITING;
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
};
#endif
static void clear_cover_mode(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 3) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
if (sec->cmd_param[0] > 1) {
info->flip_enable = true;
info->cover_type = sec->cmd_param[1];
#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
if (TRUSTEDUI_MODE_TUI_SESSION & trustedui_get_current_mode()) {
fts_delay(500);
tui_force_close(1);
fts_delay(200);
if (TRUSTEDUI_MODE_TUI_SESSION & trustedui_get_current_mode()) {
trustedui_clear_mask(TRUSTEDUI_MODE_VIDEO_SECURED|TRUSTEDUI_MODE_INPUT_SECURED);
trustedui_set_mode(TRUSTEDUI_MODE_OFF);
}
}
tui_cover_mode_set(true);
#endif
} else {
info->flip_enable = false;
#ifdef CONFIG_TRUSTONIC_TRUSTED_UI
tui_cover_mode_set(false);
#endif
}
if (!info->touch_stopped && info->reinit_done) {
if (info->flip_enable) {
#ifdef CONFIG_GLOVE_TOUCH
if (info->glove_enabled
&& (strncmp(info->board->project_name, "TB", 2) != 0))
fts_command(info, FTS_CMD_GLOVE_OFF);
#endif
fts_set_cover_type(info, true);
} else {
fts_set_cover_type(info, false);
#ifdef CONFIG_GLOVE_TOUCH
if (info->fast_glove_enabled)
fts_command(info, FTS_CMD_SET_FAST_GLOVE_MODE);
else if (info->glove_enabled)
fts_command(info, FTS_CMD_GLOVE_ON);
#endif
}
}
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_WAITING;
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
};
static void report_rate(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
goto out;
}
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 2) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
if (sec->cmd_param[0] == REPORT_RATE_90HZ)
fts_change_scan_rate(info, FTS_CMD_FAST_SCAN);
else if (sec->cmd_param[0] == REPORT_RATE_60HZ)
fts_change_scan_rate(info, FTS_CMD_SLOW_SCAN);
else if (sec->cmd_param[0] == REPORT_RATE_30HZ)
fts_change_scan_rate(info, FTS_CMD_USLOW_SCAN);
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_WAITING;
out:
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
static void interrupt_control(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
goto out;
}
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
int enables;
enables = sec->cmd_param[0];
if (enables)
fts_irq_enable(info, true);
else
fts_irq_enable(info, false);
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_WAITING;
out:
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
#endif
static void set_wirelesscharger_mode(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
info->wirelesscharger_mode = sec->cmd_param[0];
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
goto out;
}
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
info->wirelesscharger_mode = sec->cmd_param[0];
fts_wirelesscharger_mode(info);
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_WAITING;
out:
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
};
/* ######################################################
flag 1 : set edge handler
2 : set (portrait, normal) edge zone data
4 : set (portrait, normal) dead zone data
8 : set landscape mode data
16 : mode clear
data
0x30, FFF (y start), FFF (y end), FF(direction)
0x31, FFFF (edge zone)
0x32, FF (up x), FF (down x), FFFF (y)
0x33, FF (mode), FFF (edge), FFF (dead zone)
case
edge handler set : 0x30....
booting time : 0x30... + 0x31...
normal mode : 0x32... (+0x31...)
landscape mode : 0x33...
landscape -> normal (if same with old data) : 0x33, 0
landscape -> normal (etc) : 0x32.... + 0x33, 0
###################################################### */
void fts_set_grip_data_to_ic(struct fts_ts_info *info, u8 flag){
u8 data[4] = { 0 };
u8 regAdd[6] = {0xC6, 0x00, 0x00, 0x00, 0x00, 0x00};
input_info(true, &info->client->dev, "%s: flag: %02X (clr,lan,nor,edg,han)\n", __func__, flag);
if (flag & G_SET_EDGE_HANDLER) {
if (info->grip_edgehandler_direction == 0) {
data[0] = 0x0;
data[1] = 0x0;
data[2] = 0x0;
data[3] = 0x0;
} else {
data[0] = (info->grip_edgehandler_start_y >> 4) & 0xFF;
data[1] = (info->grip_edgehandler_start_y << 4 & 0xF0) | ((info->grip_edgehandler_end_y >> 8) & 0xF);
data[2] = info->grip_edgehandler_end_y & 0xFF;
data[3] = info->grip_edgehandler_direction & 0x3;
}
regAdd[1] = FTS_CMD_EDGE_HANDLER;
regAdd[2] = data[0];
regAdd[3] = data[1];
regAdd[4] = data[2];
regAdd[5] = data[3];
fts_write_reg(info, regAdd, 6);
input_info(true, &info->client->dev, "%s: 0x%02X %02X,%02X,%02X,%02X\n",
__func__, FTS_CMD_EDGE_HANDLER, data[0], data[1], data[2], data[3]);
}
if (flag & G_SET_EDGE_ZONE) {
data[0] = (info->grip_edge_range >> 8) & 0xFF;
data[1] = info->grip_edge_range & 0xFF;
regAdd[1] = FTS_CMD_EDGE_AREA;
regAdd[2] = data[0];
regAdd[3] = data[1];
fts_write_reg(info, regAdd, 4);
input_info(true, &info->client->dev, "%s: 0x%02X %02X,%02X\n",
__func__, FTS_CMD_EDGE_AREA, data[0], data[1]);
}
if (flag & G_SET_NORMAL_MODE) {
data[0] = info->grip_deadzone_up_x & 0xFF;
data[1] = info->grip_deadzone_dn_x & 0xFF;
data[2] = (info->grip_deadzone_y >> 8) & 0xFF;
data[3] = info->grip_deadzone_y & 0xFF;
regAdd[1] = FTS_CMD_DEAD_ZONE;
regAdd[2] = data[0];
regAdd[3] = data[1];
regAdd[4] = data[2];
regAdd[5] = data[3];
fts_write_reg(info, regAdd, 6);
input_info(true, &info->client->dev, "%s: 0x%02X %02X,%02X,%02X,%02X\n",
__func__, FTS_CMD_DEAD_ZONE, data[0], data[1], data[2], data[3]);
}
if (flag & G_SET_LANDSCAPE_MODE) {
data[0] = info->grip_landscape_mode & 0x1;
data[1] = (info->grip_landscape_edge >> 4) & 0xFF;
data[2] = (info->grip_landscape_edge << 4 & 0xF0) | ((info->grip_landscape_deadzone >> 8) & 0xF);
data[3] = info->grip_landscape_deadzone & 0xFF;
regAdd[1] = FTS_CMD_LANDSCAPE_MODE;
regAdd[2] = data[0];
regAdd[3] = data[1];
regAdd[4] = data[2];
regAdd[5] = data[3];
fts_write_reg(info, regAdd, 6);
input_info(true, &info->client->dev, "%s: 0x%02X %02X,%02X,%02X,%02X\n",
__func__, FTS_CMD_LANDSCAPE_MODE, data[0], data[1], data[2], data[3]);
}
if (flag & G_CLR_LANDSCAPE_MODE) {
data[0] = info->grip_landscape_mode;
regAdd[1] = FTS_CMD_LANDSCAPE_MODE;
regAdd[2] = data[0];
fts_write_reg(info, regAdd, 3);
input_info(true, &info->client->dev, "%s: 0x%02X %02X\n",
__func__, FTS_CMD_LANDSCAPE_MODE, data[0]);
}
}
/* ######################################################
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)
ex) echo set_grip_data,2,1,200,100 > cmd
2, 0 (portrait mode)
ex) echo set_grip_data,2,0 > cmd
###################################################### */
static void set_grip_data(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
u8 mode = G_NONE;
sec_cmd_set_default_result(sec);
memset(buff, 0, sizeof(buff));
mutex_lock(&info->device_mutex);
if (sec->cmd_param[0] == 0) { // edge handler
if (sec->cmd_param[1] == 0) { // clear
info->grip_edgehandler_direction = 0;
} else if (sec->cmd_param[1] < 3) {
info->grip_edgehandler_direction = sec->cmd_param[1];
info->grip_edgehandler_start_y = sec->cmd_param[2];
info->grip_edgehandler_end_y = sec->cmd_param[3];
} else {
input_err(true, &info->client->dev, "%s: cmd1 is abnormal, %d (%d)\n",
__func__,sec->cmd_param[1], __LINE__);
goto err_grip_data;
}
mode = mode | G_SET_EDGE_HANDLER;
fts_set_grip_data_to_ic(info, mode);
} else if (sec->cmd_param[0] == 1) { // normal mode
if (info->grip_edge_range != sec->cmd_param[1])
mode = mode | G_SET_EDGE_ZONE;
info->grip_edge_range = sec->cmd_param[1];
info->grip_deadzone_up_x = sec->cmd_param[2];
info->grip_deadzone_dn_x = sec->cmd_param[3];
info->grip_deadzone_y = sec->cmd_param[4];
mode = mode | G_SET_NORMAL_MODE;
if (info->grip_landscape_mode == 1) {
info->grip_landscape_mode = 0;
mode = mode | G_CLR_LANDSCAPE_MODE;
}
fts_set_grip_data_to_ic(info, mode);
} else if (sec->cmd_param[0] == 2) { // landscape mode
if (sec->cmd_param[1] == 0) { // normal mode
info->grip_landscape_mode = 0;
mode = mode | G_CLR_LANDSCAPE_MODE;
} else if (sec->cmd_param[1] == 1) {
info->grip_landscape_mode = 1;
info->grip_landscape_edge = sec->cmd_param[2];
info->grip_landscape_deadzone = sec->cmd_param[3];
mode = mode | G_SET_LANDSCAPE_MODE;
} else {
input_err(true, &info->client->dev, "%s: cmd1 is abnormal, %d (%d)\n",
__func__,sec->cmd_param[1], __LINE__);
goto err_grip_data;
}
fts_set_grip_data_to_ic(info, mode);
} else {
input_err(true, &info->client->dev, "%s: cmd0 is abnormal, %d", __func__,sec->cmd_param[0]);
goto err_grip_data;
}
mutex_unlock(&info->device_mutex);
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec_cmd_set_cmd_exit(sec);
return;
err_grip_data:
mutex_unlock(&info->device_mutex);
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec_cmd_set_cmd_exit(sec);
return;
}
static void set_dead_zone(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char regAdd[2] = {0xC4, 0x00};
int ret;
sec_cmd_set_default_result(sec);
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 6) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
if (sec->cmd_param[0]==1)
regAdd[1] = 0x01; /* side edge top */
else if (sec->cmd_param[0]==2)
regAdd[1] = 0x02; /* side edge bottom */
else if (sec->cmd_param[0]==3)
regAdd[1] = 0x03; /* side edge All On */
else if (sec->cmd_param[0]==4)
regAdd[1] = 0x04; /* side edge Left Off */
else if (sec->cmd_param[0]==5)
regAdd[1] = 0x05; /* side edge Right Off */
else if (sec->cmd_param[0]==6)
regAdd[1] = 0x06; /* side edge All Off */
else
regAdd[1] = 0x0; /* none */
ret = fts_write_reg(info, regAdd, 2);
if (ret < 0)
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
else
input_info(true, &info->client->dev, "%s: reg:%d, ret: %d\n", __func__, sec->cmd_param[0], ret);
fts_delay(1);
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_WAITING;
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void dead_zone_enable(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char regAdd[2] = {0xC2, 0x0C};
int ret;
sec_cmd_set_default_result(sec);
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
if (sec->cmd_param[0]==0) {
regAdd[0] = 0xC1; /* dead zone disable */
} else {
regAdd[0] = 0xC2; /* dead zone enable */
}
ret = fts_write_reg(info, regAdd, 2);
if (ret < 0)
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
else
input_info(true, &info->client->dev, "%s: reg:%d, ret: %d\n", __func__, sec->cmd_param[0], ret);
fts_delay(1);
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_WAITING;
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void drawing_test_enable(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
#ifdef FTS_SUPPORT_STRINGLIB
unsigned short addr = FTS_CMD_STRING_ACCESS;
#endif
int ret = 0;
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
if (!sec->cmd_param[0]) {
info->lowpower_flag |= FTS_MODE_PRESSURE;
} else {
info->lowpower_flag &= ~FTS_MODE_PRESSURE;
}
#ifdef FTS_SUPPORT_STRINGLIB
ret = info->fts_write_to_string(info, &addr, &info->lowpower_flag, sizeof(info->lowpower_flag));
#endif
if (ret < 0) {
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
goto out;
}
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
out:
sec->cmd_state = SEC_CMD_STATUS_WAITING;
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void spay_enable(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
#ifdef FTS_SUPPORT_STRINGLIB
unsigned short addr = FTS_CMD_STRING_ACCESS;
#endif
int ret = 0;
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
if (sec->cmd_param[0]) {
info->lowpower_flag |= FTS_MODE_SPAY;
} else {
info->lowpower_flag &= ~FTS_MODE_SPAY;
}
#ifdef FTS_SUPPORT_STRINGLIB
ret = info->fts_write_to_string(info, &addr, &info->lowpower_flag, sizeof(info->lowpower_flag));
#endif
if (ret < 0) {
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
goto out;
}
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
out:
sec->cmd_state = SEC_CMD_STATUS_WAITING;
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void aod_enable(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
#ifdef FTS_SUPPORT_STRINGLIB
unsigned short addr = FTS_CMD_STRING_ACCESS;
#endif
int ret = 0;
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
if (sec->cmd_param[0]) {
info->lowpower_flag |= FTS_MODE_AOD;
} else {
info->lowpower_flag &= ~FTS_MODE_AOD;
}
#ifdef FTS_SUPPORT_STRINGLIB
ret = info->fts_write_to_string(info, &addr, &info->lowpower_flag, sizeof(info->lowpower_flag));
#endif
if (ret < 0) {
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
goto out;
}
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
out:
sec->cmd_state = SEC_CMD_STATUS_WAITING;
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void set_aod_rect(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
u8 data[8] = {0, };
int i, ret = -1;
#ifdef FTS_SUPPORT_STRINGLIB
unsigned short addr = FTS_CMD_STRING_ACCESS + 2;
#endif
sec_cmd_set_default_result(sec);
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
input_info(true, &info->client->dev, "%s: w:%d, h:%d, x:%d, y:%d\n",
__func__, sec->cmd_param[0], sec->cmd_param[1],
sec->cmd_param[2], sec->cmd_param[3]);
#endif
for (i = 0; i < 4; i++) {
data[i * 2] = sec->cmd_param[i] & 0xFF;
data[i * 2 + 1] = (sec->cmd_param[i] >> 8) & 0xFF;
info->rect_data[i] = sec->cmd_param[i];
}
disable_irq(info->client->irq);
#ifdef FTS_SUPPORT_STRINGLIB
ret = info->fts_write_to_string(info, &addr, data, sizeof(data));
#endif
if (ret < 0) {
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
goto NG;
}
enable_irq(info->client->irq);
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec_cmd_set_cmd_exit(sec);
return;
NG:
enable_irq(info->client->irq);
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec_cmd_set_cmd_exit(sec);
}
static void get_aod_rect(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
u8 data[8] = {0, };
u16 rect_data[4] = {0, };
int i, ret = -1;
#ifdef FTS_SUPPORT_STRINGLIB
unsigned short addr = FTS_CMD_STRING_ACCESS + 2;
#endif
sec_cmd_set_default_result(sec);
disable_irq(info->client->irq);
#ifdef FTS_SUPPORT_STRINGLIB
ret = info->fts_read_from_string(info, &addr, data, sizeof(data));
#endif
if (ret < 0) {
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
goto NG;
}
enable_irq(info->client->irq);
for (i = 0; i < 4; i++)
rect_data[i] = (data[i * 2 + 1] & 0xFF) << 8 | (data[i * 2] & 0xFF);
#if !defined(CONFIG_SAMSUNG_PRODUCT_SHIP)
input_info(true, &info->client->dev, "%s: w:%d, h:%d, x:%d, y:%d\n",
__func__, rect_data[0], rect_data[1], rect_data[2], rect_data[3]);
#endif
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec_cmd_set_cmd_exit(sec);
return;
NG:
enable_irq(info->client->irq);
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec_cmd_set_cmd_exit(sec);
}
/*
* C2 13: Disable dex mode
* C1 13 01: Full screen mode
* C1 13 02: Iris mode
*/
static void dex_enable(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char regAdd[3] = {0xC1, 0x13};
int ret;
sec_cmd_set_default_result(sec);
if (!info->board->support_dex) {
input_err(true, &info->client->dev, "%s: not support DeX mode\n", __func__);
goto out;
}
if ((sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) &&
(sec->cmd_param[1] < 0 || sec->cmd_param[1] > 1)) {
input_err(true, &info->client->dev, "%s: not support param\n", __func__);
goto out;
}
info->dex_mode = sec->cmd_param[0];
if (info->dex_mode) {
input_err(true, &info->client->dev, "%s: set DeX touch_pad mode%s\n",
__func__, sec->cmd_param[1] ? " & Iris mode" : "");
info->input_dev = info->input_dev_pad;
regAdd[0] = 0xC1;
if (sec->cmd_param[1]) {
/* Iris mode */
info->dex_mode = 0x02;
info->dex_name = "[DeXI]";
} else {
info->dex_name = "[DeX]";
}
regAdd[2] = info->dex_mode;
} else {
input_err(true, &info->client->dev, "%s: set touch mode\n", __func__);
info->input_dev = info->input_dev_touch;
info->dex_name = "";
regAdd[0] = 0xC2;
}
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
goto out;
}
ret = fts_write_reg(info, regAdd, info->dex_mode ? 3 : 2);
if (ret < 0)
input_err(true, &info->client->dev, "%s: failed. ret: %d\n", __func__, ret);
else
input_info(true, &info->client->dev, "%s: reg:%d, ret: %d\n", __func__, regAdd[2], ret);
snprintf(buff, sizeof(buff), "%s", "OK");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_OK;
sec_cmd_set_cmd_exit(sec);
return;
out:
snprintf(buff, sizeof(buff), "%s", "NG");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_FAIL;
sec_cmd_set_cmd_exit(sec);
}
static void brush_enable(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char regAdd[2] = {0xC1, 0x14};
int ret;
sec_cmd_set_default_result(sec);
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
goto out;
}
info->brush_mode = sec->cmd_param[0];
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
goto out;
}
input_info(true, &info->client->dev,
"%s: set brush mode %s\n", __func__, info->brush_mode ? "enable" : "disable");
if (info->brush_mode == 0)
regAdd[0] = 0xC2; /* 0: Disable Artcanvas min phi mode */
else
regAdd[0] = 0xC1; /* 1: Enable Artcanvas min phi mode */
ret = fts_write_reg(info, regAdd, 2);
if (ret < 0) {
input_err(true, &info->client->dev,
"%s: failed to set brush mode\n", __func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
goto out;
}
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
out:
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void set_touchable_area(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
unsigned char regAdd[2] = {0xC1, 0x15};
int ret;
sec_cmd_set_default_result(sec);
if (sec->cmd_param[0] < 0 || sec->cmd_param[0] > 1) {
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
goto out;
}
info->touchable_area = sec->cmd_param[0];
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
sec->cmd_state = SEC_CMD_STATUS_NOT_APPLICABLE;
goto out;
}
input_info(true, &info->client->dev,
"%s: set 16:9 mode %s\n", __func__, info->touchable_area ? "enable" : "disable");
if (info->touchable_area == 0)
regAdd[0] = 0xC2; /* 0: Disable 16:9 mode */
else
regAdd[0] = 0xC1; /* 1: Enable 16:9 mode */
ret = fts_write_reg(info, regAdd, 2);
if (ret < 0) {
input_err(true, &info->client->dev,
"%s: failed to set 16:9 mode\n", __func__);
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
goto out;
}
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
out:
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void delay(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
info->delay_time = sec->cmd_param[0];
input_info(true, &info->client->dev, "%s: delay time is %d\n", __func__, info->delay_time);
snprintf(buff, sizeof(buff), "%d", info->delay_time);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_WAITING;
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static void debug(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
sec_cmd_set_default_result(sec);
info->debug_string = sec->cmd_param[0];
input_info(true, &info->client->dev, "%s: command is %d\n", __func__, info->debug_string);
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
sec->cmd_state = SEC_CMD_STATUS_WAITING;
sec_cmd_set_cmd_exit(sec);
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
}
static bool tsp_connection_check(struct fts_ts_info *info)
{
int ret;
ret = fts_panel_ito_test(info, OPEN_TEST);
return (ret == 0) ? true : false;
}
static void run_force_calibration(void *device_data)
{
struct sec_cmd_data *sec = (struct sec_cmd_data *)device_data;
struct fts_ts_info *info = container_of(sec, struct fts_ts_info, sec);
char buff[SEC_CMD_STR_LEN] = { 0 };
bool touch_on = false;
sec_cmd_set_default_result(sec);
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n",
__func__);
snprintf(buff, sizeof(buff), "%s", "TSP turned off");
goto autotune_fail;
}
if (info->rawdata_read_lock == 1) {
input_err(true, &info->client->dev, "%s: ramdump mode is runing, %d\n", __func__, info->rawdata_read_lock);
snprintf(buff, sizeof(buff), "%s", "NG");
goto autotune_fail;
}
if (info->touch_count > 0) {
touch_on = true;
input_err(true, info->dev, "%s: finger on touch(%d)\n", __func__, info->touch_count);
}
/* for Tablet model : TSP connection check at pretest apk */
if (info->tdata->external_factory && !tsp_connection_check(info)) {
input_err(true, info->dev, "%s: TSP is not connected. Do not run calibration\n", __func__);
snprintf(buff, sizeof(buff), "%s", "NG_TSP_NOT_CONNECT");
goto autotune_fail;
}
disable_irq(info->irq);
fts_interrupt_set(info, INT_DISABLE);
fts_command(info, SENSEOFF);
fts_delay(50);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey) {
fts_command(info, FTS_CMD_KEY_SENSE_OFF);
}
#endif
fts_command(info, FLUSHBUFFER);
fts_delay(10);
fts_release_all_finger(info);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_release_all_key(info);
#endif
fts_command(info,FTS_CMD_FORCE_AUTOTUNE);
if (touch_on) {
input_err(true, info->dev, "%s: finger! do not run autotune\n", __func__);
} else {
input_info(true, info->dev, "%s: run autotune\n", __func__);
input_err(true, &info->client->dev, "%s: RUN OFFSET CALIBRATION \n", __func__);
fts_execute_autotune(info, true);
#ifdef TCLM_CONCEPT
/* devide tclm case */
sec_tclm_case(info->tdata, sec->cmd_param[0]);
input_info(true, &info->client->dev, "%s: param, %d, %c, %d\n", __func__,
sec->cmd_param[0], sec->cmd_param[0], info->tdata->root_of_calibration);
if (sec_execute_tclm_package(info->tdata, 1) < 0)
input_err(true, &info->client->dev,
"%s: sec_execute_tclm_package\n", __func__);
sec_tclm_root_of_cal(info->tdata, CALPOSITION_NONE);
#endif
}
fts_command(info, SENSEON);
#ifdef FTS_SUPPORT_PRESSURE_SENSOR
fts_command(info, FTS_CMD_PRESSURE_SENSE_ON);
#endif
fts_fw_wait_for_event (info, STATUS_EVENT_FORCE_CAL_DONE_D3);
#ifdef FTS_SUPPORT_TOUCH_KEY
if (info->board->support_mskey)
fts_command(info, FTS_CMD_KEY_SENSE_ON);
#endif
fts_interrupt_set(info, INT_ENABLE);
enable_irq(info->irq);
if (touch_on) {
snprintf(buff, sizeof(buff), "NG_FINGER_ON");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
} else {
snprintf(buff, sizeof(buff), "%s", "OK");
sec->cmd_state = SEC_CMD_STATUS_OK;
}
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
#ifdef TCLM_CONCEPT
info->tdata->external_factory = false;
#endif
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
return;
autotune_fail:
#ifdef TCLM_CONCEPT
info->tdata->external_factory = false;
#endif
snprintf(buff, sizeof(buff), "%s", "NG");
sec->cmd_state = SEC_CMD_STATUS_FAIL;
sec_cmd_set_cmd_result(sec, buff, strnlen(buff, sizeof(buff)));
input_info(true, &info->client->dev, "%s: %s\n", __func__, buff);
return;
}
#ifdef FTS_SUPPORT_TOUCH_KEY
int read_touchkey_data(struct fts_ts_info *info, unsigned char type, unsigned int keycode)
{
unsigned char pCMD[3] = { 0xD0, 0x00, 0x00};
unsigned char buf[9] = { 0 };
int i;
int ret = 0;
pCMD[2] = type;
ret = fts_read_reg(info, &pCMD[0], 3, buf, 3);
if (ret >= 0) {
pCMD[1] = buf[2];
pCMD[2] = buf[1];
} else
return -1;
ret = fts_read_reg(info, &pCMD[0], 3, buf, 9);
if (ret < 0)
return -2;
for (i = 0 ; i < info->board->num_touchkey ; i++)
if (info->board->touchkey[i].keycode == keycode) {
return *(short *)&buf[(info->board->touchkey[i].value - 1) * 2 + 1];
}
return -3;
}
static ssize_t touchkey_recent_strength(struct device *dev,
struct device_attribute *attr, char *buf) {
struct fts_ts_info *info = dev_get_drvdata(dev);
int value = 0;
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
return sprintf(buf, "%d\n", value);
}
value = read_touchkey_data(info, TYPE_TOUCHKEY_STRENGTH, KEY_RECENT);
return sprintf(buf, "%d\n", value);
}
static ssize_t touchkey_back_strength(struct device *dev,
struct device_attribute *attr, char *buf) {
struct fts_ts_info *info = dev_get_drvdata(dev);
int value = 0;
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
return sprintf(buf, "%d\n", value);
}
value = read_touchkey_data(info, TYPE_TOUCHKEY_STRENGTH, KEY_BACK);
return sprintf(buf, "%d\n", value);
}
static ssize_t touchkey_recent_raw(struct device *dev,
struct device_attribute *attr, char *buf) {
struct fts_ts_info *info = dev_get_drvdata(dev);
int value = 0;
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
return sprintf(buf, "%d\n", value);
}
value = read_touchkey_data(info, TYPE_TOUCHKEY_RAW, KEY_RECENT);
return sprintf(buf, "%d\n", value);
}
static ssize_t touchkey_back_raw(struct device *dev,
struct device_attribute *attr, char *buf) {
struct fts_ts_info *info = dev_get_drvdata(dev);
int value = 0;
if (info->touch_stopped) {
input_err(true, &info->client->dev, "%s: [ERROR] Touch is stopped\n", __func__);
return sprintf(buf, "%d\n", value);
}
value = read_touchkey_data(info, TYPE_TOUCHKEY_RAW, KEY_BACK);
return sprintf(buf, "%d\n", value);
}
static ssize_t touchkey_threshold(struct device *dev,
struct device_attribute *attr, char *buf) {
struct fts_ts_info *info = dev_get_drvdata(dev);
unsigned char pCMD[3] = { 0xD0, 0x00, 0x00};
int value;
int ret = 0;
value = -1;
pCMD[2] = FTS_SI_SS_KEY_THRESHOLD;
ret = fts_read_reg(info, &pCMD[0], 3, buf, 3);
if (ret >= 0) {
value = *(unsigned short *)&buf[1];
}
info->touchkey_threshold = value;
return sprintf(buf, "%d\n", info->touchkey_threshold);
}
static ssize_t fts_touchkey_led_control(struct device *dev,
struct device_attribute *attr, const char *buf,
size_t size)
{
struct fts_ts_info *info = dev_get_drvdata(dev);
int ret;
unsigned long data;
if (size > 2) {
input_err(true, &info->client->dev,
"%s: cmd length is over (%s,%d)!!\n",
__func__, buf, (int)strlen(buf));
return -EINVAL;
}
ret = kstrtoul(buf, 10, &data);
if (ret != 0) {
input_err(true, &info->client->dev, "%s: failed to read:%d\n",
__func__, ret);
return -EINVAL;
}
input_dbg(true, &info->client->dev, "%s: %d\n", __func__, data);
if (data != 0 && data != 1) {
input_err(true, &info->client->dev, "%s: wrong cmd %x\n",
__func__, data);
return size;
}
ret = info->board->led_power(info, (bool)data);
if (ret) {
input_err(true, &info->client->dev, "%s: Error turn on led %d\n",
__func__, ret);
goto out;
}
msleep(30);
out:
return size;
}
static DEVICE_ATTR(brightness, S_IRUGO | S_IWUSR | S_IWGRP, NULL, fts_touchkey_led_control);
static DEVICE_ATTR(touchkey_recent, S_IRUGO, touchkey_recent_strength, NULL);
static DEVICE_ATTR(touchkey_back, S_IRUGO, touchkey_back_strength, NULL);
static DEVICE_ATTR(touchkey_recent_raw, S_IRUGO, touchkey_recent_raw, NULL);
static DEVICE_ATTR(touchkey_back_raw, S_IRUGO, touchkey_back_raw, NULL);
static DEVICE_ATTR(touchkey_threshold, S_IRUGO, touchkey_threshold, NULL);
static struct attribute *sec_touchkey_factory_attributes[] = {
&dev_attr_touchkey_recent.attr,
&dev_attr_touchkey_back.attr,
&dev_attr_touchkey_recent_raw.attr,
&dev_attr_touchkey_back_raw.attr,
&dev_attr_touchkey_threshold.attr,
&dev_attr_brightness.attr,
NULL,
};
static struct attribute_group sec_touchkey_factory_attr_group = {
.attrs = sec_touchkey_factory_attributes,
};
#endif
#endif