ENDPT_410_pstnCtlTaskMain

while ( 1 )
	bosSleep( PSTN_CTL_CFG_TASK_RATE_MS );		//延时50 ms
	
	for (i = 0; i < PSTN_CTL_MAX_CHANNELS; i++)	//遍历所有FXO口
		//如果当前FXO口线路摘机并等待播号音
		if ((pstnCtlState.chanState[i].vhdHdl != 0xFF) &&(pstnCtlState.chanState[i].state == 
			PSTN_CTL_CHAN_STATE_WAIT_DIAL_TONE) )
			//进行超时累计
			pstnCtlState.chanState[i].timeoutCount += PSTN_CTL_CFG_TASK_RATE_MS;
			
			//FXO口摘机后5秒还没有收到播号音
			if (pstnCtlState.chanState[i].timeoutCount== PSTN_CPTONE_TIMEOUT_PERIOD)
				//关闭CMTD控制
				cmtdCtlDisable( pstnCtlState.chanState[i].vhdHdl );
				
				//复位状态,并上报等待进展音超时事件
				eventInfo.event = PSTN_CTL_EVT_CPTONE_TIMEOUT;
				eventInfo.pInfo = NULL;
				pstnCtlState.chanState[i].state = PSTN_CTL_CHAN_STATE_IDLE;
				pstnCtlState.chanState[i].timeoutCount = 0;
				pstnCtlState.callback( pstnCtlState.chanState[i].vhdHdl, &eventInfo );
	
	eventGet( &evt );	//获取用户事件
	
	//ENDPT主任务退出,则FXO口任务退出
	if ( eventTaskCheckPendingReset() == VRG_TRUE )
		return;
	
	//如果没有事件,则标记为空事件
	if( status != PSTN_CTL_SUCCESS )
		evt.hsxevt = PSTN_CTL_EVT_NONE;
	
	//DTMF来显检测处理
	pstnCtlDTMFClidRxProcess( &evt );
		nullEvt.hsxdevhdl = 0x0000;
   		nullEvt.hsxevt = PSTN_CTL_EVT_NONE;
		
		for ( i = 0; i < pstnCtlState.numChannels; i++ )	//遍历所有FXO口通道
			//合法性校验,及开启来显检测标记校验
			if( (pstnCtlState.chanState[ i ].vhdHdl == 
			pstnCtlState.chanState[ i ].dtmfClidRx.vhdHdl) 
			&&(pstnCtlState.chanState[ i ].dtmfClidRx.enabled == VRG_TRUE) )	
				//当前事件的PSTN线路ID是否与当前PSTN线路ID相同
				if ( pstnCtlState.chanState[ i ].dtmfClidRx.vhdHdl == evtp->hsxdevhdl )
					processDTMFClidRxEvent( &pstnCtlState.chanState[ i ].dtmfClidRx, 
					evtp );
				else
					processDTMFClidRxEvent( &pstnCtlState.chanState[ i ].dtmfClidRx, 
					&nullEvt );
				
	//PSTN控制事件处理
	pstnCtlEventProcess( &evt );
		switch( evtp->hsxevt )
		case PSTN_CTL_EVT_CALL_SETUP:			//发起呼叫事件
			if ( chanState->state == PSTN_CTL_CHAN_STATE_IDLE )
				//上层是否设置要呼叫的DTMF按键
				if (evtp->hsxop2.ref != NULL)
					strcpy( chanState->dialString, ( char * )evtp->hsxop2.ref );
				else
					chanState->dialString[0] = 0;
				
				//如果上层没有设置仅连接(拨号音直接透传到FXS口)
				if ( strcmp( chanState->dialString, PSTN_CONNECTONLY_DLSTRNG ) !=0 )
					//切为等待播号音状态
					chanState->state = PSTN_CTL_CHAN_STATE_WAIT_DIAL_TONE;
					
					//设置过滤器,捕获播号音
					cmtdCtlConfigFilter( chanState->vhdHdl, pstnCtlState.country,
						CMTD_TONE_TYPE_DIAL, CMTD_FILTER_1 )
				else		//如果上层设置仅仅连接事件
					//上报呼叫完成事件,交给《ENDPT_410_PstnEventProcess》处理
					chanState->state = PSTN_CTL_CHAN_STATE_IDLE;
					eventInfo.event = PSTN_CTL_EVT_CALL_SETUP_COMPLETE;
					eventInfo.pInfo = NULL;
					pstnCtlState.callback( chanState->vhdHdl, &eventInfo );
					
		case PSTN_CTL_EVT_CPTONE_DETECT:		//检测到拨号音 或忙音事件
			//在等待播号音状态
			if ( chanState->state == PSTN_CTL_CHAN_STATE_WAIT_DIAL_TONE )
				chanState->timeoutCount = 0;	//复位超时计数
				
				cmtdCtlDisable( chanState->vhdHdl );	//关闭声音检测服务
				
				//切为生成DTMF状态
				chanState->state = PSTN_CTL_CHAN_STATE_GENERATE_DTMF;
				
				//向PSTN侧发送DTMF按键
				genDialString( lineId, chanState->vhdHdl, chanState->dialString );
				
			//在空闲状态,检测到忙音
			else if ( chanState->state == PSTN_CTL_CHAN_STATE_IDLE )
				//关闭声音检测服务
				cmtdCtlDisable( chanState->vhdHdl );
			
		case PSTN_CTL_EVT_DIAL_COMPLETE:		//按键完成事件
			//在生成DTMF状态
			if ( chanState->state == PSTN_CTL_CHAN_STATE_GENERATE_DTMF )
				chanState->state = PSTN_CTL_CHAN_STATE_IDLE;	//复位状态
				
				//上报呼叫完成事件,交给《ENDPT_410_PstnEventProcess》处理
				eventInfo.event = PSTN_CTL_EVT_CALL_SETUP_COMPLETE;
				eventInfo.pInfo = NULL;
				pstnCtlState.callback( chanState->vhdHdl, &eventInfo );
				
				//开启忙音检测
				cmtdCtlConfigFilter( chanState->vhdHdl, pstnCtlState.country,
				CMTD_TONE_TYPE_RELEASE, CMTD_FILTER_1 );
				
	if ( evt.hsxop2.ref != NULL )
		free( evt.hsxop2.ref );


