/**
	@file test_TVSDK.c
	@author miki 
	@ingroup L1SW2
	@date 2009.10.18
**/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
#include <signal.h>
#include <sys/time.h>
#include <time.h>
#include <termios.h>

#include <pthread.h>

#include "event.h"
#include "camessage.h"

#include "hx_types.h"
#include "hx_debug.h"
#include "qw_util.h"
#include "pid_filter_map.h"
#include "AZBoxTVSDK_DEF.h"
#include "AZBoxTVSDK.h"
#include "ChannelSDK.h"

#include "parse_psi.h"

#define ALL_CHANNEL_FILE "/DISK2/all_channel.dat"
#define CHANNEL_TEXT "/DISK2/channel.text"
#define RESERVED_DATA_NAME	"/DISK2/reserved.dat"

struct save_channel_info_st {
	char 			mTunerId;
	short 			mPosition;
	unsigned long 	mFreq;
	char			mPolarisation;
	unsigned short	mServiceId;
	unsigned short	mOriginalNetworkId;
	unsigned short	mTransportId;
	unsigned short	mATag;
	unsigned short	mAPid;
	unsigned short	mVTag;
	unsigned short	mVPid;
	unsigned short	mPCR;
	unsigned short	mPMT;
	char			mChannelType;
	unsigned char	mChannelName[MAX_SERVICE_NAME_LEN];
	unsigned char	mProviderPackageCode[MAX_SERVICE_NAME_LEN];
	char			mCrypt;
	int				mGenre;
	int 			mCountry;
	char			mSDHD;
};


int default_dtv = 0;

struct tuner_list_st *tuner_list;

int verbosity_map[MAX_DEBUG_MODULE_ID_COUNT];

static struct channel_list_st *ChannelList = NULL;
static struct all_networks_st *NetworkList = NULL;

static int SaveChannelInfo(struct save_channel_info_st* save_channel_info, int channel_count);
static int AddChannel(struct network_st *net_info, struct save_channel_info_st* channel_info);
static int AddChannelFromFile(const char *FileName);
static struct network_st* FindNetworkByPosition(HX_INT32 orbital_pos);
static struct multiplex_st* FindMultiplexByNetwork(struct network_st *net, HX_UINT32 freq, HX_UINT polar);
static struct channel_st* GetChannel(HX_UINT8 ni, HX_UINT16 on_id, HX_UINT16 ts_id, HX_UINT32 freq, HX_UINT16 sid, HX_UINT8 polar);
static struct channel_group_st* GetProviderInfo(HX_INT8 *find_name, HX_INT8 find_name_len);

static HX_INT16 AddProviderInfo(struct channel_group_st add_provider);

static HX_INT16 VTYPE_GetVCHIndexByTSInfo(HX_INT8 tuner_id, HX_UINT8 ni,
		HX_UINT16 on_id, HX_UINT16 ts_id, HX_UINT32 freq, HX_UINT16 sid,
		HX_UINT8 polar, HX_INT8 vch_type);

static struct virtual_channel_st* GetVirtualChannelST(char type);

static HX_INT16* GetVirtualChannelVNumber(char type);
static struct channel_st *get_rch_ch_info_by_tp_ch(struct tp_ch_st *tp_ch_info, HX_UINT16 service_id);

static struct tp_ch_st *AllocTPCHInfo(HX_UINT16 transport_id, HX_UINT32 frequency, HX_UINT8 polar);
static struct tp_ch_st *GetTPCHInfoByNetworkCh(struct network_ch_st *net_info, HX_UINT16 ts_id, HX_UINT32 freq, HX_UINT8 polar);
static struct network_ch_st *AllocNetworkCHInfo(HX_UINT8 net_index, HX_UINT16 network_id, HX_UINT8 *name );
static struct network_ch_st* GetNetworkCHInfo(HX_UINT8 ni, HX_UINT16 on_id);
static HX_STATUS AddRCHInfo(struct channel_st *ch, HX_UINT8 *network_name);
static HX_INT16 GetProviderNewId(void);

static HX_STATUS PrintReservedList(struct reserved_list_st *reserved_list);
static void PrintReservedInfo(struct reserved_info_st *info); 

static struct termios tio_save;
static int init_count = 0;

static void TermInit(int block_int)
{
	struct termios tio;
	
	if (init_count++) return;

	if (tcgetattr(STDIN_FILENO, &tio_save) < 0) {
		init_count--;
		return;
	}
	tio = tio_save;
	if (block_int) {
		tio.c_lflag &= ~(ECHO | ICANON | ISIG);
		tio.c_iflag &= ~(BRKINT);
	} else {
		tio.c_lflag |= (ISIG);
		tio.c_lflag &= ~(ECHO | ICANON);
		tio.c_iflag |= (BRKINT);
		tio.c_iflag &= ~(IGNBRK);
	}
	
	/* 
	   arrows or F1 characters generate a sequence of 3 characters in a row:
	   like ESC [ A (up arrow).
	   
	   To avoid reading [ or A as an individual character, we set
	   an inter character interval of 1/10 second. If characters
	   are received in less of 1/10 second then it is treated as
	   an individual character and is discard.
	*/
	
	tio.c_cc[VMIN] = 3;   /* up to 3 chars at a time */
	tio.c_cc[VTIME] = 1;  /* after receiving 1 char and after a delay of 1/10 second, 'read' returns */
	tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio);
}

static void TermExit(void)
{
	if (--init_count) return;
	tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio_save);
}

static int TermGetKey(void)
{
	struct timeval tv;
	fd_set in;

	int numfd;
	
	tv.tv_sec = 0;
	tv.tv_usec = 10000;

	FD_ZERO(&in);
	FD_SET(0, &in);

	numfd = select(1, &in, 0, 0, &tv);
				
	if (numfd < 0) {
		perror("select");
	}
	else if (numfd == 0) {
		/* timeout */
	}
	else {
		char c;

		if (FD_ISSET(0, &in)) {
			if (read(0, &c, 1) == 1) {
				return c;
			}
		} 
	}

	return -1;
}


#if 0
static void PrintChannelInfo(struct channel_st *ch_info)
{
	if(ch_info == NULL)
		return;

	info(TEST_DBG_ID,"--------------------------------------------------------------------------\n");
	info(TEST_DBG_ID,"\t\t + name: %s\n",ch_info->channel_name_list.name[0].data);
#if 0
	info(TEST_DBG_ID,"\t\t + name_len: %d\n",ch_info->channel_name_list.name[0].len);
	info(TEST_DBG_ID,"\t\t + net_index: %d\n",ch_info->net_index);
#endif
	info(TEST_DBG_ID,"\t\t + freq: %lld\n",ch_info->freq);
	info(TEST_DBG_ID,"\t\t + polarisation: %d\n",ch_info->polarisation);
	info(TEST_DBG_ID,"\t\t + service_id: %02x\n",ch_info->service_id);
#if 0
	info(TEST_DBG_ID,"\t\t + network_id: %02x\n",ch_info->original_network_id);
	info(TEST_DBG_ID,"\t\t + transport_id: %02x\n",ch_info->ts_id);
//	info(TEST_DBG_ID,"\t\t + type: %d\n",ch_info->type >> 8);
	info(TEST_DBG_ID,"\t\t + fta type: %d\n",ch_info->type);
	info(TEST_DBG_ID,"\t\t + lock type: %d\n",ch_info->type);
	info(TEST_DBG_ID,"\t\t + pat_version_number: %d\n",ch_info->pat_version_number);
	info(TEST_DBG_ID,"\t\t + pmt_version_number: %d\n",ch_info->pmt_version_number);
#endif
	info(TEST_DBG_ID,"\t\t + pmt_pid: %02x(%d)\n",ch_info->pmt_pid,ch_info->pmt_pid);
	info(TEST_DBG_ID,"\t\t + pcr_pid: %02x(%d)\n",ch_info->pcr_pid,ch_info->pcr_pid);
	info(TEST_DBG_ID,"\t\t + video_pid: %02x(%d)\n",ch_info->video_pid,ch_info->video_pid);
	info(TEST_DBG_ID,"\t\t + video_tag: %02x(%d)\n",ch_info->video_tag,ch_info->video_tag);
	info(TEST_DBG_ID,"\t\t + audio_pid: %02x(%d)\n",ch_info->audio_pid,ch_info->audio_pid);
	info(TEST_DBG_ID,"\t\t + audio_tag: %02x(%d)\n",ch_info->audio_tag,ch_info->audio_tag);
#if 0
	info(TEST_DBG_ID,"\t\t + audio_lang: %s\n",ch_info->audio_lang);
	info(TEST_DBG_ID,"\t\t + pdata_num: %d\n",ch_info->pdata_num);
	info(TEST_DBG_ID,"\t\t + ecm_pid: %d\n",ch_info->ecm_pid);
	info(TEST_DBG_ID,"\t\t + flag: %d\n",ch_info->flag);
	info(TEST_DBG_ID,"\t\t + use_num: %d\n",ch_info->use_num);
#endif
	info(TEST_DBG_ID,"--------------------------------------------------------------------------\n");
}
#endif

