/******************************************************************************/
/**
 *
 * @file            APSTable_api.c
 *
 * @brief
 *
 * @note
 *
 * @author
******************************************************************************/
/*******************************************************************************
* Header include
******************************************************************************/
#include "ai_aps_table.h"
#include "al_aps_table_api.h"
#include "al_database.h"
#ifdef CONFIG_ATV_SUPPORT
#include "mid_atv_scan.h"
#endif
#include "cust_db_cfg.h"

/********************************************************************
	Macros
********************************************************************/
// Debug:
#define APP_SM_SEARCH_APS_DEBUG
#ifdef APP_SM_SEARCH_APS_DEBUG
#undef	DEBF
#define	DEBF(fmt, arg...)	UMFDBG(0,"[APSTable]:"fmt, ##arg)
#else
#define	DEBF(fmt, arg...)
#endif

#define APS_INVALID_PID     (0xFFFF)
#define INVALID_CHANNEL      (0xFF)
#define INVALID_CNI         (0xFFFF)

#define TUNER_CCIR_FREQ_STEP1   (7*1000000)
#define TUNER_CCIR_FREQ_STEP2   (8*1000000)

#define TUNER_CCIR_FREQ_E1      (40*1000000)
#define TUNER_CCIR_FREQ_E4      (68*1000000)

#define TUNER_CCIR_FREQ_S75     (68*1000000)
#define TUNER_CCIR_FREQ_S79     (104*1000000)

#define TUNER_CCIR_FREQ_S1      (104*1000000)
#define TUNER_CCIR_FREQ_S10     (174*1000000)

#define TUNER_CCIR_FREQ_E5      (174*1000000)
#define TUNER_CCIR_FREQ_E12     (230*1000000)

#define TUNER_CCIR_FREQ_S11     (230*1000000)
#define TUNER_CCIR_FREQ_S20     (302*1000000)

#define TUNER_CCIR_FREQ_S21     (302*1000000)
#define TUNER_CCIR_FREQ_S41     (470*1000000)

#define TUNER_CCIR_FREQ_E21     (470*1000000)
#define TUNER_CCIR_FREQ_E69     (870*1000000)

#define VPSCTY_GERMANY       (0x0D)
#define VPSCTY_AUSTRIA       (0x0A)
#define VPSCTY_UKRAINE       (0x07)
#define VPSCTY_SWITZERLAND   (0x04)
#define VPS_ARD_ZDF          (0x03)
#define VPS_ARD              (0x01)
#define VPS_ZDF              (0x02)

/*******************************************************************************
* Structure
******************************************************************************/
typedef struct _TUNER_CCIR_STRUCT
{
    al_uint32  FreqMinimum;    // Frequency minimum
    al_uint32  FreqMaximum;    // Frequency maximum
    al_uint32  FreqStep;       // Frequency step
    al_uint8   ChannelNoMin;   // CC/CH channel Minimum(b7: CC/CH)
    al_uint8   ChannelNoMax;   // CC/CH channel Maximum(b7: CC/CH)
} TUNER_CCIR_STRUCT, *pTUNER_CCIR_STRUCT;

typedef struct _ChannelAttribute_t
{
	al_uint8 ColorSystem;
	al_uint8 TunerStandard;
	al_uint32 Frequency;
} ChannelAttribute_t;


