/*
 *  Module_4g.c
 *
 *  Created on: 2019-11-29
 *  Update on: 2020-11-26
 *  Author: Eason Yang
 *  Version: V0.07
 */

#include    <sys/types.h>
#include    <sys/stat.h>
#include 	<sys/time.h>
#include 	<sys/timeb.h>
#include 	<sys/ipc.h>
#include 	<sys/shm.h>
#include 	<sys/mman.h>

#include 	<unistd.h>
#include 	<stdarg.h>
#include    <stdio.h>		/*標準輸入輸出定義*/
#include    <stdlib.h>		/*標準函數庫定義*/
#include    <unistd.h>		/*Unix 標準函數定義*/
#include    <fcntl.h>		/*檔控制定義*/
#include    <termios.h>		/*PPSIX 終端控制定義*/
#include    <errno.h>		/*錯誤號定義*/
#include 	<errno.h>
#include 	<string.h>
#include	<time.h>
#include	<ctype.h>
#include	"define.h"

#define DEBUG_INFO(format, args...) StoreLogMsg("[%s:%d][%s][Info] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
#define DEBUG_WARN(format, args...) StoreLogMsg("[%s:%d][%s][Warn] "format, __FILE__, __LINE__, __FUNCTION__, ##args)
#define DEBUG_ERROR(format, args...) StoreLogMsg("[%s:%d][%s][Error] "format, __FILE__, __LINE__, __FUNCTION__, ##args)

#define ARRAY_SIZE(A)		(sizeof(A) / sizeof(A[0]))
#define PASS	1
#define FAIL	-1
#define DONGLE_QUECTEL	1
#define DONGLE_UBLOX	2

// Define Module mode
#define NO_SERVICE		0
#define CDMA			1
#define GMS_GPRS		2
#define WCDMA			3
#define GMS_WCDMA		4
#define TD_SCDMA		5
#define UNKNOW			6

// Define interval
#define SystemInterval				30	// Seconds
#define CheckModemInterval			30	// Seconds
#define CheckSimInterval			30 	// Seconds
#define CheckModemInfoInterval		30	// Seconds
#define CheckConnectionInterval		30 	// Seconds
#define CheckInternetInterval		30	// Seconds
#define DisconnInterval				60 	// Seconds

// Define Telecom mode
#define DISABLE_4G_MODULE	0
#define ENABLE_4G			1

int Check4GModem(void);
int isPppUp(void);
int isReadInfo(void);
int isReadSimInfo(void);
int isReachableInternet(void);
int isModuleUnbind(void);
int isModuleBind(void);
int rstModule(void);
int Load4gConfiguration(void);
int CheckSignalRssi(void);
int at_command(int uart, char* cmd, char* rx);
int openPort(char *tty);
int set_interface_attribs (int fd, int speed, int parity);
int set_blocking (int fd, int should_block);
void trim_s(char *s, unsigned char len);
void substr(char *dest, const char* src, unsigned int start, unsigned int cnt);

char *portName[3] 				= {"/dev/ttyUSB2", "/dev/ttyUSB2", "/dev/ttyACM2"};
char *valid_Internet[2] 		= {"8.8.8.8", "180.76.76.76"};
char *Version_And_Date[2]		= {"V0.09","2021-03-11"};
pid_t	pid;

struct dongle_info
{
	int Model;
	char ICCID[20];
	char IMSI[16];
	char IMEI[16];
	char MANUFACTURER[8];
	char MODELNAME[10];
	char REVISION[18];
	unsigned char MODE;
	int CSQ;
	int cnt_InternetFail;
	int cnt_ReadInfoFail;
	int cnt_pppFail;
	int cnt_SearchModuleFail;
	int cnt_ReadSimInfoFail;
}Dongle;

struct SysConfigAndInfo			*ShmSysConfigAndInfo;
struct StatusCodeData 			*ShmStatusCodeData;
struct FanModuleData			*ShmFanModuleData;
struct OCPP16Data				*ShmOCPP16Data;

int StoreLogMsg(const char *fmt, ...)
{
	char Buf[4096+256];
	char buffer[4096];
	time_t CurrentTime;
	struct tm *tm;
	va_list args;

	va_start(args, fmt);
	int rc = vsnprintf(buffer, sizeof(buffer), fmt, args);
	va_end(args);

	memset(Buf,0,sizeof(Buf));
	CurrentTime = time(NULL);
	tm=localtime(&CurrentTime);
	sprintf(Buf,"echo -n \"[%04d.%02d.%02d %02d:%02d:%02d] - %s\" >> /Storage/SystemLog/[%04d.%02d]4g_SystemLog",
			tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,
			buffer,
			tm->tm_year+1900,tm->tm_mon+1);
#ifdef SystemLogMessage
	system(Buf);
#endif

#ifdef ConsloePrintLog
	printf("[%04d.%02d.%02d %02d:%02d:%02d] - %s", tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec, buffer);
#endif

	return rc;
}

int DiffTimeb(struct timeb ST, struct timeb ET)
{
	//return milli-second
	unsigned int StartTime,StopTime;

	StartTime=(unsigned int)ST.time;
	StopTime=(unsigned int)ET.time;
	return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
}