processDTMFClidRxEvent
	//更新当前FXO通道的所有定时器,如果有任意类型定时器超时,则标记对应超时事件
	clidRxState->internalEvents |= updateTimers( &clidRxState->stateInfo );
	
	//触发DTMF来显接收状态机
	processDTMFClidRxStm( clidRxState, evtp );
		switch( FSM( evtp->hsxevt, stateInfo->serviceState ) )
		case FSM( PSTN_CTL_EVT_NONE, DTMFCLIDRX_IDLE ):	//空闲状态收到空事件
			//什么事都不做
		
		case FSM( PSTN_CTL_EVT_DTMF_DIGIT, DTMFCLIDRX_IDLE ):	//空闲状态收到DTMF
			if(  !stateInfo->offHook )	//挂机
				if( IS_START_TOKEN( &evtp->hsxop1, dtmfParms ) )//有效的来显DTMF字符
					//如果当前还没有振铃或者第一个振铃周期完成
					if( (stateInfo->ringState == DTMFCLIDRX_NORING) ||
						(stateInfo->ringState == DTMFCLIDRX_FIRSTRINGOFF) )
						//根据当前振铃时段设置来显类型
						if( stateInfo->ringState == DTMFCLIDRX_NORING )
							stateInfo->clidType = DTMFCLIDRX_PRERING_CLID;
						else
							stateInfo->clidType = DTMFCLIDRX_FIRSTRING_CLID;
						
						//将状态机切为号码收集状态
						stateInfo->serviceState = DTMFCLIDRX_COLLECTING;
						
						//复位号码收集缓冲
						clidInfo->collectBuffer[clidInfo->collectBufLen] = evtp->hsxop1;
						clidInfo->collectBufLen++;
						
						//启动总会话定时器和按键脉冲定时器