/*******************************************************************************
* Variables
******************************************************************************/
#ifdef CONFIG_ATV_SUPPORT
static ChannelAttribute_t cChatter[ADB_MAX_SERVRECS];
static al_uint32 sortFreq[ADB_MAX_SERVRECS];
static al_uint8 cChannel[ADB_MAX_SERVRECS];
static al_uint16 wPIDIndex[ADB_MAX_SERVRECS];
static al_uint8 ChannelName[ADB_MAX_SERVRECS][DB_ATV_MAX_CHNAME_LEN];
#endif
static al_uint16 m_PID[ADB_MAX_SERVRECS];
static al_uint32 m_Freq[ADB_MAX_SERVRECS];
/********************************************************************
	CCIR Frequency Table
********************************************************************/
static TUNER_CCIR_STRUCT Tuner_CCIR_Table[] =
{
	// CH
	{ TUNER_CCIR_FREQ_E1,  TUNER_CCIR_FREQ_E4,   TUNER_CCIR_FREQ_STEP1,   0x01,   0x04	},  // E1-E4
	{ TUNER_CCIR_FREQ_E5,  TUNER_CCIR_FREQ_E12,  TUNER_CCIR_FREQ_STEP1,   0x05,   0x0c	},  // E5-E12
	{ TUNER_CCIR_FREQ_E21, TUNER_CCIR_FREQ_E69,  TUNER_CCIR_FREQ_STEP2,   0x15,   0x45	},  // E21-E69
	// CC
	{ TUNER_CCIR_FREQ_S1,  TUNER_CCIR_FREQ_S10,  TUNER_CCIR_FREQ_STEP1,   0x81,   0x8a	},  // S1-S10
	{ TUNER_CCIR_FREQ_S11, TUNER_CCIR_FREQ_S20,  TUNER_CCIR_FREQ_STEP1,   0x8b,   0x94	},  // S11-S20
	{ TUNER_CCIR_FREQ_S21, TUNER_CCIR_FREQ_S41,  TUNER_CCIR_FREQ_STEP2,   0x95,   0xa9	},  // S21-S41
	{ TUNER_CCIR_FREQ_S75, TUNER_CCIR_FREQ_S79,  TUNER_CCIR_FREQ_STEP1,   0xcb,   0xcf	},  // s75-s79
};

/*******************************************************************************
* Function define
******************************************************************************/
#ifdef CONFIG_ATV_SUPPORT
static al_bool _AI_NullMatch(al_void *param, al_void const*pRec)
{
	return al_true;
}

static AL_Return_t _AI_APS_GetCurrentChannelInfo(al_uint8 u8chnIndex,ChannelAttribute_t *pbAttr)
{
	AL_RecHandle_t stHdl;
	AL_ServiceDetail_t stService;

	memset(&stService, 0, sizeof(stService));

	if (pbAttr == al_null)
	{
		return AL_INVALID_PARAM;
	}

	if (u8chnIndex >= ADB_MAX_SERVRECS)
	{
		return AL_INVALID_PARAM;
	}

	AL_DB_SearchRecords((AL_DB_RecordMatchFunc)_AI_NullMatch, al_null,
		AL_DBTYPE_DVB_ATV, AL_RECTYPE_ATVSERVICE, 1, u8chnIndex, al_null, al_null, &stHdl);

	AL_DB_QueryDetail(stHdl, &stService);

	pbAttr->ColorSystem = stService.stAnalogServ.colorSystem;
	pbAttr->TunerStandard = stService.stAnalogServ.soundSystem;
	pbAttr->Frequency = stService.stAnalogServ.u32Freq;

	return AL_SUCCESS;
}

static AL_Return_t _AI_APS_SetCurrentChannelInfo(al_uint8 u8chnIndex,ChannelAttribute_t *pbAttr)
{
	AL_RecHandle_t stHdl;
	AL_ServiceDetail_t stService;

	memset(&stService, 0, sizeof(stService));

	if (pbAttr == al_null)
	{
		return AL_INVALID_PARAM;
	}

	if (u8chnIndex >= ADB_MAX_SERVRECS)
	{
		return AL_INVALID_PARAM;
	}

	AL_DB_SearchRecords((AL_DB_RecordMatchFunc)_AI_NullMatch, al_null,
		AL_DBTYPE_DVB_ATV, AL_RECTYPE_ATVSERVICE, 1, u8chnIndex, al_null, al_null, &stHdl);
	AL_DB_QueryDetail(stHdl, &stService);

	stService.stAnalogServ.colorSystem = pbAttr->ColorSystem;
	stService.stAnalogServ.soundSystem = pbAttr->TunerStandard;
	stService.stAnalogServ.u32Freq = pbAttr->Frequency;

	AL_DB_UpdateDetail(stHdl, &stService);

	return AL_SUCCESS;
}

