/* * * FocalTech TouchScreen driver. * * Copyright (c) 2012-2018, FocalTech Systems, Ltd., all rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include "focaltech_test.h" /***************************************************************************** * Private constant and macro definitions using #define *****************************************************************************/ struct ini_ic_type ic_types[] = { {"FT5X46", 0x54000002}, {"FT5X46i", 0x54010002}, {"FT5526", 0x54020002}, {"FT3X17", 0x54030002}, {"FT5436", 0x54040002}, {"FT3X27", 0x54050002}, {"FT5526i", 0x54060002}, {"FT5416", 0x54070002}, {"FT5426", 0x54080002}, {"FT5435", 0x54090002}, {"FT7681", 0x540A0002}, {"FT7661", 0x540B0002}, {"FT7511", 0x540C0002}, {"FT7421", 0x540D0002}, {"FT7311", 0x54100002}, {"FT3327DQQ-001", 0x41000082}, {"FT5446DQS-W01", 0x40000082}, {"FT5452", 0x55000081}, {"FT3518", 0x55010081}, {"FT3558", 0x55020081}, {"FT3528", 0x55030081}, {"FT5536", 0x55040081}, {"FT5472", 0x8F000083}, {"FT5446U", 0x8F010083}, {"FT5456U", 0x8F020083}, {"FT3417U", 0x8F030083}, {"FT5426U", 0x8F040083}, {"FT3428", 0x8F050083}, {"FT3437U", 0x8F060083}, {"FT5822", 0x58000001}, {"FT5626", 0x58010001}, {"FT5726", 0x58020001}, {"FT5826B", 0x58030001}, {"FT3617", 0x58040001}, {"FT3717", 0x58050001}, {"FT7811", 0x58060001}, {"FT5826S", 0x58070001}, {"FT3517U", 0x58090001}, {"FT3557", 0x580A0001}, {"FT6X36", 0x63000003}, {"FT3X07", 0x63010003}, {"FT6416", 0x63020003}, {"FT6336G/U", 0x63030003}, {"FT7401", 0x63040003}, {"FT3407U", 0x63050003}, {"FT6236U", 0x63060003}, {"FT6436U", 0x63070003}, {"FT3267", 0x63080004}, {"FT3367", 0x63090004}, {"FT8607", 0x81000009}, {"FT8716", 0x82000005}, {"FT8716U", 0x44000005}, {"FT8716F", 0x8A000005}, {"FT8613", 0x4500000C}, {"FT8736", 0x83000006}, {"FT8006M", 0x87000007}, {"FT8201", 0x87010010}, {"FT7250", 0x87020007}, {"FT8006U", 0x8900000B}, {"FT8006S", 0x8901000B}, {"FT8719", 0x9000000D}, {"FT8615", 0x9100000F}, {"FT8739", 0x8D00000E}, {"FT8006P", 0x93000011}, }; /***************************************************************************** * Global variable or extern global variabls/functions *****************************************************************************/ /***************************************************************************** * Static function prototypes *****************************************************************************/ /* Works only for digits and letters, but small and fast */ #define TOLOWER(x) ((x) | 0x20) static int fts_strncmp(const char *cs, const char *ct, int count) { u8 c1 = 0, c2 = 0; while (count) { if ((*cs == '\0') || (*ct == '\0')) return -1; c1 = TOLOWER(*cs++); c2 = TOLOWER(*ct++); if (c1 != c2) return c1 < c2 ? -1 : 1; if (!c1) break; count--; } return 0; } static int isspace(int x) { if (x == ' ' || x == '\t' || x == '\n' || x == '\f' || x == '\b' || x == '\r') return 1; else return 0; } static int isdigit(int x) { if (x <= '9' && x >= '0') return 1; else return 0; } static long fts_atol(char *nptr) { int c; /* current char */ long total; /* current total */ int sign; /* if ''-'', then negative, otherwise positive */ /* skip whitespace */ while ( isspace((int)(unsigned char)*nptr) ) ++nptr; c = (int)(unsigned char) * nptr++; sign = c; /* save sign indication */ if (c == '-' || c == '+') c = (int)(unsigned char) * nptr++; /* skip sign */ total = 0; while (isdigit(c)) { total = 10 * total + (c - '0'); /* accumulate digit */ c = (int)(unsigned char) * nptr++; /* get next char */ } if (sign == '-') return -total; else return total; /* return result, negated if necessary */ } static int fts_atoi(char *nptr) { return (int)fts_atol(nptr); } static int fts_test_get_ini_size(char *config_name) { struct file *pfile = NULL; struct inode *inode = NULL; off_t fsize = 0; char filepath[128]; FTS_TEST_FUNC_ENTER(); memset(filepath, 0, sizeof(filepath)); sprintf(filepath, "%s%s", FTS_INI_FILE_PATH, config_name); if (NULL == pfile) pfile = filp_open(filepath, O_RDONLY, 0); if (IS_ERR(pfile)) { FTS_TEST_ERROR("error occured while opening file %s.", filepath); return -EIO; } #if 1 inode = pfile->f_inode; #else /* reserved for linux earlier verion */ inode = pfile->f_dentry->d_inode; #endif fsize = inode->i_size; filp_close(pfile, NULL); FTS_TEST_FUNC_ENTER(); return fsize; } static int fts_test_read_ini_data(char *config_name, char *config_buf) { struct file *pfile = NULL; struct inode *inode = NULL; off_t fsize = 0; char filepath[128]; loff_t pos = 0; mm_segment_t old_fs; FTS_TEST_FUNC_ENTER(); memset(filepath, 0, sizeof(filepath)); sprintf(filepath, "%s%s", FTS_INI_FILE_PATH, config_name); if (NULL == pfile) { pfile = filp_open(filepath, O_RDONLY, 0); } if (IS_ERR(pfile)) { FTS_TEST_ERROR("error occured while opening file %s.", filepath); return -EIO; } #if 1 inode = pfile->f_inode; #else /* reserved for linux earlier verion */ inode = pfile->f_dentry->d_inode; #endif fsize = inode->i_size; old_fs = get_fs(); set_fs(KERNEL_DS); pos = 0; vfs_read(pfile, config_buf, fsize, &pos); filp_close(pfile, NULL); set_fs(old_fs); FTS_TEST_FUNC_EXIT(); return 0; } static void str_space_remove(char *str) { char *t = str; char *s = str; while (*t != '\0') { if (*t != ' ') { *s = *t; s++; } t++; } *s = '\0'; } #ifdef INI_PRINT static void print_ini_data(struct ini_data *ini) { int i = 0; int j = 0; struct ini_section *section; struct ini_keyword *keyword; if (!ini || !ini->tmp) { FTS_TEST_DBG("ini is null"); return; } FTS_TEST_DBG("section num:%d, keyword num total:%d\n", ini->section_num, ini->keyword_num_total); for (i = 0; i < ini->section_num; i++) { section = &ini->section[i]; FTS_TEST_DBG("section name:[%s] keyword num:%d\n", section->name, section->keyword_num); for (j = 0; j < section->keyword_num; j++) { keyword = §ion->keyword[j]; FTS_TEST_DBG("%s=%s\n", keyword->name, keyword->value); } } } #endif static int ini_get_line(char *filedata, char *line_data, int *line_len) { int i = 0; int line_length = 0; int type; /* get a line data */ for (i = 0; i < MAX_INI_LINE_LEN; i++) { if (('\n' == filedata[i]) || ('\r' == filedata[i])) { line_data[line_length++] = '\0'; if (('\n' == filedata[i + 1]) || ('\r' == filedata[i + 1])) { line_length++; } break; } else { line_data[line_length++] = filedata[i]; } } if (i >= MAX_INI_LINE_LEN) { FTS_TEST_ERROR("line length(%d)>max(%d)", line_length, MAX_INI_LINE_LEN); return -ENODATA; } /* remove space */ str_space_remove(line_data); /* confirm line type */ if (('\0' == line_data[0]) || ('#' == line_data[0])) { type = LINE_OTHER; } else if ('[' == line_data[0]) { type = LINE_SECTION; } else { type = LINE_KEYWORD; /* key word */ } *line_len = line_length; return type; } static int ini_parse_keyword(struct ini_data *ini, char *line_buffer) { int i = 0; int offset = 0; int length = strlen(line_buffer); struct ini_section *section = NULL; for (i = 0; i < length; i++) { if (line_buffer[i] == '=') break; } if ((i == 0) || (i >= length)) { FTS_TEST_ERROR("mark(=)in keyword line fail"); return -ENODATA; } if ((ini->section_num > 0) && (ini->section_num < MAX_INI_SECTION_NUM)) { section = &ini->section[ini->section_num - 1]; } if (NULL == section) { FTS_TEST_ERROR("section is null"); return -ENODATA; } offset = ini->keyword_num_total; if (offset > MAX_KEYWORD_NUM) { FTS_TEST_ERROR("keyword num(%d)>max(%d),please check MAX_KEYWORD_NUM", ini->keyword_num_total, MAX_KEYWORD_NUM); return -ENODATA; } memcpy(ini->tmp[offset].name, &line_buffer[0], i); ini->tmp[offset].name[i] = '\0'; memcpy(ini->tmp[offset].value, &line_buffer[i + 1], length - i - 1); ini->tmp[offset].value[length - i - 1] = '\0'; section->keyword_num++; ini->keyword_num_total++; return 0; } static int ini_parse_section(struct ini_data *ini, char *line_buffer) { int length = strlen(line_buffer); struct ini_section *section = NULL; if ((length <= 2) || (length > MAX_KEYWORD_NAME_LEN)) { FTS_TEST_ERROR("section line length fail"); return -EINVAL; } if ((ini->section_num < 0) || (ini->section_num > MAX_INI_SECTION_NUM)) { FTS_TEST_ERROR("section_num(%d) fail", ini->section_num); return -EINVAL; } section = &ini->section[ini->section_num]; memcpy(section->name, line_buffer + 1, length - 2); section->name[length - 2] = '\0'; FTS_TEST_INFO("section:%s, keyword offset:%d", section->name, ini->keyword_num_total); section->keyword = (struct ini_keyword *)&ini->tmp[ini->keyword_num_total]; section->keyword_num = 0; ini->section_num++; if (ini->section_num > MAX_INI_SECTION_NUM) { FTS_TEST_ERROR("section num(%d)>max(%d), please check MAX_INI_SECTION_NUM", ini->section_num, MAX_INI_SECTION_NUM); return -ENOMEM; } return 0; } static int ini_init_inidata(struct ini_data *ini) { int pos = 0; int ret = 0; char line_buffer[MAX_INI_LINE_LEN] = { 0 }; int line_len = 0; if (!ini || !ini->data || !ini->tmp) { FTS_TEST_DBG("ini/data/tmp is null"); return -EINVAL; } while (pos < ini->length) { ret = ini_get_line(ini->data + pos, line_buffer, &line_len); if (ret < 0) { FTS_TEST_ERROR("ini_get_line fail"); return ret; } else if (ret == LINE_KEYWORD) { ret = ini_parse_keyword(ini, line_buffer); if (ret < 0) { FTS_TEST_ERROR("ini_parse_keyword fail"); return ret; } } else if (ret == LINE_SECTION) { ret = ini_parse_section(ini, line_buffer); if (ret < 0) { FTS_TEST_ERROR("ini_parse_section fail"); return ret; } } pos += line_len; } return 0; } static int ini_get_key(char *section_name, char *key_name, char *value) { int i = 0; int j = 0; struct ini_data *ini = &fts_ftest->ini; struct ini_section *section; struct ini_keyword *keyword; int key_len = 0; #ifdef INI_PRINT FTS_TEST_DBG("section name:%s, key name:%s\n", section_name, key_name); FTS_TEST_DBG("section num:%d\n", ini->section_num); #endif for (i = 0; i < ini->section_num; i++) { section = &ini->section[i]; key_len = strlen(section_name); if (key_len != strlen(section->name)) continue; if (fts_strncmp(section->name, section_name, key_len) != 0) continue; #ifdef INI_PRINT FTS_TEST_DBG("section name:%s keyword num:%d\n", section->name, section->keyword_num); #endif for (j = 0; j < section->keyword_num; j++) { keyword = §ion->keyword[j]; key_len = strlen(key_name); if (key_len == strlen(keyword->name)) { if (0 == fts_strncmp(keyword->name, key_name, key_len)) { key_len = strlen(keyword->value); memcpy(value, keyword->value, key_len); FTS_TEST_DBG("section:%s,%s=%s\n", section_name, key_name, value); return key_len; } } } } return -ENODATA; } /* return keyword's value length if success */ static int ini_get_string_value(char *section_name, char *key_name, char *rval) { if (!section_name || !key_name || !rval) { FTS_TEST_ERROR("section_name/key_name/rval is null"); return -EINVAL; } return ini_get_key(section_name, key_name, rval); } int get_keyword_value(char *section, char *name, int *value) { int ret = 0; char str[MAX_KEYWORD_VALUE_LEN] = { 0 }; ret = ini_get_string_value(section, name, str); if (ret > 0) { /* search successfully, so change value, otherwise keep default */ *value = fts_atoi(str); } return ret; } static void fts_init_buffer(int *buffer, int value, int len) { int i = 0; if (NULL == buffer) { FTS_TEST_ERROR("buffer is null\n"); return; } for (i = 0; i < len; i++) { buffer[i] = value; } } static int get_test_item(char name[][MAX_KEYWORD_NAME_LEN], int length, int *val) { int i = 0; int ret = 0; int tmpval = 0; if (length > TEST_ITEM_COUNT_MAX) { FTS_TEST_SAVE_ERR("test item count(%d) > max(%d)\n", length, TEST_ITEM_COUNT_MAX); return -EINVAL; } FTS_TEST_INFO("test items in total of driver:%d", length); *val = 0; for (i = 0; i < length; i++) { tmpval = 0; ret = get_value_testitem(name[i], &tmpval); if (ret < 0) { FTS_TEST_DBG("test item:%s not found", name[i]); } else { FTS_TEST_DBG("test item:%s=%d", name[i], tmpval); *val |= (tmpval << i); } } return 0; } static int get_basic_threshold(char name[][MAX_KEYWORD_NAME_LEN], int length, int *val) { int i = 0; int ret = 0; struct fts_test *tdata = fts_ftest; FTS_TEST_INFO("basic_thr string length(%d), count(%d)\n", length, tdata->basic_thr_count); if (length > fts_ftest->basic_thr_count) { FTS_TEST_SAVE_ERR("basic_thr string length > count\n"); return -EINVAL; } for (i = 0; i < length; i++) { ret = get_value_basic(name[i], &val[i]); if (ret < 0) { FTS_TEST_DBG("basic thr:%s not found", name[i]); } else { FTS_TEST_DBG("basic thr:%s=%d", name[i], val[i]); } } return 0; } static void get_detail_threshold(char *key_name, bool is_prex, int *thr) { char str[MAX_KEYWORD_VALUE_LEN] = { 0 }; char str_temp[MAX_KEYWORD_NAME_LEN] = { 0 }; char str_tmp[MAX_KEYWORD_VALUE_ONE_LEN] = { 0 }; struct fts_test *tdata = fts_ftest; int divider_pos = 0; int index = 0; int i = 0; int j = 0; int k = 0; int tx_num = 0; int rx_num = 0; if (!key_name || !thr) { FTS_TEST_ERROR("key_name/thr is null"); return; } if (is_prex) { tx_num = tdata->node.tx_num; rx_num = tdata->node.rx_num; } for (i = 0; i < tx_num + 1; i++) { if (is_prex) { snprintf(str_temp, MAX_KEYWORD_NAME_LEN, "%s%d", key_name, (i + 1)); } else { snprintf(str_temp, MAX_KEYWORD_NAME_LEN, "%s", key_name); } divider_pos = ini_get_string_value("SpecialSet", str_temp, str); if (divider_pos <= 0) continue; index = 0; k = 0; memset(str_tmp, 0, sizeof(str_tmp)); for (j = 0; j < divider_pos; j++) { if (',' == str[j]) { thr[i * rx_num + k] = (short)(fts_atoi(str_tmp)); index = 0; memset(str_tmp, 0x00, sizeof(str_tmp)); k++; } else { if (' ' == str[j]) continue; str_tmp[index] = str[j]; index++; } } } } static int init_node_valid(void) { char str[MAX_KEYWORD_NAME_LEN] = {0}; int i = 0; int j = 0; int chy = 0; int node_num = 0; int cnt = 0; struct fts_test *tdata = fts_ftest; if (!tdata || !tdata->node_valid || !tdata->node_valid_sc) { FTS_TEST_ERROR("tdata/node_valid/node_valid_sc is null"); return -EINVAL; } chy = tdata->node.rx_num; node_num = tdata->node.node_num; fts_init_buffer(tdata->node_valid, 1 , node_num); if ((tdata->func->hwtype == IC_HW_INCELL) || (tdata->func->hwtype == IC_HW_MC_SC)) { for (cnt = 0; cnt < node_num; cnt++) { i = cnt / chy + 1; j = cnt % chy + 1; snprintf(str, MAX_KEYWORD_NAME_LEN, "InvalidNode[%d][%d]", i, j); get_keyword_value("INVALID_NODE", str, &tdata->node_valid[cnt]); } } if (tdata->func->hwtype == IC_HW_MC_SC) { chy = tdata->sc_node.rx_num; node_num = tdata->sc_node.node_num; fts_init_buffer(tdata->node_valid_sc, 1, node_num); for (cnt = 0; cnt < node_num; cnt++) { i = (cnt >= chy) ? 2 : 1; j = (cnt >= chy) ? (cnt - chy + 1) : (cnt + 1); snprintf(str, MAX_KEYWORD_NAME_LEN, "InvalidNodeS[%d][%d]", i, j); get_keyword_value("INVALID_NODES", str, &tdata->node_valid_sc[cnt]); } } print_buffer(tdata->node_valid, tdata->node.node_num, tdata->node.rx_num); print_buffer(tdata->node_valid_sc, tdata->sc_node.node_num, tdata->sc_node.rx_num); return 0; } /* incell */ static int get_test_item_incell(void) { int ret = 0; char item_name[][MAX_KEYWORD_NAME_LEN] = TEST_ITEM_INCELL; int length = sizeof(item_name) / MAX_KEYWORD_NAME_LEN; int item_val = 0; ret = get_test_item(item_name, length, &item_val); if (ret < 0) { FTS_TEST_SAVE_ERR("get test item fail\n"); return ret; } fts_ftest->ic.incell.u.tmp = item_val; return 0; } static char bthr_name_incell[][MAX_KEYWORD_NAME_LEN] = BASIC_THRESHOLD_INCELL; static int get_test_threshold_incell(void) { int ret = 0; int length = sizeof(bthr_name_incell) / MAX_KEYWORD_NAME_LEN; struct fts_test *tdata = fts_ftest; struct incell_threshold *thr = &tdata->ic.incell.thr; int node_num = tdata->node.node_num; tdata->basic_thr_count = sizeof(struct incell_threshold_b) / sizeof(int); /* get standard basic threshold */ ret = get_basic_threshold(bthr_name_incell, length, (int *)&thr->basic); if (ret < 0) { FTS_TEST_SAVE_ERR("get basic thr fail\n"); return ret; } /* basic special set by ic */ if (tdata->func->param_init) { ret = tdata->func->param_init(); if (ret < 0) { FTS_TEST_SAVE_ERR("special basic thr init fail\n"); return ret; } } /* init buffer */ fts_init_buffer(thr->rawdata_max, thr->basic.rawdata_max, node_num); fts_init_buffer(thr->rawdata_min, thr->basic.rawdata_min, node_num); if (tdata->func->rawdata2_support) { fts_init_buffer(thr->rawdata2_max, thr->basic.rawdata2_max, node_num); fts_init_buffer(thr->rawdata2_min, thr->basic.rawdata2_min, node_num); } fts_init_buffer(thr->cb_max, thr->basic.cb_max, node_num); fts_init_buffer(thr->cb_min, thr->basic.cb_min, node_num); /* detail threshold */ get_detail_threshold("RawData_Max_Tx", true, thr->rawdata_max); get_detail_threshold("RawData_Min_Tx", true, thr->rawdata_min); get_detail_threshold("CB_Max_Tx", true, thr->cb_max); get_detail_threshold("CB_Min_Tx", true, thr->cb_min); return 0; } static void print_thr_incell(void) { struct fts_test *tdata = fts_ftest; struct incell_threshold *thr = &tdata->ic.incell.thr; FTS_TEST_DBG("short_res_min:%d", thr->basic.short_res_min); FTS_TEST_DBG("short_res_vk_min:%d", thr->basic.short_res_vk_min); FTS_TEST_DBG("open_cb_min:%d", thr->basic.open_cb_min); FTS_TEST_DBG("open_k1_check:%d", thr->basic.open_k1_check); FTS_TEST_DBG("open_k1_value:%d", thr->basic.open_k1_value); FTS_TEST_DBG("open_k2_check:%d", thr->basic.open_k2_check); FTS_TEST_DBG("open_k2_value:%d", thr->basic.open_k2_value); FTS_TEST_DBG("cb_min:%d", thr->basic.cb_min); FTS_TEST_DBG("cb_max:%d", thr->basic.cb_max); FTS_TEST_DBG("cb_vkey_check:%d", thr->basic.cb_vkey_check); FTS_TEST_DBG("cb_min_vk:%d", thr->basic.cb_min_vk); FTS_TEST_DBG("cb_max_vk:%d", thr->basic.cb_max_vk); FTS_TEST_DBG("rawdata_min:%d", thr->basic.rawdata_min); FTS_TEST_DBG("rawdata_max:%d", thr->basic.rawdata_max); FTS_TEST_DBG("rawdata_vkey_check:%d", thr->basic.rawdata_vkey_check); FTS_TEST_DBG("rawdata_min_vk:%d", thr->basic.rawdata_min_vk); FTS_TEST_DBG("rawdata_max_vk:%d", thr->basic.rawdata_max_vk); FTS_TEST_DBG("lcdnoise_frame:%d", thr->basic.lcdnoise_frame); FTS_TEST_DBG("lcdnoise_coefficient:%d", thr->basic.lcdnoise_coefficient); FTS_TEST_DBG("lcdnoise_coefficient_vkey:%d", thr->basic.lcdnoise_coefficient_vkey); FTS_TEST_DBG("open_nmos:%d", thr->basic.open_nmos); FTS_TEST_DBG("keyshort_k1:%d", thr->basic.keyshort_k1); FTS_TEST_DBG("keyshort_cb_max:%d", thr->basic.keyshort_cb_max); FTS_TEST_DBG("rawdata2_min:%d", thr->basic.rawdata2_min); FTS_TEST_DBG("rawdata2_max:%d", thr->basic.rawdata2_max); print_buffer(thr->rawdata_min, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->rawdata_max, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->cb_min, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->cb_max, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->rawdata2_min, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->rawdata2_max, tdata->node.node_num, tdata->node.rx_num); } static int ini_init_test_incell(void) { int ret = 0; ret = get_test_item_incell(); if (ret < 0) { FTS_TEST_SAVE_ERR("get incell test item fail\n"); return ret; } ret = get_test_threshold_incell(); if (ret < 0) { FTS_TEST_SAVE_ERR("get incell threshold fail\n"); return ret; } print_thr_incell(); return 0; } /* mc_sc */ static int get_test_item_mc_sc(void) { int ret = 0; char item_name[][MAX_KEYWORD_NAME_LEN] = TEST_ITEM_MC_SC; int length = sizeof(item_name) / MAX_KEYWORD_NAME_LEN; int item_val = 0; ret = get_test_item(item_name, length, &item_val); if (ret < 0) { FTS_TEST_SAVE_ERR("get test item fail\n"); return ret; } fts_ftest->ic.mc_sc.u.tmp = item_val; FTS_TEST_INFO("test item:0x%x in ini", fts_ftest->ic.mc_sc.u.tmp); return 0; } static char bthr_name_mc_sc[][MAX_KEYWORD_NAME_LEN] = BASIC_THRESHOLD_MC_SC; static int get_test_threshold_mc_sc(void) { int ret = 0; int length = sizeof(bthr_name_mc_sc) / MAX_KEYWORD_NAME_LEN; struct fts_test *tdata = fts_ftest; struct mc_sc_threshold *thr = &tdata->ic.mc_sc.thr; int node_num = tdata->node.node_num; int sc_num = tdata->sc_node.node_num; tdata->basic_thr_count = sizeof(struct mc_sc_threshold_b) / sizeof(int); /* get standard basic threshold */ ret = get_basic_threshold(bthr_name_mc_sc, length, (int *)&thr->basic); if (ret < 0) { FTS_TEST_SAVE_ERR("get basic thr fail\n"); return ret; } /* basic special set by ic */ if (tdata->func->param_init) { ret = tdata->func->param_init(); if (ret < 0) { FTS_TEST_SAVE_ERR("special basic thr init fail\n"); return ret; } } /* init buffer */ fts_init_buffer(thr->rawdata_h_min, thr->basic.rawdata_h_min, node_num); fts_init_buffer(thr->rawdata_h_max, thr->basic.rawdata_h_max, node_num); if (tdata->func->rawdata2_support) { fts_init_buffer(thr->rawdata_l_min, thr->basic.rawdata_l_min, node_num); fts_init_buffer(thr->rawdata_l_max, thr->basic.rawdata_l_max, node_num); } fts_init_buffer(thr->tx_linearity_max, thr->basic.uniformity_tx_hole, node_num); fts_init_buffer(thr->tx_linearity_min, 0, node_num); fts_init_buffer(thr->rx_linearity_max, thr->basic.uniformity_rx_hole, node_num); fts_init_buffer(thr->rx_linearity_min, 0, node_num); fts_init_buffer(thr->scap_cb_off_min, thr->basic.scap_cb_off_min, sc_num); fts_init_buffer(thr->scap_cb_off_max, thr->basic.scap_cb_off_max, sc_num); fts_init_buffer(thr->scap_cb_on_min, thr->basic.scap_cb_on_min, sc_num); fts_init_buffer(thr->scap_cb_on_max, thr->basic.scap_cb_on_max, sc_num); fts_init_buffer(thr->scap_rawdata_off_min, thr->basic.scap_rawdata_off_min, sc_num); fts_init_buffer(thr->scap_rawdata_off_max, thr->basic.scap_rawdata_off_max, sc_num); fts_init_buffer(thr->scap_rawdata_on_min, thr->basic.scap_rawdata_on_min, sc_num); fts_init_buffer(thr->scap_rawdata_on_max, thr->basic.scap_rawdata_on_max, sc_num); fts_init_buffer(thr->panel_differ_min, thr->basic.panel_differ_min, node_num); fts_init_buffer(thr->panel_differ_max, thr->basic.panel_differ_max, node_num); /* detail threshold */ get_detail_threshold("RawData_Min_High_Tx", true, thr->rawdata_h_min); get_detail_threshold("RawData_Max_High_Tx", true, thr->rawdata_h_max); if (tdata->func->rawdata2_support) { get_detail_threshold("RawData_Min_Low_Tx", true, thr->rawdata_l_min); get_detail_threshold("RawData_Max_Low_Tx", true, thr->rawdata_l_max); } get_detail_threshold("Tx_Linearity_Max_Tx", true, thr->tx_linearity_max); get_detail_threshold("Rx_Linearity_Max_Tx", true, thr->rx_linearity_max); get_detail_threshold("ScapCB_OFF_Min_", true, thr->scap_cb_off_min); get_detail_threshold("ScapCB_OFF_Max_", true, thr->scap_cb_off_max); get_detail_threshold("ScapCB_ON_Min_", true, thr->scap_cb_on_min); get_detail_threshold("ScapCB_ON_Max_", true, thr->scap_cb_on_max); get_detail_threshold("ScapRawData_OFF_Min_", true, thr->scap_rawdata_off_min); get_detail_threshold("ScapRawData_OFF_Max_", true, thr->scap_rawdata_off_max); get_detail_threshold("ScapRawData_ON_Min_", true, thr->scap_rawdata_on_min); get_detail_threshold("ScapRawData_ON_Max_", true, thr->scap_rawdata_on_max); get_detail_threshold("Panel_Differ_Min_Tx", true, thr->panel_differ_min); get_detail_threshold("Panel_Differ_Max_Tx", true, thr->panel_differ_max); return 0; } static void print_thr_mc_sc(void) { struct fts_test *tdata = fts_ftest; struct mc_sc_threshold *thr = &tdata->ic.mc_sc.thr; FTS_TEST_DBG("rawdata_h_min:%d", thr->basic.rawdata_h_min); FTS_TEST_DBG("rawdata_h_max:%d", thr->basic.rawdata_h_max); FTS_TEST_DBG("rawdata_set_hfreq:%d", thr->basic.rawdata_set_hfreq); FTS_TEST_DBG("rawdata_l_min:%d", thr->basic.rawdata_l_min); FTS_TEST_DBG("rawdata_l_max:%d", thr->basic.rawdata_l_max); FTS_TEST_DBG("rawdata_set_lfreq:%d", thr->basic.rawdata_set_lfreq); FTS_TEST_DBG("uniformity_check_tx:%d", thr->basic.uniformity_check_tx); FTS_TEST_DBG("uniformity_check_rx:%d", thr->basic.uniformity_check_rx); FTS_TEST_DBG("uniformity_check_min_max:%d", thr->basic.uniformity_check_min_max); FTS_TEST_DBG("uniformity_tx_hole:%d", thr->basic.uniformity_tx_hole); FTS_TEST_DBG("uniformity_rx_hole:%d", thr->basic.uniformity_rx_hole); FTS_TEST_DBG("uniformity_min_max_hole:%d", thr->basic.uniformity_min_max_hole); FTS_TEST_DBG("scap_cb_off_min:%d", thr->basic.scap_cb_off_min); FTS_TEST_DBG("scap_cb_off_max:%d", thr->basic.scap_cb_off_max); FTS_TEST_DBG("scap_cb_wp_off_check:%d", thr->basic.scap_cb_wp_off_check); FTS_TEST_DBG("scap_cb_on_min:%d", thr->basic.scap_cb_on_min); FTS_TEST_DBG("scap_cb_on_max:%d", thr->basic.scap_cb_on_max); FTS_TEST_DBG("scap_cb_wp_on_check:%d", thr->basic.scap_cb_wp_on_check); FTS_TEST_DBG("scap_rawdata_off_min:%d", thr->basic.scap_rawdata_off_min); FTS_TEST_DBG("scap_rawdata_off_max:%d", thr->basic.scap_rawdata_off_max); FTS_TEST_DBG("scap_rawdata_wp_off_check:%d", thr->basic.scap_rawdata_wp_off_check); FTS_TEST_DBG("scap_rawdata_on_min:%d", thr->basic.scap_rawdata_on_min); FTS_TEST_DBG("scap_rawdata_on_max:%d", thr->basic.scap_rawdata_on_max); FTS_TEST_DBG("scap_rawdata_wp_on_check:%d", thr->basic.scap_rawdata_wp_on_check); FTS_TEST_DBG("short_cg:%d", thr->basic.short_cg); FTS_TEST_DBG("short_cc:%d", thr->basic.short_cc); FTS_TEST_DBG("panel_differ_min:%d", thr->basic.panel_differ_min); FTS_TEST_DBG("panel_differ_max:%d", thr->basic.panel_differ_max); print_buffer(thr->rawdata_h_min, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->rawdata_h_max, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->rawdata_l_min, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->rawdata_l_max, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->scap_cb_off_min, tdata->sc_node.node_num, tdata->sc_node.rx_num); print_buffer(thr->scap_cb_off_max, tdata->sc_node.node_num, tdata->sc_node.rx_num); print_buffer(thr->scap_cb_on_min, tdata->sc_node.node_num, tdata->sc_node.rx_num); print_buffer(thr->scap_cb_on_max, tdata->sc_node.node_num, tdata->sc_node.rx_num); print_buffer(thr->scap_rawdata_off_min, tdata->sc_node.node_num, tdata->sc_node.rx_num); print_buffer(thr->scap_rawdata_off_max, tdata->sc_node.node_num, tdata->sc_node.rx_num); print_buffer(thr->scap_rawdata_on_min, tdata->sc_node.node_num, tdata->sc_node.rx_num); print_buffer(thr->scap_rawdata_on_max, tdata->sc_node.node_num, tdata->sc_node.rx_num); print_buffer(thr->panel_differ_min, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->panel_differ_max, tdata->node.node_num, tdata->node.rx_num); } static int ini_init_test_mc_sc(void) { int ret = 0; ret = get_test_item_mc_sc(); if (ret < 0) { FTS_TEST_SAVE_ERR("get mc_sc test item fail\n"); return ret; } ret = get_test_threshold_mc_sc(); if (ret < 0) { FTS_TEST_SAVE_ERR("get mc_sc threshold fail\n"); return ret; } print_thr_mc_sc(); return 0; } /* sc */ static int get_test_item_sc(void) { int ret = 0; char item_name[][MAX_KEYWORD_NAME_LEN] = TEST_ITEM_SC; int length = sizeof(item_name) / MAX_KEYWORD_NAME_LEN; int item_val = 0; ret = get_test_item(item_name, length, &item_val); if (ret < 0) { FTS_TEST_SAVE_ERR("get test item fail\n"); return ret; } fts_ftest->ic.sc.u.tmp = item_val; return 0; } static char bthr_name_sc[][MAX_KEYWORD_NAME_LEN] = BASIC_THRESHOLD_SC; static int get_test_threshold_sc(void) { int ret = 0; int length = sizeof(bthr_name_sc) / MAX_KEYWORD_NAME_LEN; struct fts_test *tdata = fts_ftest; struct sc_threshold *thr = &tdata->ic.sc.thr; int node_num = tdata->node.node_num; tdata->basic_thr_count = sizeof(struct sc_threshold_b) / sizeof(int); /* get standard basic threshold */ ret = get_basic_threshold(bthr_name_sc, length, (int *)&thr->basic); if (ret < 0) { FTS_TEST_SAVE_ERR("get basic thr fail\n"); return ret; } /* basic special set by ic */ if (tdata->func->param_init) { ret = tdata->func->param_init(); if (ret < 0) { FTS_TEST_SAVE_ERR("special basic thr init fail\n"); return ret; } } /* init buffer */ fts_init_buffer(thr->rawdata_min, thr->basic.rawdata_min, node_num); fts_init_buffer(thr->rawdata_max, thr->basic.rawdata_max, node_num); fts_init_buffer(thr->cb_min, thr->basic.cb_min, node_num); fts_init_buffer(thr->cb_max, thr->basic.cb_max, node_num); fts_init_buffer(thr->dcb_sort, 0, node_num); fts_init_buffer(thr->dcb_base, thr->basic.dcb_base, node_num); /* detail threshold */ get_detail_threshold("RawDataTest_Min", false, thr->rawdata_min); get_detail_threshold("RawDataTest_Max", false, thr->rawdata_max); get_detail_threshold("CbTest_Min", false, thr->cb_min); get_detail_threshold("CbTest_Max", false, thr->cb_max); get_detail_threshold("DeltaCxTest_Sort", false, thr->dcb_sort); get_detail_threshold("DeltaCbTest_Base", false, thr->dcb_base); return 0; } static void print_thr_sc(void) { struct fts_test *tdata = fts_ftest; struct sc_threshold *thr = &tdata->ic.sc.thr; FTS_TEST_DBG("rawdata_min:%d", thr->basic.rawdata_min); FTS_TEST_DBG("rawdata_max:%d", thr->basic.rawdata_max); FTS_TEST_DBG("cb_min:%d", thr->basic.cb_min); FTS_TEST_DBG("cb_max:%d", thr->basic.cb_max); FTS_TEST_DBG("dcb_differ_max:%d", thr->basic.dcb_differ_max); FTS_TEST_DBG("dcb_key_check:%d", thr->basic.dcb_key_check); FTS_TEST_DBG("dcb_key_differ_max:%d", thr->basic.dcb_key_differ_max); FTS_TEST_DBG("dcb_ds1:%d", thr->basic.dcb_ds1); FTS_TEST_DBG("dcb_ds2:%d", thr->basic.dcb_ds2); FTS_TEST_DBG("dcb_ds3:%d", thr->basic.dcb_ds3); FTS_TEST_DBG("dcb_ds4:%d", thr->basic.dcb_ds4); FTS_TEST_DBG("dcb_ds5:%d", thr->basic.dcb_ds5); FTS_TEST_DBG("dcb_ds6:%d", thr->basic.dcb_ds6); FTS_TEST_DBG("dcb_critical_check:%d", thr->basic.dcb_critical_check); FTS_TEST_DBG("dcb_cs1:%d", thr->basic.dcb_cs1); FTS_TEST_DBG("dcb_cs2:%d", thr->basic.dcb_cs2); FTS_TEST_DBG("dcb_cs3:%d", thr->basic.dcb_cs3); FTS_TEST_DBG("dcb_cs4:%d", thr->basic.dcb_cs4); FTS_TEST_DBG("dcb_cs5:%d", thr->basic.dcb_cs5); FTS_TEST_DBG("dcb_cs6:%d", thr->basic.dcb_cs6); print_buffer(thr->rawdata_min, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->rawdata_max, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->cb_min, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->cb_max, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->dcb_sort, tdata->node.node_num, tdata->node.rx_num); print_buffer(thr->dcb_base, tdata->node.node_num, tdata->node.rx_num); } static int ini_init_test_sc(void) { int ret = 0; ret = get_test_item_sc(); if (ret < 0) { FTS_TEST_SAVE_ERR("get sc test item fail\n"); return ret; } ret = get_test_threshold_sc(); if (ret < 0) { FTS_TEST_SAVE_ERR("get sc threshold fail\n"); return ret; } print_thr_sc(); return 0; } static u32 ini_get_ic_code(char *ic_name) { int i = 0; int type_size = 0; int ini_icname_len = 0; int ic_types_len = 0; ini_icname_len = strlen(ic_name); type_size = sizeof(ic_types) / sizeof(ic_types[0]); for (i = 0; i < type_size; i++) { ic_types_len = strlen(ic_name); if (ini_icname_len == ic_types_len) { if (0 == strncmp(ic_name, ic_types[i].ic_name, ic_types_len)) return ic_types[i].ic_type; } } FTS_TEST_ERROR("no IC type match"); return 0; } static void ini_init_interface(struct ini_data *ini) { char str[MAX_KEYWORD_VALUE_LEN] = { 0 }; u32 value = 0; struct fts_test *tdata = fts_ftest; /* IC type */ ini_get_string_value("Interface", "IC_Type", str); memcpy(ini->ic_name, str, sizeof(str)); value = ini_get_ic_code(str); ini->ic_code = value; FTS_TEST_INFO("ic name:%s, ic code:%x", ini->ic_name, ini->ic_code); if (IC_HW_MC_SC == tdata->func->hwtype) { get_value_interface("Normalize_Type", &value); tdata->normalize = (u8)value; FTS_TEST_DBG("normalize:%d", tdata->normalize); } } static int ini_init_test(struct ini_data *ini) { int ret = 0; struct fts_test *tdata = fts_ftest; /* interface init */ ini_init_interface(ini); /* node valid */ ret = init_node_valid(); if (ret < 0) { FTS_TEST_ERROR("init node valid fail"); return ret; } switch (tdata->func->hwtype) { case IC_HW_INCELL: ret = ini_init_test_incell(); break; case IC_HW_MC_SC: ret = ini_init_test_mc_sc(); break; case IC_HW_SC: ret = ini_init_test_sc(); break; default: FTS_TEST_SAVE_ERR("test ic type(%d) fail\n", tdata->func->hwtype); ret = -EINVAL; break; } return ret; } /* * fts_test_get_testparam_from_ini - get test parameters from ini * * read, parse the configuration file, initialize the test variable * * return 0 if succuss, else errro code */ int fts_test_get_testparam_from_ini(char *config_name) { int ret = 0; int inisize = 0; struct ini_data *ini = &fts_ftest->ini; inisize = fts_test_get_ini_size(config_name); FTS_TEST_DBG("ini file size:%d", inisize); if (inisize <= 0) { FTS_TEST_ERROR("get ini file size fail"); return -ENODATA; } ini->data = vmalloc(inisize + 1); if (NULL == ini->data) { FTS_TEST_ERROR("malloc memory for ini data fail"); return -ENOMEM; } memset(ini->data, 0, inisize + 1); ini->length = inisize + 1; ini->keyword_num_total = 0; ini->section_num = 0; ini->tmp = vmalloc(sizeof(struct ini_keyword) * MAX_KEYWORD_NUM); if (NULL == ini->tmp) { FTS_TEST_ERROR("malloc memory for ini tmp fail"); ret = -ENOMEM; goto ini_tmp_err; } memset(ini->tmp, 0, sizeof(struct ini_keyword) * MAX_KEYWORD_NUM); ret = fts_test_read_ini_data(config_name, ini->data); if (ret) { FTS_TEST_ERROR("read ini file fail"); goto get_inidata_err; } ini->data[inisize] = '\n'; /* last line is null line */ /* parse ini data to get keyword name&value */ ret = ini_init_inidata(ini); if (ret < 0) { FTS_TEST_ERROR("ini_init_inidata fail"); goto get_inidata_err; } /* parse threshold & test item */ ret = ini_init_test(ini); if (ret < 0) { FTS_TEST_ERROR("ini init fail"); goto get_inidata_err; } ret = 0; get_inidata_err: if (ini->tmp) { vfree(ini->tmp); ini->tmp = NULL; } ini_tmp_err: if (ini->data) { vfree(ini->data); ini->data = NULL; } return ret; }