#if 1
static HX_STATUS PrintNetworkList (int detail)
{
	struct network_st *net = NULL;
	struct list_head *net_pos, *net_tmp;
	struct multiplex_st *mp = NULL;
	struct list_head *mp_pos, *mp_tmp;
	
	info(TEST_DBG_ID,"==========================================================================================\n");
	info(TEST_DBG_ID,"								NETWORK LIST (%d) \n",NetworkList->number);
	info(TEST_DBG_ID,"==========================================================================================\n");
	list_for_each_safe(net_pos, net_tmp, &(NetworkList->net.list)) {
		net = list_entry(net_pos, struct network_st, list);
		int count = 0;

		if (!net) {
			errorn(TEST_DBG_ID, "Fail to get network\n");
			continue;
		}
		else {
			info(TEST_DBG_ID,"______________________________________________________________________________________________________________\n");
			info(TEST_DBG_ID,"|net_index(%d)\t|orbital_pos(%ld)\t|mp_count(%d)\t|%s|\n",net->index,(net->mp.type == DTV_DVBS) ? net->mp.info.dvb_s.orbital_pos : 0, net->mp_num, net->name);
			info(TEST_DBG_ID,"______________________________________________________________________________________________________________\n");
			fflush(stdout);
		}
		
		list_for_each_safe(mp_pos, mp_tmp, &(net->mp.list)) {
			mp = list_entry(mp_pos, struct multiplex_st, list);
			if(mp != NULL) {

				count++;

				if(detail) {
					if(mp->type == DTV_ATSC) {

					} else if (mp->type == DTV_DVBS) {

						   info(TEST_DBG_ID,"+%d\t %8ld\t %8ld\t %d\t %d\t %d\t %d\t %d\t %d\t %8lu\t 0x%04x\t 0x%04x\t\n",
						   count, mp->info.dvb_s.orbital_pos, mp->info.dvb_s.symbol_rate, mp->info.dvb_s.fec_inner, mp->info.dvb_s.polarisation,
						   mp->info.dvb_s.pilot, mp->info.dvb_s.roll_off,mp->info.dvb_s.modulation_system,
						   mp->info.dvb_s.modulation_type ,mp->frequency, mp->original_network_id, mp->transport_stream_id);

					} else if (mp->type == DTV_DVBT) {

					} else if (mp->type == DTV_DVBC) {

					} else if (mp->type == DTV_ISDBT) {

					}
					else {
					}
				}
			}
		}

	}
	return HX_OK;
}
#endif

static HX_STATUS main_task(void)
{
	struct event_st event;

	if(TVSDK_EventTask(&event) == HX_OK) {

		infon(TVSDK_DBG_ID," CMD  ---- (%02x)%d \n",event.cmd,event.cmd);

		switch(event.cmd) {
			case TVSDK_PUT_DETAILE_EIT:   
				break;

			case TVSDK_PUT_EPG_LIST:       
				break;

			case TVSDK_ADD_EPG_INFO:         	
				break;

			case TVSDK_GET_GMTOFFSET:		
				break;

			case TVSDK_SYNC_CRTVCORE:			
				break;

			case TVSDK_GET_SYSTEM_LANGUAGE:
				break;

			case TVSDK_LOCKTUNER:            
				break;

			case TVSDK_CHECKLOCKTUNER:        
				break;

			case TVSDK_PID_FILTER_START:    
				break;

			case TVSDK_PID_FILTER_STOP:     	
				break;

			case TVSDK_GET_EITMEMORYSTATUS:	
				break;

			case TVSDK_SET_EITMEMORY:        
				break;

			case TVSDK_SC_BIG_MSG:
			case TVSDK_SC_SMALL_MSG:
				break;

			default:
				infon(TVSDK_DBG_ID," SKIP  ---- (%02x)%d \n",event.cmd,event.cmd);
				break;
		}
	}
	
	TVSDK_SDCTRLTask();
	return HX_OK;
}