static AL_Return_t _AI_APS_SetCurrentChannelName(al_uint8 u8chnIndex, al_uint8 *pcName)
{
	AL_RecHandle_t stHdl;
	AL_ServiceDetail_t stService;

	memset(&stService, 0, sizeof(stService));

	if (pcName == al_null)
	{
		return AL_INVALID_PARAM;
	}

	if (u8chnIndex >= ADB_MAX_SERVRECS)
	{
		return AL_INVALID_PARAM;
	}

	AL_DB_SearchRecords((AL_DB_RecordMatchFunc)_AI_NullMatch, al_null,
		AL_DBTYPE_DVB_ATV, AL_RECTYPE_ATVSERVICE, 1, u8chnIndex, al_null, al_null, &stHdl);
	AL_DB_QueryDetail(stHdl, &stService);

	memcpy(stService.stAnalogServ.szChannelName,
		pcName, sizeof(stService.stAnalogServ.szChannelName));

	AL_DB_UpdateDetail(stHdl, &stService);

	return AL_SUCCESS;
}
#endif
/********************************************************************
	Calculate C.C.I.R (CATV Band) Channel.
	IN : FreqN = Frequency N
	OUT: b7: 0/1 = CH/CC
		 b6-0: Channel No.
********************************************************************/
static al_uint8 _AI_APS_CalculateChByFreq(al_uint32 Freq)
{
	al_uint8 index;
	pTUNER_CCIR_STRUCT pCCIRTable; // CCIR table pointer
	al_uint32 FreqMHz = Freq;

	pCCIRTable = Tuner_CCIR_Table; // initialize table pointer

	for (index = 0; index < sizeof(Tuner_CCIR_Table) / sizeof(TUNER_CCIR_STRUCT); index++)
	{
		if ((FreqMHz < pCCIRTable->FreqMaximum) && (FreqMHz >= pCCIRTable->FreqMinimum))
		{
			return (pCCIRTable->ChannelNoMin +
					(al_uint8)((FreqMHz - pCCIRTable->FreqMinimum) / pCCIRTable->FreqStep));
		}
		pCCIRTable++;
	}

	return 0xff;    // return fail
}
#ifdef CONFIG_SUPPORT_ATS

