/***********************************************************
Copyright (C), LGC Wireless.
File Name:		isdn_debug.c
Description:	ISDN Debug
Version:		v9.1.0
Author:			Gengxin Chen
Create Date:	2008-5-27
History:
	<author>	<date>		<version>		<desc>
	
************************************************************/

#include "./include/isdn_debug.h"

#define DEBUG_ID				24
#define VER_DEBUG				"R9V1_01"
#define IS_PATCH				2

//#define PROTO_ISDN				3
#define PAGE_NUM				5
#define ISDN_MONITOR_NONE			0x0000
#define ISDN_MONITOR_ERROR		0x0002
#define ISDN_MONITOR_MSG			0x0004
#define ISDN_MONITOR_FUNC			0x0008
#define ISDN_MONITOR_STATE		0x8000
#define ISDN_MONITOR_ALL			0x7fff

static ISDN_Msg_Csta isdn_csta;
static u8		AsciInBuf[4096];
static u8		AsciOutBuf[4096];
static u8		AsciTempBuf[4096];
static u16		MonitorIsdnFg;
static u8		info[4096];
static int		debug_link_id;

static u8 log_help[] = {
	"ISDN Debug Monitor Help:\n\r\
	\n\r\
	1.[help]                                    display help menu\n\r\
	2.[log all/none]                            display all/none logs\n\r\
	3.[log error on/off]                        display error logs \n\r\
	3.[log state on/off]                        display state logs \n\r\
	4.[list cg]                                 display all cg (N/A)\n\r\
	5.[list cg-x]                               display cg  (N/A)\n\r\
	6.[list circuit-x]                          display circuit->port  (N/A)\n\r\n\r"
};


static u16		disp_page[10];
static u8		*disp_ptr = (u8 *) disp_page;

static u32		debug_status_id[20] = 
{
	1,3,6,1,4,1,1373,1,1,2,3,1,2,DEBUG_ID + 2,1
};

static u8		debug_status = 1;

static u32		debug_name_id[20] = 
{
	1,3,6,1,4,1,1373,1,1,2,3,1,2,DEBUG_ID + 2,2
};

static u32 	debug_ascin_id[20] = 
{
	1,3,6,1,4,1,1373,1,1,2,3,1,2,DEBUG_ID + 2,3
};

static u32		debug_ascout_id[20] = 
{
	1,3,6,1,4,1,1373,1,1,2,3,1,2,DEBUG_ID + 2,4
};

static u32		debug_page_title[20] = 
{
	1,3,6,1,4,1,1373,1,1,2,3,1,2,DEBUG_ID + 2,1,1
};

static u32		debug_page_line[20] = 
{
	1,3,6,1,4,1,1373,1,1,2,3,1,2,DEBUG_ID + 2,1,2,1
};

const static u8		BASE_ID_LEN = 15;
const static u8		PAGE_POINT = 14;
const static u8		LINE_POINT = 15;

static u8		title1_p[] = 
{
	"    ISDN    Page 01    SAP Info\n\r\
                   0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15\n\r\
Subpage\n\r\
Enable\n\r\
SystemID\n\r\
Run mode\n\r\
Remote IP\n\r"
};

static u8		title2_p[] = 
{
	"    ISDN    Page 02    CG      Info\n\r\
                   0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15\n\r\
Subpage\n\r\
Enable\n\r\
SAP_ID\n\r\
Circuit_num\n\r\
Variant\n\r\
Priority\n\r\
TG_ID\n\r\
NFAS\n\r\
PRI\n\r\
BACKUP\n\r"
};

static u8		title3_p[] = 
{
	"    ISDN    Page 03    Circuit Info\n\r\
                   0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15\n\r\
Subpage\n\r\
Enable\n\r\
CG_ID\n\r\
PLAT_ID\n\r\
HEAD CIC\n\r\
CIC RANGE\n\r\
D-CHANNEL\n\r\
LINK_ID\n\r\
LK2_STATUS\n\r\
LK3_STATUS\n\r\
DC_STATUS\n\r"
};

static u8		title4_p[] = 
{
	"    ISDN    Page 04    Port Info\n\r\
                   0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15\n\r\
Subpage\n\r\
Enable\n\r\
Fsm_state\n\r\
CIC_state\n\r\
SU_port\n\r\
Timer_F\n\r\
Time_W\n\r"
};

static u8		title5_p[] = 
{
	"    ISDN    Page 05    Csta Info\n\r\
                   0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15\n\r\
RV-SD-SETUP\n\r\
RV-SD-SETUPACK\n\r\
RV-SD-CALLPROC\n\r\
RV-SD-ALERT\n\r\
RV-SD-CONN\n\r\
RV-SD-CONNACK\n\r\
RV-SD-DISC\n\r\
RV-SD-REL\n\r\
RV-SD-RELCOMP\n\r\
RD-SETUP\n\r\
RD-SETUPACK\n\r\
RD-CALLPROC\n\r\
RD-ALERT\n\r\
RD-CONN\n\r\
RD-CONNACK\n\r\
RD-DISC\n\r\
RD-REL\n\r\
RD-RELCOMP\n\r"
};


static void debug_setcol(int color);
static void debug_cancelcol();

static void isdn_asciout_proc(const char *fmt, ...)
{
	va_list	ap;
	char		buf[4096];

	va_start(ap, fmt);
	vsprintf(buf, fmt, ap);
	if((strlen(AsciOutBuf) + strlen(buf)) < 4096)
		strcat(AsciOutBuf, buf);
	else
		strcpy(AsciOutBuf, buf);
	va_end(ap);
}

static void list_sap(u8 sap_id)
{
	const pal_sap_struct *sap_ptr = pal_sap_ptr(sap_id);
	if(sap_ptr == NULL)
	{
		printf("list sap err!sap_id = %d, can't find sap_ptr!\n", sap_id);
		return;
	}
	
	if(sap_id >= ISDN_MAX_SAP)
		return;
	sprintf(info,"\r\n\
		#ISDN SAP Info\r\n\
		Enable=%d\r\n\
		SystemID(%d)\r\n\
		Run mode(%d)\r\n\
		Remote IP(%lx)\r\n\
		------------------\r\n",
		sap_ptr->enable,
		isdn_rs.attrib.systemID, 
		isdn_rs.attrib.isdn_run_mode, 
		isdn_rs.attrib.isdn_remote_ip);
	isdn_asciout_proc(info);
}