int main(void)
{
	time_t GMTOffset = 0;
	HX_INT32 eit_filter = -1;
	HX_INT32 pat_filter = -1;

	verbosity_map[TVSDK_DBG_ID] = DBG_INFO;
	verbosity_map[TEST_DBG_ID] = DBG_INFO;

	TermInit(0);

	TVSDK_Init();

	ChannelSDK_Init();
	ChannelSDK_Load(ALL_CHANNEL_FILE);
	ChannelSDK_InitNetwork();
	
	
	if((ChannelList = ChannelSDK_GetChannelList()) == NULL)
		return 0;

	if((NetworkList = ChannelSDK_GetNetworkList()) == NULL)
		return 0;

	GMTOffset = TVSDK_GetGMTOffset();
	info(TEST_DBG_ID,"GMTOffset %ld \n",GMTOffset);
	printf(" h : Help\n");
	printf(" 1 : Test Channel\n");
	printf(" 2 : Test EPG\n");
	printf(" 3 : Test Reserved\n");
	printf(" 4 : Test EIT Filter\n");
	printf(" 5 : Test SC MSG\n");
	printf(" u : Test CHUP\n");
	printf(" d : Test CHDOWN\n");
	printf(" q : Quit\n");

	while(1) {
		int key = 0;

		key = TermGetKey();

		switch(key) {
			case 'q':
				goto exit_main;
				break;

			case '1':
				{
					HX_STATUS err = HX_OK;
					int count = 0;

					infon(TEST_DBG_ID,"**********\t TEST CHANNEL\n");

					PrintNetworkList(0);

					count = AddChannelFromFile(CHANNEL_TEXT);
#if 1
					if(0) {
						struct save_channel_info_st channel_info; 
						struct network_st* net = NULL;
						struct multiplex_st *mp = NULL;

						channel_info.mTunerId = 0;
						channel_info.mPosition = 130;
						channel_info.mFreq = 10719000;
						channel_info.mPolarisation = 1;
						channel_info.mServiceId = 4404;
						channel_info.mOriginalNetworkId = 318;
						channel_info.mTransportId = 11000;
						channel_info.mATag = 4;
						channel_info.mAPid = 92;
						channel_info.mVTag = 2;
						channel_info.mVPid = 163;
						channel_info.mPCR = 163;
						channel_info.mPMT = 1004;
						channel_info.mChannelType = SERVICE_TYPE_TV;
						strcpy(channel_info.mChannelName,"4fun,TV-TVSDK");
						strcpy(channel_info.mProviderPackageCode,"TVSDK");
						channel_info.mGenre = 3;
						channel_info.mCountry = 5;
						channel_info.mCrypt = 0;
						channel_info.mSDHD = 1;

						net = FindNetworkByPosition(channel_info.mPosition);

						if(net != NULL) {
							mp = FindMultiplexByNetwork(net, channel_info.mFreq, channel_info.mPolarisation);

							if(mp != NULL)
								AddChannel(net,&channel_info);
							else
								infon(TEST_DBG_ID,"Can't find 'multiplex' \n");

							ChannelSDK_Save(ALL_CHANNEL_FILE);
						}
						else {
							infon(TEST_DBG_ID,"Can't find 'network' \n");
						}
					}
					else {

						int i;
						struct save_channel_info_st channel_info[5]; 
						memset(channel_info,0x00,sizeof(channel_info));

						for(i=0; i< 5; i++) {
							channel_info[i].mTunerId = 0;
							channel_info[i].mPosition = 1160;
							channel_info[i].mFreq = 11900100;
							channel_info[i].mPolarisation = 0;
							channel_info[i].mServiceId = 403+i;
							channel_info[i].mOriginalNetworkId = 173;
							channel_info[i].mTransportId = 4;
							channel_info[i].mATag = 0x81;
							channel_info[i].mAPid = 1075;
							channel_info[i].mVTag = 0x1b;
							channel_info[i].mVPid = 1072;
							channel_info[i].mPCR = 1072;
							channel_info[i].mPMT = 1082;
							channel_info[i].mChannelType = SERVICE_TYPE_TV;
							strcpy(channel_info[i].mChannelName,"[HD] KBS1-TVSDK");
							strcpy(channel_info[i].mProviderPackageCode,"TVSDK");
							channel_info[i].mGenre = 3;
							channel_info[i].mCountry = 5;
							channel_info[i].mCrypt = 1;
							channel_info[i].mSDHD = 0;
						}

						SaveChannelInfo(channel_info, 5); 
					}
#endif
					err = TVSDK_Sync(TVSDK_SYNC_ID_CHANNEL);
					if(err == HX_ERROR)
						error(TEST_DBG_ID," TVSDK_SYNC_ID_CHANNEL \n");

				}
				break;
			case '2':
				{
					HX_STATUS err = HX_OK;

					struct channel_st *ch_info = GetChannel(6,318, 11000, 10719000, 4408, 1);

					infon(TEST_DBG_ID,"**********\t TEST EPG\n");

					if(ch_info != NULL) {
						int i;
						stTVSDKChannelKey ChannelKey = TVSDK_MakeKeyByChannel(ch_info);
						struct eit_info_st EpgList[256];
						short epg_count;

						bzero(EpgList,sizeof(EpgList));

						epg_count = TVSDK_Geteit_info(&ChannelKey, time(NULL), (60*60*24), EpgList);

						infon(TEST_DBG_ID," epg_count %d \n",epg_count);

						if(epg_count == 0) {
							int i;
							struct eit_info_st eit_info; 
							bzero(&eit_info,sizeof(eit_info));
							for(i=0; i < 50; i++) {
								HX_STATUS err = 0;
								eit_info.net_index = ch_info->net_index;
								eit_info.freq = ch_info->freq;
								eit_info.polar = ch_info->polarisation;
								eit_info.service_id = ch_info->service_id;
								eit_info.net_id = ch_info->original_network_id;
								eit_info.ts_id = ch_info->ts_id;
								eit_info.event_id = i;
								eit_info.start_time = time(NULL) + (60*60*2)*i;
								eit_info.duration = (60*60*2)-1;

								eit_info.parental_rating = 18;

								strcpy(eit_info.event_lang,"eng");

								sprintf(eit_info.event_name,"TVSDK-event_name %d",i); // UTF8
								eit_info.event_name_len = strlen(eit_info.event_name);

								sprintf(eit_info.event_text,"TVSDK-event_text %d",i); // UTF8
								eit_info.event_text_len = strlen(eit_info.event_text);

								sprintf(eit_info.event_detail,"TVSDK-event_detail %d",i);	// UTF8
								eit_info.event_detail_len = strlen(eit_info.event_detail);
								err = TVSDK_AddEPGInfo(&eit_info,1);
							}
							epg_count = TVSDK_Geteit_info(&ChannelKey, time(NULL), (60*60*24), EpgList);
						}
						else {

							for(i=0; i< epg_count; i++) {
								HX_STATUS err = 0;

								struct eit_info_st eit_info; 
								eit_info = TVSDK_GetDetailEPG(&ChannelKey, EpgList[i].event_id);

								infon(TEST_DBG_ID,"EpgList[%d].event_id : %02x\n",i,EpgList[i].event_id);

								if(eit_info.net_id != 0 && eit_info.freq != 0) {
									infon(TEST_DBG_ID,"net_index %d\n",eit_info.net_index);
									infon(TEST_DBG_ID,"net_id %d\n",eit_info.net_id);
									infon(TEST_DBG_ID,"ts_id %d\n",eit_info.ts_id);
									infon(TEST_DBG_ID,"service_id %d\n",eit_info.service_id);
									infon(TEST_DBG_ID,"freq %ld\n",eit_info.freq);
									infon(TEST_DBG_ID,"polar %d\n",eit_info.polar);
									infon(TEST_DBG_ID,"event_id %d\n",eit_info.event_id);
									infon(TEST_DBG_ID,"event_name :%s\n",eit_info.event_name);
									infon(TEST_DBG_ID,"event_text :%s\n",eit_info.event_text);
									infon(TEST_DBG_ID,"event_detail :%s\n",eit_info.event_detail);

									if(1) {
										struct eit_info_st Addedeit_info = eit_info; 
										struct eit_info_st Addeit_info = eit_info; 
										Addeit_info.start_time += (60*60*24*3);
										Addeit_info.event_id += 50;

										bzero(Addeit_info.event_name,sizeof(Addeit_info.event_name));
										sprintf(Addeit_info.event_name,"TEST %d",i);
										Addeit_info.event_name_len = strlen(Addeit_info.event_name);


										err = TVSDK_AddEPGInfo(&Addeit_info,1);
										infon(TEST_DBG_ID,"++++++++++++event_id : %d\n",Addeit_info.event_id);

										Addedeit_info = TVSDK_GetDetailEPG(&ChannelKey, Addeit_info.event_id);


										infon(TEST_DBG_ID,"-----------------------------event_id : %d\n",Addedeit_info.event_id);
										infon(TEST_DBG_ID,"-----------------------------event_name :%s\n",Addedeit_info.event_name);
									}
								}
							}

							epg_count = TVSDK_Geteit_info(&ChannelKey, time(NULL)+(60*60*24*3), (60*60*24), EpgList);
						}

						for(i=0; i< epg_count; i++) {
							struct eit_info_st eit_info; 
							eit_info = TVSDK_GetDetailEPG(&ChannelKey, EpgList[i].event_id);

							infon(TEST_DBG_ID,"EpgList[%d].event_id : %02x\n",i,EpgList[i].event_id);

							if(eit_info.net_id != 0 && eit_info.freq != 0) {
								infon(TEST_DBG_ID,"event_id %d\n",eit_info.event_id);
								infon(TEST_DBG_ID,"event_name :%s\n",eit_info.event_name);
								infon(TEST_DBG_ID,"event_text :%s\n",eit_info.event_text);
								infon(TEST_DBG_ID,"event_detail :%s\n",eit_info.event_detail);

							}
						}
					}
					else {
						infon(TEST_DBG_ID,"Can't find channel\n");
					}
					err = TVSDK_Sync(TVSDK_SYNC_ID_EPG);
					if(err == HX_ERROR)
						error(TEST_DBG_ID,"TVSDK_SYNC_ID_EPG\n");
				}
				break;
			case '3':
				{
					HX_STATUS err = HX_OK;
					struct reserved_list_st *reserved_list = NULL;
					infon(TEST_DBG_ID,"**********\t TEST RESERVED\n");
					TVSDK_InitReservedList();
					TVSDK_LoadReservedList(RESERVED_DATA_NAME);
					reserved_list = TVSDK_GetReservedList(); 
					PrintReservedList(reserved_list);

					{
						int result;
						struct reserved_info_st reserved_info;
						struct channel_st *ch_info = NULL; 

						memset(&reserved_info, 0, sizeof(struct reserved_info_st));

						reserved_info.status		= RES_STA_RECORD;
						reserved_info.tuner_id 	= 0;
						reserved_info.net_index 	= 81;
						reserved_info.freq 			= 11900100;
						reserved_info.polar 		= 0;
						reserved_info.original_network_id 	= 173;
						reserved_info.transport_stream_id 	= 4;
						reserved_info.service_id 	= 403;
						reserved_info.event_id 	= 0;
						reserved_info.start_time = time(NULL) + (60*2);
						if(reserved_info.status	== RES_STA_RECORD)
							reserved_info.duration	= CHECK_1HOUR; // sec
						else 
							reserved_info.duration	= 0; // sec

						// channel info
						ch_info = GetChannel(reserved_info.net_index,reserved_info.original_network_id, reserved_info.transport_stream_id
								, reserved_info.freq, reserved_info.service_id, reserved_info.polar);
						if(ch_info == NULL) {
							errorn(TEST_DBG_ID,"Can't find channel\n");
							break;
						}


						reserved_info.ch_name_len = ch_info->channel_name_list.name[0].len;
						memcpy(reserved_info.ch_name, ch_info->channel_name_list.name[0].data, reserved_info.ch_name_len);

						strcpy(reserved_info.title, "TVSDK-title");
						reserved_info.title_len = strlen(reserved_info.title);

						if(1) {
							reserved_info.rec_devices_type = REC_DEV_HDD;
							sprintf(reserved_info.rec_path,"/DATA/hdb1");
							infon(TEST_DBG_ID,"rec_path %s \n",reserved_info.rec_path);
						}
						else {
							reserved_info.rec_devices_type = REC_DEV_USB;
							sprintf(reserved_info.rec_path,"/DATA/hdb1");
							infon(TEST_DBG_ID,"rec_path %s \n",reserved_info.rec_path);
						}

						reserved_info.repeat = RES_REPEAT_ONE;

						reserved_info.mask = 9;				

						//==========================================================

						if((result = TVSDK_AddReservedInfo(&reserved_info)) == 0) {
							if(0) {
								struct list_head *ch_pos, *ch_tmp;
								struct reserved_info_st *info;
								reserved_list = TVSDK_GetReservedList(); 
								if(reserved_list == NULL)
									infon(TEST_DBG_ID,"reserved_list NULL...\n");

								if(reserved_list->total_count > 0) {
									list_for_each_safe(ch_pos, ch_tmp, &reserved_list->info.list) {
										info = list_entry(ch_pos, struct reserved_info_st, list);
										if(info->start_time == reserved_info.start_time) {
											PrintReservedList(reserved_list);
											TVSDK_DelReservedInfo(info);
											reserved_list = TVSDK_GetReservedList(); 
											PrintReservedList(reserved_list);
										}
									}
								}
							}
						}

						infon(TEST_DBG_ID,"result %d \n", result);

						TVSDK_SaveReservedList(RESERVED_DATA_NAME);

						infon(TEST_DBG_ID,"insert reserve list !!!\n");
					}
					err = TVSDK_Sync(TVSDK_SYNC_ID_RESERVED);
					if(err == HX_ERROR)
						error(TEST_DBG_ID,"TVSDK_SYNC_ID_RESERVED\n");
				}
				break;
			case '4':
				{
					HX_INT md = 0;
					int i;
					HX_UINT8 language[32] = {0,};

					struct memory_status_st eit_mem;

					TVSDK_InitEITMemory();

					TVSDK_GetEITMemoryStatus(&eit_mem);

					tuner_list = TVSDK_GetTunerList();

					unsigned short pid = EIT_PID;

					set_eit_language_code("English");

					if(TVSDK_GetSystemLanguage(AUDIO_LANGUAGE,language) == HX_OK)
						set_eit_language_code(language);

					if(tuner_list->combination_type == TUNER_COMBINATION_COMBO)
						infon(TEST_DBG_ID, "# Tuner Combination Type : COMBO                       #\n");
					else
						infon(TEST_DBG_ID, "# Tuner Combination Type : TWIN                       #\n");
					
#if 0
					tuner_list->tuner[default_dtv].tuner_id = 0;
					tuner_list->tuner[default_dtv].net_index = 14;
					tuner_list->tuner[default_dtv].freq = 11428000;
					tuner_list->tuner[default_dtv].polar = 0;
#else

					tuner_list->tuner[default_dtv].tuner_id = 0;
					tuner_list->tuner[default_dtv].net_index = 81;
					tuner_list->tuner[default_dtv].freq = 11900100;
					tuner_list->tuner[default_dtv].polar = 0;
#endif

					if(0) {
						for(i=0; i<5; i++) {
							md = TVSDK_LockTuner(tuner_list->tuner[default_dtv].tuner_id, 
									tuner_list->tuner[default_dtv].net_index, 
									tuner_list->tuner[default_dtv].freq, tuner_list->tuner[default_dtv].polar);
							usleep(50000);
							if(md > -2)
								break;
						}

						if(md < 0) {
							break;
						}

						if(md > 0) {
							infon(TEST_DBG_ID," MOVE %d sec\n",md);
							//	sleep(md);
						}

						infon(TEST_DBG_ID, "LOCKING TUNER freq=%ld\n", tuner_list->tuner[default_dtv].freq);
					}

					eit_filter = TVSDK_PidFilterStart(pid, dvb_eit_full_table_ids,
							dvb_eit_full_table_num, 20,0x0000,
							SECTION_PSI,(void*)parse_section);

					infon(TEST_DBG_ID,"parse_section %p, eit_filter %ld \n",parse_section, eit_filter);
					
				}
				break;
			case '5':
				{
					char send_buf[10] = {0,};
					char received_buf[8192] = {0,};
					unsigned short send_size;
					short received_size;
					send_buf[0] = 0;
					send_buf[1] = 12;
					send_size = 2;

					infon(TEST_DBG_ID,"SEND SC MSG\n");
					received_size = TVSDK_SCMSG(send_buf, send_size, NULL);
					infon(TEST_DBG_ID,"RECEIVED SC MSG : len (%d)\n",received_size);
				}
				break;

			case 'u':
				if(TVSDK_GoToChannelUp() == HX_ERROR)
					errorn(TEST_DBG_ID, "TVSDK_GoToChannelUp()\n");
				infon(TEST_DBG_ID, "TVSDK_GoToChannelUp()\n");

				break;

			case 'd':
				if(TVSDK_GoToChannelDown() == HX_ERROR)
					errorn(TEST_DBG_ID, "TVSDK_GoToChannelDown()\n");
				infon(TEST_DBG_ID, "TVSDK_GoToChannelDown()\n");
				break;

			case 'h':
				{
					printf(" 1 : Test Channel\n");
					printf(" 2 : Test EPG\n");
					printf(" 3 : Test Reserved\n");
					printf(" 4 : Test EIT Filter\n");
					printf(" 5 : Test SC MSG\n");
					printf(" u : Test CHUP\n");
					printf(" d : Test CHDOWN\n");
					printf(" q : Quit\n");
				}
				break;

		}

		main_task();
	}

exit_main:

	if(eit_filter != -1)
		TVSDK_PidFilterStop(eit_filter);
	if(pat_filter != -1)
		TVSDK_PidFilterStop(pat_filter);
		
	ChannelSDK_Destroy();

	TVSDK_Deinit(0);
	TermExit();
	return 1;
}