START_TIMER(stateInfo->timer[DTMFCLIDRX_DTMF_PAUSE_TIMER]
START_TIMER(stateInfo->timer[DTMFCLIDRX_SESSION_TIMER]);
					else
						//标记无效的来显
						stateInfo->clidType = DTMFCLIDRX_INVALID_CLID;
				else
					//标记无效的来显
					stateInfo->clidType = DTMFCLIDRX_INVALID_CLID;
			else
				//标记无效的来显
				stateInfo->clidType = DTMFCLIDRX_INVALID_CLID;
		
		case FSM( PSTN_CTL_EVT_RINGON, DTMFCLIDRX_IDLE ):	//在空闲状态检测到振铃
			//如果当前没有振铃,则标记振铃状态为第一次振铃
			//如果当前第一次振铃结束,则标记收到第二次振铃
			if( stateInfo->ringState == DTMFCLIDRX_NORING )
				stateInfo->ringState = DTMFCLIDRX_FIRSTRINGON;
			else if( stateInfo->ringState == DTMFCLIDRX_FIRSTRINGOFF )
				stateInfo->ringState = DTMFCLIDRX_SECONDRING;
		
		case FSM( PSTN_CTL_EVT_RINGOFF, DTMFCLIDRX_IDLE ):	//在空闲状态检测到停振
			//如果当前为第一次振铃ON,则标记收到第一次振铃OFF
			if( stateInfo->ringState == DTMFCLIDRX_FIRSTRINGON )
				stateInfo->ringState = DTMFCLIDRX_FIRSTRINGOFF;
		
		//在空闲状态收到振铃结束事件
		case FSM( PSTN_CTL_EVT_RINGEND, DTMFCLIDRX_IDLE ):\
			//振铃状态复位
			if( stateInfo->ringState != DTMFCLIDRX_NORING )
				stateInfo->ringState = DTMFCLIDRX_NORING;
		
		//在空闲状态收到摘机事件
		case FSM( PSTN_CTL_EVT_OFFHOOK, DTMFCLIDRX_IDLE ):	
			stateInfo->offHook = VRG_TRUE;		//标记摘机
			stateInfo->ringState = DTMFCLIDRX_RINGEND;	//标记振铃结束
		
		//在空闲状态收到挂机事件
		case FSM( PSTN_CTL_EVT_ONHOOK, DTMFCLIDRX_IDLE ):
			stateInfo->offHook = VRG_FALSE;	//标记挂机
			stateInfo->ringState = DTMFCLIDRX_NORING;	//复位振铃指示
			clidRxState->internalEvents |= DTMFCLIDRX_EVT_NEEDRESET;	//需要进行复位
		
		//在来显收集状态收到空事件
		case FSM( PSTN_CTL_EVT_NONE, DTMFCLIDRX_COLLECTING ):
			//如果会话超时或DTMF脉冲超时
			if( (clidRxState->internalEvents & DTMFCLIDRX_EVT_DTMF_PAUSE_TIMEOUT ) ||
			(clidRxState->internalEvents & DTMFCLIDRX_EVT_SESSION_TIMEOUT) )
				if( stateInfo->ringState == DTMFCLIDRX_NORING )	//还未收到振铃
					//设置需要复位事件
					clidRxState->internalEvents |= DTMFCLIDRX_EVT_NEEDRESET;
				//收到第一声停振
				else if( stateInfo->ringState == DTMFCLIDRX_FIRSTRINGOFF )
					//停止定时器
					clidRxState->internalEvents &= ~~(DTMFCLIDRX_EVT_DTMF_PAUSE_TIMEOUT |DTMFCLIDRX_EVT_SESSION_TIMEOUT);
					STOP_TIMER(stateInfo->timer[DTMFCLIDRX_DTMF_PAUSE_TIMER]);
					STOP_TIMER(stateInfo->timer[DTMFCLIDRX_SESSION_TIMER]);
					
					//标记无效的来显
					stateInfo->clidType = DTMFCLIDRX_INVALID_CLID;
					//切到等待结束状态
					stateInfo->serviceState = DTMFCLIDRX_WAITINGFOREND;
					//设置无效的来显事件
					clidRxState->internalEvents |= DTMFCLIDRX_EVT_INVALID_DTMF_CLID;
				else
					//设置错误事件
					clidRxState->internalEvents |= DTMFCLIDRX_EVT_ERROR;
		
		//在来显收集状态收到DTMF按键
		case FSM( PSTN_CTL_EVT_DTMF_DIGIT, DTMFCLIDRX_COLLECTING ):
			//去除DTMF脉冲定时器
			if( clidRxState->internalEvents & DTMFCLIDRX_EVT_DTMF_PAUSE_TIMEOUT )
				clidRxState->internalEvents &= ~DTMFCLIDRX_EVT_DTMF_PAUSE_TIMEOUT;
			
			//如果会话总时间超时,并且还未收到DTMF结束码
			if( (clidRxState->internalEvents & DTMFCLIDRX_EVT_SESSION_TIMEOUT) &&
			(evtp->hsxop1 != dtmfParms->endCode) )
				//如果未收到振铃,则设置需要复位事件
				if( stateInfo->ringState == DTMFCLIDRX_NORING )
					clidRxState->internalEvents |= DTMFCLIDRX_EVT_NEEDRESET;
					break;
				//如果已经收到第一声停振
				else if( stateInfo->ringState == DTMFCLIDRX_FIRSTRINGOFF )
					//停止定时器
					clidRxState->internalEvents &= ~DTMFCLIDRX_EVT_SESSION_TIMEOUT;					STOP_TIMER(stateInfo->timer[DTMFCLIDRX_DTMF_PAUSE_TIMER]);
					STOP_TIMER(stateInfo->timer[DTMFCLIDRX_SESSION_TIMER]);
					
					stateInfo->clidType = DTMFCLIDRX_INVALID_CLID;	//标记无效来显
					//切到等待结束状态
					stateInfo->serviceState = DTMFCLIDRX_WAITINGFOREND;
					
					//设置无效来显事件
					clidRxState->internalEvents |= DTMFCLIDRX_EVT_INVALID_DTMF_CLID;
					
					break;
				else
					//设置错误事件
					clidRxState->internalEvents |= DTMFCLIDRX_EVT_ERROR;
					break;
			
			//存储来显
			clidInfo->collectBuffer[clidInfo->collectBufLen] = evtp->hsxop1;
			clidInfo->collectBufLen++;
			
			//如果未收到结束码,则重起DTMF脉冲定时器
			if( (evtp->hsxop1 != dtmfParms->endCode) &&(clidInfo->collectBufLen < 
			(DTMFCLIDRX_MAX_BUFFER_SIZE + 1)) )
				RESET_TIMER(stateInfo->timer[DTMFCLIDRX_DTMF_PAUSE_TIMER]);
				break;
			
			//如果收到来显结束码
			else if( evtp->hsxop1 == dtmfParms->endCode )
				//停止定时器
				clidRxState->internalEvents &= ~(DTMFCLIDRX_EVT_DTMF_PAUSE_TIMEOUT |DTMFCLIDRX_EVT_SESSION_TIMEOUT);
				STOP_TIMER(stateInfo->timer[DTMFCLIDRX_DTMF_PAUSE_TIMER]);
				STOP_TIMER(stateInfo->timer[DTMFCLIDRX_SESSION_TIMER]);
				
				//如果来显收全了,但还没有振铃,则等待振铃
				if( stateInfo->ringState == DTMFCLIDRX_NORING )
					START_TIMER(stateInfo->timer[DTMFCLIDRX_RINGAFTERCLID_TIMER]);
				
				//设置DTMF收集完成事件
				clidRxState->internalEvents |= 
					DTMFCLIDRX_EVT_DTMF_COLLECT_COMPLETE;
				
				//切为等待结束状态
				stateInfo->serviceState = DTMFCLIDRX_WAITINGFOREND;
				
				//将来显号码转换为字符串,并转换来显事件
				parseDTMFClidRx( clidRxState );
				break;
			//来显接收BUF已经满
			else if( clidInfo->collectBufLen == (DTMFCLIDRX_MAX_BUFFER_SIZE + 1) )
				//停止定时器
				clidRxState->internalEvents &= ~(DTMFCLIDRX_EVT_DTMF_PAUSE_TIMEOUT |DTMFCLIDRX_EVT_SESSION_TIMEOUT);
				STOP_TIMER(stateInfo->timer[DTMFCLIDRX_DTMF_PAUSE_TIMER]);
				STOP_TIMER(stateInfo->timer[DTMFCLIDRX_SESSION_TIMER]);
				
				//已经收到振铃
				if( stateInfo->ringState != DTMFCLIDRX_NORING )
					stateInfo->clidType = DTMFCLIDRX_INVALID_CLID;	//无效的来显
					//切到等待结束状态
					stateInfo->serviceState = DTMFCLIDRX_WAITINGFOREND;
					//设置无效的来显事件
					clidRxState->internalEvents |= DTMFCLIDRX_EVT_INVALID_DTMF_CLID;
				else
					//设置需要复位事件
					clidRxState->internalEvents |= DTMFCLIDRX_EVT_NEEDRESET;
				
				break;
		
		//在来显收集状态收到振铃
case FSM( PSTN_CTL_EVT_RINGON, DTMFCLIDRX_COLLECTING ):
	//如果还未收到振铃,或者收到过第一声振铃
	if( (stateInfo->ringState == DTMFCLIDRX_NORING) ||(stateInfo->ringState == 
	DTMFCLIDRX_FIRSTRINGOFF) )
		//设置对应的振铃状态
		if( stateInfo->ringState == DTMFCLIDRX_NORING )
			stateInfo->ringState = DTMFCLIDRX_FIRSTRINGON;
		else
			stateInfo->ringState = DTMFCLIDRX_SECONDRING;
		
		//停止定时器
		clidRxState->internalEvents &= ~(DTMFCLIDRX_EVT_DTMF_PAUSE_TIMEOUT |DTMFCLIDRX_EVT_SESSION_TIMEOUT);
		STOP_TIMER(stateInfo->timer[DTMFCLIDRX_DTMF_PAUSE_TIMER]);
		STOP_TIMER(stateInfo->timer[DTMFCLIDRX_SESSION_TIMER]);
		
		//切为等待结束状态,设置无效来显事件
		stateInfo->clidType = DTMFCLIDRX_INVALID_CLID;
		stateInfo->serviceState = DTMFCLIDRX_WAITINGFOREND;
		clidRxState->internalEvents |= DTMFCLIDRX_EVT_INVALID_DTMF_CLID;
		break;
	else
		//设置错误事件
		clidRxState->internalEvents |= DTMFCLIDRX_EVT_ERROR;
		break;

//在来显收集状态收到停振或振铃结束
case FSM( PSTN_CTL_EVT_RINGOFF, DTMFCLIDRX_COLLECTING ):
case FSM( PSTN_CTL_EVT_RINGEND, DTMFCLIDRX_COLLECTING ):
	//设置错误事件
	clidRxState->internalEvents |= DTMFCLIDRX_EVT_ERROR;
	break;

//在来显收集状态收到摘机
case FSM( PSTN_CTL_EVT_OFFHOOK, DTMFCLIDRX_COLLECTING ):
	//停止定时器
clidRxState->internalEvents &= ~(DTMFCLIDRX_EVT_DTMF_PAUSE_TIMEOUT |DTMFCLIDRX_EVT_SESSION_TIMEOUT);
STOP_TIMER(stateInfo->timer[DTMFCLIDRX_DTMF_PAUSE_TIMER]);
    STOP_TIMER(stateInfo->timer[DTMFCLIDRX_SESSION_TIMER]);
	
stateInfo->offHook = VRG_TRUE;	//标记摘机
        stateInfo->ringState = DTMFCLIDRX_RINGEND;	//振铃结束
        stateInfo->clidType = DTMFCLIDRX_INVALID_CLID;	//无效的来显
		//切为等待结束状态
        stateInfo->serviceState = DTMFCLIDRX_WAITINGFOREND;
		//设置无效的来显事件
        clidRxState->internalEvents |= DTMFCLIDRX_EVT_INVALID_DTMF_CLID;
	
//在来显收集状态收到挂机
	case FSM( PSTN_CTL_EVT_ONHOOK, DTMFCLIDRX_COLLECTING ):
		//设置错误事件
		clidRxState->internalEvents |= DTMFCLIDRX_EVT_ERROR;
	
	//在等待结束状态收到超时或按键
	case FSM( PSTN_CTL_EVT_NONE, DTMFCLIDRX_WAITINGFOREND ):
	case FSM( PSTN_CTL_EVT_DTMF_DIGIT, DTMFCLIDRX_WAITINGFOREND ):
		//如果来显收完后,仍无振铃,并超时
		if( clidRxState->internalEvents & DTMFCLIDRX_EVT_RINGAFTERCLID_TIMEOUT )
			//设置需要复位事件
			clidRxState->internalEvents |= DTMFCLIDRX_EVT_NEEDRESET;
		
		break;
	
	//在等待结束状态收到振铃事件
	case FSM( PSTN_CTL_EVT_RINGON, DTMFCLIDRX_WAITINGFOREND ):
		//还未收到振铃,则更新振铃状态
		if( stateInfo->ringState == DTMFCLIDRX_NORING )
			STOP_TIMER(stateInfo->timer[DTMFCLIDRX_RINGAFTERCLID_TIMER]);
			stateInfo->ringState = DTMFCLIDRX_FIRSTRINGON;
		//已经有一次振铃
		else if( stateInfo->ringState == DTMFCLIDRX_FIRSTRINGOFF )
			//更新振铃状态
			stateInfo->ringState = DTMFCLIDRX_SECONDRING;
	
	//在等待结束状态收到停振事件
	case FSM( PSTN_CTL_EVT_RINGOFF, DTMFCLIDRX_WAITINGFOREND ):
		//如果已经是第一次振铃,则记为第一次停振
		if( stateInfo->ringState == DTMFCLIDRX_FIRSTRINGON )
			stateInfo->ringState = DTMFCLIDRX_FIRSTRINGOFF;
	
	//在等待结束状态收到振铃结束事件
	case FSM( PSTN_CTL_EVT_RINGEND, DTMFCLIDRX_WAITINGFOREND ):
		//记下需要复位事件
		clidRxState->internalEvents |= DTMFCLIDRX_EVT_NEEDRESET;
	
	//在等待结束状态收到摘机事件
	case FSM( PSTN_CTL_EVT_OFFHOOK, DTMFCLIDRX_WAITINGFOREND ):
		//停止等待振铃定时器,并设置对应状态
		stateInfo->offHook = VRG_TRUE;
		stateInfo->ringState = DTMFCLIDRX_RINGEND;
		STOP_TIMER(stateInfo->timer[DTMFCLIDRX_RINGAFTERCLID_TIMER]);
	
	//在等待结束状态收到挂机事件
	case FSM( PSTN_CTL_EVT_ONHOOK, DTMFCLIDRX_WAITINGFOREND ):
		//设置需要复位事件
		clidRxState->internalEvents |= DTMFCLIDRX_EVT_NEEDRESET;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值