static void list_cg(u16 cg_id)
{
	const pal_cg_struct *cg_ptr = pal_cg_ptr(cg_id);
	if(cg_ptr == NULL)
	{
		printf("list cg err!cg_id = %d, can't find cg_ptr!\n", cg_id);
		return;
	}
	if(cg_ptr->attrib.protocol != PROTO_ISDN)
		return;
	
	if(cg_id >= ISDN_MAX_CG)
		return;
	sprintf(info,"\r\n\
		#ISDN CG- %d Info\r\n\
		enable:%d\r\n\
		sap_id:%d\r\n\
		circuit_num:%d\r\n\
		Attrib-->\r\n\
		variant_type(%d)\r\n\
		priority(%d)\r\n\
		tg_id(%ld)\r\n\
		NFAS(%d)\r\n\
		pri_link(%ld)\r\n\
		backup_link(%ld)\r\n\
		---------------------\r\n",
		cg_id,
		cg_ptr->enable,
		cg_ptr->sap_id,
		cg_ptr->circuit_num,
		cg_ptr->attrib.variant,
		cg_ptr->attrib.priority,
		cg_ptr->attrib.tg_id,
		cg_ptr->attrib.nfas.flag,
		cg_ptr->attrib.nfas.prim_link,
		cg_ptr->attrib.nfas.backup_link
		);
	isdn_asciout_proc(info);
}
static void list_all_cg(void)
{
	int i;
	const pal_cg_struct *cg_ptr = NULL;

	isdn_asciout_proc("CgId\tSapId\tCircirtNum\tVariant\tPrior\tTgId\tNFAS\tPRI\tBackUp\r\n");
	for(i = 0; i < ISDN_MAX_CG; i++)
	{
		cg_ptr = pal_cg_ptr(i);
		if(cg_ptr == NULL)
			continue;
		if(cg_ptr->attrib.protocol != PROTO_ISDN)
			continue;
	
		if(cg_ptr->enable == 0)
			continue;
		sprintf(info,"%d\t%d\t%d\t\t%d\t%d\t%ld\t%d\t%ld\t%ld\r\n",
			i,
			cg_ptr->sap_id,
			cg_ptr->circuit_num,
			cg_ptr->attrib.variant,
			cg_ptr->attrib.priority,
			cg_ptr->attrib.tg_id,
			cg_ptr->attrib.nfas.flag,
			cg_ptr->attrib.nfas.prim_link,
			cg_ptr->attrib.nfas.backup_link);
		isdn_asciout_proc(info);
	}
}

static void list_circuit(u16 circuit_id)
{
	const pal_cg_struct *cg_ptr = NULL;
	const pal_circuit_struct *circuit_ptr = pal_circuit_ptr(circuit_id);
	if(circuit_ptr == NULL)
	{
		printf("list circuit err!circuit_id = %d, can't find circuit_ptr!\n", circuit_id);
		return;
	}
	if(circuit_id >= ISDN_MAX_CIRCUIT)
		return;
	cg_ptr = pal_cg_ptr(circuit_ptr->cg_id);
	if(cg_ptr == NULL)
		return;
	if(cg_ptr->attrib.protocol != PROTO_ISDN)
		return;
	sprintf(info,"\r\n\
		#ISDN Circuit-%d Info\r\n\
		enable:%d\r\n\
		cg_id:%d\r\n\
		Attrib->\r\n\
		plat_id(%d)\r\n\
		head_cic(%ld)\r\n\
		cic_range(%d)\r\n\
		d_channel(%d)\r\n\
		link_id(%ld)\r\n\
		lk2_status(%d)\r\n\
		lk3_status(%d)\r\n\
		dc_status(%d)\r\n\
		-------------------\r\n",
		circuit_id,
		circuit_ptr->enable,
		circuit_ptr->cg_id,
		circuit_ptr->attrib.plat_id,
		circuit_ptr->attrib.head_cic,
		circuit_ptr->attrib.cic_range,
		circuit_ptr->attrib.d_chnl,
		circuit_ptr->attrib.link_id,
		isdn_rs.link_pond[circuit_ptr->attrib.link_id].lk2_status,
		isdn_rs.link_pond[circuit_ptr->attrib.link_id].lk3_status,
		isdn_rs.link_pond[circuit_ptr->attrib.link_id].dc_status);
	isdn_asciout_proc(info);
}
static void list_all_circuit()
{
	int i;
	const pal_cg_struct *cg_ptr = NULL;
	const pal_circuit_struct *circuit_ptr = NULL;
	
	isdn_asciout_proc("CircuitId\tCgId\tPlatId\tHeatCic\tRange\tD_Chnl\tLinkId\tLk2Status\tLk3Status\tDcStatus\r\n");
	for(i = 0; i < ISDN_MAX_CIRCUIT; i++)
	{
		circuit_ptr = pal_circuit_ptr(i);
		if(circuit_ptr == NULL)
			continue;		
		if(circuit_ptr->enable == 0)
			continue;
		
		cg_ptr = pal_cg_ptr(circuit_ptr->cg_id);
		if(cg_ptr == NULL)
			continue;
		if(cg_ptr->attrib.protocol != PROTO_ISDN)
			continue;

		sprintf(info,"%d\t\t%d\t%d\t%ld\t%d\t%d\t%ld\t%d\t\t%d\t\t%d\r\n",
			i,
			circuit_ptr->cg_id,
			circuit_ptr->attrib.plat_id,
			circuit_ptr->attrib.head_cic,
			circuit_ptr->attrib.cic_range,
			circuit_ptr->attrib.d_chnl,
			circuit_ptr->attrib.link_id,
			isdn_rs.link_pond[circuit_ptr->attrib.link_id].lk2_status,
			isdn_rs.link_pond[circuit_ptr->attrib.link_id].lk3_status,
			isdn_rs.link_pond[circuit_ptr->attrib.link_id].dc_status);
		isdn_asciout_proc(info);
	}
}
static void list_all_circuit_by(u16 cg_id)
{
	int i;
	const pal_cg_struct *cg_ptr = NULL;
	const pal_circuit_struct *circuit_ptr = NULL;
	
	isdn_asciout_proc("--->circuit:\r\n");
	isdn_asciout_proc("CircuitId\tCgId\tPlatId\tHeatCic\tRange\tD_Chnl\tLinkId\tLk2Status\tLk3Status\tDcStatus\r\n");
	for(i = 0; i < ISDN_MAX_CIRCUIT; i++)
	{
		circuit_ptr = pal_circuit_ptr(i);
		if(circuit_ptr == NULL)
			continue;	
		if(circuit_ptr->enable == 0 && 
			circuit_ptr->cg_id != cg_id)
			continue;
		cg_ptr = pal_cg_ptr(circuit_ptr->cg_id);
		if(cg_ptr == NULL)
			continue;
		if(cg_ptr->attrib.protocol != PROTO_ISDN)
			continue;

		sprintf(info,"%d\t\t%d\t%d\t%ld\t%d\t%d\t%ld\t%d\t\t%d\t\t%d\r\n",
			i,
			circuit_ptr->cg_id,
			circuit_ptr->attrib.plat_id,
			circuit_ptr->attrib.head_cic,
			circuit_ptr->attrib.cic_range,
			circuit_ptr->attrib.d_chnl,
			circuit_ptr->attrib.link_id,
			isdn_rs.link_pond[circuit_ptr->attrib.link_id].lk2_status,			
			isdn_rs.link_pond[circuit_ptr->attrib.link_id].lk3_status,
			isdn_rs.link_pond[circuit_ptr->attrib.link_id].dc_status);
		isdn_asciout_proc(info);
	}
}