static int AddChannel(struct network_st *net_info, struct save_channel_info_st* channel_info)
{

	struct channel_st *ch = NULL;
	unsigned char service_type = 0;
	unsigned short type = 0;
	short minor_number = 0;

	short ch_index = 0;
	int new_channel = 0;

	service_type = channel_info->mChannelType;

	type = (SOURCE_TYPE_DVBS << 8) | service_type;

	debugn(TEST_DBG_ID,"MAX_CHANNEL %d  original_vnumber %d ,tv_vnumber %d, radio_vnumber %d\n",
			MAX_CHANNEL, ChannelList->original_vnumber,ChannelList->tv_vnumber,ChannelList->radio_vnumber);

	if(ChannelList->original_vnumber >= MAX_CHANNEL) {
		errorn(TEST_DBG_ID, "original_vnumber %d/ MAX_CHANNEL %d \n",ChannelList->original_vnumber,MAX_CHANNEL);
		return -1;
	}

	if(service_type == SERVICE_TYPE_TV && ChannelList->tv_vnumber >= MAX_TV_CHANNEL) {
		errorn(TEST_DBG_ID, "tv_vnumber %d/ MAX_TV_CHANNEL %d \n",ChannelList->tv_vnumber,MAX_TV_CHANNEL);
		return -1;
	}

	if(service_type == SERVICE_TYPE_RADIO && (ChannelList->radio_vnumber >= MAX_RADIO_CHANNEL)) {
		errorn(TEST_DBG_ID, "radio_vnumber %d/ MAX_RADIO_CHANNEL %d \n",ChannelList->radio_vnumber,MAX_RADIO_CHANNEL);
		return -1;
	}

	if (!(service_type == SERVICE_TYPE_TV || service_type == SERVICE_TYPE_RADIO || service_type == SERVICE_TYPE_ANALOG)) {
		verbosen(TEST_DBG_ID, "service[on(0x%x) ts(0x%x) sid(0x%x) name(%s)] is not tv or radio type(0x%x)\n",
				channel_info->mOriginalNetworkId, channel_info->mTransportId, channel_info->mServiceId, channel_info->mChannelName, service_type);
		return -1;
	}

	debug(TEST_DBG_ID, "s_id(0x%x), original_network_id(0x%x), ts_id(0x%x), type(0x%04x) %s \n", 
				channel_info->mServiceId, channel_info->mOriginalNetworkId, channel_info->mTransportId, type, channel_info->mChannelName);

	ch = GetChannel(net_info->index, channel_info->mOriginalNetworkId, channel_info->mTransportId, channel_info->mFreq, channel_info->mServiceId, channel_info->mPolarisation);

	if(ch != NULL) {
	//	warning(TEST_DBG_ID, "SERVICE: ni(%d),sid(0x%x),on(0x%x),ts(0x%x),type(0x%04x),name=%s\n", 
	//			net->index,channel_info->mServiceId, channel_info->mOriginalNetworkId, channel_info->mTransportId, type, channel_info->mChannelName);
	
	//	warning(TEST_DBG_ID, "CHANNEL: ni(%d),sid(0x%x),on(0x%x),ts(0x%x),type(0x%04x),name=%s\n",
	//			net->index, ch->service_id, ch->original_network_id, ch->ts_id, ch->type, ch->channel_name_list.name[0].data);
	//	return -1;
	}
	else {
		ch = ChannelSDK_CreateChannel();
		new_channel = 1;
	}


	if(ch != NULL) {
		char tuner_id = channel_info->mTunerId;
		struct channel_group_st provider_info;
		struct channel_group_st *tmp_provider_info = NULL;

		ch->channel_name_list.name[0].len = strlen(channel_info->mChannelName);
		memcpy(ch->channel_name_list.name[0].data, channel_info->mChannelName, ch->channel_name_list.name[0].len);

		provider_info.name_len = strlen(channel_info->mProviderPackageCode);
		if(provider_info.name_len > MAX_SERVICE_NAME_LEN)
			provider_info.name_len = MAX_SERVICE_NAME_LEN;

		memcpy(provider_info.name ,channel_info->mProviderPackageCode, provider_info.name_len);


		if(provider_info.name_len) {
			if((tmp_provider_info = GetProviderInfo(provider_info.name, provider_info.name_len)) == NULL) {
				ch->provider_id = AddProviderInfo(provider_info);
			}
			else {
				ch->provider_id = tmp_provider_info->id;
			}
		}

		ch->net_index = net_info->index;

		ch->freq = channel_info->mFreq;

		ch->polarisation = channel_info->mPolarisation;

		ch->type = type;

		ch->ts_id = channel_info->mTransportId;	//transport_stream_id
		ch->original_network_id = channel_info->mOriginalNetworkId;	
		ch->service_id = channel_info->mServiceId;

		if(new_channel)
			ch->flag = CHANNEL_FLAG_NONE;

		ch->pmt_pid = channel_info->mPMT;
		ch->pcr_pid = channel_info->mPCR;
		ch->pat_version_number = 0;
		ch->pmt_version_number = 0;

		if ((channel_info->mAPid == 0xffff) && (channel_info->mAPid == 0xffff)) 
		{
			debug(TEST_DBG_ID, "This channel(sid=0x%02x,freq=%ld, type=0x%04x name=%s) uses auto pid detection mode\n",
					channel_info->mServiceId, channel_info->mFreq, type, channel_info->mChannelName);
			ch->flag |= CHANNEL_FLAG_AUTOPID;
		}
		else {

			ch->video_tag = channel_info->mVTag;
			ch->video_pid = channel_info->mVPid;
			ch->video_ecm_pid = 0xffff;

			ch->audio_tag = channel_info->mATag;
			ch->audio_pid = channel_info->mAPid;
			ch->audio_ecm_pid = 0xffff;
			//		memcpy(ch->pdata, s->pdata, sizeof(private_data_st)*PRIVATE_DATA_MAX);
			//		ch->pdata_num = s->pdata_num;
		}

		ch->genre_id = channel_info->mGenre;
		ch->country_id = channel_info->mCountry;

		ch->flag |= (channel_info->mCrypt == 1 ? CHANNEL_FLAG_SCRAMBLED : 0);
		ch->flag |= channel_info->mSDHD == 1 ? CHANNEL_FLAG_HD : 0;

		if(!new_channel) {

			HX_INT16 v_index = -1;
			v_index = VTYPE_GetVCHIndexByTSInfo(tuner_id, ch->net_index, ch->original_network_id, ch->ts_id, ch->freq, ch->service_id, ch->polarisation, VINDEX_TYPE_DEFAULT);

			if(v_index != -1)
				return -1;
		}

		if(net_info != NULL) {
			AddRCHInfo(ch, net_info->name);
		}
		else { 
			errorn(TEST_DBG_ID, "Fail to find network(%d)\n", net_info->index);
			AddRCHInfo(ch, "(UNKNOWN)");
		}

		// add original channel list

		if((service_type == SERVICE_TYPE_TV) 
				|| (service_type == SERVICE_TYPE_RADIO)
#ifdef _TD115S_P
				|| (service_type == SERVICE_TYPE_PROMO) 
				|| (service_type == SERVICE_TYPE_MPROMO)
#endif
				|| ((((type & 0xff00) >> 8) == SOURCE_TYPE_ATSC) && (service_type == SERVICE_TYPE_ANALOG))) {
		//	ChannelList->original_vch[ChannelList->original_vnumber].type = type;
			ChannelList->original_vch[ChannelList->original_vnumber].tuner_id = tuner_id;

			ChannelList->original_vch[ChannelList->original_vnumber].major_ch_num = ChannelList->original_vnumber+1;
			ChannelList->original_vch[ChannelList->original_vnumber].minor_ch_num = minor_number;
			ChannelList->original_vch[ChannelList->original_vnumber].net_index = net_info->index;
			ChannelList->original_vch[ChannelList->original_vnumber].original_network_id = channel_info->mOriginalNetworkId;
			ChannelList->original_vch[ChannelList->original_vnumber].transport_id = channel_info->mTransportId;
			ChannelList->original_vch[ChannelList->original_vnumber].frequency = channel_info->mFreq;
			ChannelList->original_vch[ChannelList->original_vnumber].service_id = channel_info->mServiceId;
			ChannelList->original_vch[ChannelList->original_vnumber].polar = channel_info->mPolarisation;
			ChannelList->original_vch[ChannelList->original_vnumber].r_ch = ch;

		//	debug(TEST_DBG_ID," %d-%d, index=%d\n", 
			info(TEST_DBG_ID," %d-%d, index=%d\n", 
					ChannelList->original_vch[ChannelList->original_vnumber].major_ch_num,
					ChannelList->original_vch[ChannelList->original_vnumber].minor_ch_num, ChannelList->original_vnumber);
			ChannelList->original_vnumber++;
		}
		else {
			warning(TEST_DBG_ID,"service_type %02x :",service_type);
		}

		if((service_type == SERVICE_TYPE_TV) 
#ifdef _TD115S_P
				|| (service_type == SERVICE_TYPE_PROMO) 
				|| (service_type == SERVICE_TYPE_MPROMO)
#endif
		  ) 
		{ //digital television
		//	ChannelList->tv_vch[ChannelList->tv_vnumber].type = type;
			ChannelList->tv_vch[ChannelList->tv_vnumber].tuner_id = tuner_id;
				ChannelList->tv_vch[ChannelList->tv_vnumber].major_ch_num = ChannelList->tv_vnumber+1;
			ChannelList->tv_vch[ChannelList->tv_vnumber].minor_ch_num = minor_number;
			ChannelList->tv_vch[ChannelList->tv_vnumber].net_index = net_info->index;
			ChannelList->tv_vch[ChannelList->tv_vnumber].original_network_id = channel_info->mOriginalNetworkId;
			ChannelList->tv_vch[ChannelList->tv_vnumber].transport_id = channel_info->mTransportId;
			ChannelList->tv_vch[ChannelList->tv_vnumber].frequency = channel_info->mFreq;
			ChannelList->tv_vch[ChannelList->tv_vnumber].service_id = channel_info->mServiceId;
			ChannelList->tv_vch[ChannelList->tv_vnumber].polar = channel_info->mPolarisation;
			ChannelList->tv_vch[ChannelList->tv_vnumber].r_ch = ch;
			debug(TEST_DBG_ID, "\ttv_channel_number %d, type %02x freq %ld\n\n",ChannelList->tv_vch[ChannelList->tv_vnumber].major_ch_num,type, channel_info->mFreq);
			ch_index = ChannelList->tv_vnumber;
			ChannelList->tv_vnumber++;

		}
		else if(service_type == SERVICE_TYPE_RADIO) { //digital readio sound
		//	ChannelList->radio_vch[ChannelList->radio_vnumber].type = type;
			ChannelList->radio_vch[ChannelList->radio_vnumber].tuner_id = tuner_id;

				ChannelList->radio_vch[ChannelList->radio_vnumber].major_ch_num = ChannelList->radio_vnumber+1;
			ChannelList->radio_vch[ChannelList->radio_vnumber].minor_ch_num = minor_number;
			ChannelList->radio_vch[ChannelList->radio_vnumber].net_index = net_info->index;
			ChannelList->radio_vch[ChannelList->radio_vnumber].original_network_id = channel_info->mOriginalNetworkId;
			ChannelList->radio_vch[ChannelList->radio_vnumber].transport_id = channel_info->mTransportId;
			ChannelList->radio_vch[ChannelList->radio_vnumber].frequency = channel_info->mFreq;
			ChannelList->radio_vch[ChannelList->radio_vnumber].service_id = channel_info->mServiceId;
			ChannelList->radio_vch[ChannelList->radio_vnumber].polar = channel_info->mPolarisation;
			ChannelList->radio_vch[ChannelList->radio_vnumber].r_ch = ch;
			debug(TEST_DBG_ID, "\t\tradio_channel_number %d, type %02x\n\n",ChannelList->radio_vch[ChannelList->radio_vnumber].major_ch_num,type);
			ch_index = ChannelList->radio_vnumber;
			ChannelList->radio_vnumber++;
		}
	}
	return ch_index;
}

