#include "./include/mtp3.h"
#include "./include/mtpstm.h"
#include "./include/mtpext.h"
#include "./include/mtpfunc.h"

/*@ignore@*/
void sltc_proc(WORD	chl)
{
	ls_info		*ls;
	ls = &mtp3.ls[mtp3_para->lk[chl].e1_to_linkset];

	if (mtp3ObjInput.sltc_input[chl] == SLTC_STOP)
	{
		mtp3ObjInput.sltc_input[chl] = IDLE;
		mtp3ObjState.sltc_state[chl] = SLTC_IDLE_STATE;
	}

	switch (mtp3ObjState.sltc_state[chl])
	{
		case SLTC_IDLE_STATE:
			if (mtp3ObjInput.sltc_input[chl] == SLTC_START)
			{
				mtp3ObjInput.sltc_input[chl] = IDLE;
				hmrt_sltc_signalling_link_test_msg(chl);
				sltc_t1_delay[chl] = 4;
				mtp3ObjState.sltc_state[chl] = SLTC_FIRST_TRY_STATE;
			}
			break;

		case SLTC_FIRST_TRY_STATE:
			sltc_t1_delay[chl] --;
			if ( mtp3ObjInput.sltc_input[chl] == SLTA_MSG )
			{
				mtp3ObjInput.sltc_input[chl] = IDLE;
				mtp3ObjInput.lsac_input_from_sltc[chl] = LSAC_SLTC_SLT_SUCCESSFUL;
				mtp3ObjState.sltc_state[chl] = SLTC_RUNNING_STATE;
				sltc_t2_delay[chl] = 30;
			}
			else if ( sltc_t1_delay[chl] == 0 )
			{
				mtp3ObjInput.sltc_input[chl] = IDLE;
				sltc_t1_delay[chl] = 4;
				hmrt_sltc_signalling_link_test_msg(chl);
				mtp3ObjState.sltc_state[chl] = SLTC_SECOND_TRY_STATE;
			}
			break;

		case SLTC_SECOND_TRY_STATE:
			sltc_t1_delay[chl]--;
			if ( mtp3ObjInput.sltc_input[chl] == SLTA_MSG )
			{
				mtp3ObjInput.sltc_input[chl] = IDLE;
				mtp3ObjInput.lsac_input_from_sltc[chl] = LSAC_SLTC_SLT_SUCCESSFUL;
				mtp3ObjState.sltc_state[chl] = SLTC_RUNNING_STATE;
				sltc_t2_delay[chl] = 30;
			}
			else if ( sltc_t1_delay[chl] == 0 )
			{
				mtp3ObjInput.sltc_input[chl] = IDLE;
				sltc_t1_delay[chl] = 4;
				hmrt_sltc_signalling_link_test_msg(chl);
				mtp3ObjState.sltc_state[chl] = SLTC_THIRD_TRY_STATE;
			}
			break;

		case SLTC_THIRD_TRY_STATE:
			sltc_t1_delay[chl]--;
			if ( mtp3ObjInput.sltc_input[chl] == SLTA_MSG )
			{
				mtp3ObjInput.sltc_input[chl] = IDLE;
				mtp3ObjInput.lsac_input_from_sltc[chl] = LSAC_SLTC_SLT_SUCCESSFUL;
				mtp3ObjState.sltc_state[chl] = SLTC_RUNNING_STATE;
				sltc_t2_delay[chl] = 30;
			}
			else if ( sltc_t1_delay[chl] == 0 )
			{
				mtp3ObjInput.sltc_input[chl] = IDLE;
				mtp3ObjInput.lsac_input_from_sltc[chl] = LSAC_SLTC_SLT_FAILED;
				mtp3ObjState.sltc_state[chl] = SLTC_IDLE_STATE;
			}
			break;

		case SLTC_RUNNING_STATE:
			sltc_t2_delay[chl] --;
			if ( sltc_t2_delay[chl] == 0 )
			{
				mtp3ObjInput.sltc_input[chl] = IDLE;
				hmrt_sltc_signalling_link_test_msg(chl);
				mtp3ObjState.sltc_state[chl] = SLTC_FIRST_TRY_STATE;
				sltc_t1_delay[chl] = 4;
			}
			break;

		default:
			break;
	}
}