static void list_port(u32 pid)
{
	if(pid >= ISDN_MAX_PORT)
		return;
	sprintf(info,"\r\n\
		#ISDN Port-%ld Info\r\n\
		enable:%d\r\n\
		su_proc_id:%ld\r\n\
		msg_cmd:%d\r\n\
		primitive_cmd:%d\r\n\
		------------------------\r\n\
		call_state:%d\r\n\
		maintenance_state:%d\r\n\
		------------------------\r\n\
		cpc_state:%d\r\n\
		m_state:%d\r\n\
		------------------------\r\n",
		pid,
		isdn_rs.port_pond[pid].enable,
		isdn_rs.port_pond[pid].su_proc_id,
		isdn_rs.port_pond[pid].msg_cmd,
		isdn_rs.port_pond[pid].primitive_cmd,
		isdn_rs.port_pond[pid].cic_state.call_state,
		isdn_rs.port_pond[pid].cic_state.maintenance_state,
		isdn_rs.port_pond[pid].fsm_state.cpc_state,
		isdn_rs.port_pond[pid].fsm_state.m_state);
	isdn_asciout_proc(info);
}
static void list_all_port()
{
	int i, j = 0;
	isdn_asciout_proc("index\tPort\tSuID\tcall_state\tmain_state\tcpc_state\tm_state\r\n");
	for(i = 0; i < ISDN_MAX_PORT; i++)
	{
		if(isdn_rs.port_pond[i].enable == 0)
			continue;
		sprintf(info,"%d\t%d\t%ld\t%d\t\t%d\t\t%d\t\t%d\r\n",
			j++,
			i,
			isdn_rs.port_pond[i].su_proc_id,
			isdn_rs.port_pond[i].cic_state.call_state,
			isdn_rs.port_pond[i].cic_state.maintenance_state,
			isdn_rs.port_pond[i].fsm_state.cpc_state,
			isdn_rs.port_pond[i].fsm_state.m_state);
		isdn_asciout_proc(info);
	}
}
static void list_all_port_by(u16 circuit_id)
{
	int i,cic,pid;
	const pal_cg_struct *cg_ptr = NULL;
	const pal_circuit_struct *circuit_ptr = pal_circuit_ptr(circuit_id);
	if(circuit_ptr == NULL)
	{
		printf("list all port by circuit_id err!circuit_id = %d, can't find circuit_ptr!\n", circuit_id);
		return;
	}
	cg_ptr = pal_cg_ptr(circuit_ptr->cg_id);
	if(cg_ptr == NULL)
		return;
	if(cg_ptr->attrib.protocol != PROTO_ISDN)
		return;
	
	pid = ISDN_CIRCUIT_CIC * circuit_id;
	cic = circuit_ptr->attrib.head_cic;

	isdn_asciout_proc("-->port:\r\n");
	isdn_asciout_proc("CIC\tPort\tSuID\tcall_state\tmain_state\tcpc_state\tm_state\r\n");

	for(i = 0; i < circuit_ptr->attrib.cic_range; i++)
	{		
		isdn_asciout_proc("%d\t%d\t%d\t%d\t\t%d\t\t%d\t\t%d\r\n",
			cic,
			pid,
			isdn_rs.port_pond[pid].su_proc_id,
			isdn_rs.port_pond[pid].cic_state.call_state,
			isdn_rs.port_pond[pid].cic_state.maintenance_state,
			isdn_rs.port_pond[pid].fsm_state.cpc_state,
			isdn_rs.port_pond[pid].fsm_state.m_state);
		cic++;
		pid++;
	}
}