static int SaveChannelInfo(struct save_channel_info_st* save_channel_info, int channel_count) 
{
	int i=0;
	int count = 0;
	HX_STATUS err = HX_OK;


	if(save_channel_info == NULL) 
		return 0;

	infon(TEST_DBG_ID,"%d \n",channel_count);

	for(i=0; i<channel_count; i++) {
		int ret = 0;
		struct multiplex_st *mp;
		struct network_st *net;

		short position = 0;

		position = save_channel_info[i].mPosition;

		net = FindNetworkByPosition(position);

		if(net == NULL) {
			warningn(TEST_DBG_ID, "find Position (%d)\n",position);
			continue;
		}

		mp = FindMultiplexByNetwork(net, save_channel_info[i].mFreq, save_channel_info[i].mPolarisation);

		if(mp == NULL){
			warningn(TEST_DBG_ID, "find multiplex (%d)\n",position);
			continue;
		}

		mp->original_network_id = save_channel_info[i].mOriginalNetworkId;
		mp->transport_stream_id = save_channel_info[i].mTransportId;

		//		info(TEST_DBG_ID," %s \n",save_channel_info[i].mChannelName);

		/*
		   info(TEST_DBG_ID,"add tp: %d : %ld net_index(%d), freq(%ld), symbol(%ld), polar(%d), system(%d), type(%d),  fec(%d), pilot(%d)\n", 
		   i,net->mp.info.dvb_s.orbital_pos,net->index, mp->frequency, mp->info.dvb_s.symbol_rate, mp->info.dvb_s.polarisation, 
		   mp->info.dvb_s.modulation_system, mp->info.dvb_s.modulation_type,
		   mp->info.dvb_s.fec_inner, mp->info.dvb_s.pilot);
		 */

		ret = AddChannel(net, &save_channel_info[i]);
		if(ret > -1)
			count++;
	}

	err = ChannelSDK_SaveNetwork(DTV_DVBS, DVBS_NETWORK_NAME);

	if (err == HX_ERROR) {
		errorn(TEST_DBG_ID, "Fail to save network %s\n",DVBS_NETWORK_NAME);
	}

	ChannelSDK_Save(ALL_CHANNEL_FILE);

	return err;
}

static struct network_st* FindNetworkByPosition(HX_INT32 orbital_pos)
{
   struct list_head *pos = NULL; 
   struct network_st *net = NULL;
   list_for_each(pos, &NetworkList->net.list) {
      net = list_entry(pos, struct network_st, list);
		if (net->mp.type != DTV_DVBS)
			continue;

      if (net->mp.info.dvb_s.orbital_pos ==  orbital_pos) {
         return net;
	  }
   }