/******************************************************************************/
/**
* @brief   Confirm  PID to the channel using all information available
*
* @param   Cni_Data_t* eCNIData: CNI_Info
*
* @return   found Program ID or APS_INVALID_PID
*
******************************************************************************/
static AL_Return_t _AI_APS_ConfirmPID(Cni_Data_t* peCNIData, al_uint16 *pRetCNIData)
{
	al_uint16 VPSAddr;
	al_uint8  VPSCountry;
	al_uint16 TempchangVPS;
	al_bool ARD_ZDF;
	al_uint16 PID = APS_INVALID_PID;
	al_uint16 Sorting = 0;

	VPSAddr    = peCNIData->wVPS & 0x7fff;
	ARD_ZDF    = peCNIData->wVPS >> 15;
	VPSCountry = VPSAddr >> 8;                  /* bit[15-8]: Country, bit[7-0]: Network identification or Program provider */
	TempchangVPS = (VPSAddr ^ 0x00C0)& 0x00C0;  /* invert bit[7-6] */
	VPSAddr = (VPSAddr & 0x003F)|TempchangVPS;  /* bit[5-0] = APS_ChannelName[].bVPS */

	if(VPSCTY_GERMANY == VPSCountry )
	{
		/* Check ADR & ZDF */
		if(VPS_ARD_ZDF == VPSAddr)
		{
			if(ARD_ZDF == al_true)
			{
				VPSAddr = VPS_ARD;
			}
			else
			{
				VPSAddr = VPS_ZDF;
			}
		}
	}

	/* Check VPS country */
	if(( VPSCTY_GERMANY == VPSCountry )
        || ( VPSCTY_AUSTRIA == VPSCountry ))
    {
		VPSCountry |= 0x10;
    }
    else if(VPSCTY_SWITZERLAND == VPSCountry)
    {
		VPSCountry |= 0x20;
    }
    else if(VPSCTY_UKRAINE == VPSCountry)
    {
		VPSCountry |= 0x30;
    }

	for(Sorting=0; Sorting<APS_TABLE_LIST; Sorting++)
	{
		/* Check packet 8/30 format 1 information */
		if(APS_ChannelName[Sorting].wF1_Data)
		{
			if(APS_ChannelName[Sorting].wF1_Data == peCNIData->wCNI1)
			{
				PID = Sorting;
				*pRetCNIData = PID;
				DEBF("#### 8/30F1_PID: %d\n", PID);
				return AL_SUCCESS;
			}
		}
	}

	for(Sorting=0; Sorting<APS_TABLE_LIST; Sorting++)
	{
		/* Check packet 8/30 format 2 information */
		//if(APS_ChannelName[Sorting].bF2_NetworkId)
		{
			al_uint16 wSorting = ( APS_ChannelName[Sorting].bF2_Country << 8 ) |
			( APS_ChannelName[Sorting].bF2_NetworkId );

			if(wSorting == peCNIData->wCNI2)
			{
				PID = Sorting;
				*pRetCNIData = PID;
				DEBF("#### 8/30F2_PID: %d\n", PID);
				return AL_SUCCESS;
			}
		}
	}

	for(Sorting=0; Sorting<APS_TABLE_LIST; Sorting++)
	{
		/* Check VPS information */
		if(VPSCountry == APS_ChannelName[Sorting].bF2_Country)
		{
			al_uint16 wSorting = (APS_ChannelName[Sorting].bAddr <<6 ) | APS_ChannelName[Sorting].bVPS;

			if(VPSAddr == wSorting)
			{
				PID = Sorting;
				*pRetCNIData = PID;
				DEBF("#### VPS_PID: %d\n", PID);
				return AL_SUCCESS;
			}
		}
	}

	*pRetCNIData = PID;
	DEBF(" NO PID: %d\n", PID);
	return AL_SUCCESS;
}
#endif
/******************************************************************************/
/**
* @brief    Assigns channel Name. if PID is available uses the APS
*           tables otherwise "0xff, 0xff, 0xff, 0xff, 0xff 0xff"
*
* @param    al_uint8* pbChannelName: Channel Name
* @param    al_uint16 wPID: program id of APS tables
*
* @return    AL_SUCCESS on success
*
******************************************************************************/
static AL_Return_t _AI_APS_ChannelName(al_uint8* pbChannelName, al_uint16 wPID, al_uint32 dFreqHz)
{
	al_uint8 NameIndex;

	if(APS_INVALID_PID != wPID)
	{
		for(NameIndex=0; NameIndex<6; NameIndex++)
		{
			pbChannelName[NameIndex] = APS_ChannelName[wPID].bNameData[NameIndex];
		}
	}
	else
	{
		al_uint8 Ch;
		Ch = _AI_APS_CalculateChByFreq(dFreqHz);
		if (Ch != 0xff) // CCIR valid
		{
			if (Ch & 0x80)  // CC
			{
				pbChannelName[0] = 'S';
			}
			else            // CH
			{
				pbChannelName[0] = 'C';
			}

			// channel number
			Ch &= 0x7f;
			pbChannelName[1] = '0' + (Ch / 10);
			pbChannelName[2] = '0' + (Ch % 10);
		}
	}

	return AL_SUCCESS;
}