//==========================================
// Init all share memory
//==========================================
int InitShareMemory()
{
	int result = PASS;
	int MeterSMId;

	//creat ShmSysConfigAndInfo
	if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo),  0777)) < 0)
    {
		DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n");
		result = FAIL;
	}
    else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1)
    {
    	DEBUG_ERROR("shmat ShmSysConfigAndInfo NG\n");
    	result = FAIL;
   	 }
    else
    {}

   	 //creat ShmStatusCodeData
   	 if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData),  0777)) < 0)
    {
   		DEBUG_ERROR("shmget ShmStatusCodeData NG\n");
   		result = FAIL;
	}
    else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1)
    {
    	DEBUG_ERROR("shmat ShmStatusCodeData NG\n");
    	result = FAIL;
   	}
    else
    {}

   	//creat ShmOCPP16Data
	if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data),  0777)) < 0)
	{
		DEBUG_ERROR("shmget ShmOCPP16Data NG");
		result = FAIL;
	}
	else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) -1)
	{
		DEBUG_ERROR("shmat ShmOCPP16Data NG");
		result = FAIL;
	}
	else
	{}

    return result;
}

//==========================================
// Check dongle model
//==========================================
int Check4GModem(void)
{
    int result = FAIL;

    if((access("/dev/ttyUSB0", F_OK) != -1) &&
       (access("/dev/ttyUSB1", F_OK) != -1) &&
	   (access("/dev/ttyUSB2", F_OK) != -1) &&
	   (access("/dev/ttyUSB3", F_OK) != -1))
    {
    	result = DONGLE_QUECTEL;
    }
    else if((access("/dev/ttyACM0", F_OK) != -1) &&
    		(access("/dev/ttyACM1", F_OK) != -1) &&
        	(access("/dev/ttyACM2", F_OK) != -1) &&
			(access("/dev/ttyACM3", F_OK) != -1) &&
			(access("/dev/ttyACM4", F_OK) != -1) &&
			(access("/dev/ttyACM5", F_OK) != -1))
    {
    	result = DONGLE_UBLOX;
    }
    else
    {}

    if(result == DONGLE_QUECTEL)
    {
    	DEBUG_INFO("Quectel 4G modem be found\n");
    }
    else if(result == DONGLE_UBLOX)
    {
    	DEBUG_INFO("Ublox 4G modem be found\n");
    }
    else
    {
    	DEBUG_WARN("No 4G modem be found\n");
    }

    return result;
}