   return NULL;
}

static struct multiplex_st* FindMultiplexByNetwork(struct network_st *net, HX_UINT32 freq, HX_UINT polar)
{
	struct multiplex_st *mp = NULL;
	struct list_head *mp_pos = NULL;
	HX_UINT32 freq_tmp = 0;

	if (!net) {
		errorn(TEST_DBG_ID,"network is NULL\n");
		return NULL;
	}

	if(freq <= 0)
	{
		errorn(TEST_DBG_ID,"freq is zero!!\n");
		return NULL;
	}
	
	list_for_each(mp_pos, &(net->mp.list)) {
		mp = list_entry(mp_pos, struct multiplex_st, list);
	
		if ((mp->type == DTV_DVBT) || (mp->type == DTV_DVBC) || (mp->type == DTV_ISDBT) || (mp->type == DTV_ATSC)) {
			freq_tmp = freq/1000;
		} else {
			freq_tmp = freq;
		}

		//infon(TEST_DBG_ID,"%ld, %ld, %ld\n", freq, mp->frequency, freq_tmp);
		
		if (is_same_frequency(mp->frequency, freq_tmp)) {
			if (mp->type == DTV_DVBS 
					&& mp->info.dvb_s.polarisation != polar)
				continue;
			else	
				return mp;
		}
	}
	return NULL;
}

static struct channel_st* GetChannel(HX_UINT8 ni, HX_UINT16 on_id, HX_UINT16 ts_id, HX_UINT32 freq, HX_UINT16 sid, HX_UINT8 polar)
{
	struct list_head *net_pos = NULL, *net_tmp = NULL;
	struct network_ch_st *net_ch_info = NULL;
	struct list_head *tp_ch_pos = NULL, *tp_ch_tmp = NULL;
	struct tp_ch_st *tp_ch_info = NULL;
	struct list_head *rch_pos = NULL, *rch_tmp = NULL;
	struct channel_st *rch_info = NULL;

	   list_for_each_safe(net_pos, net_tmp, &(ChannelList->network.list)) {
		   net_ch_info = list_entry(net_pos, struct network_ch_st, list);

		   if(net_ch_info->net_index == ni && net_ch_info->network_id == on_id)
		   {

			   list_for_each_safe(tp_ch_pos, tp_ch_tmp, &(net_ch_info->tp_ch.list)) {
				   tp_ch_info = list_entry(tp_ch_pos, struct tp_ch_st, list);
				   if(is_same_frequency(tp_ch_info->frequency ,freq)
						   && tp_ch_info->polarisation == polar
						   && tp_ch_info->transport_id == ts_id) {

					   list_for_each_safe(rch_pos, rch_tmp, &(tp_ch_info->rch.list)) {
						   rch_info = list_entry(rch_pos, struct channel_st, list);
						   if(rch_info->service_id == sid)
							   return rch_info;
					   }
				   }
			   }
		   }
	   }
	
	return NULL;
}

static struct channel_group_st* GetProviderInfo(HX_INT8 *find_name, HX_INT8 find_name_len)
{
	int i = 0;

	for(i=0; i<ChannelList->provider_number; i++) {
		if(find_name_len == ChannelList->provider_info[i].name_len 
				&& ((memcmp(find_name, ChannelList->provider_info[i].name,find_name_len) == 0))) {

			return &ChannelList->provider_info[i];
		}
	}
	return NULL;
}

static HX_INT16 AddProviderInfo(struct channel_group_st add_provider)
{
	int i = 0;
	int inserted = 0;

	if(add_provider.name_len < 0)
		return -1;

	for(i=0; i<ChannelList->provider_number; i++) {
		if(strcasecmp((const char *)ChannelList->provider_info[i].name, (const char *)add_provider.name) > 0) {
			inserted = 1;

			verbose(TEST_DBG_ID,"add index %d provider : %s \n",i,add_provider.name);

			add_provider.id = GetProviderNewId();

			memmove(&ChannelList->provider_info[i+1], &ChannelList->provider_info[i], 
					(ChannelList->provider_number - i) * sizeof(struct channel_group_st));


			ChannelList->provider_info[i] = add_provider;
			ChannelList->provider_number++;
			return add_provider.id;
		}
	}

	if(inserted == 0) {

		verbose(TEST_DBG_ID,"add index %d provider : %s \n",ChannelList->provider_number,add_provider.name);

		add_provider.id = GetProviderNewId();

		ChannelList->provider_info[ChannelList->provider_number] = add_provider;
		ChannelList->provider_number++;

		return add_provider.id;
	}
	
	return -1;
}

static struct virtual_channel_st* GetVirtualChannelST(char type)
{
	if(type == VINDEX_TYPE_DEFAULT) { // all channel
		return ChannelList->original_vch;
	}
	else if(type == VINDEX_TYPE_TV) { //digital television
		return ChannelList->tv_vch;
	}
	else if(type == VINDEX_TYPE_RADIO) { //digital radio sound
		return ChannelList->radio_vch;
	}
	else if(type == VINDEX_TYPE_USER) { //USER
		return ChannelList->user_vch;
	}
	else if(type == VINDEX_TYPE_TEMP) { //USER
		return NULL;
	}
	else if(type >= VINDEX_TYPE_FAV_MIN && type <= VINDEX_TYPE_FAV_MAX) { 	// favorite channel
		return ChannelList->favorite_vch[type-VINDEX_TYPE_FAV_MIN];
	}
	else {
		warningn(TEST_DBG_ID, "unknown vch_type=%d\n", type);
	}
	return NULL;
}

static HX_INT16 VTYPE_GetVCHIndexByTSInfo(HX_INT8 tuner_id, HX_UINT8 ni, HX_UINT16 on_id, HX_UINT16 ts_id, HX_UINT32 freq, HX_UINT16 sid, HX_UINT8 polar, HX_INT8 vch_type)
{
	int i=0;

	struct virtual_channel_st *vch = GetVirtualChannelST(vch_type);
	HX_INT16 *vch_number = GetVirtualChannelVNumber(vch_type);

	if(vch == NULL || vch_number == NULL) {
		return -1;	
	}

	for(i=0; i<*vch_number; i++) {
		verbose(TEST_DBG_ID, "tuner_id(%d-%d) ni(%d-%d) on_id(0x%x-0x%x) ts_id(0x%x-0x%x) freq(%ld-%ld) sid(0x%x-0x%x) polar(%d,%d)\n"
				,vch[i].tuner_id, tuner_id
				,vch[i].net_index, ni
				,vch[i].original_network_id ,on_id
				,vch[i].transport_id ,ts_id 
				,vch[i].frequency, freq
				,vch[i].service_id , sid
				,vch[i].polar , polar);

		if(vch[i].tuner_id == tuner_id 
				&& vch[i].net_index == ni
				&& vch[i].original_network_id == on_id
				&&	vch[i].transport_id == ts_id 
				&& is_same_frequency(vch[i].frequency,freq)
				&&	vch[i].service_id == sid
				&&	vch[i].polar == polar) {

			return i;
		}
		if(freq == 0) {
			if(vch[i].net_index == ni 
					&& vch[i].original_network_id == on_id
					&&	vch[i].transport_id == ts_id 
					&&	vch[i].service_id == sid) {

				return i;
			}
		}
	}
	return -1;
}

static HX_INT16* GetVirtualChannelVNumber(char type)
{
	if(type == VINDEX_TYPE_DEFAULT) { // all channel
		return &ChannelList->original_vnumber;
	}
	else if(type == VINDEX_TYPE_TV) { //digital television
		return &ChannelList->tv_vnumber;
	}
	else if(type == VINDEX_TYPE_RADIO) { //digital radio sound
		return &ChannelList->radio_vnumber;
	}
	else if(type == VINDEX_TYPE_USER) { //USER
		return &ChannelList->user_vnumber;
	}
	else if(type == VINDEX_TYPE_TEMP) { //USER
		return NULL;
	}
	else if(type >= VINDEX_TYPE_FAV_MIN && type <= VINDEX_TYPE_FAV_MAX) { 	// favorite channel
		return &ChannelList->favorite_vnumber[type-VINDEX_TYPE_FAV_MIN];
	}
	else {
		warningn(TEST_DBG_ID, "unknown vch_type=%d\n", type);
	}
	return NULL;
}