static int list_cic(u8 link_id, u32 cic_val)
{	
	int i,pid;
	u32 head_cic;
	const pal_circuit_struct *circuit_ptr = NULL;
	const pal_cg_struct *cg_ptr = NULL;

	for(i = 0; i < ISDN_MAX_CIRCUIT; i++)
	{
		circuit_ptr = pal_circuit_ptr(i);
		if(circuit_ptr == NULL)
			continue;
	
		if(circuit_ptr->enable == 0)
			continue;
		
		if((cic_val < circuit_ptr->attrib.head_cic) || 
			((cic_val - circuit_ptr->attrib.head_cic ) >= 
				circuit_ptr->attrib.cic_range))
			continue;
		cg_ptr = pal_cg_ptr(circuit_ptr->cg_id);
		if(cg_ptr == NULL)
			continue;
		if(cg_ptr->attrib.protocol != PROTO_ISDN)
			continue;

		if(cg_ptr->attrib.nfas.flag)
		{
			if(cg_ptr->attrib.nfas.prim_link != link_id &&
				cg_ptr->attrib.nfas.backup_link != link_id)
				continue;
		}
		else
		{
			if(circuit_ptr->attrib.link_id != link_id)
				continue;
		}

		head_cic = circuit_ptr->attrib.head_cic;
		if(circuit_ptr->attrib.cic_range == 24)
			head_cic--;
		pid = ISDN_CIRCUIT_CIC * i + (cic_val - head_cic);
				
		list_sap(cg_ptr->sap_id);				
		list_cg(circuit_ptr->cg_id);
		list_circuit(i);
		list_port(pid);
		
		return 1;
	}
	sprintf(info, "illegal cic value! link_id=%d,cic=%ld\r\n", link_id, cic_val);
	isdn_asciout_proc(info);

	return -1;
}

static void debug_setcol(int color)
{
	isdn_asciout_proc("%c[%dm",COL_ESC , color);
}

static void debug_cancelcol()
{
	isdn_asciout_proc("%c[m",COL_ESC);
}

static u16 debug_disp_line(u8 page, u8 line)
{
	u16 disp_length;

	disp_length = 0;
	disp_ptr = (u8 *)disp_page;
	const pal_sap_struct *sap_ptr = pal_sap_ptr(disp_page[page]);
	if(sap_ptr == NULL)
		return ISDN_CM_FAILED;
	const pal_circuit_struct *circuit_ptr = pal_circuit_ptr(disp_page[page]);
	if(circuit_ptr == NULL)
		return ISDN_CM_FAILED;
	const pal_cg_struct *cg_ptr = pal_cg_ptr(disp_page[page]);
	if(cg_ptr == NULL)
		return ISDN_CM_FAILED;	
	if(cg_ptr->attrib.protocol != PROTO_ISDN)
		return ISDN_CM_FAILED;

	switch(page)
	{
		case 1:	// Page 1: sap Info
			switch(line)
			{
				case 0:
					disp_ptr = (u8 *)&disp_page[page];	//Subpage
					disp_length = 2;
					break;
				case 1:											//enable
					disp_ptr = (u8 *)&(sap_ptr->enable);
					disp_length = 1;
					break;
				case 2:											//systemID
					disp_ptr = (u8 *)&(isdn_rs.attrib.systemID);
					disp_length = 1;
					break;
				case 3:											//run_mode
					disp_ptr = (u8 *)&(isdn_rs.attrib.isdn_run_mode);
					disp_length = 1;
					break;
				case 4:											//isdn_remote_ip
					disp_ptr = (u8 *)&(isdn_rs.attrib.isdn_remote_ip);
					disp_length = 4;
					break;
				default:
					break;
			}
			break;
		case 2:	// Page 2: cg  Info
			switch(line)
			{
				case 0:
					disp_ptr = (u8 *)&disp_page[page];	//Subpage
					disp_length = 2;
					break;
				case 1:											//enable
					disp_ptr = (u8 *)&(cg_ptr->enable);
					disp_length = 1;
					break;
				case 2:											//sap_id
					disp_ptr = (u8 *)&(cg_ptr->sap_id);
					disp_length = 1;
					break;
				case 3:											//circuit_num
					disp_ptr = (u8 *)&(cg_ptr->circuit_num);
					disp_length = 1;
					break;
				case 4:											//variant_type
					disp_ptr = (u8 *)&(cg_ptr->attrib.variant);
					disp_length = 1;
					break;
				case 5:											//priority
					disp_ptr = (u8 *)&(cg_ptr->attrib.priority);
					disp_length = 1;
					break;
				case 6:											//tg_id
					disp_ptr = (u8 *)&(cg_ptr->attrib.tg_id);
					disp_length = 4;
					break;
				case 7:											//nfas
					disp_ptr = (u8 *)&(cg_ptr->attrib.nfas.flag);
					disp_length = 1;
					break;
				case 8:											//pri
					disp_ptr = (u8 *)&(cg_ptr->attrib.nfas.prim_link);
					disp_length = 1;
					break;
				case 9:											//backup
					disp_ptr = (u8 *)&(cg_ptr->attrib.nfas.backup_link);
					disp_length = 1;
					break;
				default:
					break;
			}
			break;
		case 3:	// Page 3: circuit Info
			switch(line)
			{
				case 0:
					disp_ptr = (u8 *)&disp_page[page];	//Subpage
					disp_length = 2;
					break;
				case 1:											//enable
					disp_ptr = (u8 *)&(circuit_ptr->enable);
					disp_length = 1;
					break;
				case 2:											//cg_id
					disp_ptr = (u8 *)&(circuit_ptr->cg_id);
					disp_length = 2;
					break;
				case 3:											//plat_id
					disp_ptr = (u8 *)&(circuit_ptr->attrib.plat_id);
					disp_length = 1;
					break;
				case 4:											//head_cic
					disp_ptr = (u8 *)&(circuit_ptr->attrib.head_cic);
					disp_length = 4;
					break;
				case 5:											//cic_range
					disp_ptr = (u8 *)&(circuit_ptr->attrib.cic_range);
					disp_length = 1;
					break;
				case 6:											//d-channel
					disp_ptr = (u8 *)&(circuit_ptr->attrib.d_chnl);
					disp_length = 4;
					break;
				case 7:											//link_id
					disp_ptr = (u8 *)&(circuit_ptr->attrib.link_id);
					disp_length = 1;
					break;
				case 8:											//lk2_status
					disp_ptr = (u8 *)&(isdn_rs.link_pond[circuit_ptr->attrib.link_id].lk2_status);
					disp_length = 1;
					break;
				case 9:											//lk3_status
					disp_ptr = (u8 *)&(isdn_rs.link_pond[circuit_ptr->attrib.link_id].lk3_status);
					disp_length = 1;
					break;
				case 10:											//dc_status
					disp_ptr = (u8 *)&(isdn_rs.link_pond[circuit_ptr->attrib.link_id].dc_status);
					disp_length = 1;
					break;
				default:
					break;
			}
			break;
		case 4:	// Page 4: port Info
			switch(line)
			{
				case 0:
					disp_ptr = (u8 *)&disp_page[page];	//Subpage
					disp_length = 2;
					break;
				case 1:											//enable
					disp_ptr = (u8 *)&(isdn_rs.port_pond[disp_page[page]].enable);
					disp_length = 1;
					break;
				case 2:											//fsm_state	
					disp_ptr = (u8 *)&(isdn_rs.port_pond[disp_page[page]].fsm_state);
					disp_length = 2;
					break;
				case 3:											//cic_state
					disp_ptr = (u8 *)&(isdn_rs.port_pond[disp_page[page]].cic_state);
					disp_length = 2;
					break;
				case 4:											//su_proc_id
					disp_ptr = (u8 *)&(isdn_rs.port_pond[disp_page[page]].su_proc_id);
					disp_length = 4;
					break;
				case 5:											//timer_flag
					disp_ptr = (u8 *)&(isdn_rs.port_pond[disp_page[page]].timer_flag);
					disp_length = 2;
					break;
				case 6:											//w_time
					disp_ptr = (u8 *)&(isdn_rs.port_pond[disp_page[page]].w_time);
					disp_length = 4;
					break;
				default:
					break;
			}
			break;
		case 5:	// Page 5: call statistics Info
			switch(line)
			{
				//receive and send
				case 0:
					disp_ptr = (u8 *)&isdn_csta.rv_setup;
					disp_length = 8;
					break;
				case 1:
					disp_ptr = (u8 *)&isdn_csta.rv_setupAck;
					disp_length = 8;
					break;
				case 2:
					disp_ptr = (u8 *)&isdn_csta.rv_callProc;
					disp_length = 8;
					break;
				case 3:
					disp_ptr = (u8 *)&isdn_csta.rv_alert;
					disp_length = 8;
					break;
				case 4:		
					disp_ptr = (u8 *)&isdn_csta.rv_conn;
					disp_length = 8;
					break;
				case 5:
					disp_ptr = (u8 *)&isdn_csta.rv_connAck;
					disp_length = 8;
					break;
				case 6:
					disp_ptr = (u8 *)&isdn_csta.rv_disc;
					disp_length = 8;
					break;
				case 7:
					disp_ptr = (u8 *)&isdn_csta.rv_rel;
					disp_length = 8;
					break;
				case 8:
					disp_ptr = (u8 *)&isdn_csta.rv_relComp;
					disp_length = 8;
					break;
				//redirect
				case 9:
					disp_ptr = (u8 *)&isdn_csta.rd_setup;
					disp_length = 4;
					break;
				case 10:
					disp_ptr = (u8 *)&isdn_csta.rd_setupAck;
					disp_length = 4;
					break;
				case 11:
					disp_ptr = (u8 *)&isdn_csta.rd_callProc;
					disp_length = 4;
					break;
				case 12:
					disp_ptr = (u8 *)&isdn_csta.rd_alert;
					disp_length = 4;
					break;
				case 13:		
					disp_ptr = (u8 *)&isdn_csta.rd_conn;
					disp_length = 4;
					break;
				case 14:
					disp_ptr = (u8 *)&isdn_csta.rd_connAck;
					disp_length = 4;
					break;
				case 15:
					disp_ptr = (u8 *)&isdn_csta.rd_disc;
					disp_length = 4;
					break;
				case 16:
					disp_ptr = (u8 *)&isdn_csta.rd_rel;
					disp_length = 4;
					break;
				case 17:
					disp_ptr = (u8 *)&isdn_csta.rd_relComp;
					disp_length = 4;
					break;
				default:
					break;
			}
			break;
		default:
			disp_length = 0;
			break;
	}

	return disp_length;
}

