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;
ENDPT_410_pstnCtlTaskMain
最新推荐文章于 2024-05-28 09:00:00 发布