int link_auc(WORD chl)
{
	WORD	linkset;

	linkset = mtp3_para->lk[chl].e1_to_linkset;
	if 	( (mtp3ObjState.lk_configured[chl] != PARA_CONFIGURED) 	||
		  (mtp3ObjState.lk_mtp3[chl] != mtp3_localip)	)
		return 3;
	if (mtp3ObjState.link_l1_state[chl] != 1)
		return 2;
	if (mtp3.ls[linkset].links_available == 0)
		return 1;
	else
		return 0;

/*	return value:
 *	0=linkset not only one link available
 *	1=linkset only one link available
 *	2=send command to enable this link
 *	3=no need to send command to this link */
}

void lsac_proc(WORD chl)
{
	int		aucResult;
	static  BYTE timer[MAX_LK];

	if (init_lsac_state[chl] == TRUE)
	{
		init_lsac_state[chl] = IDLE;
		mtp3ObjState.lsac_state[chl] = LSAC_INACTIVE_STATE;
		return;
	}

	switch (mtp3ObjState.lsac_state[chl])
	{
		case LSAC_INACTIVE_STATE:
			switch (mtp3ObjInput.lsac_input_from_mgmt[chl])
			{
				case LSAC_MGMT_ACTIVATE_LINK:
					if (timer[chl]++>50)
					{
					timer[chl] = 0;
					aucResult = link_auc(chl);
					switch (aucResult)
					{
						case 0:
							if (MTP3_LINK_TYPE(chl) == LKTYPE_SIGTRAN)//m2ua link
								send_command_to_mtp2(chl,MTP3_M2UA_ENABLE);
							send_command_to_mtp2(chl,MTP2_ACTIVE_LINK);
							mtp3_debug(MTP3DB_EVENT,"[lsac]link %d normal alignment",chl);
//							printf("chl %d normal alignment\n",chl);
							mtp3ObjState.lsac_state[chl] = LSAC_RESTORING_STATE;
							timer[chl] = 0;
							break;
						case 1:
							if (MTP3_LINK_TYPE(chl) == LKTYPE_SIGTRAN)//m2ua link
								send_command_to_mtp2(chl,MTP3_M2UA_ENABLE);
							send_command_to_mtp2(chl,MTP2_EMERGEN_ALIGNMENT);
							mtp3_debug(MTP3DB_EVENT,"[lsac]link %d emergent alignment",chl);
//							printf("chl %d emergent alignment\n",chl);
							mtp3ObjState.lsac_state[chl] = LSAC_RESTORING_STATE;
							timer[chl] = 0;
							break;
						case 2:
							if (MTP3_LINK_TYPE(chl) != LKTYPE_MTP3_LITE)//m2ua link
								send_command_to_mtp2(chl,MTP3_M2UA_ENABLE);
							break;
						default:
							break;
					}
					}
				break;

				case LSAC_MGMT_DEACTIVATE_LINK:
				break;

				default:
				break;
			}

			switch (mtp3ObjInput.lsac_input_from_l2[chl])
			{
				case LSAC_L2_IN_SERVICE:
				break;

				case LSAC_L2_OUT_OF_SERVICE:
					mtp3ObjInput.lsac_input_from_l2[chl] = IDLE;
				break;

				case LSAC_L2_REMOTE_PROCESSOR_RECOV:
				break;

				default:
				break;
			}
		break;

		case LSAC_RESTORING_STATE:
			switch (mtp3ObjInput.lsac_input_from_mgmt[chl])
			{
				case LSAC_MGMT_ACTIVATE_LINK:
					if ( (mtp3ObjState.sltc_state[chl] == SLTC_IDLE_STATE)	&&
						 (timer[chl]++>60)) // change timer 8s to 9.6s
					{
						timer[chl] = 0;
						aucResult = link_auc(chl);
						switch (aucResult)
						{
							case 0:
								if (MTP3_LINK_TYPE(chl) == LKTYPE_SIGTRAN)//m2ua link
									send_command_to_mtp2(chl,MTP3_M2UA_ENABLE);
								send_command_to_mtp2(chl,MTP2_ACTIVE_LINK);
								break;
							case 1:
								if (MTP3_LINK_TYPE(chl) == LKTYPE_SIGTRAN)//m2ua link
									send_command_to_mtp2(chl,MTP3_M2UA_ENABLE);
								send_command_to_mtp2(chl,MTP2_EMERGEN_ALIGNMENT);
								break;
							default:
								mtp3ObjState.lsac_state[chl] = LSAC_INACTIVE_STATE;
								break;
						}
					}
				break;

				case LSAC_MGMT_DEACTIVATE_LINK:
					send_command_to_mtp2(chl,MTP2_DEACTIVE_LINK);
					mtp3ObjState.lsac_state[chl] = LSAC_INACTIVE_STATE;
				break;

				default:
				break;
			}

			switch (mtp3ObjInput.lsac_input_from_l2[chl])
			{
				case LSAC_L2_IN_SERVICE:
					mtp3ObjInput.lsac_input_from_l2[chl] = IDLE;
					mtp3_debug(MTP3DB_EVENT,"[lsac]link %d L2 in service,start testing procedure",chl);
					mtp3ObjInput.sltc_input[chl] = SLTC_START;
					sltc_proc(chl);/* start to send sltm */
				break;

				case LSAC_L2_OUT_OF_SERVICE:
					mtp3ObjInput.lsac_input_from_l2[chl] = IDLE;
				break;

				case LSAC_L2_REMOTE_PROCESSOR_RECOV:
				break;

				default:
				break;
			}

			switch (mtp3ObjInput.lsac_input_from_sltc[chl])
			{
				case LSAC_SLTC_SLT_SUCCESSFUL:
					mtp3ObjInput.lsac_input_from_sltc[chl] = IDLE;
					mtp3ObjInput.tlac_input_from_slm[chl] = TLAC_LSAC_LINK_IN_SERVICE;
					mtp3ObjState.lsac_state[chl] = LSAC_ACTIVE_STATE;
					mtp3_debug(MTP3DB_EVENT,"[lsac]link %d complete test procedure,test pass",chl);
				break;

				case LSAC_SLTC_SLT_FAILED:
					mtp3ObjInput.lsac_input_from_sltc[chl] = IDLE;
					mtp3ObjState.link_l2_state[chl] = UNAVAILABLE;
					send_command_to_mtp2(chl,MTP2_STOP_L2);
					mtp3ObjState.lsac_state[chl] = LSAC_INACTIVE_STATE;
					mtp3_debug(MTP3DB_EVENT,"[lsac]link %d complete test procedure,test failed",chl);
				break;

				default:
				break;
			}
		break;

		case LSAC_ACTIVE_STATE:
			switch (mtp3ObjInput.lsac_input_from_mgmt[chl])
			{
				case LSAC_MGMT_ACTIVATE_LINK:
				break;

				case LSAC_MGMT_DEACTIVATE_LINK:
					mtp3ObjInput.tlac_input_from_slm[chl] = TLAC_LSAC_SIGLINK_FAILED;
					mtp3ObjState.lsac_state[chl] = LSAC_WAIT_STATE;
//					mtp3ObjState.lsac_state[chl] = LSAC_INACTIVE_STATE;
				break;

				default:
				break;
			}

			switch (mtp3ObjInput.lsac_input_from_l2[chl])
			{
				case LSAC_L2_IN_SERVICE:
					mtp3ObjInput.lsac_input_from_l2[chl] = IDLE;
				break;

				case LSAC_L2_OUT_OF_SERVICE:
					mtp3_debug(MTP3DB_EVENT,"[lsac]link %d failed",chl);
//				printf("lsac link %d failed\n",chl);
					mtp3ObjInput.lsac_input_from_l2[chl] = IDLE;
					if (link_inhibited[chl] != TRUE)
					{
						mtp3ObjInput.tlac_input_from_slm[chl] = TLAC_LSAC_SIGLINK_FAILED;
						mtp3ObjState.lsac_state[chl] = LSAC_FAILED_STATE;
					}
				break;

				case LSAC_L2_REMOTE_PROCESSOR_RECOV:
				break;

				default:
				break;
			}

			switch (mtp3ObjInput.lsac_input_from_sltc[chl])
			{
				case LSAC_SLTC_SLT_SUCCESSFUL:
					mtp3ObjInput.lsac_input_from_sltc[chl] = IDLE;
				break;

				case LSAC_SLTC_SLT_FAILED:
					mtp3ObjInput.lsac_input_from_sltc[chl] = IDLE;
					mtp3ObjState.lsac_state[chl] = LSAC_INACTIVE_STATE;
					send_command_to_mtp2(chl,MTP2_STOP_L2);
					mtp3_debug(MTP3DB_EVENT,"[lsac]link %d test failed during active state",chl);
					mtp3ObjState.link_l2_state[chl] = UNAVAILABLE;
					mtp3_send_alarm(MTP3_LINK_COMPONENT+chl,MTP3ALARM_LINK_TEST_FAILED);
					if (link_inhibited[chl] != TRUE)
					{
						mtp3ObjInput.tlac_input_from_slm[chl] = TLAC_LSAC_SIGLINK_FAILED;
						mtp3ObjState.lsac_state[chl] = LSAC_FAILED_STATE;
					}
				break;

				default:
				break;
			}

			switch (mtp3ObjInput.lsac_input_from_tcoc[chl])
			{
				case LSAC_TCOC_STM_READY:
					mtp3ObjInput.lsac_input_from_tcoc[chl] = IDLE;
				break;

				case LSAC_TCOC_STOP_L2:
					mtp3ObjInput.lsac_input_from_tcoc[chl] = IDLE;
					send_command_to_mtp2(chl,MTP2_STOP_L2);
					mtp3_send_alarm(MTP3_LINK_COMPONENT+chl,MTP3ALARM_LINK_CHANGE_OVER);
					if (link_inhibited[chl] != TRUE)
					{
						mtp3ObjState.lsac_state[chl] = LSAC_FAILED_STATE;
					}
				break;

				default:
				break;
			}

			switch (mtp3ObjInput.lsac_input_from_stm[chl])
			{
				case LSAC_TLAC_CHANGEOVER_ORDER_RECEIVED:
					mtp3ObjInput.lsac_input_from_stm[chl] = IDLE;
					send_command_to_mtp2(chl,MTP2_STOP_L2);
					mtp3_send_alarm(MTP3_LINK_COMPONENT+chl,MTP3ALARM_LINK_CHANGE_OVER);
					mtp3_debug(MTP3DB_EVENT,"[lsac]receive coo");
//					printf("lsac receive coo\n");
					mtp3ObjState.lsac_state[chl] = LSAC_FAILED_STATE;
				break;

				default:
				break;
			}
		break;

		case LSAC_WAIT_STATE:
			if ( mtp3ObjInput.lsac_input_from_tcoc[chl] == LSAC_TCOC_STM_READY)
			{
				mtp3ObjInput.lsac_input_from_tcoc[chl] = IDLE;
				send_command_to_mtp2(chl,MTP2_STOP_L2);
				mtp3_send_alarm(MTP3_LINK_COMPONENT+chl,MTP3ALARM_LINK_MGMT_REQUEST);
				mtp3ObjState.lsac_state[chl] = LSAC_INACTIVE_STATE;
			}
		break;

		case LSAC_FAILED_STATE:
			if (mtp3ObjInput.lsac_input_from_stm[chl] != IDLE)
			{
				mtp3ObjInput.lsac_input_from_stm[chl] = IDLE;
			}
			if ( mtp3ObjInput.lsac_input_from_tcoc[chl] == LSAC_TCOC_STM_READY )
			{
				mtp3ObjInput.lsac_input_from_tcoc[chl] = IDLE;
				changeover_in_progress[chl] = FALSE;
				if (mtp3ObjState.lk_mtp3[chl] == mtp3_localip)
					send_command_to_mtp2(chl,MTP2_ACTIVE_LINK);
				mtp3ObjState.lsac_state[chl] = LSAC_RESTORING_STATE;
			}
		break;

		default:
		break;
	}
}
/*@end@*/