static void debug_disp_page(u8 page)
{
	u8 disp_line;
	u16 disp_length;

	debug_page_line[PAGE_POINT] = page + 5;

	for (disp_line = 0; disp_line < 22; disp_line++)
	{
		disp_length = debug_disp_line(page, disp_line);
		debug_page_line[LINE_POINT] = disp_line + 2;
		debug_page_line[LINE_POINT + 1] = 2;	// Data Pointer
		debug_set_response(BASE_ID_LEN + 2, debug_page_line, disp_ptr, disp_length);
	}
}

int isdn_debug_init(void)
{
	u8 page;
	u8 data[10];
	u8 *ptr;

	strcpy(AsciInBuf, "\0");
	strcpy(AsciOutBuf, "\0");
	MonitorIsdnFg = ISDN_MONITOR_NONE;
	bzero(disp_page, 20);
	memset(&isdn_csta, 0, sizeof(ISDN_Msg_Csta));
	ptr = data;

	debug_set_response(BASE_ID_LEN, debug_status_id, &debug_status, 1);
	debug_set_response(BASE_ID_LEN, debug_name_id, VER_DEBUG, 10);
	debug_set_response(BASE_ID_LEN, debug_ascin_id, AsciInBuf, 4096);
	debug_set_response(BASE_ID_LEN, debug_ascout_id, AsciOutBuf, 4096);

	for (page = 1; page <= PAGE_NUM; page++)
	{
		switch (page)
		{
			case 1: //page 1
				ptr = title1_p;
				break;
			case 2: //page 2
				ptr = title2_p;
				break;
			case 3: //page 3
				ptr = title3_p;
				break;
			case 4: //page 4
				ptr = title4_p;
				break;
			case 5: //page 5
				ptr = title5_p;
				break;
			default:
				break;				
		}
		debug_page_title[PAGE_POINT] = 5 + page;
		debug_set_response(BASE_ID_LEN + 1, debug_page_title, ptr, strlen(ptr));
		debug_disp_page(page);
	}
	return ISDN_CM_OK;
}

