blob: 2d255e90cde83ed0fe94e16c32ab6f3b9d21b45b [file] [log] [blame]
/************************************************************************
* Copyright (C) 2012-2018, Focaltech Systems (R)£¬All Rights Reserved.
*
* File Name: focaltech_test_ini.c
*
* Author: Focaltech Driver Team
*
* Created: 2016-08-01
*
* Abstract: parsing function of INI file
*
************************************************************************/
#include "focaltech_test.h"
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
/* '[' ']':Section Symbol-Can be defined according to the special need to change */
const char CFG_SSL = '[';
const char CFG_SSR = ']';
const char CFG_NIS = ':'; /* Separator between name and index */
const char CFG_NTS = '#'; /* annotator */
const char CFG_EQS = '='; /* The equal sign */
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
/* Works only for digits and letters, but small and fast */
#define TOLOWER(x) ((x) | 0x20)
int fts_strncmp(const char *cs, const char *ct, size_t count)
{
u8 c1 = 0, c2 = 0;
while (count) {
c1 = TOLOWER(*cs++);
c2 = TOLOWER(*ct++);
if (c1 != c2)
return c1 < c2 ? -1 : 1;
if (!c1)
break;
count--;
}
return 0;
}
/*************************************************************
Function: Get the value of key
Input: char * filedata; char * section; char * key
Output: char * value¡¡key
Return: 0 SUCCESS
-1 can not find section
-2 can not find key
-10 File open failed
-12 File read failed
-14 File format error
-22 Out of buffer size
Note:
*************************************************************/
int ini_get_key(char *filedata, char *section, char *key, char *value)
{
int i = 0;
int ret = -2;
for (i = 0; i < test_data.ini_keyword_num; i++) {
if (fts_strncmp(section, test_data.ini_data[i].section_name,
test_data.ini_data[i].section_name_len) != 0)
continue;
//FTS_TEST_DBG("Section Name:%s, Len:%d\n", test_data.ini_data[i].section_name, test_data.ini_data[i].section_name_len);
if (strlen(key) == test_data.ini_data[i].key_name_len) {
if (fts_strncmp(key, test_data.ini_data[i].key_name, test_data.ini_data[i].key_name_len) == 0)
//test_data.ini_data[i].key_name_len) == 0)
{
memcpy(value, test_data.ini_data[i].key_value, test_data.ini_data[i].key_value_len);
ret = 0;
break;
}
}
}
return ret;
}
/*************************************************************
Function: Remove empty character on the right side of the string
Input: char * buf --String pointer
Output:
Return: String pointer
Note:
*************************************************************/
char *ini_str_trim_r(char *buf)
{
int len, i;
char tmp[MAX_CFG_BUF_LINE_LEN] = { 0 };
memset(tmp, 0, sizeof(tmp));
len = strlen(buf);
if (len > MAX_CFG_BUF_LINE_LEN) {
FTS_TEST_SAVE_ERR("%s:buf len(%d) fail\n", __func__, len);
return NULL;
}
memset(tmp, 0x00, len);
for (i = 0; i < len; i++) {
if (buf[i] != ' ')
break;
}
if (i < len) {
strncpy(tmp, (buf + i), (len - i));
}
strncpy(buf, tmp, len);
return buf;
}
/*************************************************************
Function: Remove empty character on the left side of the string
Input: char * buf --String pointer
Output:
Return: String pointer
Note:
*************************************************************/
char *ini_str_trim_l(char *buf)
{
int len, i;
char tmp[MAX_CFG_BUF_LINE_LEN] = { 0 };
memset(tmp, 0, sizeof(tmp));
len = strlen(buf);
if (len > MAX_CFG_BUF_LINE_LEN) {
FTS_TEST_SAVE_ERR("%s:buf len(%d) fail\n", __func__, len);
return NULL;
}
memset(tmp, 0x00, len);
for (i = 0; i < len; i++) {
if (buf[len - i - 1] != ' ')
break;
}
if (i < len) {
strncpy(tmp, buf, len - i);
}
strncpy(buf, tmp, len);
return buf;
}
/*************************************************************
Function: Read a line from file
Input: FILE *fp; int maxlen-- Maximum length of buffer
Output: char *buffer -- A string
Return: >0 Actual read length
-1 End of file
-2 Error reading file
Note:
*************************************************************/
static int ini_file_get_line(char *filedata, char *buffer, int maxlen)
{
int i = 0;
int j = 0;
int iRetNum = -1;
char ch1 = '\0';
for (i = 0, j = 0; i < maxlen; j++) {
ch1 = filedata[j];
iRetNum = j + 1;
if (ch1 == '\n' || ch1 == '\r') { //line end
ch1 = filedata[j + 1];
if (ch1 == '\n' || ch1 == '\r') {
iRetNum++;
}
break; // line breaks
} else if (ch1 == 0x00) {
iRetNum = -1;
break; //file end
} else {
buffer[i++] = ch1; /* ignore carriage return */
}
}
buffer[i] = '\0';
return iRetNum;
}
int isspace(int x)
{
if (x == ' ' || x == '\t' || x == '\n' || x == '\f' || x == '\b' || x == '\r')
return 1;
else
return 0;
}
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 */
}
int fts_atoi(char *nptr)
{
return (int)fts_atol(nptr);
}
int init_key_data(void)
{
int i = 0;
FTS_TEST_FUNC_ENTER();
test_data.ini_keyword_num = 0;
for (i = 0; i < MAX_KEYWORD_NUM; i++) {
memset(test_data.ini_data[i].section_name, 0, MAX_KEYWORD_NAME_LEN);
memset(test_data.ini_data[i].key_name, 0, MAX_KEYWORD_NAME_LEN);
memset(test_data.ini_data[i].key_value, 0, MAX_KEYWORD_VALUE_LEN);
test_data.ini_data[i].section_name_len = 0;
test_data.ini_data[i].key_name_len = 0;
test_data.ini_data[i].key_value_len = 0;
}
FTS_TEST_FUNC_EXIT();
return 1;
}
int print_key_data(void)
{
int i = 0;
FTS_TEST_DBG("test_data.ini_keyword_num = %d", test_data.ini_keyword_num);
for (i = 0; i < MAX_KEYWORD_NUM; i++) {
FTS_TEST_DBG("section_name_%d:%s, key_name_%d:%s\n,key_value_%d:%s",
i, test_data.ini_data[i].section_name,
i, test_data.ini_data[i].key_name,
i, test_data.ini_data[i].key_value
);
}
return 0;
}
/*************************************************************
Function: Read all the parameters and values to the structure.
Return: Returns the number of key. If you go wrong, return a negative number.
-10 File open failed
-12 File read failed
-14 File format error
Note:
*************************************************************/
int ini_get_key_data(char *filedata)
{
char buf1[MAX_CFG_BUF_LINE_LEN + 1] = {0};
int n = 0;
int ret = 0;
int dataoff = 0;
int iEqualSign = 0;
int i = 0;
char tmsection_name[MAX_CFG_BUF_LINE_LEN + 1] = {0};
FTS_TEST_FUNC_ENTER();
ret = init_key_data();
if (ret < 0) {
FTS_TEST_ERROR("init key data failed");
return -1;
}
test_data.ini_keyword_num = 0;
while (1) { /*find section */
ret = CFG_ERR_READ_FILE;
n = ini_file_get_line(filedata + dataoff, buf1, MAX_CFG_BUF_LINE_LEN);
if (n < -1)
goto cfg_scts_end;
if (n < 0)
break;/* file end */
if (n >= MAX_CFG_BUF_LINE_LEN) {
FTS_TEST_ERROR("Error Length:%d\n", n);
goto cfg_scts_end;
}
dataoff += n;
n = strlen(ini_str_trim_l(ini_str_trim_r(buf1)));
if (n == 0 || buf1[0] == CFG_NTS)
continue; /* A blank line or a comment line */
ret = CFG_ERR_FILE_FORMAT;
//get section name
if (n > 2 && ((buf1[0] == CFG_SSL && buf1[n - 1] != CFG_SSR))) {
FTS_TEST_ERROR("Bad Section:%s\n", buf1);
goto cfg_scts_end;//bad section
}
if (buf1[0] == CFG_SSL) {
test_data.ini_data[test_data.ini_keyword_num].section_name_len = n - 2;
if (MAX_KEYWORD_NAME_LEN < test_data.ini_data[test_data.ini_keyword_num].section_name_len) {
ret = CFG_ERR_OUT_OF_LEN;
FTS_TEST_ERROR("MAX_KEYWORD_NAME_LEN: CFG_ERR_OUT_OF_LEN\n");
goto cfg_scts_end;
}
buf1[n - 1] = 0x00;
strcpy((char *)tmsection_name, buf1 + 1);
continue;
}
//get section name end
strcpy( test_data.ini_data[test_data.ini_keyword_num].section_name, tmsection_name);
test_data.ini_data[test_data.ini_keyword_num].section_name_len = strlen(tmsection_name);
iEqualSign = 0;
for (i = 0; i < n; i++) {
if (buf1[i] == CFG_EQS ) {
iEqualSign = i;
break;
}
}
if (0 == iEqualSign)
continue;
/* before equal sign is assigned to the key name*/
test_data.ini_data[test_data.ini_keyword_num].key_name_len = iEqualSign;
if (MAX_KEYWORD_NAME_LEN < test_data.ini_data[test_data.ini_keyword_num].key_name_len) {
ret = CFG_ERR_OUT_OF_LEN;
FTS_TEST_ERROR("MAX_KEYWORD_NAME_LEN: CFG_ERR_OUT_OF_LEN\n");
goto cfg_scts_end;
}
memcpy(test_data.ini_data[test_data.ini_keyword_num].key_name,
buf1, test_data.ini_data[test_data.ini_keyword_num].key_name_len);
/* After equal sign is assigned to the key value*/
test_data.ini_data[test_data.ini_keyword_num].key_value_len = n - iEqualSign - 1;
if (MAX_KEYWORD_VALUE_LEN < test_data.ini_data[test_data.ini_keyword_num].key_value_len) {
ret = CFG_ERR_OUT_OF_LEN;
FTS_TEST_ERROR("MAX_KEYWORD_VALUE_LEN: CFG_ERR_OUT_OF_LEN\n");
goto cfg_scts_end;
}
memcpy(test_data.ini_data[test_data.ini_keyword_num].key_value,
buf1 + iEqualSign + 1, test_data.ini_data[test_data.ini_keyword_num].key_value_len);
ret = test_data.ini_keyword_num;
test_data.ini_keyword_num++; /*Parameter number accumulation*/
if (MAX_KEYWORD_NUM < test_data.ini_keyword_num) {
ret = CFG_ERR_TOO_MANY_KEY_NUM;
FTS_TEST_ERROR("MAX_KEYWORD_NUM: CFG_ERR_TOO_MANY_KEY_NUM\n");
goto cfg_scts_end;
}
}
FTS_TEST_FUNC_EXIT();
return 0;
cfg_scts_end:
FTS_TEST_FUNC_EXIT();
return ret;
}
int GetPrivateProfileString(char *section, char *ItemName, char *defaultvalue, char *returnValue, char *IniFile)
{
char value[MAX_KEYWORD_VALUE_LEN] = { 0 };
int len = 0;
if (NULL == returnValue) {
FTS_TEST_DBG("return Value==NULL");
return 0;
}
if (ini_get_key(IniFile, section, ItemName, value) < 0) {
if (NULL != defaultvalue)
memcpy(value, defaultvalue, strlen(defaultvalue));
sprintf(returnValue, "%s", value);
return 0;
} else {
len = sprintf(returnValue, "%s", value);
}
return len;
}
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;
}
//Read configuration to memory
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;
}
int init_interface(char *ini)
{
char str[MAX_KEYWORD_VALUE_LEN] = { 0 };
u32 ic_type = 0xFF;
FTS_TEST_FUNC_ENTER();
/* IC type */
GetPrivateProfileString("Interface", "IC_Type", "FT5X36", str, ini);
ic_type = fts_ic_table_get_ic_code_from_ic_name(str);
if (0 == ic_type) {
FTS_TEST_ERROR("get ic code fail");
return -EINVAL;
}
test_data.screen_param.selected_ic = ic_type;
/*Get IC Name*/
sprintf(test_data.ini_ic_name, "%s", str);
FTS_TEST_INFO("IC Name:%s IC Code:0x%02x. ", test_data.ini_ic_name, test_data.screen_param.selected_ic );
/* Normalize Type */
GetPrivateProfileString("Interface", "Normalize_Type" , 0 , str, ini);
test_data.screen_param.normalize = fts_atoi(str);
FTS_TEST_FUNC_EXIT();
return 0;
}
/************************************************************************
* Name: set_param_data
* Brief: load Config. Set IC series, init test items, init basic threshold, int detailThreshold, and set order of test items
* Input: TestParamData, from ini file.
* Output: none
* Return: 0. No sense, just according to the old format.
***********************************************************************/
int set_param_data(char *test_param)
{
int ret = 0;
FTS_TEST_FUNC_ENTER();
test_data.ini_data = (struct _ini_data *)fts_malloc(sizeof(struct _ini_data) * MAX_KEYWORD_NUM);
if (NULL == test_data.ini_data) {
FTS_ERROR("mallock memory for ini_data fail");
goto SET_PARAM_ERR;
}
ret = ini_get_key_data(test_param);
if (ret < 0) {
FTS_TEST_ERROR("ini_get_key_data error.");
return ret;
}
/* Read the selected chip from the configuration */
ret = init_interface(test_param);
if (ret < 0) {
FTS_TEST_ERROR("IC_Type in ini is not supported");
return ret;
}
/* Get test function */
ret = init_test_funcs(test_data.screen_param.selected_ic);
if (ret < 0) {
FTS_TEST_ERROR("no ic series match");
return ret;
}
if (NULL == test_data.func) {
FTS_TEST_ERROR("test function is NULL");
return -ENODATA;
}
/* test configuration */
if (test_data.func->init_testitem) {
test_data.func->init_testitem(test_param);
}
if (test_data.func->init_basicthreshold) {
test_data.func->init_basicthreshold(test_param);
}
if (test_data.func->init_detailthreshold)
test_data.func->init_detailthreshold(test_param);
if (test_data.func->set_testitem_sequence) {
test_data.func->set_testitem_sequence();
}
if (test_data.ini_data) {
fts_free(test_data.ini_data);
}
FTS_TEST_FUNC_EXIT();
return 0;
SET_PARAM_ERR:
if (test_data.ini_data) {
fts_free(test_data.ini_data);
}
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;
char *ini_file_data = NULL;
int inisize = 0;
FTS_TEST_FUNC_ENTER();
inisize = fts_test_get_ini_size(config_name);
FTS_TEST_DBG("ini_size = %d ", inisize);
if (inisize <= 0) {
FTS_TEST_ERROR("%s ERROR:Get firmware size failed", __func__);
return -EIO;
}
ini_file_data = fts_malloc(inisize + 1); // 1: end mark
if (NULL == ini_file_data) {
FTS_TEST_ERROR("fts_malloc failed in function:%s", __func__);
return -ENOMEM;
}
memset(ini_file_data, 0, inisize + 1);
ret = fts_test_read_ini_data(config_name, ini_file_data);
if (ret) {
FTS_TEST_ERROR(" - ERROR: fts_test_read_ini_data failed" );
goto GET_INI_DATA_ERR;
} else {
FTS_TEST_DBG("fts_test_read_ini_data successful");
}
ret = set_param_data(ini_file_data);
if (ret) {
FTS_TEST_ERROR("set param data fail");
goto GET_INI_DATA_ERR;
}
if (ini_file_data) {
fts_free(ini_file_data);
}
FTS_TEST_FUNC_EXIT();
return 0;
GET_INI_DATA_ERR:
if (ini_file_data) {
fts_free(ini_file_data);
}
return ret;
}