int32 write_conf_to_nvram(int8 * name, int8 * pc_arr)
{
#ifdef	INI_KO_MODULE
    struct hisi_nve_info_user  info;
#endif
    int32 ret = -1;

#ifndef	INI_KO_MODULE
    ret = hweiOperaNVWR(HISI_CUST_NVRAM_WRITE, HISI_CUST_NVRAM_NUM, HISI_CUST_NVRAM_NAME, HISI_CUST_NVRAM_LEN, pc_arr);
    if (ret < -1) {
        INI_ERROR("write nvm failed");
        return INI_FAILED;
    }
#else
    memset(&info, 0, sizeof(info));
    strncpy(info.nv_name, HISI_CUST_NVRAM_NAME, strlen(HISI_CUST_NVRAM_NAME) - 1);
    info.nv_name[strlen(HISI_CUST_NVRAM_NAME) - 1] = '\0';
    info.nv_number = HISI_CUST_NVRAM_NUM;
    info.valid_size = HISI_CUST_NVRAM_LEN;
    info.nv_operation = HISI_CUST_NVRAM_WRITE;
    memcpy(info.nv_data, pc_arr, HISI_CUST_NVRAM_LEN);

    ret = hisi_nve_direct_access( &info );
    if (ret < -1) {
        INI_ERROR("write nvm failed");
        return INI_FAILED;
    }
#endif

    return INI_SUCC;
}
static int8 * get_ini_file_name(void)
{
#ifndef INI_KO_MODULE
	INI_FILE *fp = NULL;

	if ('\0' != g_ini_file_name[0])
	{
		return g_ini_file_name;
	}

	fp = fopen(INI_NAME_CFG_FILE, "r");
	if (NULL == fp)
	{
		INI_ERROR("open ini cfg file %s failed!!!, error:%s", INI_NAME_CFG_FILE, strerror(errno));
		g_ini_file_name[0] = '\0';
		return g_ini_file_name;
	}

	if(0 == fread(g_ini_file_name, 1, INI_NAME_CFG_LEN,fp))
	{
		INI_ERROR("cant get ini file form cfg file %s, error:%s", INI_NAME_CFG_FILE, strerror(errno));
		g_ini_file_name[0] = '\0';
	}
	fclose(fp);
	return g_ini_file_name;
#else
	return g_st_boardid.ini_file_name;
#endif
}
static int32 ini_check_value(int8 *puc_value)
{
	int32 l_len;

	l_len = strlen(puc_value);
	if (' ' == puc_value[0] || ' ' == puc_value[l_len - 1]
							|| '\n' == puc_value[0])
	{
		puc_value[0] = '\0';
		INI_ERROR("::%s has blank space or is blank::", puc_value);
		return INI_FAILED;
	}

    /* check \n of line */
	if ('\n' == puc_value[l_len - 1])
    {
        puc_value[l_len - 1] = '\0';
    }

    /* check \r of line */
    if ('\r' == puc_value[l_len - 2])
    {
        puc_value[l_len - 2] = '\0';
    }
	return INI_SUCC;
}
int8 * get_ini_file_path(void)
{
    FILE *          fp;
    int32           ret = 0;
    static int32    flag_got_path = 0;

    if(!flag_got_path)
    {
        fp = fopen(INI_FILE_CFG_PATH, "r");
        if (NULL == fp)
        {
            INI_ERROR("open %s failed:%s", INI_FILE_CFG_PATH, strerror(errno));
            return NULL;
        }
        ret = fread( g_ini_file_path, INI_FILE_PATH_LEN, 1, fp);
        if (0 > ret)
        {
            INI_WARNING("read %s failed:%s", INI_FILE_CFG_PATH, strerror(errno));
            fclose(fp);
            return NULL;
        }
        fclose(fp);
        flag_got_path = 1;
    }
    return g_ini_file_path;
}
int32 read_conf_from_file(int8 * name, int8* pc_arr, uint32 size)
{
    INI_FILE * fp;
    int32 len;
    uint32 read_len = 0;

#ifdef INI_KO_MODULE
    fp = filp_open(NVRAM_CUST_FILE, O_RDONLY, 0660);
    if (IS_ERR(fp))
#else
        fp = fopen(NVRAM_CUST_FILE, "r");
    if (NULL == fp)
#endif
    {
#ifdef INI_KO_MODULE
        INI_DEBUG("open %s failed", NVRAM_CUST_FILE);
#else
        INI_DEBUG("open %s failed, errno is %s", NVRAM_CUST_FILE, strerror(errno));
#endif
        return INI_FAILED;
    }

    INI_DEBUG("open %s succ", NVRAM_CUST_FILE);

#ifdef INI_KO_MODULE
    read_len = INI_MIN(size, NUM_OF_NV_PARAMS);
    len = kernel_read(fp, 0, pc_arr, read_len);
#else
    len = fread(pc_arr, 1, HISI_CUST_NVRAM_LEN,  fp);
#endif
    if (len < 0)
    {
        ini_file_close(fp);
#ifdef INI_KO_MODULE
        INI_ERROR("read %s failed, len = %d", NVRAM_CUST_FILE, len);
#else
        INI_ERROR("read %s failed, len = %d, errno is %s", NVRAM_CUST_FILE, len, strerror(errno));
#endif
        return INI_FAILED;
    }
    INI_DEBUG("read %s succ", NVRAM_CUST_FILE);
    ini_file_close(fp);

    return INI_SUCC;
}
static int32 ini_find_var(INI_FILE *fp, int32 modu, int8 * puc_var, int8 *puc_value)
{
	int32 ret;
	int8 auc_tmp[MAX_READ_LINE_NUM + 1] = {0};
    size_t search_var_len;

	/* find the modu of var, such as [HOST_WIFI_NORMAL] of wifi moduler*/
    ret = ini_find_modu(fp, modu, puc_var, puc_value);
	if (INI_FAILED == ret)
	{
		return INI_FAILED;
	}

	/* find the var in modu, such as [HOST_WIFI_NORMAL] of wifi moduler*/
	while(1)
	{
        ret = ini_readline_func(fp, auc_tmp);
        if (INI_FAILED == ret)
        {
            INI_ERROR("have end of .ini file!!!");
            return INI_FAILED;
        }

		if ('[' == auc_tmp[0])
		{
			INI_ERROR("not find %s!!!, check if var in correct mode", puc_var);
			return INI_FAILED;
		}

        search_var_len = strlen(puc_var);
        ret = ini_check_str(fp, auc_tmp, puc_var);
        if (INI_SUCC == ret)
        {
            //INI_DEBUG("have found %s", puc_var);
            /* note coverity check !!!*/
            strcpy(puc_value, &auc_tmp[search_var_len+1]);
            break;
        }
        else
        {
            continue;
        }
	}
	return INI_SUCC;
}
static int32 ko_read_line(INI_FILE *fp, char *addr) 
{
	int32 l_ret;
	int8 auc_tmp[MAX_READ_LINE_NUM + 1];
	int32 cnt = 0;

	memset(auc_tmp, 0, MAX_READ_LINE_NUM + 1);
	l_ret = kernel_read(fp, fp->f_pos, auc_tmp, MAX_READ_LINE_NUM);
	if (0 > l_ret)
	{
		INI_ERROR("kernel_line read l_ret < 0");
		return INI_FAILED;
	}
	else if (0 == l_ret)
	{
		/*end of file*/
		return 0;
	}

	cnt = 0;
	while (('\n' != auc_tmp[cnt])&&(cnt < MAX_READ_LINE_NUM))
	{
		*addr++ = auc_tmp[cnt];	
		cnt++;
	}

    if (MAX_READ_LINE_NUM != cnt)
    {
        *addr = '\n';
	}
	else
	{
		INI_ERROR("ko read_line is unexpected");
		return INI_FAILED;
	}
	
    /* change file pos to next line */
	fp->f_pos += (cnt + 1);

	return l_ret;
}
/******************************************************************************
 *  Prototype    : ini_readline_func
 *  Description  : set f_pos in curr file ptr
 *  Input        : INI_FILE *fp, int16 fp_pos
 *  Output       :
 *
 *  Return Value : int32
 *  Calls        :
 *  Called By    :
 *
 *  History		 :
 *  1.Date       : 2013/11/11
 *      Author       : zwx144390
 *      Modification : Created function
 *
 *****************************************************************************/