void isdn_debug_timer(void)
{
	u8 in_page, err_fg = 0;
	u8 *ascii_in_ptr = NULL;
	u8 *str_start = NULL;
	u16 str_len, num;

	if((str_len = strlen(AsciInBuf)) > 0)
	{
		in_page = AsciInBuf[0] - 1;
		ascii_in_ptr = AsciInBuf + 1;

		if (in_page > PAGE_NUM)
			err_fg = 1;
		else if (strcmp(ascii_in_ptr,"log error on") == 0)
		{
			MonitorIsdnFg = MonitorIsdnFg | ISDN_MONITOR_ERROR;
		}
		else if (strcmp(ascii_in_ptr,"log error off") == 0)
		{
			MonitorIsdnFg = MonitorIsdnFg & (~ISDN_MONITOR_ERROR);			
		}
		else if (strcmp(ascii_in_ptr,"log all") == 0)
		{
			MonitorIsdnFg = ISDN_MONITOR_ALL;
		}
		else if (strcmp(ascii_in_ptr,"log none") == 0)
		{
			MonitorIsdnFg = ISDN_MONITOR_NONE;
		}
		else if (strcmp(ascii_in_ptr,"log state on") == 0)
		{
			MonitorIsdnFg = MonitorIsdnFg | ISDN_MONITOR_STATE;
		}
		else if (strcmp(ascii_in_ptr,"log state off") == 0)
		{
			MonitorIsdnFg = MonitorIsdnFg & (~ISDN_MONITOR_STATE);			
		}

		else if (strcmp(ascii_in_ptr,"help") == 0)
		{
			isdn_asciout_proc(log_help);
			isdn_asciout_proc("Ver.%sp%02d\r\n",VER_DEBUG,IS_PATCH);
		}
		else if (isdigit(ascii_in_ptr[0]))
		{
			num = strtoul(ascii_in_ptr, NULL, 10);
			disp_page[in_page] = num;
			debug_disp_page(in_page);
		}
		else if ((str_start = strstr(ascii_in_ptr, ">")) != NULL)
		{
			num = strtoul(str_start + 1, NULL, 10);
			disp_page[in_page] += num;
			debug_disp_page(in_page);
		}
		else if ((str_start = strstr(ascii_in_ptr, "<"))!= NULL)
		{
			num = strtoul(str_start + 1, NULL, 10);
			disp_page[in_page] -= num;
			debug_disp_page(in_page);
		}		
		else if (strcmp(ascii_in_ptr,"reset csta") == 0)	
		{
			memset(&isdn_csta,0,sizeof(ISDN_Msg_Csta));
		}
		else if (strcmp(ascii_in_ptr,"test color") == 0)
		{
			debug_setcol(COL_WHITE);
			isdn_asciout_proc("COL_WHITE\n\r");
			debug_setcol(COL_RED);
			isdn_asciout_proc("COL_RED\n\r");
			debug_setcol(COL_YELLOW);
			isdn_asciout_proc("COL_YELLOW\n\r");
			debug_setcol(COL_GREEN);
			isdn_asciout_proc("COL_GREEN\n\r");
			debug_setcol(COL_BLUE);
			isdn_asciout_proc("COL_BLUE\n\r");
			debug_setcol(COL_BROWN);
			isdn_asciout_proc("COL_BROWN\n\r");
			debug_setcol(COL_MEGEN);
			isdn_asciout_proc("COL_MEGEN\n\r");
			debug_setcol(COL_GRAY);
			isdn_asciout_proc("COL_GRAY\n\r");
			debug_setcol(COL_HI_WHI);
			isdn_asciout_proc("COL_HI_WHI\n\r");
			debug_setcol(COL_HI_RED);
			isdn_asciout_proc("COL_HI_RED\n\r");
			debug_setcol(COL_HI_YEL);
			isdn_asciout_proc("COL_HI_YEL\n\r");
			debug_setcol(COL_HI_GRE);
			isdn_asciout_proc("COL_HI_GRE\n\r");
			debug_setcol(COL_HI_BLU);
			isdn_asciout_proc("COL_HI_BLU\n\r");
			debug_setcol(COL_HI_BRO);
			isdn_asciout_proc("COL_HI_BRO\n\r");
			debug_setcol(COL_HI_MEG);
			isdn_asciout_proc("COL_HI_MEG\n\r");
			debug_setcol(COL_BLACK);
			isdn_asciout_proc("COL_BLACK\n\r");
			debug_cancelcol();
		}		
		else if (strstr(ascii_in_ptr, "reset port") != NULL)
		{
			if ((str_start = strstr(ascii_in_ptr, "-")) != NULL)
			{
				num = strtoul(str_start + 1, NULL, 10);
				if (num >= ISDN_MAX_PORT)
					err_fg = 1;
				else
				{
					memset(&(isdn_rs.port_pond[num]),0,sizeof(ISDN_Port_struct));
				}
			}
		}
		else if (strstr(ascii_in_ptr, "set link_id") != NULL)
		{
			if ((str_start = strstr(ascii_in_ptr, "=")) != NULL)
			{
				num = strtoul(str_start + 1, NULL, 10);
				debug_link_id = num;
			}
		}
		else if (strstr(ascii_in_ptr, "list sap") != NULL)
		{
			if ((str_start = strstr(ascii_in_ptr, "-")) != NULL)
			{
				num = strtoul(str_start + 1, NULL, 10);
				list_sap(num);
			}
		}		
		else if (strstr(ascii_in_ptr, "list cg") != NULL)
		{
			if ((str_start = strstr(ascii_in_ptr, "-")) != NULL)
			{
				num = strtoul(str_start + 1, NULL, 10);
				list_cg(num);
				list_all_circuit_by(num);
			}
			else
				list_all_cg();
		}		
		else if (strstr(ascii_in_ptr, "list circuit") != NULL)
		{
			if ((str_start = strstr(ascii_in_ptr, "-")) != NULL)
			{
				num = strtoul(str_start + 1, NULL, 10);
				list_circuit(num);
				list_all_port_by(num);
			}
			else
				list_all_circuit();
		}		
		else if (strstr(ascii_in_ptr, "list debug link") != NULL)
		{
			isdn_asciout_proc("debug_link_id = %d\n\r",debug_link_id);
		}		
		else if (strstr(ascii_in_ptr, "list cic") != NULL)
		{
			if((str_start = strstr(ascii_in_ptr, "-")) != NULL)
			{
				num = strtoul(str_start + 1, NULL, 10);
				list_cic(debug_link_id, num);
			}
		}
		else if (strstr(ascii_in_ptr, "trace on") != NULL)
		{
			if((str_start = strstr(ascii_in_ptr, "-")) != NULL)
			{
				num = strtoul(str_start + 1, NULL, 10);
				isdn_rs.port_pond[num].trace_flag = 1;
			}
		}
		else if (strstr(ascii_in_ptr, "trace off") != NULL)
		{
			if((str_start = strstr(ascii_in_ptr, "-")) != NULL)
			{
				num = strtoul(str_start + 1, NULL, 10);
				isdn_rs.port_pond[num].trace_flag = 0;
			}
			else
			{
				int i;
				for(i = 0; i < ISDN_MAX_PORT; i++)
					isdn_rs.port_pond[i].trace_flag = 0;
			}
		}
		else
			err_fg = 1;

		if (err_fg == 0)
			isdn_asciout_proc("Command OK!\n\r");
		else
			isdn_asciout_proc("Command Error!\n\r");		

		strcpy(AsciInBuf, "\0");
	}
}