/******************************************************************************/
/**
* @brief    Sorting programs according to coutry specific sorting table
*
* @param    al_uint8 bCountry
* @param    al_uint16 *pwPID: pointer to PID array
* @param    al_uint16 *pwFreq
*
* @return    AL_SUCCESS on success
*
******************************************************************************/
static al_int _AI_APS_SortCountryDependent(AL_AreaIndex_en bCountry, al_uint8 u8Lang, al_uint16 *pwPID, al_uint32 *pwFreq)
{
#ifdef CONFIG_ATV_SUPPORT
	al_uint32 CountryTable_Count;
	al_uint32 No_other;
	al_uint16* pSortingTable;
	al_uint8 CurrentProgram = 0;
	al_uint8 noCNI_count = 0;
	al_uint8 b_onlyflag = 0;
	al_bool fCountryHasCNI = al_true;
    al_uint32 u8TotalChannelNumber = 0;
	al_uint32 csorting = 0;
   	if(AL_DB_GetRecordsTotalNum(AL_DBTYPE_DVB_ATV, AL_RECTYPE_ATVSERVICE, &u8TotalChannelNumber) != AL_SUCCESS)
   	{
		u8TotalChannelNumber = 0;
	}
	if( u8TotalChannelNumber < 1)
    {
        return AL_FAILURE;
    }
	if( AI_APS_GetSortingTable(bCountry, u8Lang, &pSortingTable) == AL_FAILURE )
	{
		DEBF("%s(): sort table fail!!\n",__FUNCTION__);
		fCountryHasCNI = al_false;
	}

	/* set default value */
	for(CountryTable_Count=0; CountryTable_Count<ADB_MAX_SERVRECS; CountryTable_Count++)
	{
		cChatter[CountryTable_Count].ColorSystem = 0;
		cChatter[CountryTable_Count].TunerStandard = 0;

		cChannel[CountryTable_Count] = INVALID_CHANNEL;
		wPIDIndex[CountryTable_Count] = APS_INVALID_PID;
	}

	if(fCountryHasCNI)
	{
		CountryTable_Count = 0;

		/* sorting country table list from the specific countory */
		while(pSortingTable[CountryTable_Count] != SORT_END_TABLE)
		{
			if(pSortingTable[CountryTable_Count] & LINK_ANOTHER_TABLE)
			{
				al_uint8 Another_Table;
				al_uint16 Sort_Index;
				al_uint16* LinkTable = (al_uint16*)APS_VPSCollections[pSortingTable[CountryTable_Count] & LINKED_TABLE];
			  	b_onlyflag = 0;

				for(Sort_Index=0; Sort_Index<u8TotalChannelNumber; Sort_Index++)
				{
					if(b_onlyflag)
					{
						break;
					}

	             	Another_Table = 0;
					while(SORT_END_TABLE != LinkTable[Another_Table])
					{
						if(( pwPID[Sort_Index] == LinkTable[Another_Table] )&&
							(cChannel[Sort_Index] == INVALID_CHANNEL))
						{
							cChannel[Sort_Index] = CurrentProgram;
							wPIDIndex[CurrentProgram] = pwPID[Sort_Index];
	  					   	CurrentProgram ++;

							if((pSortingTable[CountryTable_Count] & ONLY_FIRST_TRANSMISSION) != 0)
							{
								b_onlyflag = 1;
							}
							break;
	                    }
	                    Another_Table++;
                    }
			  	}
    		}
    		else
    		{
          		for(No_other=0; No_other< u8TotalChannelNumber; No_other++)
           		{
        			if((pSortingTable[CountryTable_Count] == pwPID[No_other])
            			&&(APS_INVALID_PID != pwPID[No_other]))
         			{
    					DEBF("No_other_table-> cChannel[%d]: CurProgram:%d, PID: %d \n", No_other, CurrentProgram, pwPID[No_other]);
    					cChannel[No_other] = CurrentProgram;
    					wPIDIndex[CurrentProgram] = pwPID[No_other];
    					CurrentProgram ++;
    				}
    			}
    		}
        	CountryTable_Count++;
    	}
	}

	for(CountryTable_Count=0; CountryTable_Count<u8TotalChannelNumber; CountryTable_Count++)
	{
		if ((APS_INVALID_PID != pwPID[CountryTable_Count]) &&
			( cChannel[CountryTable_Count] == INVALID_CHANNEL) &&
			fCountryHasCNI == al_true )
		{
			cChannel[CountryTable_Count] = CurrentProgram;
			/* have CNI code, but not in the specify countory*/
			DEBF("cChannel[%d]: CurProgram:%d,  PID: %d\n", CountryTable_Count, CurrentProgram, pwPID[CountryTable_Count]);
			wPIDIndex[CurrentProgram] = pwPID[CountryTable_Count];
			CurrentProgram ++;
		}

		/* no CNI channel put in sortFreq[] */
		if(APS_INVALID_PID == pwPID[CountryTable_Count] ||
			fCountryHasCNI == al_false)
		{
			if(pwFreq[CountryTable_Count]!=0)
			{
				sortFreq[noCNI_count] = pwFreq[CountryTable_Count];
				DEBF("noCNI_count: %d,  Freq = %d\n", noCNI_count, sortFreq[noCNI_count]);
				noCNI_count++;
			}
		}
	}

	/* sorting the no CNI channels according to frequence */
	for(CountryTable_Count=0; CountryTable_Count< noCNI_count; CountryTable_Count++)
	{
		for(csorting=0; csorting<u8TotalChannelNumber; csorting++)
		{
			if(sortFreq[CountryTable_Count] == pwFreq[csorting])
			{
				cChannel[csorting] = CurrentProgram;
				CurrentProgram ++;
			}
		}
	}

	/* get channel attrubute form database, and arrange channel sequence */
	for(CountryTable_Count=0; CountryTable_Count<u8TotalChannelNumber; CountryTable_Count++)
	{
		for(csorting=0; csorting<u8TotalChannelNumber; csorting++)
		{
			if(CountryTable_Count == cChannel[csorting])
			{
				_AI_APS_GetCurrentChannelInfo(csorting, &cChatter[CountryTable_Count]);
				break;
			}
		}
	}

	/* save channel attribute back to database */
	for (CountryTable_Count=0; CountryTable_Count<CurrentProgram; CountryTable_Count++)
	{
		_AI_APS_SetCurrentChannelInfo(CountryTable_Count, &cChatter[CountryTable_Count]);

		memset( ChannelName[CountryTable_Count], 0x0, DB_ATV_MAX_CHNAME_LEN );
		_AI_APS_ChannelName(ChannelName[CountryTable_Count],wPIDIndex[CountryTable_Count], cChatter[CountryTable_Count].Frequency);
        if(ChannelName[CountryTable_Count][0]!=0)
        {
		    _AI_APS_SetCurrentChannelName(CountryTable_Count, (al_uint8*)&ChannelName[CountryTable_Count]);
        }
	}
#endif

	return AL_SUCCESS;
}
#ifdef CONFIG_SUPPORT_ATS