static int32 ini_readline_func(INI_FILE *fp, int8 * rd_buf) 
{
	int8 auc_tmp[MAX_READ_LINE_NUM + 1];
    int32 l_ret;

    memset(auc_tmp, 0, MAX_READ_LINE_NUM);
#ifdef INI_KO_MODULE
    l_ret = ko_read_line(fp, auc_tmp);

    if (INI_FAILED == l_ret)
    {
        INI_ERROR("ko_read_line failed!!!");
        return INI_FAILED;
    }
    else if (0 == l_ret)
    {
        INI_ERROR("end of .ini file!!!");
        return INI_FAILED;
    }
#else
    int8* pau_ret;

    if (feof(fp))
    {
        INI_ERROR("have end of .ini file!!!");
        return INI_FAILED;
    }
    pau_ret = NULL;
    pau_ret = fgets(auc_tmp, MAX_READ_LINE_NUM, fp);
    if (NULL == pau_ret)
    {
        INI_ERROR("have end of .ini file!!!");
        return INI_FAILED;
    }
#endif
    strncpy(rd_buf, auc_tmp, MAX_READ_LINE_NUM);
    rd_buf[MAX_READ_LINE_NUM] = '\0';
    return INI_SUCC;
}
int32 read_conf_from_nvram(int8 * name, int8 * pc_out, uint32 size)
{
#ifdef	INI_KO_MODULE
    struct hisi_nve_info_user  info;
    uint32 len = 0;
#endif
#ifndef	INI_KO_MODULE
    int8 buff[HISI_CUST_NVRAM_LEN] = {0};
#endif
    int32 ret = -1;

#ifndef	INI_KO_MODULE
    ret = hweiOperaNVWR(HISI_CUST_NVRAM_READ, HISI_CUST_NVRAM_NUM, HISI_CUST_NVRAM_NAME, HISI_CUST_NVRAM_LEN, buff);
    if (ret < -1) {
        INI_ERROR("read nvm failed");
        return INI_FAILED;
    }
#else
    memset(&info, 0, sizeof(info));
    strncpy(info.nv_name, HISI_CUST_NVRAM_NAME, strlen(HISI_CUST_NVRAM_NAME) - 1);
    info.nv_name[strlen(HISI_CUST_NVRAM_NAME) - 1] = '\0';
    info.nv_number = HISI_CUST_NVRAM_NUM;
    info.valid_size = HISI_CUST_NVRAM_LEN;
    info.nv_operation = HISI_CUST_NVRAM_READ;

    ret = hisi_nve_direct_access( &info );
    if (ret < -1) {
        INI_ERROR("read nvm failed");
        return INI_FAILED;
    }
    else
    {
        len = INI_MIN(size, NUM_OF_NV_PARAMS);
        memcpy(pc_out, info.nv_data, len);
    }
#endif
    return INI_SUCC;
}
int32 ini_write_var_value(int32 modu, int8 * puc_var, int8 * puc_value)
{
	INI_FILE *fp = NULL;
	int32 l_ret;

	if (NULL == puc_var || '\0' == puc_var[0] || NULL == puc_value )
	{
		INI_ERROR("check if puc_var and puc_value is NULL or blank");
		return INI_FAILED;
	}

    if (0 == init_mutex_flag)
    {
        INI_INIT_MUTEX(&file_mutex, NULL);
        init_mutex_flag = 1;
    }

    INI_MUTEX_LOCK(&file_mutex);
	fp = ini_file_open(INI_FILE_PATH, "r+");
	if (0 == fp)
	{
		INI_ERROR("open %s failed!!!", INI_FILE_PATH);
        INI_MUTEX_UNLOCK(&file_mutex);
		return INI_FAILED;
	}

	l_ret = ini_write_mode_value(fp, modu, puc_var, puc_value);
	if (INI_FAILED == l_ret)
	{
		ini_file_close(fp);
        INI_MUTEX_UNLOCK(&file_mutex);
		return INI_FAILED;
	}

	ini_file_close(fp);
    INI_MUTEX_UNLOCK(&file_mutex);
	return INI_SUCC;
}
static int __init ini_cfg_init(void)
{

	int8 auc_value[20];

#ifdef CONFIG_HWCONNECTIVITY
    if (!isMyConnectivityChip(CHIP_TYPE_HI110X)) {
        INI_ERROR("cfg ini chip type is not match, skip driver init");
        return -EINVAL;
    } else {
        INI_INFO("cfg init type is matched with hi110x, continue");
    }
#endif

	INI_DEBUG("k3v2 .ini config search init!\n");

    /*init mutex*/
    INI_INIT_MUTEX(&file_mutex);

#ifdef INI_TEST
#if 1
	ini_find_var_value(INI_MODU_WIFI, "wifi_ini_mode", auc_value);
	ini_find_var_value(INI_MODU_GNSS, "gnss_ini_mode", auc_value);
	ini_find_var_value(INI_MODU_BT, "bt_ini_mode", auc_value);
	ini_find_var_value(INI_MODU_FM, "fm_ini_mode", auc_value);
	ini_find_var_value(INI_MODU_WIFI_PLAT, "wifi_plat_ini_mode", auc_value);
	ini_find_var_value(INI_MODU_BFG_PLAT, "bfg_plat_ini_mode", auc_value);

	ini_find_var_value(INI_MODU_WIFI, "loglevel", auc_value);
	ini_find_var_value(INI_MODU_WIFI, "data_rate_down", auc_value);
	ini_find_var_value(INI_MODU_WIFI, "data_rate_up", auc_value);

	ini_find_var_value(INI_MODU_GNSS, "gnss_gpsglonass", auc_value);
	ini_find_var_value(INI_MODU_GNSS, "gnss_bdgps", auc_value);

	ini_find_var_value(INI_MODU_BT, "bt_normal", auc_value);

	ini_find_var_value(INI_MODU_FM, "fm_normal", auc_value);

	ini_find_var_value(INI_MODU_WIFI_PLAT, "wifi_plat_normal", auc_value);
	
	ini_find_var_value(INI_MODU_BFG_PLAT, "bfg_plat_normal", auc_value);

#endif 
#endif 

	return INI_SUCC;
}
int32 set_cust_conf_string(int32 modu, int8 * name, int8 * var)
{
    int32 ret = -1;
    if (modu != CUST_MODU_NVRAM)
    {
        INI_ERROR("NOT SUPPORT MODU TO WRITE");
        return INI_FAILED;
    }

    #ifdef HISI_NVRAM_SUPPORT
    ret = write_conf_to_nvram(name, var);
    #else
    ret = write_conf_to_file(name, var);
    #endif

    return ret;
}
static int32 ini_file_seek(INI_FILE *fp, long fp_pos)
{
#ifdef INI_KO_MODULE
    fp->f_pos += fp_pos;
    return INI_SUCC;
#else
    if (INI_FAILED == fseek(fp, fp_pos, SEEK_CUR))
    {
        INI_ERROR("fseek failed, fp_pos is %ld; errno is %s", fp_pos, strerror(errno));
        return INI_FAILED;
    }
    else
    {
        return INI_SUCC;
    }
#endif
}
static bool ini_file_exist(int8 *file_path)
{
    INI_FILE *fp = NULL;

    if (NULL == file_path)
    {
        INI_ERROR("para file_path is NULL\n");
        return false;
    }

    fp = ini_file_open(file_path, "rt");
    if (NULL == fp)
    {
        INI_DEBUG("%s not exist\n", file_path);
        return false;
    }

    ini_file_close(fp);

    INI_DEBUG("%s exist\n", file_path);

    return true;
}
int32 get_cust_conf_string(int32 modu, int8 * puc_var, int8* puc_value, uint32 size)
{
    int32 ret = 0;

#ifdef INI_KO_MODULE
    struct device_node *np;
    int32  len;
    int8   out_str[HISI_CUST_NVRAM_LEN] = {0};
#endif

    switch (modu)
    {
#ifdef INI_KO_MODULE
        case CUST_MODU_DTS:
        {
            np = of_find_compatible_node(NULL, NULL, CUST_COMP_NODE);
            if (NULL == np)
            {
                INI_ERROR("no compatible node found");
                return INI_FAILED;
            }

            //ret = of_property_read_string(np, puc_var, (const char **)&out_str);
            len = of_property_count_u8_elems(np, puc_var);
            if (len < 0)
            {
                INI_ERROR("can't get len of value(%s)", puc_var);
                return INI_FAILED;
            }
            len = INI_MIN(len, NUM_OF_NV_PARAMS);
            INI_DEBUG("get len of value(%s), read len is %d", puc_var, len);
            ret = of_property_read_u8_array(np, puc_var, out_str, len);
            if (0 > ret)
            {
                INI_ERROR("conf str:%s property is not found", puc_var);
                return INI_FAILED;
            }
            //strncpy(puc_value, out_str, INI_FILE_PATH_LEN);
            memcpy(puc_value, out_str, len);
            INI_DEBUG("conf string:%s get value:%s", puc_var, puc_value);
            return INI_SUCC;
        }
#endif
        case CUST_MODU_NVRAM:
            #ifdef HISI_NVRAM_SUPPORT
            ret = read_conf_from_nvram(puc_var, puc_value, size);
            #else
            ret = read_conf_from_file(puc_var, puc_value, size);
            #endif
            if (ret < 0)
            {
                INI_ERROR("read nv_conf failed, ret(%d)", ret);
                return INI_FAILED;
            }
            return INI_SUCC;

        default:
        {
            return ini_find_var_value(modu, puc_var, puc_value, size);
        }
    }
    return INI_SUCC;
}
 int32 ini_config_init(int32 modu)
 {
     int8  log_status[10] = {0};
     int32 log_value;
	 int32 l_ret = INI_FAILED;
     INI_FILE *fp = NULL;
	/* init only once */

	if (INI_MODU_PLAT != modu)
    {
        if (NULL == INI_FILE_PATH)
        {
            INI_ERROR("didn't get ini file path!!!");
            return INI_FAILED;
        }
		strncpy(gac_file, INI_FILE_PATH, INI_VAR_FILE_LEN);
		gac_file[INI_VAR_FILE_LEN] = '\0';
		return INI_SUCC;
	}

	INI_DEBUG("open ini file:%s", gac_file);
	fp = ini_file_open(gac_file, "rt");
	if (0 == fp)
	{
		INI_ERROR("open %s failed!!!", gac_file);
        return INI_FAILED;
	}
    INI_DEBUG("open %s succ!", gac_file);

	l_ret = ini_find_var(fp, INI_MODU_PLAT, INI_VAR_LOG_CFG_STATUS, log_status);
	if (INI_FAILED == l_ret)
	{
		ini_file_close(fp);
		return INI_FAILED;
	}

	if (INI_FAILED == ini_check_value(log_status))
	{
		ini_file_close(fp);
		return INI_FAILED;
	}
	sscanf(log_status, "%d", &log_value);
	if (0 > log_value)
	{
		INI_ERROR("log_status value=%d not support!!!", log_value);
		ini_file_close(fp);
		return INI_FAILED;
	}
	INI_INFO("::log_status value=%d::", log_value);
	ini_file_close(fp);
#if 0
	if (INI_VAR_CFG_ENABLE == log_value)
	{
		fp = ini_file_open(INI_FILE_PATH, "rt");
		if (0 == fp)
		{
			INI_ERROR("open %s failed!!!", INI_FILE_PATH);
			return INI_FAILED;
		}

		l_ret = ini_find_var(fp, INI_MODU_PLAT, INI_VAR_LOG_CFG_FILE, gac_cfg_file);
		if (INI_FAILED == l_ret)
		{
			ini_file_close(fp);
			return INI_FAILED;
		}
		if (INI_FAILED == ini_check_value(gac_cfg_file))
		{
			ini_file_close(fp);
			return INI_FAILED;
		}
		//INI_DEBUG("::gac_cfg_file = %s::", gac_cfg_file);
		strncpy(gac_file, gac_cfg_file, INI_VAR_FILE_LEN);
		gac_file[INI_VAR_FILE_LEN] = '\0';
		if (INI_FAILED == access(gac_file, 0))
		{
			INI_ERROR("%s is not exist, init log control system", gac_file);
			l_ret = system("/system/bin/set_log_hisi -S init");
			if (INI_SUCC!= l_ret)
			{
				INI_ERROR("system() run err");
				ini_file_close(fp);
				return INI_FAILED;
			}
		}
	}
	ini_file_close(fp);
#endif

	return INI_SUCC;
 }