//==========================================
// Check ppp interface status
//==========================================
int isPppUp(void)
{
	int result = FAIL;

	FILE *fp;
	char cmd[256];
	char buf[512];
	char tmp[512];

	strcpy(cmd, "ifconfig ppp0");;
	fp = popen(cmd, "r");
	if(fp != NULL)
	{
		while(fgets(buf, sizeof(buf), fp) != NULL)
		{
			if(strstr(buf, "ppp") > 0)
			{
				result = PASS;
			}

			if(strstr(buf, "addr:") > 0)
			{
				sscanf(buf, "%*s%s", tmp);
				substr((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress, tmp, strspn(tmp, "addr:"), (strlen(tmp) - strspn(tmp, "addr:")));
			}
		}
	}
	pclose(fp);

	return result;
}

//==========================================
// Check dongle info read status
//==========================================
int isReadInfo(void)
{
	int result = PASS;
	int uart;
	char rx[512];
	char tmp[512];
	char Length;
	int modeStatus;

	if((uart = openPort(portName[Dongle.Model])) != FAIL)
	{
		switch(Dongle.Model)
		{
			case DONGLE_QUECTEL:
				default:
				//==============================
				// Set don't echo command
				//==============================
				Length = at_command(uart, "ate0\r", rx);
				if(Length > 0)
				{
					if(strstr(rx, "ERROR"))
					{
						result = FAIL;
					}
					else
					{}
				}
				else
					result = FAIL;

				//==============================
				// Read Manufacturer
				//==============================
				Length = at_command(uart, "at+gmi\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					memcpy(tmp, rx, strcspn(rx,"OK"));
					memset(rx, 0, sizeof rx);
					trim_s(tmp,Length);

					if(strstr(tmp, "atgmi") != NULL)
					{
						substr(tmp, tmp, 5, strlen(tmp)-5);
					}
					memset(Dongle.MANUFACTURER, 0x00, ARRAY_SIZE(Dongle.MANUFACTURER));
					strncpy(Dongle.MANUFACTURER, tmp, strlen(tmp));
				}
				else
					result = FAIL;

				//==============================
				// Read Model
				//==============================
				Length = at_command(uart, "at+gmm\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					memcpy(tmp, rx, strcspn(rx,"OK"));
					memset(rx, 0, sizeof rx);
					trim_s(tmp,Length);

					if(strstr(tmp, "atgmm") != NULL)
					{
						substr(tmp, tmp, 5, strlen(tmp)-5);
					}
					memset(Dongle.MODELNAME, 0x00, ARRAY_SIZE(Dongle.MODELNAME));
					strncpy(Dongle.MODELNAME, tmp, strlen(tmp));
				}
				else
					result = FAIL;

				//==============================
				// Read Revision
				//==============================
				Length = at_command(uart, "at+gmr\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					memcpy(tmp, rx, strcspn(rx, "OK"));
					memset(rx, 0, sizeof rx);
					trim_s(tmp,Length);

					if(strstr(tmp, "atgmr") != NULL)
					{
						substr(tmp, tmp, 5, strlen(tmp)-5);
					}
					memset(Dongle.REVISION, 0x00, ARRAY_SIZE(Dongle.REVISION));
					strncpy(Dongle.REVISION, tmp, strlen(tmp));
				}
				else
					result = FAIL;

				//==============================
				// Read IMEI
				//==============================
				Length = at_command(uart, "at+gsn\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					memcpy(tmp, rx, strcspn(rx, "OK"));
					memset(rx, 0, sizeof rx);
					trim_s(tmp,Length);

					if(strstr(tmp, "atgsn") != NULL)
					{
						substr(tmp, tmp, 5, strlen(tmp)-5);
					}
					memset(Dongle.IMEI, 0x00, ARRAY_SIZE(Dongle.IMEI));
					strncpy(Dongle.IMEI, tmp, strlen(tmp));
				}
				else
					result = FAIL;

				//==============================
				// Read CSQ
				//==============================
				Length = at_command(uart, "at+csq\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					memcpy(tmp, rx, strcspn(rx,","));
					strncpy(rx, tmp + strcspn(tmp,":")+1, 10);
					Dongle.CSQ = atoi(rx);
				}
				else
					result = FAIL;

				//==============================
				// Read Mode
				//==============================
				Length = at_command(uart, "at+qcfg= \"nwscanmode\"\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					memcpy(tmp, rx, strcspn(rx,"OK"));
					strncpy(rx, tmp + strcspn(tmp,",")+1, 1);

					modeStatus = atoi(rx);

					if(modeStatus == 0)
						Dongle.MODE = UNKNOW;
					else if(modeStatus == 1)
						Dongle.MODE = GMS_GPRS;
					else if(modeStatus == 2)
						Dongle.MODE = WCDMA;
					else if(modeStatus == 3)
						Dongle.MODE = UNKNOW;
					else if(modeStatus == 4)
						Dongle.MODE = TD_SCDMA;
					else if(modeStatus == 5)
						Dongle.MODE = UNKNOW;
					else if(modeStatus == 6)
						Dongle.MODE = CDMA;
					else
						Dongle.MODE = UNKNOW;
				}
				else
					result = FAIL;

				break;
			case DONGLE_UBLOX:
				//==============================
				// Set don't echo command
				//==============================
				Length = at_command(uart, "ate0\r", rx);
				if(Length > 0)
				{
					if(strstr(rx, "ERROR"))
					{
						result = FAIL;
					}
					else
					{}
				}
				else
					result = FAIL;

				//==============================
				// Read Manufacturer
				//==============================
				Length = at_command(uart, "at+cgmi\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					memcpy(tmp, rx, strcspn(rx,"OK"));
					memset(rx, 0, sizeof rx);
					memset(Dongle.MANUFACTURER, 0x00, ARRAY_SIZE(Dongle.MANUFACTURER));
					strncpy(Dongle.MANUFACTURER, tmp+2, 6);
				}
				else
					result = FAIL;

				//==============================
				// Read Model
				//==============================
				Length = at_command(uart, "at+cgmm\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					memcpy(tmp, rx, strcspn(rx,"OK"));
					memset(rx, 0, sizeof rx);
					memset(Dongle.MODELNAME, 0x00, ARRAY_SIZE(Dongle.MODELNAME));
					strncpy(Dongle.MODELNAME , tmp+2, 9);
				}
				else
					result = FAIL;

				//==============================
				// Read Revision
				//==============================
				Length = at_command(uart, "at+cgmr\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					memcpy(tmp, rx, strcspn(rx, "OK"));
					memset(rx, 0, sizeof rx);
					memset(Dongle.REVISION, 0x00, ARRAY_SIZE(Dongle.REVISION));
					strncpy(Dongle.REVISION, tmp+2, 5);
				}
				else
					result = FAIL;

				//==============================
				// Read IMEI
				//==============================
				Length = at_command(uart, "at+cgsn\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					memcpy(tmp, rx, strcspn(rx, "OK"));
					memset(rx, 0, sizeof rx);
					trim_s(tmp,Length);
					memset(Dongle.IMEI, 0x00, ARRAY_SIZE(Dongle.IMEI));
					strncpy(Dongle.IMEI, tmp, strlen(tmp));
				}
				else
					result = FAIL;

				//==============================
				// Read CSQ
				//==============================
				Length = at_command(uart, "at+csq\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					memcpy(tmp, rx, strcspn(rx,","));
					strncpy(rx, tmp + strcspn(tmp,":")+1, 10);
					Dongle.CSQ = atoi(rx);
				}
				else
					result = FAIL;

				break;
		}
	}
	else
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("%s open fail.\n", portName[Dongle.Model]);
		#endif
		result = FAIL;
	}

	close(uart);

	return result;
}