static HX_STATUS AddRCHInfo(struct channel_st *ch, HX_UINT8 *network_name)
{
	struct network_ch_st *net_info = NULL;
	struct tp_ch_st *tp_ch_info = NULL;
	struct channel_st *rch_info = NULL;

	net_info = GetNetworkCHInfo(ch->net_index, ch->original_network_id);

	if(net_info == NULL) {
	//	struct network_st * network_st_info = find_network_by_net_index(net_index);
		net_info = AllocNetworkCHInfo(ch->net_index,ch->original_network_id,network_name);
	}

	tp_ch_info = GetTPCHInfoByNetworkCh(net_info, ch->ts_id, ch->freq, ch->polarisation);

	if(tp_ch_info == NULL) {
		tp_ch_info = AllocTPCHInfo(ch->ts_id, ch->freq, ch->polarisation);

		list_add_tail(&(tp_ch_info->list),&(net_info->tp_ch.list));
		net_info->tp_num++;
	}

	rch_info = get_rch_ch_info_by_tp_ch(tp_ch_info, ch->service_id);
	if (rch_info != NULL) {
		warningn(TEST_DBG_ID, "rch: s_id(0x%x), n_id(0x%x), ts_id(0x%x), name(%s), type(0x%04x)\n", rch_info->service_id, rch_info->original_network_id, rch_info->ts_id, rch_info->channel_name_list.name[0].data, rch_info->type);
		//warning(TEST_DBG_ID, "\tch: s_id(0x%x), n_id(0x%x), ts_id(0x%x), name(%s), type(0x%04x)\n", ch->service_id, ch->original_network_id, ch->ts_id, ch->channel_name_list.name[0].data, ch->type);
		return HX_OK;
	}

	list_add_tail(&ch->list,&tp_ch_info->rch.list);
	tp_ch_info->rch_num++;

	return HX_OK;
}

static struct network_ch_st* GetNetworkCHInfo(HX_UINT8 ni, HX_UINT16 on_id)
{
	struct list_head *net_pos=NULL, *net_tmp=NULL;
	struct network_ch_st *net_info = NULL;

	list_for_each_safe(net_pos, net_tmp, &ChannelList->network.list) {
		net_info = list_entry(net_pos, struct network_ch_st, list);
		if(net_info->network_id == on_id
				&& net_info->net_index == ni)
			return net_info;
	}
	verbosen(TEST_DBG_ID, "Fail to find network_ch ni=%d, on_id=0x%x\n", ni, on_id);
	return NULL;
}

static struct network_ch_st *AllocNetworkCHInfo(HX_UINT8 net_index, HX_UINT16 network_id, HX_UINT8 *name )
{
	struct network_ch_st *network = NULL;
	network = (struct network_ch_st *)calloc(1,sizeof(struct network_ch_st));
	INIT_LIST_HEAD(&(network->list));
	if (network != NULL) {
		network->net_index = net_index;
		network->network_id = network_id;

		if(name != NULL) 
			memcpy(network->name,name,MAX_SAT_NAME_LEN);

		INIT_LIST_HEAD(&(network->tp_ch.list));
		list_add_tail(&(network->list), &(ChannelList->network.list));
		ChannelList->network_num++;
	}
		
	return network;
}

static struct tp_ch_st *GetTPCHInfoByNetworkCh(struct network_ch_st *net_info, HX_UINT16 ts_id, HX_UINT32 freq, HX_UINT8 polar)
{
	struct list_head *tp_ch_pos, *tp_ch_tmp;
	struct tp_ch_st *tp_ch_info = NULL;

	list_for_each_safe(tp_ch_pos, tp_ch_tmp, &net_info->tp_ch.list) {
		tp_ch_info = list_entry(tp_ch_pos, struct tp_ch_st, list);
#if 1
		if (freq == 0) {
			if(tp_ch_info->transport_id == ts_id) 
				return tp_ch_info;
		}
		else {
			if (is_same_frequency(tp_ch_info->frequency,freq)
					&& tp_ch_info->polarisation == polar)
				return tp_ch_info;
		}
#else
		if(tp_ch_info->transport_id == ts_id
				&& (freq == 0 ? 1: is_same_frequency(tp_ch_info->frequency,freq));
				&& (tp_ch_info->polarisation == polar))
			return tp_ch_info;
#endif
	}
	verbosen(TEST_DBG_ID, "Fail to find tp_ch ts_id=0x%x, freq=%ld, polar %d \n", ts_id, freq, polar);
	return NULL;
}

static struct tp_ch_st *AllocTPCHInfo(HX_UINT16 transport_id, HX_UINT32 frequency, HX_UINT8 polar)
{
	struct tp_ch_st *tp_ch_info = NULL;

	tp_ch_info = (struct tp_ch_st *)calloc(1,sizeof(struct tp_ch_st));

	INIT_LIST_HEAD(&(tp_ch_info->list));
	INIT_LIST_HEAD(&(tp_ch_info->rch.list));
	if(tp_ch_info != NULL) {
		tp_ch_info->transport_id = transport_id;
		tp_ch_info->frequency = frequency;
		tp_ch_info->polarisation = polar;

		INIT_LIST_HEAD(&(tp_ch_info->rch.list));
	//	list_add_tail(&(tp_ch_info->list), &(ChannelList->network.tp_ch.list));
	//	ChannelList->network.tp_num++;
	}
	return tp_ch_info;
}

static struct channel_st *get_rch_ch_info_by_tp_ch(struct tp_ch_st *tp_ch_info, HX_UINT16 service_id)
{
	struct list_head *rch_pos, *rch_tmp;
	struct channel_st *rch_info = NULL;
	if (tp_ch_info == NULL)
		return NULL;

	list_for_each_safe(rch_pos, rch_tmp, &tp_ch_info->rch.list) {
		rch_info = list_entry(rch_pos, struct channel_st, list);
		if(rch_info->service_id == service_id) {
			return rch_info;
		}
	}
	verbosen(TEST_DBG_ID, "Fail to find rchannel sid=0x%x\n", service_id);
	return NULL;
}

static HX_INT16 GetProviderNewId(void)
{
	int i;
	short insert_flag[MAX_PROVIDER];

	memset(insert_flag,-1,sizeof(insert_flag));

	for(i=0; i<ChannelList->provider_number; i++) {
		insert_flag[ChannelList->provider_info[i].id] = ChannelList->provider_info[i].id;
	}

	for(i=0; i< MAX_PROVIDER; i++) {
		if(insert_flag[i] == -1 )
			return i;
	}
	errorn(TEST_DBG_ID,"\n");
	return -1;
}

enum eChannelClolumn {
	eTUNERID = 0,
	ePOSITION,
	eFREQUENCY,
	ePOLARISATION,
	eSERVICE_ID,
	eORIGINAL_NETWORK_ID,
	eTRANSPORT_ID,
	eATAG,
	eAPID,
	eVTAG,
	eVPID,
	ePCR,
	ePMT,
	eCHANNEL_TYPE,
	eCHANNEL_NAME,
	ePACKAGE_CODE,
	eCOUNTRY,
	eGENRE,
	eCRYPT,
	eSD_HD,
};