/******************************************************************************/
/**
 * @brief       APS Get CNI and VPS code
 *
 * @param       Cni_Data_t* apsCNIData
 * @param       al_uint8 ChlIdx: Channel ID 0~200
 * @param       Uint 32 ChlFreq: Channel frequency
 *
 * @return      AL_SUCCESS on success \n
 * 				eMID_VBI_INVALID_PARAM if any of the parameters is invalid \n
 *
 ******************************************************************************/
static AL_Return_t _AI_APS_PrcoessVpsCniInfo(Cni_Data_t* apsCNIData, al_uint8 bChlIdx, al_uint32 wChlFreq)
{
	_AI_APS_ConfirmPID(apsCNIData, &m_PID[bChlIdx]);
	m_Freq[bChlIdx]= wChlFreq;

	return AL_SUCCESS;
}
#endif
/******************************************************************************/
/**
 * @brief       Initial APS
 * @param       void
 * @return      AL_SUCCESS on success
 *
 ******************************************************************************/
static AL_Return_t _AI_APS_Init(void)
{
#ifdef CONFIG_ATV_SUPPORT
	al_uint16 CI;
	for (CI=0/*1*/; CI<ADB_MAX_SERVRECS; CI++)
	{
		m_PID[CI] = APS_INVALID_PID;
		m_Freq[CI] = 0;
	}
#endif

	return AL_SUCCESS;
}

AL_Return_t AL_CNIInit(void)
{
    /*APS initial*/
	_AI_APS_Init();

	return AL_SUCCESS;
}
#ifdef CONFIG_SUPPORT_ATS
void AL_GetCNI(Cni_Data_t* pstCniData,
	al_uint8 bChnNumber, al_uint32 dFreq, al_uint8* pbGetChannelName)
{
	al_uint16 usGetPID;

	_AI_APS_PrcoessVpsCniInfo(pstCniData, bChnNumber, dFreq);
	_AI_APS_ConfirmPID(pstCniData, &usGetPID);
	memset(pbGetChannelName, 0x0, DB_ATV_MAX_CHNAME_LEN);
    _AI_APS_ChannelName(pbGetChannelName, usGetPID, dFreq);
}
#else
void AL_GetCNI(Cni_Data_t* pstCniData,
	al_uint8 bChnNumber, al_uint32 dFreq, al_uint8* pbGetChannelName)
{
	memset(pbGetChannelName, 0x0, DB_ATV_MAX_CHNAME_LEN);
    _AI_APS_ChannelName(pbGetChannelName, APS_INVALID_PID, dFreq);
}

#endif

/******************************************************************************/
/**
 * @brief       Sorting the channel
 *
 * @param       CountryNumber  0:German 1:UK 2:Austria 3:France 4:Greece
 *                             5:Italy 6:Spain 0xff:others
 *
 * @return      AL_SUCCESS on success
 * 				eMID_VBI_INVALID_PARAM if any of the parameters is invalid
 *
 ******************************************************************************/
AL_Return_t AL_APS_SortingByCountry(AL_AreaIndex_en bCountryNumber, al_uint8 u8Lang)
{
	return _AI_APS_SortCountryDependent(bCountryNumber, u8Lang, m_PID, m_Freq);
}