//==========================================
// Read sim card information
//==========================================
int isReadSimInfo(void)
{
	int result = PASS;
	int uart;
	char rx[512];
	char tmp[512];
	char Length;

	if((uart = openPort(portName[Dongle.Model])) != FAIL)
	{
		switch(Dongle.Model)
		{
			case DONGLE_QUECTEL:
				default:
				//==============================
				// Set don't echo command
				//==============================
				Length = at_command(uart, "ate0\r", rx);
				if(Length > 0)
				{
					if(strstr(rx, "ERROR"))
					{
						result = FAIL;
					}
					else
					{}
				}
				else
					result = FAIL;

				//==============================
				// Read IMSI
				//==============================
				Length = at_command(uart, "at+cimi\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					if(strstr(rx, "ERROR"))
					{
						memset(Dongle.IMSI, 0, sizeof Dongle.IMSI);
						result = FAIL;
					}
					else
					{
						memcpy(tmp, rx, strcspn(rx, "OK"));
						trim_s(tmp, Length);
						memset(rx, 0, sizeof rx);

						if(strstr(tmp, "atcimi") != NULL)
						{
							substr(tmp, tmp, 6, strlen(tmp)-6);
						}
						memset(Dongle.IMSI, 0x00, ARRAY_SIZE(Dongle.IMSI));
						strncpy(Dongle.IMSI, tmp, strlen(tmp));
					}
				}
				else
					result = FAIL;

				//==============================
				// Read CCID
				//==============================
				Length = at_command(uart, "at+qccid\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					if(strstr(rx, "ERROR"))
					{
						memset(Dongle.ICCID, 0, sizeof Dongle.ICCID);
						result = FAIL;
					}
					else
					{
						memcpy(tmp, rx, strcspn(rx, "OK"));
						memset(rx, 0, sizeof rx);
						memset(Dongle.ICCID, 0x00, ARRAY_SIZE(Dongle.ICCID));
						strncpy(Dongle.ICCID, tmp + strcspn(tmp, ":") + 2, 20);
					}
				}
				else
					result = FAIL;

				break;
			case DONGLE_UBLOX:
				//==============================
				// Set don't echo command
				//==============================
				Length = at_command(uart, "ate0\r", rx);
				if(Length > 0)
				{
					if(strstr(rx, "ERROR"))
					{
						result = FAIL;
					}
					else
					{}
				}
				else
					result = FAIL;

				//==============================
				// Read IMSI
				//==============================
				Length = at_command(uart, "at+cimi\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					if(strstr(rx, "ERROR"))
					{
						memset(Dongle.IMSI, 0, sizeof Dongle.IMSI);
						result = FAIL;
					}
					else
					{
						memcpy(tmp, rx, strcspn(rx,"OK"));
						memset(rx, 0, sizeof rx);
						trim_s(tmp,Length);

						if(strstr(tmp, "atcimi") != NULL)
						{
							substr(tmp, tmp, 6, strlen(tmp)-6);
						}
						memset(Dongle.IMSI, 0x00, ARRAY_SIZE(Dongle.IMSI));
						strncpy(Dongle.IMSI, tmp, strlen(tmp));
					}
				}
				else
					result = FAIL;

				//==============================
				// Read CCID
				//==============================
				Length = at_command(uart, "at+ccid\r", rx);
				if(Length > 0)
				{
					memset(tmp, 0, sizeof tmp);
					if(strstr(rx, "ERROR"))
					{
						memset(Dongle.ICCID, 0, sizeof Dongle.ICCID);
						result = FAIL;
					}
					else
					{
						memcpy(tmp, rx, strcspn(rx, "OK"));
						memset(rx, 0, sizeof rx);
						memset(Dongle.ICCID, 0x00, ARRAY_SIZE(Dongle.ICCID));
						strncpy(Dongle.ICCID, tmp + strcspn(tmp, ":") + 2, 20);
					}
				}
				else
					result = FAIL;

				break;
		}
	}
	else
	{
		DEBUG_ERROR("%s open fail.\n", portName[Dongle.Model]);
		result = FAIL;
	}

	close(uart);

	return result;
}

//==========================================
// Read signal information
//==========================================
int CheckSignalRssi(void)
{
	int result = PASS;
	int uart;
	char rx[512];
	char tmp[512];
	char Lenght;

	if((uart = openPort(portName[Dongle.Model])) != FAIL)
	{
		switch (Dongle.Model)
		{
			case DONGLE_UBLOX:
				//==============================
				// Set don't echo command
				//==============================
				Lenght = at_command(uart, "ate0\r", rx);
				if(Lenght > 0)
				{
					if(strstr(rx, "ERROR"))
					{
						result = FAIL;
					}
					else
					{}
				}
				else
					result = FAIL;

				//==============================
				// Read CSQ
				//==============================
				Lenght = at_command(uart, "at+csq\r", rx);
				if(Lenght > 0)
				{
					memset(tmp, 0, sizeof tmp);
					memcpy(tmp, rx, strcspn(rx, ","));
					strncpy(rx, tmp + strcspn(tmp, ":") + 1, 10);
					Dongle.CSQ = atoi(rx);
				}
				else
					result = FAIL;

				break;

			case DONGLE_QUECTEL:
			default:
				//==============================
				// Set don't echo command
				//==============================
				Lenght = at_command(uart, "ate0\r", rx);
				if(Lenght > 0)
				{
					if(strstr(rx, "ERROR"))
					{
						result = FAIL;
					}
					else
					{}
				}
				else
					result = FAIL;

				//==============================
				// Read CSQ
				//==============================
				Lenght = at_command(uart, "at+csq\r", rx);
				if(Lenght > 0)
				{
					memset(tmp, 0, sizeof tmp);
					memcpy(tmp, rx, strcspn(rx, ","));
					strncpy(rx, tmp + strcspn(tmp, ":") + 1, 10);
					Dongle.CSQ = atoi(rx);
				}
				else
					result = FAIL;

				break;
		}
	}
	else
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("%s open fail.\n", portName[Dongle.Model]);
		#endif
		result = FAIL;
	}

	close(uart);

	return result;
}