int32 ini_find_var_value(int32 modu, int8 * puc_var, int8* puc_value)
{
	INI_FILE *fp = NULL;
    
#ifdef INI_KO_MODULE
	static int32 sl_once = 1;
#endif
#ifdef INI_TIME_TEST
	struct timeval tv[2];
#endif

	int32 l_ret;

	if (NULL == puc_var || '\0' == puc_var[0] || NULL == puc_value)
	{
		INI_ERROR("check if puc_var and puc_value is NULL or blank");
		return INI_FAILED;
	}

#ifdef INI_TIME_TEST
	do_gettimeofday(&tv[0]);
#endif

#ifndef INI_KO_MODULE
    if (0 == init_mutex_flag)
    {
        INI_INIT_MUTEX(&file_mutex, NULL);
        init_mutex_flag = 1;
    }
#endif

    INI_MUTEX_LOCK(&file_mutex);

	strncpy(gac_file, INI_FILE_PATH, INI_VAR_FILE_LEN);
	gac_file[INI_VAR_FILE_LEN] = '\0';
#ifndef INI_KO_MODULE
    l_ret = ini_config_init(modu);
    if (INI_FAILED == l_ret)
    {
        INI_MUTEX_UNLOCK(&file_mutex);
        return INI_FAILED;
    }
#endif

	fp = ini_file_open(gac_file, "rt");
	if (0 == fp)
	{
		fp = NULL;
		INI_ERROR("open %s failed!!!", INI_FILE_PATH);
        INI_MUTEX_UNLOCK(&file_mutex);
		return INI_FAILED;
	}
#ifdef INI_KO_MODULE
	/* init g_board_version.board_version and g_param_version.param_version
	 * just once while call ini_find_var_value */
	if (sl_once)
	{
		int8 version_buff[32] = {0};

		INI_DEBUG("sl_once = %d", sl_once);
		sl_once = 0;
		l_ret = ini_find_var(fp, INI_MODU_PLAT, INI_VAR_PLAT_BOARD, version_buff);
		if (INI_FAILED == l_ret)
		{
			version_buff[0] = '\0';
			ini_file_close(fp);
            INI_MUTEX_UNLOCK(&file_mutex);
			return INI_FAILED;
		}
		if (INI_FAILED == ini_check_value(version_buff))
		{
			ini_file_close(fp);
            INI_MUTEX_UNLOCK(&file_mutex);
			return INI_FAILED;
		}
		memset(g_board_version.board_version, 0, sizeof(g_board_version.board_version));
		strncpy(g_board_version.board_version, version_buff, sizeof(g_board_version.board_version) - 1);
		INI_DEBUG("::g_board_version.board_version = %s::", g_board_version.board_version);
		fp->f_pos = 0;

		l_ret = ini_find_var(fp, INI_MODU_PLAT, INI_VAR_PLAT_PARAM, version_buff);
		if (INI_FAILED == l_ret)
		{
			version_buff[0] = '\0';
			ini_file_close(fp);
            INI_MUTEX_UNLOCK(&file_mutex);
			return INI_FAILED;
		}
		if (INI_FAILED == ini_check_value(version_buff))
		{
			ini_file_close(fp);
            INI_MUTEX_UNLOCK(&file_mutex);
			return INI_FAILED;
		}
		INI_DEBUG("::g_param_version.param_version = %s::", g_param_version.param_version);
		memset(g_param_version.param_version, 0, sizeof(g_param_version.param_version));
		strncpy(g_param_version.param_version, version_buff, sizeof(g_param_version.param_version) - 1);
		fp->f_pos = 0;
	}
#endif

	l_ret = ini_find_mode(fp, modu, puc_var, puc_value);
	if (INI_FAILED == l_ret)
	{
        ini_file_close(fp);
        INI_MUTEX_UNLOCK(&file_mutex);
		return INI_FAILED;
	}
	else if (INI_SUCC_MODE_VAR == l_ret)
	{
		INI_DEBUG("::return %s:%s::", puc_var, puc_value);
        ini_file_close(fp);
        INI_MUTEX_UNLOCK(&file_mutex);
		return  ini_check_value(puc_value);
	}
	
	/* find puc_var in .ini return puc_value */
	l_ret = ini_find_var(fp, modu, puc_var, puc_value);
	if (INI_FAILED == l_ret)
	{
		puc_value[0] = '\0';
        ini_file_close(fp);
        INI_MUTEX_UNLOCK(&file_mutex);
		return INI_FAILED;
	}

#ifdef INI_TIME_TEST
	do_gettimeofday(&tv[1]);
	INI_DEBUG("time take = %ld", (tv[1].tv_sec - tv[0].tv_sec) * 1000 + (tv[1].tv_usec - tv[0].tv_usec) / 1000);
#endif

    ini_file_close(fp);
    INI_MUTEX_UNLOCK(&file_mutex);

	/* check blank space of puc_value */
	if (INI_SUCC == ini_check_value(puc_value))
	{
		INI_DEBUG("::return %s:%s::", puc_var, puc_value);
		return INI_SUCC;
	}
	return INI_FAILED;
}
static int32 ini_write_mode_value(INI_FILE *fp, int32 modu, int8 * puc_var, int8 * puc_value)
{
	int32 l_len;
	int32 ret;
	int8 auc_tmp[MAX_READ_LINE_NUM + 1] = {0};
	int8 auc_mode_var[INI_STR_MODU_LEN + 1] = {0};
	int8 *puc_val = NULL;
	int8 auc_change_bin[INI_STR_MODU_LEN * 2 + 1] = {0};
	int8 auc_cmd[INI_STR_MODU_LEN * 4 + 1] = {0};
    int16 search_var_len;

	switch (modu)
	{
		case INI_MODU_WIFI:			 
			strncpy(auc_mode_var, INI_MODE_VAR_WIFI, INI_STR_MODU_LEN);
			if ('0' > puc_value[0] || '2' < puc_value[0])
			{
				INI_ERROR("not support mode!!!");
				return INI_FAILED;
			}
			break;
		case INI_MODU_GNSS:			 
			if ('0' > puc_value[0] || '1' < puc_value[0])
			{
				INI_ERROR("not support mode!!!");
				return INI_FAILED;
			}
			strncpy(auc_mode_var, INI_MODE_VAR_GNSS, INI_STR_MODU_LEN);
			break;
		case INI_MODU_BT:			 
			if ('0' != puc_value[0])
			{
				INI_ERROR("not support mode!!!");
				return INI_FAILED;
			}
			strncpy(auc_mode_var, INI_MODE_VAR_BT, INI_STR_MODU_LEN);
			break;
		case INI_MODU_FM:			 
			if ('0' != puc_value[0])
			{
				INI_ERROR("not support mode!!!");
				return INI_FAILED;
			}
			strncpy(auc_mode_var, INI_MODE_VAR_FM, INI_STR_MODU_LEN);
			break;
		case INI_MODU_WIFI_PLAT:			 
			if ('0' != puc_value[0])
			{
				INI_ERROR("not support mode!!!");
				return INI_FAILED;
			}
			strncpy(auc_mode_var, INI_MODE_VAR_WIFI_PLAT, INI_STR_MODU_LEN);
			break;
		case INI_MODU_BFG_PLAT:			 
			if ('0' != puc_value[0])
			{
				INI_ERROR("not support mode!!!");
				return INI_FAILED;
			}
			strncpy(auc_mode_var, INI_MODE_VAR_BFG_PLAT, INI_STR_MODU_LEN);
			break;
		default :
			INI_ERROR("not suport modu type!!!");
			break;
	}

	while(1)
	{
        ret = ini_readline_func(fp, auc_tmp);
        if (INI_FAILED == ret)
        {
            INI_ERROR("have end of .ini file!!!");
            return INI_FAILED;
        }

		if (NULL != strstr(auc_tmp, INI_STR_WIFI_NORMAL0))
		{
			INI_ERROR("not find %s!!!", auc_mode_var);
			return INI_FAILED;
		}
		
        ret = ini_check_str(fp, auc_tmp, auc_mode_var);
        if (INI_SUCC == ret)
        {
            INI_DEBUG("have found %s", auc_mode_var);
            break;
        }
        else
        {
            continue;
        }
	}

	puc_val = strstr(auc_tmp, "=");
	if (NULL == puc_val)
	{
		INI_ERROR("has not find = in %s", auc_tmp);
		return INI_FAILED;
	}
	if (INI_FAILED == ini_check_value(puc_val + 1))
	{
		INI_ERROR("not support to write :%s:", auc_tmp);
		return INI_FAILED;
	}
	
	l_len = strlen(auc_tmp);
	search_var_len = strlen(puc_var);
    strncpy(&auc_tmp[search_var_len+1], puc_value, 1);

	if (INI_FAILED == fseek(fp, -l_len, SEEK_CUR))
	{
		INI_ERROR("file seek failed!!!");
		return INI_FAILED;
	}
	if (fputs(auc_tmp, fp))
	{
		INI_DEBUG("puc_write_val :%s: ok", auc_tmp);
	}
	
    if (INI_MODU_WIFI == modu)
    {
        if ('0' == puc_value[0])
        {
            strncpy(auc_change_bin, INI_SDIOBIN_NORMAL, INI_STR_MODU_LEN * 2);
        }
        else if ('1' == puc_value[0])
        {
            strncpy(auc_change_bin, INI_SDIOBIN_PERFORMANCE, INI_STR_MODU_LEN * 2);
        }
        else if ('2' == puc_value[0])
        {
            strncpy(auc_change_bin, INI_SDIOBIN_CERTIFY, INI_STR_MODU_LEN * 2);
        }
        else
        {
            INI_ERROR("not support to bin type %s", auc_change_bin);
            return INI_FAILED;
        }
        sprintf(auc_cmd, INI_STR_MODU_LEN * 4,"cp %s %s", auc_change_bin, INI_SDIOBIN_DEFAULT);
        INI_INFO("exct %s", auc_cmd);
        system(auc_cmd);
    }

	return INI_SUCC;
}
int32 ini_find_var_value(int32 modu, int8 * puc_var, int8* puc_value, uint32 size)
{
	INI_FILE *fp = NULL;

#ifdef INI_KO_MODULE
	static int32 sl_once = 1;
#endif
#ifdef INI_TIME_TEST
	struct timeval tv[2];
#endif

	int32 l_ret;

	if (NULL == puc_var || '\0' == puc_var[0] || NULL == puc_value)
	{
		INI_ERROR("check if puc_var and puc_value is NULL or blank");
		return INI_FAILED;
	}

#ifdef INI_TIME_TEST
	do_gettimeofday(&tv[0]);
#endif

#ifndef INI_KO_MODULE
    if (0 == init_mutex_flag)
    {
        INI_INIT_MUTEX(&file_mutex, NULL);
        init_mutex_flag = 1;
    }
#endif

    INI_MUTEX_LOCK(&file_mutex);

#ifndef INI_KO_MODULE
    l_ret = ini_config_init(modu);
    if (INI_FAILED == l_ret)
    {
        INI_MUTEX_UNLOCK(&file_mutex);
        return INI_FAILED;
    }
#endif

	fp = ini_file_open(INI_FILE_PATH, "rt");
	if (0 == fp)
	{
		fp = NULL;
		INI_ERROR("open %s failed!!!", INI_FILE_PATH);
        INI_MUTEX_UNLOCK(&file_mutex);
		return INI_FAILED;
	}
#ifdef INI_KO_MODULE
	/* init g_board_version.board_version and g_param_version.param_version
	 * just once while call ini_find_var_value */
	if (sl_once)
	{
        print_device_version(fp);
        sl_once = 0;
	}
#endif

	l_ret = ini_find_mode(fp, modu, puc_var, puc_value, size);
	if (INI_FAILED == l_ret)
	{
        ini_file_close(fp);
        INI_MUTEX_UNLOCK(&file_mutex);
		return INI_FAILED;
	}
	else if (INI_SUCC_MODE_VAR == l_ret)
	{
		INI_DEBUG("::return %s:%s::", puc_var, puc_value);
        ini_file_close(fp);
        INI_MUTEX_UNLOCK(&file_mutex);
		return  ini_check_value(puc_value);
	}
	
	/* find puc_var in .ini return puc_value */
	l_ret = ini_find_var(fp, modu, puc_var, puc_value, size);
	if (INI_FAILED == l_ret)
	{
		puc_value[0] = '\0';
        ini_file_close(fp);
        INI_MUTEX_UNLOCK(&file_mutex);
		return INI_FAILED;
	}

#ifdef INI_TIME_TEST
	do_gettimeofday(&tv[1]);
	INI_DEBUG("time take = %ld", (tv[1].tv_sec - tv[0].tv_sec) * 1000 + (tv[1].tv_usec - tv[0].tv_usec) / 1000);
#endif

    ini_file_close(fp);
    INI_MUTEX_UNLOCK(&file_mutex);

	/* check blank space of puc_value */
	if (INI_SUCC == ini_check_value(puc_value))
	{
		INI_DEBUG("::return %s:%s::", puc_var, puc_value);
		return INI_SUCC;
	}
	return INI_FAILED;
}
int ini_cfg_init(void)
{
//	int8 auc_value[20];
    int32 ret;
    int8 auc_dts_ini_path[INI_FILE_PATH_LEN]  = {0};
    int8 auc_cust_spec_ini_path[INI_FILE_PATH_LEN] = {0};
    int8 auc_cust_comm_ini_path[INI_FILE_PATH_LEN] = {0};

#ifdef CONFIG_HWCONNECTIVITY
    if (!isMyConnectivityChip(CHIP_TYPE_HI110X)) {
        INI_ERROR("cfg ini chip type is not match, skip driver init");
        return -EINVAL;
    } else {
        INI_INFO("cfg init type is matched with hi110x, continue");
    }
#endif

    INI_DEBUG("hi110x ini config search init!\n");

    ret = get_cust_conf_string(CUST_MODU_DTS, PROC_NAME_INI_FILE_NAME, auc_dts_ini_path, sizeof(auc_dts_ini_path));
    if ( 0 > ret )
    {
        INI_ERROR("can't find dts proc %s\n", PROC_NAME_INI_FILE_NAME);
        return INI_FAILED;
    }

    snprintf(auc_cust_spec_ini_path, sizeof(auc_cust_spec_ini_path), "%s%s", CUST_PATH_SPEC, auc_dts_ini_path);
    snprintf(auc_cust_comm_ini_path, sizeof(auc_cust_comm_ini_path), "%s%s", CUST_PATH_COMM, auc_dts_ini_path);

    /*如果ini文件在cust中,则使用cust中的ini文件,否则使用dts中配置的ini文件*/
    /*recovery 模式下,此时ini文件可能不能访问,这种情况下,使用dts里配置的值为默认值*/
    if (ini_file_exist(auc_cust_spec_ini_path))
    {
        snprintf(g_ini_file_name, sizeof(g_ini_file_name), "%s", auc_cust_spec_ini_path);
        INI_INFO("%s@%s\n", PROC_NAME_INI_FILE_NAME, g_ini_file_name);
    }
    else if (ini_file_exist(auc_cust_comm_ini_path))
    {
        snprintf(g_ini_file_name, sizeof(g_ini_file_name), "%s", auc_cust_comm_ini_path);
        INI_INFO("%s@%s\n", PROC_NAME_INI_FILE_NAME, g_ini_file_name);
    }
    else
    {
        snprintf(g_ini_file_name, sizeof(g_ini_file_name), "%s", auc_dts_ini_path);
        INI_INFO("%s@%s\n", PROC_NAME_INI_FILE_NAME, g_ini_file_name);
    }

    INI_INIT_MUTEX(&file_mutex);

#ifdef INI_TEST
#if 1
	ini_find_var_value(INI_MODU_WIFI, "wifi_ini_mode", auc_value);
	ini_find_var_value(INI_MODU_GNSS, "gnss_ini_mode", auc_value);
	ini_find_var_value(INI_MODU_BT, "bt_ini_mode", auc_value);
	ini_find_var_value(INI_MODU_FM, "fm_ini_mode", auc_value);
	ini_find_var_value(INI_MODU_WIFI_PLAT, "wifi_plat_ini_mode", auc_value);
	ini_find_var_value(INI_MODU_BFG_PLAT, "bfg_plat_ini_mode", auc_value);

	ini_find_var_value(INI_MODU_WIFI, "loglevel", auc_value);
	ini_find_var_value(INI_MODU_WIFI, "data_rate_down", auc_value);
	ini_find_var_value(INI_MODU_WIFI, "data_rate_up", auc_value);

	ini_find_var_value(INI_MODU_GNSS, "gnss_gpsglonass", auc_value);
	ini_find_var_value(INI_MODU_GNSS, "gnss_bdgps", auc_value);

	ini_find_var_value(INI_MODU_BT, "bt_normal", auc_value);

	ini_find_var_value(INI_MODU_FM, "fm_normal", auc_value);

	ini_find_var_value(INI_MODU_WIFI_PLAT, "wifi_plat_normal", auc_value);
	
	ini_find_var_value(INI_MODU_BFG_PLAT, "bfg_plat_normal", auc_value);

#endif 
#endif 

	return INI_SUCC;
}
static int32 ini_find_modu(INI_FILE *fp, int32 modu, int8 * puc_var, int8 *puc_value)
{
	int8 auc_tmp[MAX_READ_LINE_NUM];
	int8 auc_modu[INI_STR_MODU_LEN];
	int32 l_mode_value;
	int32 ret;

	/* check the mode of moduler */
	if (INI_FAILED == ini_check_value(puc_value))
	{
		return INI_FAILED;
	}

	/* INI_MODU_PLAT has no mode*/
	if (INI_MODU_PLAT != modu)
	{
		l_mode_value = puc_value[0] - '0';
		if (10 < l_mode_value || 0 > l_mode_value)
		{
			INI_ERROR("not support value %s", puc_value);
			return INI_FAILED;
		}
	}

	switch (modu)
	{
		case INI_MODU_WIFI:
			/*find mode var*/
			if (INI_MODE_NORMAL	== l_mode_value)
			{
				strncpy(auc_modu, INI_STR_WIFI_NORMAL, INI_STR_MODU_LEN);
			}
			else if (INI_MODE_PERFORMANCE == l_mode_value)
			{
				strncpy(auc_modu, INI_STR_WIFI_PERFORMANCE, INI_STR_MODU_LEN);
			}
			else if (INI_MODE_CERTIFY == l_mode_value)
			{
				strncpy(auc_modu, INI_STR_WIFI_CERTIFY, INI_STR_MODU_LEN);
			}
            else if (INI_MODE_CERTIFY_CE == l_mode_value)
			{
				strncpy(auc_modu, INI_STR_WIFI_CERTIFY_CE, INI_STR_MODU_LEN);
			}

			else
			{
				INI_ERROR("not support mode!!!");
				return INI_FAILED;
			}
			break;
		case INI_MODU_GNSS:
			if (INI_MODE_GPSGLONASS	== l_mode_value)
			{
				strncpy(auc_modu, INI_STR_GNSS_GPSGLONASS, INI_STR_MODU_LEN);
			}
			else if (INI_MODE_BDGPS == l_mode_value)
			{
				strncpy(auc_modu, INI_STR_GNSS_BDGPS, INI_STR_MODU_LEN);
			}
			else
			{
				INI_ERROR("not support mode!!!");
				return INI_FAILED;
			}
			break;
		case INI_MODU_BT:
			strncpy(auc_modu, INI_STR_BT_NORMAL, INI_STR_MODU_LEN);
			break;
		case INI_MODU_FM:
			strncpy(auc_modu, INI_STR_FM_NORMAL, INI_STR_MODU_LEN);
			break;
		case INI_MODU_WIFI_PLAT:
			strncpy(auc_modu, INI_STR_WIFI_PLAT_NORMAL, INI_STR_MODU_LEN);
			break;
		case INI_MODU_BFG_PLAT:
			strncpy(auc_modu, INI_STR_BFG_PLAT_NORMAL, INI_STR_MODU_LEN);
			break;
		case INI_MODU_PLAT:
			strncpy(auc_modu, INI_STR_PLAT, INI_STR_MODU_LEN);
			break;
		case INI_MODU_HOST_VERSION:
		    strncpy(auc_modu, INT_STR_HOST_VERSION, INI_STR_MODU_LEN);
			break;
		case INI_MODU_WIFI_MAC:
		    strncpy(auc_modu, INI_STR_WIFI_MAC, INI_STR_MODU_LEN);
			break;
		case INI_MODU_COEXIST:
		    strncpy(auc_modu, INI_STR_COEXIST, INI_STR_MODU_LEN);
			break;
		default :
			INI_ERROR("not suport modu type!!!");
			break;
	}

	/* find the value of mode var, such as ini_wifi_mode 
	 * every mode except PLAT mode has only one mode var */
	while(1)
	{
        ret = ini_readline_func(fp, auc_tmp);
        if (INI_FAILED == ret)
        {
            INI_ERROR("have end of .ini file!!!");
            return INI_FAILED;
        }

		if (NULL != strstr(auc_tmp, INI_STR_DEVICE_BFG_PLAT))
		{
			INI_ERROR("not find %s!!!", auc_modu);
			return INI_FAILED;
		}

        ret = ini_check_str(fp, auc_tmp, auc_modu);
        if (INI_SUCC == ret)
        {
			INI_DEBUG("have found %s", auc_modu);
			break;
        }
        else
        {
			continue;
        }
	}

	return INI_SUCC;
}
static int32 ini_find_mode(INI_FILE *fp, int32 modu, int8 *puc_var, int8 *puc_value, uint32 size)
{
    int32 ret;
	int8 auc_tmp[MAX_READ_LINE_NUM];
	int8 auc_mode_var[INI_STR_MODU_LEN];
	int8 *puc_val = NULL;

	switch (modu)
	{
		case INI_MODU_WIFI:
			strncpy(auc_mode_var, INI_MODE_VAR_WIFI, INI_STR_MODU_LEN);
			break;
		case INI_MODU_GNSS:
			strncpy(auc_mode_var, INI_MODE_VAR_GNSS, INI_STR_MODU_LEN);
			break;
		case INI_MODU_BT:
			strncpy(auc_mode_var, INI_MODE_VAR_BT, INI_STR_MODU_LEN);
			break;
		case INI_MODU_FM:
			strncpy(auc_mode_var, INI_MODE_VAR_FM, INI_STR_MODU_LEN);
			break;
		case INI_MODU_WIFI_PLAT:
			strncpy(auc_mode_var, INI_MODE_VAR_WIFI_PLAT, INI_STR_MODU_LEN);
			break;
		case INI_MODU_BFG_PLAT:
			strncpy(auc_mode_var, INI_MODE_VAR_BFG_PLAT, INI_STR_MODU_LEN);
			break;
		case INI_MODU_PLAT:
		case INI_MODU_HOST_VERSION:
		case INI_MODU_WIFI_MAC:
		case INI_MODU_COEXIST:
			return INI_SUCC;
			break;
		default :
			INI_ERROR("not suport modu type!!!");
			break;
	}

	while(1)
	{
        ret = ini_readline_func(fp, auc_tmp);
        if (INI_FAILED == ret)
        {
            INI_ERROR("have end of .ini file!!!");
            return INI_FAILED;
        }

		if (NULL != strstr(auc_tmp, INI_STR_DEVICE_BFG_PLAT))
		{
			INI_ERROR("not find %s!!!", auc_mode_var);
			return INI_FAILED;
		}

        ret = ini_check_str(fp, auc_tmp, auc_mode_var);
        if (INI_SUCC == ret)
        {
            INI_DEBUG("have found %s", auc_mode_var);
            break;
        }
        else
        {
            continue;
        }
	}

	puc_val = strstr(auc_tmp, "=");
	if (NULL == puc_val)
	{
		INI_ERROR("has not find = in %s", auc_tmp);
		return INI_FAILED;
	}

	strncpy(puc_value, puc_val + 1, size);
	if (0 == strcmp(auc_mode_var, puc_var))
	{
		return INI_SUCC_MODE_VAR;			
	}
	return INI_SUCC;
}
int32 get_cust_conf_int32(int32 modu, int8 * puc_var, int32* puc_value)
{
    int32  ret = 0;
#ifdef INI_KO_MODULE
    struct device_node * np;
#endif

	switch (modu)
	{
#ifdef INI_KO_MODULE
        case CUST_MODU_DTS:
        {
            np = of_find_compatible_node(NULL, NULL, CUST_COMP_NODE);
            if (NULL == np)
            {
                INI_ERROR("no compatible node found");
                return INI_FAILED;
            }

            ret = of_property_read_u32(np, puc_var, puc_value);
            if (ret < 0)
            {
                /* driver has log, delete this log */
                INI_DEBUG("conf %s is not exist, ret = %d", puc_var, ret);
                return INI_FAILED;
            }

            INI_DEBUG("conf %s get vale:%d", puc_var, *puc_value);
            return INI_SUCC;
        }
#endif
        default:
        {
            int8  out_str[INI_READ_VALUE_LEN] = {0};

            ret = ini_find_var_value(modu, puc_var, out_str, sizeof(out_str));
            if (ret < 0)
            {
                /* ini_find_var_value has error log, delete this log */
                INI_DEBUG("cust modu didn't get var of %s.", puc_var);
                return INI_FAILED;
            }
            if ( !strncmp(out_str, "0x", strlen("0x")) || !strncmp(out_str, "0X", strlen("0X")))
            {
                INI_DEBUG("get hex of:%s.", puc_var);
                ret = sscanf(out_str, "%x", puc_value);
            }
            else
            {
                ret = sscanf(out_str, "%d", puc_value);
            }

	        if(ret < 0)
            {
	            INI_ERROR("%s trans to int failed", puc_var);
                return INI_FAILED;
            }
            INI_DEBUG("conf %s get vale:%d", puc_var, *puc_value);

            return INI_SUCC;
        }
    }
    return INI_SUCC;
}
int32 ini_check_str(INI_FILE *fp, int8 * auc_tmp, int8 * puc_var)
{
    uint16 auc_len;
    uint16 curr_var_len;
    uint16 search_var_len;

    if ((NULL == fp)||(NULL == puc_var)||('\0' == puc_var[0]))
    {
        INI_ERROR("check if puc_var is NULL or blank");
        return INI_FAILED;
    }

    do{
        auc_len = strlen(auc_tmp);
        curr_var_len = 0;

        while ((curr_var_len < MAX_READ_LINE_NUM) && (auc_tmp[curr_var_len] != '\r') && (auc_tmp[curr_var_len] != '\n') &&
                (auc_tmp[curr_var_len] != 0))
        {
            curr_var_len++;
        }

        if (('#' == auc_tmp[0]) || (' ' == auc_tmp[0]) || ('\n' == auc_tmp[0]) || ('\r' == auc_tmp[0]))
        {
            break;
        }
        search_var_len = strlen(puc_var);
        if (search_var_len > curr_var_len)
        {
            search_var_len = curr_var_len;
        }
        if (0 == strncmp(auc_tmp, puc_var, search_var_len))
        {
            return INI_SUCC;
        }
        else
        {
            break;
        }
    }while(0);

    if (INI_FAILED == ini_file_seek(fp, -auc_len))
    {
        INI_ERROR("file seek failed!!!");
        return INI_FAILED;
    }
    if (INI_FAILED == ini_file_seek(fp, curr_var_len+1))
    {
        INI_ERROR("file seek failed!!!");
        return INI_FAILED;
    }
    if (auc_tmp[curr_var_len + 1] == '\n')
    {
        if (INI_FAILED == ini_file_seek(fp, 1))
        {
            INI_ERROR("file seek failed!!!");
            return INI_FAILED;
        }
    }
    return INI_FAILED;
}