static void display_isdn_msgtype(u8 msgtype, u8 proto_discr)
{
	if(proto_discr == PROTOCOL_DISCR)
	{
		switch(msgtype)
		{
			case MSG_ALERT:
				isdn_asciout_proc("Alerting");
				break;
			case MSG_CALL_PROC:
				isdn_asciout_proc("Call proceeding");
				break;
			case MSG_CONN:
				isdn_asciout_proc("Connect");
				break;
			case MSG_CONNACK:
				isdn_asciout_proc("Connect acknowledge");
				break;
			case MSG_PROG:
				isdn_asciout_proc("Progress");
				break;
			case MSG_SETUP:
				isdn_asciout_proc("Setup");
				break;
			case MSG_SETUP_ACK:
				isdn_asciout_proc("Setup acknowledge");
				break;
			case MSG_DISC:
				isdn_asciout_proc("Disconnect");
				break;
			case MSG_REL:
				isdn_asciout_proc("Release");
				break;
			case MSG_REL_COMP:
				isdn_asciout_proc("Release complete");
				break;
			case MSG_RESTART:
				isdn_asciout_proc("Restart");
				break;
			case MSG_REST_ACK:
				isdn_asciout_proc("Restart acknowledge");
				break;
			case MSG_INFORMATION:
				isdn_asciout_proc("Information");
				break;
			case MSG_NOTI:
				isdn_asciout_proc("Notify");
				break;
			case MSG_STATUS:
				isdn_asciout_proc("Status");
				break;
			case MSG_STAT_ENQ:
				isdn_asciout_proc("Status enquiry");
				break;
			case MSG_FAC:
				isdn_asciout_proc("Facility (connectionless)");
				break;
			default:
				isdn_asciout_proc("Unknown message");
				break;
		}
	}
	else if(proto_discr == M_PROTOCOL_DISCR)
	{
		switch(msgtype)
		{
			case MSG_SERVICE:
				isdn_asciout_proc("Service");
				break;
			case MSG_SERVICE_ACK:
				isdn_asciout_proc("Service acknowledge");
				break;
			default:
				isdn_asciout_proc("Unknown message");
				break;
		}
	}
	isdn_asciout_proc("(message type=0x%x)\r\n",msgtype);		
}

void isdn_log_err(u32 pid,const char *fmt, ...)
{
	va_list			ap;
	struct timeval	tv;
	struct timezone	tz;
	struct tm		*t;
	char		timestr[1024];
	
	if((MonitorIsdnFg & ISDN_MONITOR_ERROR) != ISDN_MONITOR_ERROR)
		return;
	
	gettimeofday(&tv, &tz);
	t = localtime(&tv.tv_sec);
	sprintf(timestr, "[%d:%d:%d.%ld]", t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec);
	
	va_start(ap, fmt);
	vsprintf(AsciTempBuf, fmt, ap);
	debug_setcol(COL_RED);
	isdn_asciout_proc("%s%s (pid=%d)", timestr, AsciTempBuf, pid);
	debug_cancelcol();
	isdn_asciout_proc("\r\n");
	va_end(ap);
}

void isdn_trace_func(u32 pid,const char *fmt, ...)
{
	va_list			ap;
	struct timeval	tv;
	struct timezone	tz;
	struct tm		*t;
	char timestr[1024];

	if (((MonitorIsdnFg & ISDN_MONITOR_FUNC) != ISDN_MONITOR_FUNC) || 
			(isdn_rs.port_pond[pid%ISDN_MAX_PORT].trace_flag != 1))
		return;

	gettimeofday(&tv, &tz);
	t = localtime(&tv.tv_sec);
	sprintf(timestr, "[%d:%d:%d.%ld]", t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec );
	
	va_start(ap, fmt);
	vsprintf(AsciTempBuf, fmt, ap);
	debug_setcol(COL_YELLOW);
	isdn_asciout_proc("%s%s (pid=%d)",timestr,AsciTempBuf,pid);
	debug_cancelcol();
	isdn_asciout_proc("\r\n");
	va_end(ap);
}