static int AddChannelFromFile(const char *FileName)
{
	struct save_channel_info_st channel_info;
	int iCnt = 0;
	FILE *fp;
	char buffer[256];

	//eTUNERID;ePOSITION;eFREQUENCY;ePOLARISATION;eSERVICE_ID;eORIGINAL_NETWORK_ID;eTRANSPORT_ID;eATAG;eAPID;eVTAG;eVPID;ePCR;ePMT;eCHANNEL_TYPE;eCHANNEL_NAME;ePACKAGE_CODE;eCOUNTRY;eGENRE;eCRYPT;eSD_HD;
	//0;1160;11900100;0;403;173;4;129;1075;27;1072;1072;1082;1;KBS1-TVSDK;TVSDK;2;3;5;0;1;
	//0;130;10719000;1;4408;318;11000;4;108;2;167;167;1008;1;PATIO TV-TVSDK;TVSDK;2;3;5;0;1;

	if((fp = fopen(FileName, "r")) == NULL) {
		errorn(TEST_DBG_ID,"Can't load File '%s'",FileName);
		return -1;
	}

	while(fgets(buffer, 256, fp) != NULL){
		int iOffSet = 0;
		int iColumnNum = 0;
		int i=0;
		int read_size = strlen(buffer);
		struct network_st* net = NULL;
		struct multiplex_st *mp = NULL;

		buffer[read_size - 1] = '\0';

		for(i=0; i<read_size-1; i++) {

			if(buffer[i] == ';' || buffer[i] == '\n') {

				switch(iColumnNum) {
					case eTUNERID : 
						{
							char temp[2];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mTunerId = atoi(temp);
						}
						break;
					case ePOSITION : 
						{
							char temp[5];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mPosition = atoi(temp);

							if(channel_info.mPosition <= 0)
								return -1;
						}
						break;
					case eFREQUENCY:
						{
							char temp[10];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mFreq = atoll(temp);


							if(channel_info.mFreq <= 0)
								return -1;

						}
						break;
					case ePOLARISATION :
						{
							char temp[2];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mPolarisation = atoi(temp);
						}
						break;
					case eSERVICE_ID :
						{
							char temp[6];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mServiceId = atoi(temp);
						}
						break;
					case eORIGINAL_NETWORK_ID :
						{
							char temp[6];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mOriginalNetworkId = atoi(temp);
						}
						break;
					case eTRANSPORT_ID :
						{
							char temp[6];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mTransportId = atoi(temp);
						}
						break;
					case eATAG :
						{
							char temp[6];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mATag = atoi(temp);
						}
						break;

					case eAPID :
						{
							char temp[6];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mAPid = atoi(temp);
						}
						break;
					case eVTAG :
						{
							char temp[6];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mVTag = atoi(temp);
						}
						break;
					case eVPID :
						{
							char temp[6];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mVPid = atoi(temp);
						}
						break;
					case ePCR :
						{
							char temp[6];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mPCR = atoi(temp);
						}
						break;
					case ePMT :
						{
							char temp[6];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mPMT = atoi(temp);
						}
						break;

					case eCHANNEL_TYPE :
						{
							char temp[2];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mChannelType = atoi(temp);
						}
						break;
					case eCHANNEL_NAME :
						{
							if(i-iOffSet > MAX_SERVICE_NAME_LEN-1)
								memcpy(channel_info.mChannelName,buffer+iOffSet,MAX_SERVICE_NAME_LEN-1);
							else
								memcpy(channel_info.mChannelName,buffer+iOffSet,i-iOffSet);
						}
						break;
					case ePACKAGE_CODE :
						{
							if(i-iOffSet > MAX_SERVICE_NAME_LEN-1)
								memcpy(channel_info.mProviderPackageCode,buffer+iOffSet,MAX_SERVICE_NAME_LEN-1);
							else
								memcpy(channel_info.mProviderPackageCode,buffer+iOffSet,i-iOffSet);
						}
						break;

					case eCOUNTRY :
						{
							char temp[4];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mCountry = atoi(temp);
						}
						break;
					case eGENRE :
						{
							char temp[4];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mGenre = atoi(temp);
						}
						break;

					case eCRYPT :
						{
							char temp[2];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mCrypt = atoi(temp);
						}
						break;

					case eSD_HD :
						{
							char temp[2];
							memset(temp,0x00,sizeof(temp));
							memcpy(temp,buffer+iOffSet,i-iOffSet);
							channel_info.mSDHD = atoi(temp);
						}
						break;

					default:
						break;
				}

				iOffSet =  i+1;
				iColumnNum++;
			}
		}

		if(buffer[i] == '\n' || buffer[i] == '\0' ) {

#if 1
			infon(TEST_DBG_ID,"===================================================\n");
			infon(TEST_DBG_ID,"\tTuner_id : %d \n", channel_info.mTunerId);
			infon(TEST_DBG_ID,"\tPosition : %d \n", channel_info.mPosition);
			infon(TEST_DBG_ID,"\tFrequency : %lu \n", channel_info.mFreq);
			infon(TEST_DBG_ID,"\tPolarisation : %d \n", channel_info.mPolarisation);
			infon(TEST_DBG_ID,"\tService_id: %d \n", channel_info.mServiceId);
			infon(TEST_DBG_ID,"\tOriginal_id: %d \n", channel_info.mOriginalNetworkId);
			infon(TEST_DBG_ID,"\tTransport_id: %d \n", channel_info.mTransportId);
			infon(TEST_DBG_ID,"\tA-PID: %d \n", channel_info.mAPid);
			infon(TEST_DBG_ID,"\tV-PID: %d \n", channel_info.mVPid);
			infon(TEST_DBG_ID,"\tPCR: %d \n", channel_info.mPCR);
			infon(TEST_DBG_ID,"\tPMT: %d \n", channel_info.mPMT);
			infon(TEST_DBG_ID,"\tChannelType: %d \n", channel_info.mChannelType);
			infon(TEST_DBG_ID,"\tChannelName: %s \n", channel_info.mChannelName);
			infon(TEST_DBG_ID,"\tCountry: %d \n", channel_info.mCountry);
			infon(TEST_DBG_ID,"\tProvider: %s \n", channel_info.mProviderPackageCode);
			infon(TEST_DBG_ID,"\tCrypt: %d \n", channel_info.mCrypt);
			infon(TEST_DBG_ID,"\tGenre: %d \n", channel_info.mGenre);
			infon(TEST_DBG_ID,"\tSD-HD: %d \n", channel_info.mSDHD);
#endif


			net = FindNetworkByPosition(channel_info.mPosition);

			if(net != NULL) {
				mp = FindMultiplexByNetwork(net, channel_info.mFreq, channel_info.mPolarisation);

				if(mp != NULL) {
					AddChannel(net,&channel_info);
				}
				else
					infon(TEST_DBG_ID,"Can't find 'multiplex' \n");

			}
			else {
				infon(TEST_DBG_ID,"Can't find 'network' \n");
			}

			iCnt++;
			iColumnNum = 0;
			iOffSet =  i+1;
		}
	}
	info(TEST_DBG_ID,"iCnt %d \n",iCnt);

	ChannelSDK_Save(ALL_CHANNEL_FILE);
	return iCnt;
}

#if 1
static HX_STATUS PrintReservedList(struct reserved_list_st *reserved_list) 
{
	struct list_head *ch_pos, *ch_tmp;
	struct reserved_info_st *info;
	if(reserved_list == NULL)
		infon(TEST_DBG_ID,"reserved_list NULL...\n");

	info(TEST_DBG_ID,"********************************************************************\n");
	info(TEST_DBG_ID,"********************************************************************\n");
	info(TEST_DBG_ID,"*\tversion %d \n",reserved_list->version);
	info(TEST_DBG_ID,"*\ttotal_count %d \n",reserved_list->total_count);
	info(TEST_DBG_ID,"*\treserved_cnt %d \n",reserved_list->reserved_cnt);
	info(TEST_DBG_ID,"*\tmax_reserved_cnt %d \n",reserved_list->max_reserved_cnt);
	info(TEST_DBG_ID,"*\tcur_cnt %d \n",reserved_list->cur_cnt);
	info(TEST_DBG_ID,"********************************************************************\n");

	if(reserved_list->total_count > 0) {
		list_for_each_safe(ch_pos, ch_tmp, &reserved_list->info.list) {
			info = list_entry(ch_pos, struct reserved_info_st, list);
			PrintReservedInfo(info);
		}
	}
	return HX_OK;
}

static void PrintReservedInfo(struct reserved_info_st *info) 
{
	if (info != NULL) {

#if 1
		info(TEST_DBG_ID,"__________________________________________________________\n");
		info(TEST_DBG_ID,"status = %s\n",RES_STATUS(info->status));
		info(TEST_DBG_ID,"rec_file = %s\n",info->rec_file);
		info(TEST_DBG_ID,"rec_path = %s\n",info->rec_path);
		info(TEST_DBG_ID,"real_start = %ld\n",info->real_start);
		info(TEST_DBG_ID,"preserve = %ld\n",info->preserve);
		info(TEST_DBG_ID,"mode = %d\n",info->mode);
		info(TEST_DBG_ID,"repeat = %d\n",info->repeat);
		info(TEST_DBG_ID,"mask = %d\n",info->mask);
		{
			int i;
			for(i=0; i<7 ;i++) {
				if(i==0)
					info(TEST_DBG_ID,"(SUN)");
				else if(i==1)
					info(TEST_DBG_ID,"(MON)");
				else if(i==2)
					info(TEST_DBG_ID,"(TUE)");
				else if(i==3)
					info(TEST_DBG_ID,"(WED)");
				else if(i==4)
					info(TEST_DBG_ID,"(THU)");
				else if(i==5)
					info(TEST_DBG_ID,"(FRI)");
				else if(i==6)
					info(TEST_DBG_ID,"(SAT)");

				info(TEST_DBG_ID,"%d : %d\n",i,((info->mask >> i) & 0x01));
			}
		}
		info(TEST_DBG_ID,"start_time = %lu\n",info->start_time);
		info(TEST_DBG_ID,"TIME = %s\n",ctime(&info->start_time));

#if 1
		info(TEST_DBG_ID,"tuner id = %d\n",info->tuner_id);
		info(TEST_DBG_ID,"net_index = %d\n",info->net_index);
		info(TEST_DBG_ID,"freq = %ld\n",info->freq);
		info(TEST_DBG_ID,"polar = %d\n",info->polar);
		info(TEST_DBG_ID,"original_network_id = %02x\n",info->original_network_id);
		info(TEST_DBG_ID,"transport_stream_id = %02x\n",info->transport_stream_id);
		info(TEST_DBG_ID,"service_id = %02x\n",info->service_id);
		info(TEST_DBG_ID,"event_id = %02x\n",info->event_id);
		info(TEST_DBG_ID,"duration = %lu\n",info->duration);
		info(TEST_DBG_ID,"nibble_level_1 = %x\n",info->nibble_level_1);
		info(TEST_DBG_ID,"nibble_level_2 = %x\n",info->nibble_level_2);
		info(TEST_DBG_ID,"user_nibble_level_1 = %x\n",info->nibble_level_1);
		info(TEST_DBG_ID,"user_nibble_level_2 = %x\n",info->nibble_level_2);
		info(TEST_DBG_ID,"parental_rating = %x\n",info->parental_rating);
		info(TEST_DBG_ID,"event_lang = %c%c%c\n",info->event_lang[0],info->event_lang[1],info->event_lang[2]);
		info(TEST_DBG_ID,"ch_name = %s\n",info->ch_name);
		info(TEST_DBG_ID,"ch_name_len = %d\n",info->ch_name_len);
		info(TEST_DBG_ID,"title = %s\n",info->title);
		info(TEST_DBG_ID,"title_len = %d\n",info->title_len);
#endif
		info(TEST_DBG_ID,"__________________________________________________________\n");
#endif

	}
}
#endif