//==========================================
// Init 4G dongle configuration
//==========================================
int  Load4gConfiguration()
{
	int result = FAIL;
	unsigned char CopyTmp[1024];

	if(strlen((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomApn) > 0)
	{
		system("cat /dev/null > /root/ppp/auto-apn.conf");
		system("chmod 600 /root/ppp/auto-apn.conf");
		system("cat /dev/null > /etc/ppp/pap-secrets");
		system("chmod 600 /etc/ppp/pap-secrets");
		system("cat /dev/null > /etc/ppp/chap-secrets");
		system("chmod 600 /etc/ppp/chap-secrets");
		system("cat /dev/null > /etc/ppp/auth");
		system("chmod 600 /etc/ppp/auth");
		memset(CopyTmp,0,sizeof(CopyTmp));
		sprintf((char*)CopyTmp,"echo APN=\"%s\" > /root/ppp/auto-apn.conf",ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomApn);
		system((char*)CopyTmp);
		memset(CopyTmp,0,sizeof(CopyTmp));
		sprintf((char*)CopyTmp,"echo ACCOUNT=\"%s\" >> /root/ppp/auto-apn.conf",ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId);
		system((char*)CopyTmp);
		memset(CopyTmp,0,sizeof(CopyTmp));
		sprintf((char*)CopyTmp,"echo PASSWORD=\"%s\" >> /root/ppp/auto-apn.conf",ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapPwd);
		system((char*)CopyTmp);
		memset(CopyTmp,0,sizeof(CopyTmp));
		sprintf((char*)CopyTmp,"echo %s > /etc/ppp/auth",ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId);
		system((char*)CopyTmp);
		sprintf((char*)CopyTmp,"echo %s >> /etc/ppp/auth",ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapPwd);
		system((char*)CopyTmp);

		if(strlen((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId)>0)
		{
			memset(CopyTmp,0,sizeof(CopyTmp));
			if(strlen((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapPwd)>0)
				sprintf((char*)CopyTmp,"echo \"%s * %s \" > /etc/ppp/pap-secrets",	ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId, ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapPwd);
			else
				sprintf((char*)CopyTmp,"echo \"%s *  \\<Your\\ Password\\> \" > /etc/ppp/pap-secrets",	ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId);
			system((char*)CopyTmp);

			memset(CopyTmp,0,sizeof(CopyTmp));
			if(strlen((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapPwd)>0)
				sprintf((char*)CopyTmp,"echo \"%s * %s \" > /etc/ppp/chap-secrets",	ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId, ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapPwd);
			else
				sprintf((char*)CopyTmp,"echo \"%s *  \\<Your\\ Password\\> \" > /etc/ppp/chap-secrets",	ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomChapPapId);
			system((char*)CopyTmp);
		}

		result = PASS;
	}

	return result;
}

//==========================================
// Check internet access status
//==========================================
int isReachableInternet(void)
{
	int result = FAIL;
	FILE *fp;
	char cmd[256];
	char buf[512];
	char tmp[256];
	char isPppGetGw = FALSE;

	for(int idx=0;idx<ARRAY_SIZE(valid_Internet);idx++)
	{
		sprintf(cmd, "ping -c 1 -w 3 -I ppp0 %s", valid_Internet[idx]);
		fp = popen(cmd, "r");
		if(fp != NULL)
		{
			while(fgets(buf, sizeof(buf), fp) != NULL)
			{
				if(strstr(buf, "transmitted") > 0)
				{
					//sscanf(buf, "%*s%*s%*s%*s%*s%s", tmp);

					if(strstr(buf,"100%") != NULL)
					{}
					else
					{
						result = PASS;
					}
					//DEBUG_INFO("%s",buf);
					//DEBUG_INFO("%s\n",tmp);
				}
			}
		}
		pclose(fp);
	}
	
	// Check ppp0 gateway
	if(result == TRUE)
	{
		fp = popen("ip route", "r");
		if(fp == NULL)
			result = FAIL;
		else
		{
			while(fgets(buf, sizeof(buf), fp) != NULL)
			{
				if((strstr(buf, "default") != NULL) && (strstr(buf, "ppp0") != NULL))
				{
					isPppGetGw = TRUE;
					break;
				}

				if(strstr(buf, "ppp0") != NULL)
				{
					break;
				}
			}

			if((isPppGetGw == FALSE) && (strstr(buf, "ppp0") != NULL))
			{
				sscanf(buf, "%s", tmp);
				DEBUG_INFO("ppp0 does not get default route gateway force assign to %s\n", tmp);

				sprintf(cmd,"route add default gw %s ppp0 &", tmp);
				system(cmd);
			}
		}
		pclose(fp);
		memset(buf, 0x00, sizeof(buf));
	}

	return result;
}

//==========================================
// Unbind USB port
//==========================================
int isModuleUnbind(void)
{
	int result = FAIL;
	FILE *fp;
	char cmd[256];

	strcpy(cmd, "echo '1-1'> /sys/bus/usb/drivers/usb/unbind");
	fp = popen(cmd, "r");

	if(fp == NULL)
	{
		result = FAIL;
	}
	else
	{
		result = PASS;

		#ifdef SystemLogMessage
    	DEBUG_INFO("Unbind USB for dongle.\n");
		#endif
	}

	return result;
}

//==========================================
// Bind USB port
//==========================================
int isModuleBind(void)
{
	int result = FAIL;
	FILE *fp;
	char cmd[256];

	strcpy(cmd, "echo '1-1'> /sys/bus/usb/drivers/usb/bind");
	fp = popen(cmd, "r");

	if(fp == NULL)
	{
		result = FAIL;
	}
	else
	{
		#ifdef SystemLogMessage
    	DEBUG_INFO("Bind USB for dongle.\n");
		#endif

		result = PASS;
	}

	return result;
}

//==========================================
// Dongle reset process
//==========================================
int rstModule(void)
{
	int result = PASS;
	int uart;
	char rx[512];

	if((uart = openPort(portName[Dongle.Model])) != FAIL)
	{
		//==============================
		// Reset module
		//==============================
		switch(Dongle.Model)
		{
			case DONGLE_QUECTEL:
			default:
				if(at_command(uart, "at+cfun=1,1\r", rx) <= 0)
				{
					result = FAIL;
				}
				
				DEBUG_INFO("Dongle hardware reset...\n");

				break;
			case DONGLE_UBLOX:
				if(at_command(uart, "at+cfun=1,1\r", rx) <= 0)
				{
					result = FAIL;
				}
				
				DEBUG_INFO("Dongle hardware reset...\n");

				break;
		}
	}
	else
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("%s open fail.\n", portName[Dongle.Model]);
		#endif
		result = FAIL;
	}
	close(uart);
	sleep(40);

	return result;
}

//==========================================
// AT command send/receive
//==========================================
int at_command(int uart, char* cmd, char* rx)
{
	int len;
	//sleep(2); //required to make flush work, for some reason
	//DEBUG_INFO("cmd : %s \n", cmd);
	tcflush(uart,TCIOFLUSH);
	if(write(uart, cmd, strlen(cmd)) >= sizeof(cmd))
	{
		usleep(500000);
		len = read(uart, rx, 512);
		//DEBUG_INFO("rx : %s \n", rx);
	}
	else
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("AT command %s response fail.\n", cmd);
		#endif
	}

	return len;
}

//==========================================
// Dongle communication port open
//==========================================
int openPort(char *tty)
{
	int uart = open(tty, O_RDWR | O_NOCTTY | O_NDELAY);

	if(uart!=FAIL)
	{
		if((set_interface_attribs(uart, B115200, 0) != PASS) || (set_blocking(uart, 0) != PASS))
			uart = FAIL;
	}

	return uart;
}

//==========================================
// Port parameter set
//==========================================
int set_interface_attribs (int fd, int speed, int parity)
{
	int result = FAIL;
	struct termios tty;
    memset (&tty, 0, sizeof tty);

    if (tcgetattr (fd, &tty) == 0)
	{
    	cfsetospeed (&tty, speed);
		cfsetispeed (&tty, speed);

		tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
		// disable IGNBRK for mismatched speed tests; otherwise receive break
		// as \000 chars
		tty.c_iflag &= ~IGNBRK;         		// disable break processing
		tty.c_lflag = 0;                		// no signaling chars, no echo,
												// no canonical processing
		tty.c_oflag = 0;                		// no remapping, no delays
		tty.c_cc[VMIN]  = 0;            		// read doesn't block
		tty.c_cc[VTIME] = 10;            		// 1 seconds read timeout

		tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

		tty.c_cflag |= (CLOCAL | CREAD);		// ignore modem controls,
												// enable reading
		tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
		tty.c_cflag |= parity;
		tty.c_cflag &= ~CSTOPB;
		tty.c_cflag &= ~CRTSCTS;

		if (tcsetattr (fd, TCSANOW, &tty) == 0)
			result = PASS;
	}

	return result;
}

int set_blocking (int fd, int should_block)
{
	int result = FAIL;
	struct termios tty;
	memset (&tty, 0, sizeof tty);
	if (tcgetattr (fd, &tty) == 0)
	{
		tty.c_cc[VMIN]  = should_block ? 1 : 0;
		tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

		if (tcsetattr (fd, TCSANOW, &tty) == 0)
			result = PASS;
	}

	return result;
}

//==========================================
// Common routine
//==========================================
void trim_s(char *s, unsigned char len)
{
	for(unsigned char i = 0 ; i < len; i++)
	{
		if (!((s[i]>='a') && (s[i]<='z')) && !((s[i]>='A') && (s[i]<='Z'))&& !((s[i]>='0') && (s[i]<='9')))
		{
			s[i] = s[i + 1];
			strncpy(s + i, s + i + 1, len);
			i -= 1;
			len -= 1;
		}
	}
	s[len + 1] = '\0';
}

void substr(char *dest, const char* src, unsigned int start, unsigned int cnt)
{
	strncpy(dest, src + start, cnt);
	dest[cnt] = 0;
}

//==========================================
// Main process
//==========================================
int main(void)
{
	//==========================================
	//Initialization share memory
	//==========================================
	if(InitShareMemory() == FAIL)
	{
		#ifdef SystemLogMessage
		DEBUG_ERROR("InitShareMemory NG\n");
		#endif

		if(ShmStatusCodeData!=NULL)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1;
		}
		sleep(5);

		return 0;
	}
	
	DEBUG_INFO("========================================\n");
	DEBUG_INFO("Latest Firmware Version : [ %s ].\n", Version_And_Date[0]);
	DEBUG_INFO("Latest Upgrade Date : [ %s ].\n", Version_And_Date[1]);
	DEBUG_INFO("========================================\n");
	
	for(;;)
	{
TOP:
		switch(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled)
		{
			case ENABLE_4G:
				DEBUG_INFO("4G module : [ Enable ].\n");
				if(((Dongle.Model = Check4GModem()) != FAIL))
				{
					ShmStatusCodeData->FaultCode.FaultEvents.bits.Telecom4GModuleBroken = 0;

					Dongle.cnt_SearchModuleFail = 0;
					if(isReadInfo() == PASS)
					{
						if(strcmp((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName, Dongle.MODELNAME) != 0)
							memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName));
						memcpy(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName, Dongle.MODELNAME, sizeof Dongle.MODELNAME);

						if(strcmp((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer, Dongle.REVISION) != 0)
							memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer));
						memcpy(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer, Dongle.REVISION, sizeof Dongle.REVISION);

						if(strcmp((char*)ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev, Dongle.REVISION) != 0)
							memset(ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev));
						memcpy(ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev, Dongle.REVISION, sizeof Dongle.REVISION);

						if(strcmp((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei, Dongle.IMEI) != 0)
							memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei));
						memcpy(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei, Dongle.IMEI, sizeof Dongle.IMEI);

						ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi = Dongle.CSQ;
						ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemMode = Dongle.MODE;

						DEBUG_INFO("========================================\n");
						DEBUG_INFO("Status: Device info readable...\n");
						DEBUG_INFO("========================================\n");
						DEBUG_INFO("Device MANUFACTURER: %s\n", Dongle.MANUFACTURER);
						DEBUG_INFO("Device MODEL: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName);
						DEBUG_INFO("Device REVISION: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer);
						DEBUG_INFO("Device IMEI: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei);
						DEBUG_INFO("Device RSSI: %d\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi);
						DEBUG_INFO("Device MODE: %d\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemMode);
						DEBUG_INFO("========================================\n");
						
						Dongle.cnt_ReadInfoFail = 0;
						if(isReadSimInfo() == PASS)
						{
							ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimStatus = 1;

							if(strcmp((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid, Dongle.ICCID) != 0)
								memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid));
							memcpy(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid, Dongle.ICCID, sizeof Dongle.ICCID);

							if(strcmp((char*)ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi, Dongle.IMSI) != 0)
								memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi, 0x00, ARRAY_SIZE(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi));
							memcpy(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi, Dongle.IMSI, sizeof Dongle.IMSI);

							DEBUG_INFO("========================================\n");
							DEBUG_INFO("Status: SIM card info readable...\n");
							DEBUG_INFO("========================================\n");
							DEBUG_INFO("Device IMSI: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi);
							DEBUG_INFO("Device ICCID: %.20s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid);
							DEBUG_INFO("TelcomSimStatus: %d\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimStatus);
							DEBUG_INFO("========================================\n");
						
							Dongle.cnt_ReadSimInfoFail = 0;
							if(isPppUp() == PASS)
							{
								DEBUG_INFO("========================================\n");
								DEBUG_INFO("Status: PPP interface found...\n");
								DEBUG_INFO("========================================\n");
								DEBUG_INFO("PPP IP: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress);
								DEBUG_INFO("========================================\n");

								Dongle.cnt_pppFail = 0;
								if(isReachableInternet() == PASS)
								{
									ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomNetworkConn = 1;
									ShmStatusCodeData->AlarmCode.AlarmEvents.bits.Telecom4GModuleCommFail = 0;
									ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectVia4Gi = 0;
									ShmStatusCodeData->InfoCode.InfoEvents.bits.ApnDisconnectVia4Gi = 0;
									Dongle.cnt_InternetFail = 0;
									
									// Update Rssi Value
									if(CheckSignalRssi() != PASS)
										DEBUG_INFO("No RSSI\n");
									else
										ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi = Dongle.CSQ;

									DEBUG_INFO("========================================\n");
									DEBUG_INFO("Status: 4G Device connecting...\n");
									DEBUG_INFO("========================================\n");
									DEBUG_INFO("Network connection: %d\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomNetworkConn);
									DEBUG_INFO("Dongle internet valid result: Pass\n");
									DEBUG_INFO("========================================\n");
								
									// Escape to the top
									if(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomEnabled == DISABLE_4G_MODULE)
									{
										goto TOP;
									}

									sleep(CheckInternetInterval);
								}
								else
								{
									DEBUG_INFO("Dongle internet valid result: Fail %d time\n", Dongle.cnt_InternetFail);

									ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomNetworkConn = 0;
									ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectVia4Gi = 1;
									ShmStatusCodeData->InfoCode.InfoEvents.bits.ApnDisconnectVia4Gi = 1;

									Dongle.cnt_InternetFail++;
									if(Dongle.cnt_InternetFail > 3)
									{
										system("killall 4GDetection");
										system("killall pppd");
										sleep(2);
										
										Dongle.cnt_InternetFail = 0;
										rstModule();
									}
									
									sleep(DisconnInterval);
								}
							}
							else
							{
								if(Load4gConfiguration() == FAIL)
								{
									DEBUG_ERROR("4G configuration value NG.\n");
									if(ShmStatusCodeData!=NULL)
									{
										ShmStatusCodeData->AlarmCode.AlarmEvents.bits.Telecom4GModuleCommFail=1;
									}
								}
								else
								{
									DEBUG_WARN("PPP interface not found.\n");

									memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress, 0 , sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress);

									Dongle.cnt_pppFail++;
									if(Dongle.cnt_pppFail > 3)
									{
										system("killall 4GDetection");
										system("killall pppd");
										sleep(2);
										
										Dongle.cnt_pppFail = 0;
										rstModule();
									}

									system("killall 4GDetection");
									system("killall pppd");
									sleep(2);

									if(Dongle.Model == DONGLE_QUECTEL)
									{
										system("/root/ppp/4GDetection /dev/ttyUSB3 &");
										printf("4GDetection for primary device.\n");
									}
									else if(Dongle.Model == DONGLE_UBLOX)
									{
										system("/root/ppp/4GDetection /dev/ttyACM0 &");
										printf("4GDetection for second device.\n");
									}
									else
									{}
								}

								sleep(CheckConnectionInterval);
							}
						}
						else
						{
							DEBUG_ERROR("SIM card info read error fail: %d\n", Dongle.cnt_ReadSimInfoFail);

							ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimStatus = 0;
							memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi);
							memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid);
							memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress, 0 , sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress);

							DEBUG_INFO("========================================\n");
							DEBUG_INFO("Status: Read Sim card info fail...\n");
							DEBUG_INFO("Device ICCID: %.20s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid);
							DEBUG_INFO("Device IMSI: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi);
							DEBUG_INFO("========================================\n");

							Dongle.cnt_ReadSimInfoFail ++;
							if(Dongle.cnt_ReadSimInfoFail > 3)
							{
								system("killall 4GDetection");
								system("killall pppd");
								sleep(2);
								
								Dongle.cnt_ReadSimInfoFail = 0;
								rstModule();
							}

							sleep(CheckSimInterval);
						}
					}
					else
					{
						DEBUG_ERROR("Device info read error fail: %d\n", Dongle.cnt_ReadInfoFail);
						
						Dongle.MODE = NO_SERVICE;
						memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName);
						memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer);
						memset(ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev, 0, sizeof ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev);
						memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei);
						ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi = 0;
						ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemMode = 0;
						
						DEBUG_INFO("========================================\n");
						DEBUG_INFO("Status: Read device info fail...\n");
						DEBUG_INFO("Device MANUFACTURER: %s\n", Dongle.MANUFACTURER);
						DEBUG_INFO("Device MODEL: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName);
						DEBUG_INFO("Device REVISION: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer);
						DEBUG_INFO("Device IMEI: %s\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei);
						DEBUG_INFO("Device RSSI: %d\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi);
						DEBUG_INFO("Device MODE: %d\n", ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemMode);
						DEBUG_INFO("========================================\n");

						Dongle.cnt_ReadInfoFail++;
						if(Dongle.cnt_ReadInfoFail > 3)
						{
							system("killall 4GDetection");
							system("killall pppd");
							sleep(2);
							
							Dongle.cnt_ReadInfoFail = 0;
							rstModule();
						}
						
						sleep(CheckModemInfoInterval);
					}
				}
				else
				{
					DEBUG_ERROR("Device search error fail: %d\n", Dongle.cnt_SearchModuleFail);
					
					ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectVia4Gi = 1;
					ShmStatusCodeData->InfoCode.InfoEvents.bits.ApnDisconnectVia4Gi = 1;
					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.Telecom4GModuleCommFail = 0;
					ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomNetworkConn = 0;
					ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi = 0;
					ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimStatus = 0;
					ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemMode = 0;
					memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei);
					memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi);
					memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress);
					memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid);
					memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer);
					memset(ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev, 0, sizeof ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev);
					memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName);
					
					Dongle.cnt_SearchModuleFail++;
					if(Dongle.cnt_SearchModuleFail > 3)
					{
						DEBUG_ERROR("4G Module was broken.\n");
						
						if(isModuleUnbind() == PASS)
						{
							isModuleBind();
						}

						ShmStatusCodeData->FaultCode.FaultEvents.bits.Telecom4GModuleBroken = 1;
						Dongle.cnt_SearchModuleFail = 0;
					}

					sleep(CheckModemInterval);
				}
				break;
				
			case DISABLE_4G_MODULE:
			default:
				DEBUG_INFO("4G module : [ Disable ].\n");
				
				ShmStatusCodeData->InfoCode.InfoEvents.bits.InternetDisconnectVia4Gi = 0;
				ShmStatusCodeData->InfoCode.InfoEvents.bits.ApnDisconnectVia4Gi= 0;
				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.Telecom4GModuleCommFail = 0;
				ShmStatusCodeData->FaultCode.FaultEvents.bits.Telecom4GModuleBroken = 0;
				ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomNetworkConn = 0;
				ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomRssi = 0;
				ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimStatus = 0;
				ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemMode = 0;
				memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModemImei);
				memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimImsi);
				memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomIpAddress);
				memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSimIccid);
				memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomSoftwareVer);
				memset(ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev, 0, sizeof ShmSysConfigAndInfo->SysInfo.TelcomModemFwRev);
				memset(ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName, 0, sizeof ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomModelName);
				
				system("killall 4GDetection");
				system("killall pppd");
				system("ifconfig ppp0 down");
				
				sleep(SystemInterval);
				
				break;
			
		}
	}

	return 0;
}