void monitor_isdn_msg(u32 pid,u8 *head,IuaMsgStr *msg,u8 col)
{
	int i, len;
	u32 cic;
	struct timeval tv;
	struct timezone tz;
	struct tm *t;
	char timestr[1024];
	int circuit_id = pid / ISDN_CIRCUIT_CIC;
	const pal_circuit_struct *circuit_ptr = pal_circuit_ptr(circuit_id);
	if(circuit_ptr == NULL)
	{
		printf("monitor isdn msg err!pid=%ld, circuit_id = %d, can't find circuit_ptr!\n", pid, circuit_id);
		return;
	}
	
	if((MonitorIsdnFg & ISDN_MONITOR_MSG) != ISDN_MONITOR_MSG)
		return;

	if(circuit_ptr->attrib.cic_range == 32)
		cic = circuit_ptr->attrib.head_cic + (pid % ISDN_CIRCUIT_CIC);
	else
		
		cic = circuit_ptr->attrib.head_cic + (pid % ISDN_CIRCUIT_CIC) - 1;
	gettimeofday(&tv, &tz);
	t = localtime(&tv.tv_sec);
	sprintf(timestr, "[%d:%d:%d.%ld]", t->tm_hour, t->tm_min, t->tm_sec, tv.tv_usec);
	
	debug_setcol(col);
	isdn_asciout_proc("%s%s ",timestr,head);
	if(msg->msgcontent.isdn_msg.msg_m.call_ref[0] & 0x80)
		isdn_asciout_proc("msg send to originating side\n\r");
	else
		isdn_asciout_proc("msg send from originating side\n\r");
	display_isdn_msgtype(msg->msgcontent.isdn_msg.msg_m.msg_type, msg->msgcontent.isdn_msg.msg_m.proto_Discr);
	isdn_asciout_proc("--cic=0x%04x,cref=0x%02x%02x,link=%d,proto=%d,pid=%d->\n\r",
		cic,
		msg->msgcontent.isdn_msg.msg_m.call_ref[0]&0x7F,
		msg->msgcontent.isdn_msg.msg_m.call_ref[1],
		msg->e1_no,
		msg->msgcontent.isdn_msg.msg_m.proto_Discr,
		pid);
	len = msg->msg_length - 5;
	debug_cancelcol();
	for (i = 0; i < len; i ++)
	{
		sprintf(&AsciTempBuf[3*i]," %02x", msg->msgcontent.isdn_msg.ie_content[i]);
	}
	sprintf(&AsciTempBuf[3*i],"\n\r");
	isdn_asciout_proc(AsciTempBuf);
	return;
}

void monitor_isdn_port(u32 call_ref,u32 port)
{
	if ((MonitorIsdnFg & ISDN_MONITOR_STATE) != ISDN_MONITOR_STATE)
		return;

	isdn_asciout_proc("-->port:\r\n");
	isdn_asciout_proc("CallRef\tPort\tSuID\tcall_state\tmain_state\tcpc_state\tm_state\r\n");
	sprintf(info,"%lx\t%ld\t%ld\t%d\t\t%d\t\t%d\t\t%d\r\n",
		call_ref,
		port,
		isdn_rs.port_pond[port].su_proc_id,
		isdn_rs.port_pond[port].cic_state.call_state,
		isdn_rs.port_pond[port].cic_state.maintenance_state,
		isdn_rs.port_pond[port].fsm_state.cpc_state,
		isdn_rs.port_pond[port].fsm_state.m_state);
	isdn_asciout_proc(info);
}

void isdn_msg_csta(u8 msgtype,u8 flag)
{
	switch(msgtype)
	{
		case MSG_ALERT:
			if(flag==0)			//receive
				isdn_csta.rv_alert++;
			else if(flag == 1)		//send
				isdn_csta.sd_alert++;
			else					//redirect
				isdn_csta.rd_alert++;
			break;
		case MSG_CALL_PROC:
			if(flag==0)			//receive
				isdn_csta.rv_callProc++;
			else if(flag == 1)		//send
				isdn_csta.sd_callProc++;
			else					//redirect
				isdn_csta.rd_callProc++;
			break;
		case MSG_CONN:
			if(flag==0)			//receive
				isdn_csta.rv_conn++;
			else if(flag == 1)		//send
				isdn_csta.sd_conn++;
			else					//redirect
				isdn_csta.rd_conn++;
			break;
		case MSG_CONNACK:
			if(flag==0)			//receive
				isdn_csta.rv_connAck++;
			else if(flag == 1)		//send
				isdn_csta.sd_connAck++;
			else					//redirect
				isdn_csta.rd_connAck++;
			break;
		case MSG_PROG:
			break;
		case MSG_SETUP:
			if(flag==0)			//receive
				isdn_csta.rv_setup++;
			else if(flag == 1)		//send
				isdn_csta.sd_setup++;
			else					//redirect
				isdn_csta.rd_setup++;
			break;
		case MSG_SETUP_ACK:
			if(flag==0)			//receive
				isdn_csta.rv_setupAck++;
			else if(flag == 1)		//send
				isdn_csta.sd_setupAck++;
			else					//redirect
				isdn_csta.rd_setupAck++;
			break;
		case MSG_DISC:
			if(flag==0)			//receive
				isdn_csta.rv_disc++;
			else if(flag == 1)		//send
				isdn_csta.sd_disc++;
			else					//redirect
				isdn_csta.rd_disc++;
			break;
		case MSG_REL:
			if(flag==0)			//receive
				isdn_csta.rv_rel++;
			else if(flag == 1)		//send
				isdn_csta.sd_rel++;
			else					//redirect
				isdn_csta.rd_rel++;
			break;
		case MSG_REL_COMP:
			if(flag==0)			//receive
				isdn_csta.rv_relComp++;
			else if(flag == 1)		//send
				isdn_csta.sd_relComp++;
			else					//redirect
				isdn_csta.rd_relComp++;
			break;
		case MSG_RESTART:
			break;
		case MSG_REST_ACK:
			break;
		case MSG_INFORMATION:
			break;
		case MSG_NOTI:
			break;
		case MSG_STATUS:
			break;
		case MSG_STAT_ENQ:
			break;
		case MSG_FAC:
			break;
		default:
			break;
	}
}

