3125 lines
80 KiB
C
3125 lines
80 KiB
C
/***********************************************************
|
||
Copyright (C), LGC Wireless.
|
||
File Name: isdn_fsm.c
|
||
Description: ISDN FSM
|
||
Version: v9.0.0
|
||
Author: Gengxin Chen
|
||
Create Date: 2008-2-19
|
||
History:
|
||
<author> <date> <version> <desc>
|
||
|
||
************************************************************/
|
||
|
||
#include "./include/isdn_const.h"
|
||
#include "./include/isdn_rm.h"
|
||
#include "./include/isdn_debug.h"
|
||
#include "./include/isdn_ext.h"
|
||
#include "./include/isdn_inc.h"
|
||
|
||
|
||
#define USR 0x00
|
||
#define LN 0x02
|
||
#define TN 0x03
|
||
#define RLN 0x04
|
||
#define DF RLN
|
||
u8 cause_to_loc[128]={
|
||
DF, LN, LN, LN, DF, DF, LN, LN, DF, DF,
|
||
DF, DF, DF, DF, DF, DF, USR,USR,RLN,RLN,
|
||
DF, USR,LN, DF, DF, RLN,LN, RLN,RLN,RLN,
|
||
LN, RLN,DF, DF, RLN,DF, DF, DF, USR,DF,
|
||
DF, RLN,RLN,LN, LN, DF, DF, USR,DF, DF,
|
||
RLN,DF, DF, DF, DF, RLN,DF, LN, LN, DF,
|
||
DF, DF, DF, LN, DF, LN, DF, DF, DF, RLN,
|
||
DF, DF, DF, DF, DF, DF, DF, DF, DF, DF,
|
||
DF, LN, DF, LN, LN, LN, LN, RLN,USR,DF,
|
||
DF, LN, DF, DF, DF, LN, LN, RLN,LN, RLN,
|
||
LN, LN, RLN,DF, DF, DF, DF, DF, DF, DF,
|
||
DF, RLN,DF, DF, DF, DF, DF, DF, DF, DF,
|
||
DF, DF, DF, DF, DF, DF, DF, DF
|
||
};
|
||
|
||
u16 cr_start[ISDN_MAX_CG] = {0};
|
||
u8 cr_state[4096] = {0};
|
||
|
||
void isdn_cpc_proc(u32 pid);
|
||
int isdn_event_handle(u32 pid, u8 primitive);//, u8 eventType)
|
||
static int isdn_cc_nt(u32 pid);
|
||
static int isdn_cc_lt(u32 pid);
|
||
extern int isdn_send_msg(u32 pid, u8 msg_type);
|
||
extern int isdn_send_maintenance_msg(u32 pid, u8 msg_type);
|
||
|
||
|
||
/*************************************************************
|
||
Function: cr_sel
|
||
Description: according to port id, selection the idle call reference
|
||
Input: pid:port id, indicate the cic of the IUA link
|
||
Return: ISDN_CM_OK:success
|
||
ISDN_CM_FAILED:failed
|
||
*************************************************************/
|
||
int cr_sel(u32 pid)
|
||
{
|
||
u16 tmp_cr, i, byte_offset, circuit_id, cg_id;
|
||
u8 bit_offset, key;
|
||
const pal_circuit_struct *circuit_ptr = NULL;
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
circuit_id = pid / ISDN_CIRCUIT_CIC;
|
||
circuit_ptr = pal_circuit_ptr(circuit_id);
|
||
if(circuit_ptr == NULL)
|
||
return ISDN_CM_FAILED;
|
||
|
||
cg_id = circuit_ptr->cg_id;
|
||
tmp_cr = (cr_start[cg_id] & 0x3FFF);
|
||
|
||
for(i = 0; i < 0x3FFF; i++)
|
||
{
|
||
tmp_cr++;
|
||
tmp_cr &= 0x3FFF;
|
||
if(tmp_cr != 0)
|
||
{
|
||
tmp_cr = (tmp_cr | ((circuit_ptr->attrib.plat_id & 0x01) << 14));
|
||
byte_offset = tmp_cr / 8;
|
||
bit_offset = tmp_cr % 8;
|
||
key = ((cr_state[byte_offset] >> bit_offset) & 0x01);
|
||
if(key == 0)
|
||
{
|
||
pPort->call_ref = (tmp_cr | 0x8000); //call_ref[pid]
|
||
cr_start[cg_id] = tmp_cr;
|
||
cr_state[byte_offset] = (cr_state[byte_offset] | (0x01 << bit_offset));
|
||
return ISDN_CM_OK;
|
||
}
|
||
}
|
||
}
|
||
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: rel_cr
|
||
Description: release the call reference
|
||
Input: pid:port id
|
||
Return: ISDN_CM_OK:success
|
||
*************************************************************/
|
||
int rel_cr(u32 pid)
|
||
{
|
||
u16 tmp_cr, byte_offset;
|
||
u8 bit_offset;
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
tmp_cr = (pPort->call_ref & 0x7FFF);
|
||
|
||
if(pPort->call_ref & 0x8000)
|
||
{
|
||
byte_offset = tmp_cr / 8;
|
||
bit_offset = tmp_cr % 8;
|
||
cr_state[byte_offset] = (cr_state[byte_offset] ^ (0x01 << bit_offset));
|
||
}
|
||
pPort->call_ref = 0;
|
||
pPort->callout_fg = 0;
|
||
//msg_cref[pid] = 0;
|
||
|
||
return ISDN_CM_OK;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: rel_B_chnl
|
||
Description: release B-channel link
|
||
Input: pid:port id
|
||
Return: ISDN_CM_OK:success
|
||
*************************************************************/
|
||
int rel_B_chnl(u32 pid)
|
||
{
|
||
u8 flag;
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
flag = pPort->enable;
|
||
if (flag != 0)
|
||
{
|
||
pPort->enable = 0;
|
||
pPort->su_proc_id = 0;
|
||
pPort->cic_val = 0;
|
||
pPort->pre_send_msg = 0;
|
||
}
|
||
|
||
return ISDN_CM_OK;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: isdn_cpc_clear
|
||
Description: clearing the interrelated state of the call at call processing control
|
||
Output: pPort:port structure pointer
|
||
Return: NULL
|
||
*************************************************************/
|
||
inline void isdn_cpc_clear(ISDN_Port_struct *pPort)
|
||
{
|
||
pPort->timer_flag = 0;
|
||
pPort->cic_state.call_state = IDLE_FLAG;
|
||
pPort->fsm_state.cpc_state = NULL_STATE;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: isdn_rel_proc
|
||
Description: release isdn module process, include rel_B_chnl() and rel_cr()
|
||
Input: pid:port id, cause:release reason value
|
||
Return: ISDN_CM_OK:success
|
||
*************************************************************/
|
||
int isdn_rel_proc(u32 pid, u32 cause)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
isdn_event_handle(pid, ISDN_RELEASE_IND);
|
||
pPort->w_time = 0;
|
||
rel_B_chnl(pid);
|
||
isdn_send_msg(pid, MSG_REL_COMP);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
return ISDN_CM_OK;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: nr_proc
|
||
Description: processing nr, nr is the interval state identifier in the SDL diagrams
|
||
Input: pid:port id
|
||
Return: if LT side, successfully enter the state u19
|
||
if NT side, successfully enter the state n19
|
||
*************************************************************/
|
||
int nr_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
pPort->w_time = 0; //start t308
|
||
pPort->timeout_fg = 0;
|
||
isdn_send_msg(pid, MSG_REL);
|
||
return REL_REQ_STATE;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: nd_proc
|
||
Description: processing nd, nd is the interval state identifier in the SDL diagrams
|
||
Input: pid:port id
|
||
Return: if LT side, successfully enter the state u12
|
||
if NT side, successfully enter the state n11
|
||
*************************************************************/
|
||
int nd_proc(u32 pid)
|
||
{
|
||
int circuit_id;
|
||
const pal_circuit_struct *circuit_ptr = NULL;
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
circuit_id = pid / ISDN_CIRCUIT_CIC;
|
||
circuit_ptr = pal_circuit_ptr(circuit_id);
|
||
if(circuit_ptr == NULL)
|
||
{
|
||
isdn_log_err(pid, "nd_proc err!circuit_id %d can't find circuit_ptr", circuit_id);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
|
||
/*disconnect B-channel*/
|
||
pPort->w_time = 0; //stop all
|
||
isdn_event_handle(pid, ISDN_DISCONNECT_IND);
|
||
if(circuit_ptr->attrib.user_network_if)
|
||
return DISC_IND_STATE;
|
||
else
|
||
return DISC_REQ_STATE;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: nc_proc
|
||
Description: processing nc, nc is the interval state identifier in the SDL diagrams
|
||
Input: pid:port id
|
||
Return: if LT side, successfully enter the state u11
|
||
if NT side, successfully enter the state n12
|
||
*************************************************************/
|
||
int nc_proc(u32 pid)
|
||
{
|
||
int circuit_id;
|
||
const pal_circuit_struct *circuit_ptr = NULL;
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
circuit_id = pid / ISDN_CIRCUIT_CIC;
|
||
circuit_ptr = pal_circuit_ptr(circuit_id);
|
||
if(circuit_ptr == NULL)
|
||
{
|
||
isdn_log_err(pid, "nc_proc err!circuit_id %d can't find circuit_ptr", circuit_id);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
|
||
/*disconnect B-channel*/
|
||
pPort->w_time = 0; //stop all and start t305
|
||
isdn_send_msg(pid, MSG_DISC);
|
||
if(circuit_ptr->attrib.user_network_if)
|
||
return DISC_REQ_STATE;
|
||
else
|
||
return DISC_IND_STATE;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: isdn_set_cause
|
||
Description: set the reason value, and keep into cause_ptr
|
||
Input: val:reason value
|
||
Output: cause_ptr:cause structure pointer
|
||
Return: NULL
|
||
*************************************************************/
|
||
void isdn_set_cause(CauseStr *cause_ptr, u8 val)
|
||
{
|
||
cause_ptr->pres = 1;
|
||
cause_ptr->ext_flag = 0x0;
|
||
cause_ptr->b3.has_ext_a = 1;
|
||
cause_ptr->b3.code_stan = 0x0; //CCITT standardized coding
|
||
cause_ptr->b3.loc = cause_to_loc[val];
|
||
cause_ptr->cause_val = val;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: isdn_set_status
|
||
Description: set the call state, and keep into status_ptr
|
||
Input: state:call state, cause_val:reason value
|
||
Output: status_ptr:status structure pointer
|
||
Return: NULL
|
||
*************************************************************/
|
||
void isdn_set_status(IsdnStatus *status_ptr, u8 state, u8 cause_val)
|
||
{
|
||
isdn_set_cause(&status_ptr->cause, cause_val);
|
||
status_ptr->call_stat.code_stan = 0x0;
|
||
status_ptr->call_stat.stat_val = (state & 0x3F);
|
||
}
|
||
|
||
|
||
/*************************************************************
|
||
Function: n0_proc
|
||
Description: Null State, no call exists.
|
||
Handling the process and entering into next call state
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
-1:failed
|
||
*************************************************************/
|
||
int n0_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->primitive_cmd == ISDN_SETUP_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
if(cr_sel(pid) != 1)
|
||
{
|
||
isdn_log_err(pid, "cr_sel error!\r\n");
|
||
return NULL_STATE;
|
||
}
|
||
isdn_send_msg(pid, MSG_SETUP);
|
||
pPort->timer_flag = CALLIN_FLAG;
|
||
pPort->w_time = 0; //start t303
|
||
pPort->timeout_fg = 0;
|
||
return CALL_PRE_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_SETUP)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
//pPort->call_ref = msg_cref[pid];
|
||
isdn_event_handle(pid, ISDN_SETUP_IND);
|
||
return CALL_INIT_STATE;
|
||
}
|
||
//MSG_REL, MSG_REL_COMP, MSG_STATUS, and MSG_STAT_ENQ are doing in n0_ext_proc()
|
||
|
||
return -1;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: n1_proc
|
||
Description: Call initiated state, this state exists for an outgoing call
|
||
when the network has received a call establishment request
|
||
but has not yet responded.
|
||
Handling the process and entering into next call state.
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
-1:failed
|
||
*************************************************************/
|
||
int n1_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->primitive_cmd == ISDN_PROC_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
/*Connect B-channel*/
|
||
isdn_send_msg(pid, MSG_CALL_PROC);
|
||
return OUT_CALL_PROC_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_MORE_INFO_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
pPort->w_time = 0; //start t302
|
||
/*Connect B-channel*/
|
||
isdn_send_msg(pid, MSG_SETUP_ACK);
|
||
return OVERLAP_SD_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_REJECT_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
rel_B_chnl(pid);
|
||
isdn_send_msg(pid, MSG_REL_COMP);
|
||
rel_cr(pid);
|
||
return NULL_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: n2_proc
|
||
Description: Overlap sending state, this state exists for an outgoing call
|
||
when the network has acknowledged the call establishment request
|
||
and is prepared to receive additional call information (if any)
|
||
in overlap mode.
|
||
Handling the process and entering into next call state.
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
-1:failed
|
||
*************************************************************/
|
||
int n2_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->primitive_cmd == ISDN_PROC_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
pPort->w_time = 0; //stop t302
|
||
isdn_send_msg(pid, MSG_CALL_PROC);
|
||
return OUT_CALL_PROC_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_INFORMATION)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //start or restart t302
|
||
isdn_event_handle(pid, ISDN_INFO_IND);
|
||
return OVERLAP_SD_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_ALERT_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
pPort->w_time = 0; //stop t302
|
||
isdn_send_msg(pid, MSG_ALERT);
|
||
return CALL_DV_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_SETUP_RSP)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
pPort->w_time = 0; //stop t302
|
||
/* Connect Backwards B-channel Here */
|
||
isdn_send_msg(pid, MSG_CONN);
|
||
return ACTIVE_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_PROG_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
pPort->w_time = 0; //stop t302
|
||
isdn_send_msg(pid, MSG_PROG);
|
||
return OVERLAP_SD_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: n3_proc
|
||
Description: Outgoing call proceeding state, this state exists for an outgoing call
|
||
when the network has sent acknowledgement that the network has received
|
||
all call information necessary to effect call establishment.
|
||
Handling the process and entering into next call state.
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
-1:failed
|
||
*************************************************************/
|
||
int n3_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->primitive_cmd == ISDN_ALERT_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_send_msg(pid, MSG_ALERT);
|
||
return CALL_DV_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_SETUP_RSP)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
/* Connect Backwards B-channel Here */
|
||
isdn_send_msg(pid, MSG_CONN);
|
||
return ACTIVE_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_PROG_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_send_msg(pid, MSG_PROG);
|
||
return OUT_CALL_PROC_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: n4_proc
|
||
Description: Call delivered state, this state exists for an outgoing call
|
||
when the network has indicated that remote user alerting
|
||
has been initiated.
|
||
Handling the process and entering into next call state.
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
-1:failed
|
||
*************************************************************/
|
||
int n4_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->primitive_cmd == ISDN_SETUP_RSP)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
/* Connect Backwards B-channel Here */
|
||
isdn_send_msg(pid, MSG_CONN);
|
||
return ACTIVE_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_PROG_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_send_msg(pid, MSG_PROG);
|
||
return CALL_DV_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: n6_proc
|
||
Description: Call present state, this state exists for an incoming call
|
||
when the network has sent a call establishment request
|
||
but has not yet received a satisfactory response.
|
||
Handling the process and entering into next call state.
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
-1:failed
|
||
*************************************************************/
|
||
int n6_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_CALL_PROC)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t303 and start t310
|
||
isdn_event_handle(pid, ISDN_PROC_IND);
|
||
return IN_CALL_PROC_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_ALERT)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t303 and start t301
|
||
isdn_event_handle(pid, ISDN_ALERT_IND);
|
||
return CALL_RV_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_CONN)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t303
|
||
pPort->primitive_cmd = ISDN_SETUP_CNF; //msc does not provide ISDN_SETUP_COMP_REQ to isdn
|
||
isdn_event_handle(pid, ISDN_SETUP_CNF);
|
||
return CONN_REQ_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_SETUP_ACK)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t303 and start t304
|
||
isdn_event_handle(pid, ISDN_MORE_INFO_IND);
|
||
return OVERLAP_RV_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_REL_COMP) //do it temporarily in isdn_comm_ctrl()
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t303
|
||
// isdn_event_handle(pid, ISDN_REJ_IND);
|
||
rel_B_chnl(pid);
|
||
rel_cr(pid);
|
||
return NULL_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: n7_proc
|
||
Description: Call received state, this state exists for an incoming call
|
||
when the network has received an indication that the user is alerting
|
||
but has not yet received an answer.
|
||
Handling the process and entering into next call state.
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
-1:failed
|
||
*************************************************************/
|
||
int n7_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_CONN)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t301
|
||
pPort->primitive_cmd = ISDN_SETUP_CNF; //msc does not provide ISDN_SETUP_COMP_REQ to isdn
|
||
isdn_event_handle(pid, ISDN_SETUP_CNF);
|
||
return CONN_REQ_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_PROG) //support U04_09
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t310
|
||
isdn_event_handle(pid, ISDN_PROG_IND);
|
||
return CALL_DV_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: n8_proc
|
||
Description: Connect request state, this state exists for an incoming call
|
||
when the network has received an answer but the network has not yet
|
||
awarded the call.
|
||
Handling the process and entering into next call state.
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
-1:failed
|
||
*************************************************************/
|
||
int n8_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->primitive_cmd == ISDN_SETUP_COMP_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
/* Connect Backwards B-channel Here */
|
||
isdn_send_msg(pid, MSG_CONNACK);
|
||
return ACTIVE_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: n9_proc
|
||
Description: Incoming call proceeding state, this state exists for an incoming call
|
||
when the network has received acknowledgement that the user has received
|
||
all call information necessary to effect call establishment.
|
||
Handling the process and entering into next call state.
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
-1:failed
|
||
*************************************************************/
|
||
int n9_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_ALERT)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t310 and start t301
|
||
isdn_event_handle(pid, ISDN_ALERT_IND);
|
||
return CALL_RV_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_CONN)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t310
|
||
pPort->primitive_cmd = ISDN_SETUP_CNF; //msc does not provide ISDN_SETUP_COMP_REQ to isdn
|
||
isdn_event_handle(pid, ISDN_SETUP_CNF);
|
||
return CONN_REQ_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_PROG)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
isdn_event_handle(pid, ISDN_PROG_IND);
|
||
return IN_CALL_PROC_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: n10_proc
|
||
Description: Active state, this state exists for an incoming call
|
||
when the network has awarded the call to the called user, and
|
||
this state exists for an outgoing call when the network has indicated
|
||
that the remote user has answered the call.
|
||
Handling the process and entering into next call state.
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
-1:failed
|
||
*************************************************************/
|
||
int n10_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_CONNACK)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
return ACTIVE_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_NOTI)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
isdn_event_handle(pid, ISDN_NOTI_IND);
|
||
return ACTIVE_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_NOTI_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_send_msg(pid, MSG_NOTI);
|
||
return ACTIVE_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: n11_proc
|
||
Description: Disconnect request state, this state exists when the network has received
|
||
a request from the user to clear the end-to-end connection (if any).
|
||
Handling the process and entering into next call state.
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
-1:failed
|
||
*************************************************************/
|
||
int n11_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->primitive_cmd == ISDN_RELEASE_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
return nr_proc(pid); //REL_REQ_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_REL)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop all
|
||
memcpy(&isdn_sd_msg.msg_list.relComp.cause, &isdn_rv_msg.msg_list.rel.cause, sizeof(CauseStr));
|
||
isdn_event_handle(pid, ISDN_RELEASE_CNF);
|
||
rel_B_chnl(pid);
|
||
isdn_send_msg(pid, MSG_REL_COMP);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
return NULL_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: n12_proc
|
||
Description: Disconnect indication state, this state exists when the network has
|
||
disconnected the end-to-end connection (if any) and has sent an
|
||
invitation to disconnect the user-network connection.
|
||
Handling the process and entering into next call state.
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
-1:failed
|
||
*************************************************************/
|
||
int n12_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_DISC)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
memcpy(&isdn_sd_msg.msg_list.rel.cause, &isdn_rv_msg.msg_list.disc.cause, sizeof(CauseStr));
|
||
return nr_proc(pid); //REL_REQ_STATE
|
||
}
|
||
else if(pPort->msg_cmd == MSG_REL)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t305 or t306
|
||
memcpy(&isdn_sd_msg.msg_list.relComp.cause, &isdn_rv_msg.msg_list.rel.cause, sizeof(CauseStr));
|
||
// isdn_event_handle(pid, ISDN_RELEASE_IND);
|
||
isdn_event_handle(pid, ISDN_RELEASE_CNF);
|
||
rel_B_chnl(pid);
|
||
isdn_send_msg(pid, MSG_REL_COMP);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
return NULL_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: n19_proc
|
||
Description: Release request state, this state exists when the network has
|
||
requested the user to release and is waiting for a response.
|
||
Handling the process and entering into next call state.
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
-1:failed
|
||
*************************************************************/
|
||
int n19_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if((pPort->msg_cmd == MSG_REL_COMP)
|
||
|| (pPort->msg_cmd == MSG_REL))
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t308
|
||
isdn_event_handle(pid, ISDN_RELEASE_CNF);
|
||
rel_B_chnl(pid);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
return NULL_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_STATUS)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
if(isdn_rv_msg.msg_list.status.call_stat.stat_val != 0)
|
||
return REL_REQ_STATE;
|
||
pPort->w_time = 0; //stop t308
|
||
isdn_event_handle(pid, ISDN_STAT_IND);
|
||
rel_B_chnl(pid);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
return NULL_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: n25_proc
|
||
Description: Overlap receiving state, this state exists for an incoming call
|
||
when the network has received acknowledgement of the call
|
||
establishment request which permits the network to send
|
||
additional call information (if any) in the overlap mode
|
||
Handling the process and entering into next call state.
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
-1:failed
|
||
*************************************************************/
|
||
int n25_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->primitive_cmd == ISDN_INFO_REQ) //ISDN_MORE_INFO_REQ
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
pPort->w_time = 0; //start or restart t304
|
||
isdn_send_msg(pid, MSG_INFORMATION);
|
||
return OVERLAP_RV_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_ALERT)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t304 and start t301
|
||
isdn_event_handle(pid, ISDN_ALERT_IND);
|
||
return CALL_RV_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_CONN)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t304
|
||
pPort->primitive_cmd = ISDN_SETUP_CNF; //msc does not provide ISDN_SETUP_COMP_REQ to isdn
|
||
isdn_event_handle(pid, ISDN_SETUP_CNF);
|
||
return CONN_REQ_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_CALL_PROC)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t304 and start t310
|
||
isdn_event_handle(pid, ISDN_PROC_IND);
|
||
return IN_CALL_PROC_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_PROG)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
isdn_event_handle(pid, ISDN_PROG_IND);
|
||
return OVERLAP_RV_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
|
||
/*user side state processing*/
|
||
int u0_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->primitive_cmd == ISDN_SETUP_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
if(cr_sel(pid) != 1)
|
||
{
|
||
isdn_log_err(pid, "cr_sel error!\r\n");
|
||
return NULL_STATE;
|
||
}
|
||
isdn_send_msg(pid, MSG_SETUP);
|
||
pPort->timer_flag = CALLOUT_FLAG;
|
||
pPort->w_time = 0; //start t303
|
||
pPort->timeout_fg = 0;
|
||
return CALL_INIT_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_SETUP)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
//pPort->call_ref = msg_cref[pid];
|
||
isdn_event_handle(pid, ISDN_SETUP_IND);
|
||
return CALL_PRE_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int u1_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_SETUP_ACK)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t303 and start t304
|
||
isdn_event_handle(pid, ISDN_MORE_INFO_IND);
|
||
return OVERLAP_SD_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_CALL_PROC)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t303 and start t310
|
||
isdn_event_handle(pid, ISDN_PROC_IND);
|
||
return OUT_CALL_PROC_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_ALERT)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t303
|
||
isdn_event_handle(pid, ISDN_ALERT_IND);
|
||
return CALL_DV_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_CONN)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t303
|
||
isdn_event_handle(pid, ISDN_SETUP_CNF);
|
||
isdn_send_msg(pid, MSG_CONNACK);
|
||
return ACTIVE_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_REL_COMP) //do it temporarily in isdn_comm_ctrl()
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t303
|
||
//isdn_event_handle(pid, ISDN_REJ_IND);
|
||
rel_cr(pid);
|
||
return NULL_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int u2_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_CALL_PROC)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t304 and start t310
|
||
isdn_event_handle(pid, ISDN_PROC_IND);
|
||
return OUT_CALL_PROC_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_ALERT)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t304
|
||
isdn_event_handle(pid, ISDN_ALERT_IND);
|
||
return CALL_DV_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_CONN)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t304
|
||
isdn_event_handle(pid, ISDN_SETUP_CNF);
|
||
isdn_send_msg(pid, MSG_CONNACK);
|
||
return ACTIVE_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_PROG)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t304
|
||
isdn_event_handle(pid, ISDN_PROG_IND);
|
||
return OVERLAP_SD_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_INFO_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
pPort->w_time = 0; //start or restart t304
|
||
isdn_send_msg(pid, MSG_INFORMATION);
|
||
return OVERLAP_SD_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int u3_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_ALERT)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t310 and start t301
|
||
isdn_event_handle(pid, ISDN_ALERT_IND);
|
||
return CALL_DV_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_CONN)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t310
|
||
isdn_event_handle(pid, ISDN_SETUP_CNF);
|
||
isdn_send_msg(pid, MSG_CONNACK);
|
||
return ACTIVE_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_PROG)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t310
|
||
isdn_event_handle(pid, ISDN_PROG_IND);
|
||
return OUT_CALL_PROC_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int u4_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_CONN)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
isdn_event_handle(pid, ISDN_SETUP_CNF);
|
||
isdn_send_msg(pid, MSG_CONNACK);
|
||
return ACTIVE_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_PROG) //support U04_09
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t310
|
||
isdn_event_handle(pid, ISDN_PROG_IND);
|
||
return CALL_DV_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int u6_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->primitive_cmd == ISDN_MORE_INFO_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
pPort->w_time = 0; //start t302
|
||
isdn_send_msg(pid, MSG_SETUP_ACK);
|
||
return OVERLAP_RV_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_PROC_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_send_msg(pid, MSG_CALL_PROC);
|
||
return IN_CALL_PROC_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_ALERT_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_send_msg(pid, MSG_ALERT);
|
||
return CALL_RV_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_SETUP_RSP)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
pPort->w_time = 0; //start t313
|
||
isdn_send_msg(pid, MSG_CONN);
|
||
return CONN_REQ_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_REJECT_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
rel_B_chnl(pid);
|
||
isdn_send_msg(pid, MSG_REL_COMP);
|
||
rel_cr(pid);
|
||
return NULL_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int u7_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->primitive_cmd == ISDN_SETUP_RSP)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
pPort->w_time = 0; //start t313
|
||
isdn_send_msg(pid, MSG_CONN);
|
||
return CONN_REQ_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_PROG_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_send_msg(pid, MSG_PROG);
|
||
return CALL_DV_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int u8_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_CONNACK)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t313
|
||
isdn_event_handle(pid, ISDN_SETUP_COMP_IND);
|
||
return ACTIVE_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int u9_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->primitive_cmd == ISDN_ALERT_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_send_msg(pid, MSG_ALERT);
|
||
return CALL_RV_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_SETUP_RSP)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
pPort->w_time = 0; //start t313
|
||
isdn_send_msg(pid, MSG_CONN);
|
||
return CONN_REQ_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_PROG_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_send_msg(pid, MSG_PROG);
|
||
return IN_CALL_PROC_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int u10_proc(u32 pid) //?? add by gengxin
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_NOTI)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
isdn_event_handle(pid, ISDN_NOTI_IND);
|
||
return ACTIVE_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_NOTI_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_send_msg(pid, MSG_NOTI);
|
||
return ACTIVE_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int u11_proc(u32 pid) //0911
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_DISC)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
memcpy(&isdn_sd_msg.msg_list.rel.cause, &isdn_rv_msg.msg_list.disc.cause, sizeof(CauseStr));
|
||
return nr_proc(pid);
|
||
}
|
||
else if(pPort->msg_cmd == MSG_REL)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t305
|
||
memcpy(&isdn_sd_msg.msg_list.relComp.cause, &isdn_rv_msg.msg_list.rel.cause, sizeof(CauseStr));
|
||
// isdn_event_handle(pid, ISDN_RELEASE_IND);
|
||
isdn_event_handle(pid, ISDN_RELEASE_CNF);
|
||
rel_B_chnl(pid);
|
||
isdn_send_msg(pid, MSG_REL_COMP);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
return NULL_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int u12_proc(u32 pid) //0911
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_REL)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
memcpy(&isdn_sd_msg.msg_list.relComp.cause, &isdn_rv_msg.msg_list.rel.cause, sizeof(CauseStr));
|
||
// isdn_event_handle(pid, ISDN_RELEASE_IND);
|
||
isdn_event_handle(pid, ISDN_RELEASE_CNF);
|
||
rel_B_chnl(pid);
|
||
isdn_send_msg(pid, MSG_REL_COMP);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
return NULL_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_RELEASE_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
return nr_proc(pid);
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int u19_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if((pPort->msg_cmd == MSG_REL_COMP) ||
|
||
(pPort->msg_cmd == MSG_REL))
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
isdn_event_handle(pid, ISDN_RELEASE_CNF);
|
||
rel_B_chnl(pid);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
return NULL_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_STATUS)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
if(isdn_rv_msg.msg_list.status.call_stat.stat_val != 0)
|
||
return REL_REQ_STATE;
|
||
isdn_event_handle(pid, ISDN_STAT_IND);
|
||
rel_B_chnl(pid);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
return NULL_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int u25_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_INFORMATION)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //start t302
|
||
isdn_event_handle(pid, ISDN_INFO_IND);
|
||
return OVERLAP_RV_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_PROC_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
pPort->w_time = 0; //stop t302
|
||
isdn_send_msg(pid, MSG_CALL_PROC);
|
||
return IN_CALL_PROC_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_ALERT_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
pPort->w_time = 0; //stop t302
|
||
isdn_send_msg(pid, MSG_ALERT);
|
||
return CALL_RV_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_SETUP_RSP)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
pPort->w_time = 0; //stop t302 and start t313
|
||
isdn_send_msg(pid, MSG_CONN);
|
||
return CONN_REQ_STATE;
|
||
}
|
||
else if(pPort->primitive_cmd == ISDN_PROG_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_send_msg(pid, MSG_PROG);
|
||
return OVERLAP_RV_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
|
||
/* Global Call Reference Procedures */
|
||
/*************************************************************
|
||
Function: trans_callref_sd_rest_req
|
||
Description:
|
||
Input:
|
||
Output:
|
||
Return:
|
||
*************************************************************/
|
||
int trans_callref_sd_rest_req(u32 pid, u8 g_pri_cmd) //isdn_restart_req()
|
||
{
|
||
int i, link_id, cic_range;
|
||
u16 circuit_id;
|
||
const pal_circuit_struct *circuit_ptr = NULL;
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
circuit_id = pid / ISDN_CIRCUIT_CIC;
|
||
circuit_ptr = pal_circuit_ptr(circuit_id);
|
||
if(circuit_ptr == NULL)
|
||
return ISDN_CM_FAILED;
|
||
|
||
link_id = circuit_ptr->attrib.link_id;
|
||
cic_range = circuit_ptr->attrib.cic_range;
|
||
if(cic_range == 24) //T1
|
||
cic_range++;
|
||
if(isdn_rs.link_pond[link_id].restart_clas == 0) //indicated channels
|
||
{
|
||
if(pPort->cic_val != 0)
|
||
{
|
||
pid = find_port_by_cic(pPort->cic_val, circuit_id);
|
||
pPort = &isdn_rs.port_pond[pid];
|
||
if(g_pri_cmd == ISDN_RESTART_REQ)
|
||
{
|
||
pPort->g_pri_cmd = ISDN_RESTART_REQ;
|
||
isdn_cpc_proc(pid);
|
||
if(pPort->g_pri_cmd != 0 && pPort->g_pri_cmd != ISDN_RESTART_CNF)
|
||
{
|
||
isdn_trace_func(pid, "[waring]primitive cmd discard.(cmd=%d)\r\n", pPort->primitive_cmd);
|
||
pPort->g_pri_cmd = 0;
|
||
}
|
||
return circuit_ptr->attrib.cic_range;
|
||
}
|
||
else if(g_pri_cmd == ISDN_RESTART_CNF)
|
||
{
|
||
if(pPort->g_pri_cmd != g_pri_cmd)
|
||
{
|
||
pPort->g_pri_cmd = 0;
|
||
isdn_trace_func(pid, "[waring]primitive cmd is not ISDN_RESTART_CNF.(cmd=%d)\r\n", pPort->primitive_cmd);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
pPort->g_pri_cmd = 0;
|
||
return circuit_ptr->attrib.cic_range;
|
||
}
|
||
}
|
||
}
|
||
else if(isdn_rs.link_pond[link_id].restart_clas == 6) //single interface
|
||
{
|
||
for(i = 1; i < cic_range; i++)
|
||
{
|
||
pid = circuit_id * ISDN_CIRCUIT_CIC + i;
|
||
pPort = &isdn_rs.port_pond[pid];
|
||
if(pPort->enable != 0)
|
||
{
|
||
if(g_pri_cmd == ISDN_RESTART_REQ)
|
||
{
|
||
pPort->g_pri_cmd = ISDN_RESTART_REQ;
|
||
isdn_cpc_proc(pid);
|
||
if(pPort->g_pri_cmd != 0 && pPort->g_pri_cmd != ISDN_RESTART_CNF)
|
||
{
|
||
isdn_trace_func(pid, "[waring]primitive cmd discard.(cmd=%d)\r\n", pPort->primitive_cmd);
|
||
pPort->g_pri_cmd = 0;
|
||
}
|
||
}
|
||
else if(g_pri_cmd == ISDN_RESTART_CNF)
|
||
{
|
||
if(pPort->g_pri_cmd != g_pri_cmd)
|
||
{
|
||
pPort->g_pri_cmd = 0;
|
||
isdn_trace_func(pid, "[waring]primitive cmd is not ISDN_RESTART_CNF.(cmd=%d)\r\n", pPort->primitive_cmd);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
pPort->g_pri_cmd = 0;
|
||
}
|
||
}
|
||
}
|
||
// isdn_rs.link_pond[link_id].restart_clas = 0;
|
||
return circuit_ptr->attrib.cic_range;
|
||
}
|
||
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
|
||
static inline void restart_clear(u32 pid)
|
||
{
|
||
int i, link_id, cic_range;
|
||
u16 circuit_id = pid / ISDN_CIRCUIT_CIC;
|
||
const pal_circuit_struct *circuit_ptr = pal_circuit_ptr(circuit_id);
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
if(circuit_ptr == NULL)
|
||
return;
|
||
|
||
link_id = circuit_ptr->attrib.link_id;
|
||
cic_range = circuit_ptr->attrib.cic_range;
|
||
if(cic_range == 24) //T1
|
||
cic_range++;
|
||
if(isdn_rs.link_pond[link_id].restart_clas == 0) //indicated channels
|
||
{
|
||
pid = find_port_by_cic(pPort->cic_val, circuit_id);
|
||
pPort->cic_val = 0;
|
||
rel_B_chnl(pid);
|
||
isdn_cpc_clear(pPort);
|
||
}
|
||
else
|
||
{
|
||
isdn_rs.link_pond[link_id].restart_clas = 0;
|
||
for(i = 1; i < cic_range; i++)
|
||
{
|
||
pid = circuit_id * ISDN_CIRCUIT_CIC + i;
|
||
pPort = &isdn_rs.port_pond[pid];
|
||
if(pPort->enable != 0)
|
||
{
|
||
rel_B_chnl(pid);
|
||
isdn_cpc_clear(pPort);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
int rest0_proc(u32 pid, IsdnRestart *restart)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_RESTART)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //start t317
|
||
memcpy(restart, &isdn_rv_msg.msg_list.restart, sizeof(IsdnRestart));
|
||
trans_callref_sd_rest_req(pid, ISDN_RESTART_REQ);
|
||
return GLOBAL_RESTART_STATE;
|
||
}
|
||
else if(pPort->g_pri_cmd == ISDN_M_RESTART_REQ)
|
||
{
|
||
pPort->g_pri_cmd = 0;
|
||
pPort->timeout_fg = 0;
|
||
pPort->w_time = 0; //start t316
|
||
isdn_send_msg(pid, MSG_RESTART);
|
||
trans_callref_sd_rest_req(pid, ISDN_RESTART_REQ);
|
||
return GLOBAL_RESTART_REQ_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int rest1_proc(u32 pid)
|
||
{
|
||
static int rest_resp_on = 0; //??
|
||
static int rest_ack_on = 0;
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->msg_cmd == MSG_REST_ACK)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t316
|
||
if(rest_resp_on)
|
||
{
|
||
rest_resp_on = 0;
|
||
restart_clear(pid);
|
||
return GLOBAL_NULL_STATE;
|
||
}
|
||
else
|
||
rest_ack_on = 1;
|
||
}
|
||
else if(pPort->g_pri_cmd == ISDN_RESTART_CNF)
|
||
{
|
||
pPort->g_pri_cmd = 0;
|
||
if(rest_ack_on)
|
||
{
|
||
rest_ack_on = 0;
|
||
restart_clear(pid);
|
||
return GLOBAL_NULL_STATE;
|
||
}
|
||
else
|
||
rest_resp_on = 1;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_RESTART)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
trans_callref_sd_rest_req(pid, ISDN_RESTART_REQ);
|
||
return GLOBAL_RESTART_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
int rest2_proc(u32 pid, IsdnRestart restart)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
if(pPort->g_pri_cmd == ISDN_RESTART_CNF)
|
||
{
|
||
pPort->g_pri_cmd = 0;
|
||
pPort->w_time = 0;
|
||
memcpy(&isdn_sd_msg.msg_list.restAck, (IsdnRestAck *)&restart, sizeof(IsdnRestAck));
|
||
isdn_send_msg(pid, MSG_REST_ACK);
|
||
restart_clear(pid);
|
||
return GLOBAL_NULL_STATE;
|
||
}
|
||
else if(pPort->msg_cmd == MSG_RESTART)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
trans_callref_sd_rest_req(pid, ISDN_RESTART_REQ);
|
||
return GLOBAL_RESTART_STATE;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
void isdn_restart_ctrl(u32 pid)
|
||
{
|
||
int num = 0;
|
||
static IsdnRestart restart;
|
||
ISDN_Port_struct *pPort = &(isdn_rs.port_pond[pid]);
|
||
const pal_circuit_struct *circuit_ptr = pal_circuit_ptr(pid / ISDN_CIRCUIT_CIC);
|
||
if(circuit_ptr == NULL)
|
||
return;
|
||
|
||
switch(pPort->cic_state.call_state)
|
||
{
|
||
case CALLOUT_FLAG:
|
||
case CALLIN_FLAG:
|
||
case GLOBAL_NULL_STATE:
|
||
switch(rest0_proc(pid, &restart))
|
||
{
|
||
case GLOBAL_RESTART_REQ_STATE:
|
||
pPort->cic_state.call_state = GLOBAL_RESTART_REQ_STATE;
|
||
break;
|
||
case GLOBAL_RESTART_STATE:
|
||
pPort->cic_state.call_state = GLOBAL_RESTART_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case GLOBAL_RESTART_REQ_STATE:
|
||
switch(rest1_proc(pid))
|
||
{
|
||
case GLOBAL_NULL_STATE:
|
||
pPort->cic_state.call_state = GLOBAL_NULL_STATE;
|
||
break;
|
||
case GLOBAL_RESTART_STATE:
|
||
pPort->cic_state.call_state = GLOBAL_RESTART_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case GLOBAL_RESTART_STATE:
|
||
switch(rest2_proc(pid, restart))
|
||
{
|
||
case GLOBAL_NULL_STATE:
|
||
pPort->cic_state.call_state = GLOBAL_NULL_STATE;
|
||
break;
|
||
case GLOBAL_RESTART_STATE:
|
||
pPort->cic_state.call_state = GLOBAL_RESTART_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
// printf("global state = 0x%02x\n",pPort->cic_state.call_state);
|
||
if(pPort->g_pri_cmd == ISDN_RESTART_REQ)
|
||
{
|
||
pPort->g_pri_cmd = 0;
|
||
if(pPort->cic_state.call_state == GLOBAL_RESTART_STATE)
|
||
memcpy(&isdn_sd_msg.msg_list.restAck, &isdn_rv_msg.msg_list.restart, sizeof(IsdnRestart));
|
||
if((num = trans_callref_sd_rest_req(pid, ISDN_RESTART_CNF)) == circuit_ptr->attrib.cic_range)
|
||
pPort->g_pri_cmd = ISDN_RESTART_CNF;
|
||
// isdn_restart_ctrl(pid);
|
||
}
|
||
else if(pPort->g_pri_cmd != 0)
|
||
{
|
||
isdn_log_err(pid, "global g_pri_cmd = 0x%x\r\n", pPort->g_pri_cmd);
|
||
pPort->g_pri_cmd = 0;
|
||
}
|
||
|
||
if(pPort->msg_cmd != 0)
|
||
{
|
||
isdn_log_err(pid, "global msg_cmd = 0x%x\r\n", pPort->msg_cmd);
|
||
pPort->msg_cmd = 0;
|
||
isdn_set_status(&isdn_sd_msg.msg_list.status, pPort->cic_state.call_state, CAUSE_INVALID_CR); //cause 81
|
||
isdn_send_msg(pid, MSG_STATUS);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/*************************************************************
|
||
Function: not_isdn_rel_st
|
||
Description: Handling state is isdn release state or not
|
||
Input: state:call state
|
||
Return: ISDN_CM_OK:success
|
||
ISDN_CM_FAILED:failed
|
||
*************************************************************/
|
||
static int not_isdn_rel_st(u8 state)
|
||
{
|
||
if((state != NULL_STATE) &&
|
||
(state != DISC_REQ_STATE) &&
|
||
(state != DISC_IND_STATE) &&
|
||
(state != REL_REQ_STATE))
|
||
return ISDN_CM_OK;
|
||
else
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
|
||
/*************************************************************
|
||
Function: isdn_comm_ctrl
|
||
Description: ISDN Protocol Common Control
|
||
Input: pid:port id
|
||
Return: state value:success
|
||
*************************************************************/
|
||
u8 isdn_comm_ctrl(u32 pid)
|
||
{
|
||
u8 state, msg_cmd, pri_cmd, g_pri_cmd;
|
||
ISDN_Port_struct *pPort = &(isdn_rs.port_pond[pid]);
|
||
const pal_circuit_struct *circuit_ptr = pal_circuit_ptr(pid / ISDN_CIRCUIT_CIC);
|
||
if(circuit_ptr == NULL)
|
||
{
|
||
isdn_log_err(pid, "isdn_comm_ctrl err! circuit_id %d can't find circuit_ptr!\r\n",pid/ISDN_CIRCUIT_CIC);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
|
||
state = pPort->fsm_state.cpc_state;
|
||
msg_cmd = pPort->msg_cmd;
|
||
pri_cmd = pPort->primitive_cmd;
|
||
g_pri_cmd = pPort->g_pri_cmd;
|
||
if(not_isdn_rel_st(state))
|
||
{
|
||
if(msg_cmd == MSG_DISC)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
if(state != ACTIVE_STATE)
|
||
{
|
||
isdn_log_err(pid, "isdn_comm_ctrl err1!\r\n");
|
||
}
|
||
return nd_proc(pid);
|
||
}
|
||
else if(pri_cmd == ISDN_DISCONNECT_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
if(state != ACTIVE_STATE)
|
||
{
|
||
isdn_log_err(pid, "isdn_comm_ctrl err2!\r\n");
|
||
}
|
||
return nc_proc(pid);
|
||
}
|
||
else if(pri_cmd == ISDN_RELEASE_REQ)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_log_err(pid, "isdn_comm_ctrl err3, rv release req!\r\n");
|
||
return nr_proc(pid);
|
||
}
|
||
else if(msg_cmd == MSG_REL)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop all
|
||
isdn_log_err(pid, "isdn_comm_ctrl err4, rv rel!\r\n");
|
||
isdn_event_handle(pid, ISDN_RELEASE_IND);
|
||
rel_B_chnl(pid);
|
||
// memcpy(&isdn_sd_msg.msg_list.relComp, &isdn_rv_msg.msg_list.rel, sizeof(IsdnRel));
|
||
isdn_send_msg(pid, MSG_REL_COMP);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
return NULL_STATE;
|
||
}
|
||
}
|
||
|
||
if((state != NULL_STATE) && (state != REL_REQ_STATE))
|
||
{
|
||
if(msg_cmd == MSG_STATUS)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
if(isdn_rv_msg.msg_list.status.call_stat.stat_val == 0)
|
||
{
|
||
isdn_log_err(pid, "isdn_comm_ctrl err5, rv status with null state!\r\n");
|
||
isdn_event_handle(pid, ISDN_STAT_IND);
|
||
rel_B_chnl(pid);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
return NULL_STATE;
|
||
}
|
||
else if(isdn_rv_msg.msg_list.status.call_stat.stat_val != state)
|
||
{
|
||
isdn_log_err(pid, "isdn_comm_ctrl err5, rv status with no compatible state!\r\n");
|
||
if(state == ACTIVE_STATE)
|
||
{
|
||
isdn_send_msg(pid, MSG_STAT_ENQ);
|
||
return ACTIVE_STATE;
|
||
}
|
||
isdn_set_cause(&isdn_rv_msg.msg_list.rel.cause, CAUSE_MSG_NOTCOMP_NOTIMPL);
|
||
isdn_set_cause(&isdn_sd_msg.msg_list.relComp.cause, CAUSE_MSG_NOTCOMP_NOTIMPL);
|
||
isdn_event_handle(pid, ISDN_RELEASE_IND);
|
||
rel_B_chnl(pid);
|
||
isdn_send_msg(pid, MSG_REL_COMP);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
return NULL_STATE;
|
||
}
|
||
//cs != 0 discard msg
|
||
}
|
||
else if(msg_cmd == MSG_REL_COMP)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
isdn_log_err(pid, "isdn_comm_ctrl err6, rv rel comp!\r\n");
|
||
isdn_event_handle(pid, ISDN_RELEASE_IND);
|
||
rel_B_chnl(pid);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
return NULL_STATE;
|
||
}
|
||
else if(msg_cmd == MSG_INFORMATION)
|
||
{
|
||
if(state != CALL_INIT_STATE &&
|
||
state != CALL_PRE_STATE &&
|
||
((state != OVERLAP_RV_STATE && circuit_ptr->attrib.user_network_if == USER_SIDE) ||
|
||
(state != OVERLAP_SD_STATE && circuit_ptr->attrib.user_network_if == NETWORK_SIDE)))
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
isdn_event_handle(pid, ISDN_INFO_IND);
|
||
}
|
||
}
|
||
else if(pri_cmd == ISDN_INFO_REQ)
|
||
{
|
||
if(state != CALL_INIT_STATE &&
|
||
state != CALL_PRE_STATE &&
|
||
((state != OVERLAP_SD_STATE && circuit_ptr->attrib.user_network_if == USER_SIDE) ||
|
||
(state != OVERLAP_RV_STATE && circuit_ptr->attrib.user_network_if == NETWORK_SIDE)))
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_send_msg(pid, MSG_INFORMATION);
|
||
}
|
||
}
|
||
}
|
||
|
||
if(msg_cmd == MSG_STAT_ENQ)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
isdn_log_err(pid, "isdn_comm_ctrl err7, rv status enq!\r\n");
|
||
isdn_set_status(&isdn_sd_msg.msg_list.status, state, CAUSE_STAT_ENQ);
|
||
isdn_send_msg(pid, MSG_STATUS);
|
||
}
|
||
|
||
if(g_pri_cmd == ISDN_RESTART_REQ) //restart_request
|
||
{
|
||
pPort->g_pri_cmd = 0;
|
||
pPort->w_time = 0;
|
||
isdn_log_err(pid, "isdn_comm_ctrl err8, rv restart req!\r\n");
|
||
isdn_set_cause(&isdn_rv_msg.msg_list.rel.cause, CAUSE_TEMP_FAIL);
|
||
isdn_event_handle(pid, ISDN_RELEASE_IND);
|
||
rel_cr(pid);
|
||
pPort->g_pri_cmd = ISDN_RESTART_CNF;
|
||
// isdn_event_handle(pid, ISDN_RESTART_CNF); //0411
|
||
return NULL_STATE;
|
||
}
|
||
|
||
/* DL Primitive -- Not Implemented Yet */
|
||
return state;
|
||
}
|
||
|
||
static void isdn_cpc_nt_proc(u32 pid)
|
||
/*
|
||
isdn״̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>n1 ...n25״̬
|
||
*/
|
||
{
|
||
int state;
|
||
ISDN_Port_struct *pPort = &(isdn_rs.port_pond[pid]);
|
||
|
||
state = isdn_comm_ctrl(pid);
|
||
if(state == pPort->fsm_state.cpc_state)
|
||
{
|
||
switch(state)
|
||
{
|
||
case NULL_STATE:
|
||
switch(n0_proc(pid))
|
||
{
|
||
case CALL_INIT_STATE:
|
||
state = CALL_INIT_STATE;
|
||
break;
|
||
case CALL_PRE_STATE:
|
||
state = CALL_PRE_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case CALL_INIT_STATE:
|
||
switch(n1_proc(pid))
|
||
{
|
||
case NULL_STATE:
|
||
state = NULL_STATE;
|
||
break;
|
||
case OVERLAP_SD_STATE:
|
||
state = OVERLAP_SD_STATE;
|
||
break;
|
||
case OUT_CALL_PROC_STATE:
|
||
state = OUT_CALL_PROC_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case OVERLAP_SD_STATE:
|
||
switch(n2_proc(pid))
|
||
{
|
||
case OUT_CALL_PROC_STATE:
|
||
state = OUT_CALL_PROC_STATE;
|
||
break;
|
||
case CALL_DV_STATE:
|
||
state = CALL_DV_STATE;
|
||
break;
|
||
case ACTIVE_STATE:
|
||
state = ACTIVE_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case OUT_CALL_PROC_STATE:
|
||
switch(n3_proc(pid))
|
||
{
|
||
case CALL_DV_STATE:
|
||
state = CALL_DV_STATE;
|
||
break;
|
||
case ACTIVE_STATE:
|
||
state = ACTIVE_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case CALL_DV_STATE:
|
||
switch(n4_proc(pid))
|
||
{
|
||
case ACTIVE_STATE:
|
||
state = ACTIVE_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case CALL_PRE_STATE:
|
||
switch(n6_proc(pid))
|
||
{
|
||
case NULL_STATE:
|
||
state = NULL_STATE;
|
||
break;
|
||
case CALL_RV_STATE:
|
||
state = CALL_RV_STATE;
|
||
break;
|
||
case CONN_REQ_STATE:
|
||
state = CONN_REQ_STATE;
|
||
break;
|
||
case IN_CALL_PROC_STATE:
|
||
state = IN_CALL_PROC_STATE;
|
||
break;
|
||
case OVERLAP_RV_STATE:
|
||
state = OVERLAP_RV_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case CALL_RV_STATE:
|
||
switch(n7_proc(pid))
|
||
{
|
||
case CONN_REQ_STATE:
|
||
state = CONN_REQ_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case CONN_REQ_STATE:
|
||
switch(n8_proc(pid))
|
||
{
|
||
case ACTIVE_STATE:
|
||
state = ACTIVE_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case IN_CALL_PROC_STATE:
|
||
switch(n9_proc(pid))
|
||
{
|
||
case CALL_RV_STATE:
|
||
state = CALL_RV_STATE;
|
||
break;
|
||
case CONN_REQ_STATE:
|
||
state = CONN_REQ_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case ACTIVE_STATE:
|
||
switch(n10_proc(pid))
|
||
{
|
||
case -1:
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case DISC_REQ_STATE:
|
||
switch(n11_proc(pid))
|
||
{
|
||
case REL_REQ_STATE:
|
||
state = REL_REQ_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case DISC_IND_STATE:
|
||
switch(n12_proc(pid))
|
||
{
|
||
case NULL_STATE:
|
||
state = NULL_STATE;
|
||
break;
|
||
case REL_REQ_STATE:
|
||
state = REL_REQ_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case REL_REQ_STATE:
|
||
switch(n19_proc(pid))
|
||
{
|
||
case NULL_STATE:
|
||
state = NULL_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case OVERLAP_RV_STATE:
|
||
switch(n25_proc(pid))
|
||
{
|
||
case CALL_RV_STATE:
|
||
state = CALL_RV_STATE;
|
||
break;
|
||
case CONN_REQ_STATE:
|
||
state = CONN_REQ_STATE;
|
||
break;
|
||
case IN_CALL_PROC_STATE:
|
||
state = IN_CALL_PROC_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
// printf("nt state = 0x%02x\n",state);
|
||
pPort->fsm_state.cpc_state = state;
|
||
|
||
isdn_cc_nt(pid);
|
||
|
||
//unexpected message and send_isdn_msg(status) //u03-04 u03-05 u01-03
|
||
if(pPort->msg_cmd != 0)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
isdn_log_err(pid, "isdn_cpc_nt_proc, receive msg=0x02%x, not handle!\r\n");
|
||
isdn_set_status(&isdn_sd_msg.msg_list.status, pPort->fsm_state.cpc_state, CAUSE_MSG_NOTCOMP); //cause 98 101
|
||
isdn_send_msg(pid, MSG_STATUS);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
static void isdn_cpc_lt_proc(u32 pid)
|
||
{
|
||
int state;
|
||
ISDN_Port_struct *pPort = &(isdn_rs.port_pond[pid]);
|
||
|
||
state = isdn_comm_ctrl(pid);
|
||
if(state == pPort->fsm_state.cpc_state)
|
||
{
|
||
switch(state)
|
||
{
|
||
case NULL_STATE:
|
||
switch(u0_proc(pid))
|
||
{
|
||
case CALL_INIT_STATE:
|
||
state = CALL_INIT_STATE;
|
||
break;
|
||
case CALL_PRE_STATE:
|
||
state = CALL_PRE_STATE;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case CALL_INIT_STATE:
|
||
switch(u1_proc(pid))
|
||
{
|
||
case NULL_STATE:
|
||
state = NULL_STATE;
|
||
break;
|
||
case OVERLAP_SD_STATE:
|
||
state = OVERLAP_SD_STATE;
|
||
break;
|
||
case OUT_CALL_PROC_STATE:
|
||
state = OUT_CALL_PROC_STATE;
|
||
break;
|
||
case CALL_DV_STATE:
|
||
state = CALL_DV_STATE;
|
||
break;
|
||
case ACTIVE_STATE:
|
||
state = ACTIVE_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case OVERLAP_SD_STATE:
|
||
switch(u2_proc(pid))
|
||
{
|
||
case OUT_CALL_PROC_STATE:
|
||
state = OUT_CALL_PROC_STATE;
|
||
break;
|
||
case CALL_DV_STATE:
|
||
state = CALL_DV_STATE;
|
||
break;
|
||
case ACTIVE_STATE:
|
||
state = ACTIVE_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case OUT_CALL_PROC_STATE:
|
||
switch(u3_proc(pid))
|
||
{
|
||
case CALL_DV_STATE:
|
||
state = CALL_DV_STATE;
|
||
break;
|
||
case ACTIVE_STATE:
|
||
state = ACTIVE_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case CALL_DV_STATE:
|
||
switch(u4_proc(pid))
|
||
{
|
||
case ACTIVE_STATE:
|
||
state = ACTIVE_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case CALL_PRE_STATE:
|
||
switch(u6_proc(pid))
|
||
{
|
||
case NULL_STATE:
|
||
state = NULL_STATE;
|
||
break;
|
||
case CALL_RV_STATE:
|
||
state = CALL_RV_STATE;
|
||
break;
|
||
case CONN_REQ_STATE:
|
||
state = CONN_REQ_STATE;
|
||
break;
|
||
case IN_CALL_PROC_STATE:
|
||
state = IN_CALL_PROC_STATE;
|
||
break;
|
||
case OVERLAP_RV_STATE:
|
||
state = OVERLAP_RV_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case CALL_RV_STATE:
|
||
switch(u7_proc(pid))
|
||
{
|
||
case CONN_REQ_STATE:
|
||
state = CONN_REQ_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case CONN_REQ_STATE:
|
||
switch(u8_proc(pid))
|
||
{
|
||
case ACTIVE_STATE:
|
||
state = ACTIVE_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case IN_CALL_PROC_STATE:
|
||
switch(u9_proc(pid))
|
||
{
|
||
case CALL_RV_STATE:
|
||
state = CALL_RV_STATE;
|
||
break;
|
||
case CONN_REQ_STATE:
|
||
state = CONN_REQ_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case ACTIVE_STATE:
|
||
switch(u10_proc(pid))
|
||
{
|
||
case -1:
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case DISC_REQ_STATE:
|
||
switch(u11_proc(pid))
|
||
{
|
||
case NULL_STATE:
|
||
state = NULL_STATE;
|
||
break;
|
||
case REL_REQ_STATE:
|
||
state = REL_REQ_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case DISC_IND_STATE:
|
||
switch(u12_proc(pid))
|
||
{
|
||
case NULL_STATE:
|
||
state = NULL_STATE;
|
||
break;
|
||
case REL_REQ_STATE:
|
||
state = REL_REQ_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case REL_REQ_STATE:
|
||
switch(u19_proc(pid))
|
||
{
|
||
case NULL_STATE:
|
||
state = NULL_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
case OVERLAP_RV_STATE:
|
||
switch(u25_proc(pid))
|
||
{
|
||
case CALL_RV_STATE:
|
||
state = CALL_RV_STATE;
|
||
break;
|
||
case CONN_REQ_STATE:
|
||
state = CONN_REQ_STATE;
|
||
break;
|
||
case IN_CALL_PROC_STATE:
|
||
state = IN_CALL_PROC_STATE;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
// printf("lt state = 0x%02x\n",state);
|
||
pPort->fsm_state.cpc_state = state;
|
||
|
||
isdn_cc_lt(pid);
|
||
|
||
//unexpected message and send_isdn_msg(status) //u03-04 u01-03
|
||
if(pPort->msg_cmd != 0)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
isdn_log_err(pid, "isdn_cpc_lt_proc, receive msg=0x02%x, not handle!\r\n");
|
||
isdn_set_status(&isdn_sd_msg.msg_list.status, pPort->fsm_state.cpc_state, CAUSE_MSG_NOTCOMP); //cause 98 101
|
||
isdn_send_msg(pid, MSG_STATUS);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
void isdn_cpc_proc(u32 pid)
|
||
{
|
||
int circuit_id = pid / ISDN_CIRCUIT_CIC;
|
||
const pal_circuit_struct *circuit_ptr = pal_circuit_ptr(circuit_id);
|
||
if(circuit_ptr == NULL)
|
||
return;
|
||
|
||
if(circuit_ptr->attrib.user_network_if)
|
||
isdn_cpc_lt_proc(pid);
|
||
else
|
||
isdn_cpc_nt_proc(pid);
|
||
}
|
||
|
||
static int isdn_cc_nt(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &(isdn_rs.port_pond[pid]);
|
||
|
||
switch(pPort->fsm_state.cpc_state)
|
||
{
|
||
case CONN_REQ_STATE:
|
||
if(pPort->primitive_cmd == ISDN_SETUP_CNF) //msc does not provide ISDN_SETUP_COMP_REQ to isdn
|
||
{
|
||
pPort->primitive_cmd = ISDN_SETUP_COMP_REQ;
|
||
isdn_cpc_nt_proc(pid);
|
||
}
|
||
break;
|
||
case DISC_REQ_STATE:
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
if(pPort->primitive_cmd != 0)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_log_err(pid, "isdn_cc_nt, primitive err!\r\n");
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
|
||
return ISDN_CM_OK;
|
||
}
|
||
|
||
static int isdn_cc_lt(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &(isdn_rs.port_pond[pid]);
|
||
|
||
switch(pPort->fsm_state.cpc_state)
|
||
{
|
||
case DISC_IND_STATE:
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
if(pPort->primitive_cmd != 0)
|
||
{
|
||
pPort->primitive_cmd = 0;
|
||
isdn_log_err(pid, "isdn_cc_lt, primitive err!\r\n");
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
|
||
return ISDN_CM_OK;
|
||
}
|
||
|
||
static void isdn_cpc_nt_timer(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
switch(pPort->fsm_state.cpc_state)
|
||
{
|
||
case OVERLAP_SD_STATE:
|
||
// if((++(pPort->w_time)) % (isdn_timer_var.t302) == 0)
|
||
// {
|
||
// pPort->w_time = 0;
|
||
// isdn_log_err(pid, "[timeout]: NT OVERLAP SD STATE\r\n");
|
||
// isdn_event_handle(pid, ISDN_TIMEOUT_IND);
|
||
// }
|
||
break;
|
||
case CALL_PRE_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t303) == 0)
|
||
{
|
||
pPort->w_time = 0;
|
||
if(pPort->timeout_fg == 0)
|
||
{
|
||
pPort->timeout_fg = 1;
|
||
isdn_log_err(pid, "[timeout]:t303 NT CALL PRE STATE first timeout, resend SETUP\r\n");
|
||
isdn_send_msg(pid, MSG_SETUP);
|
||
}
|
||
else
|
||
{
|
||
isdn_log_err(pid, "[timeout]:t303 NT CALL PRE STATE second timeout, clear call!\r\n");
|
||
isdn_set_cause(&isdn_rv_msg.msg_list.rel.cause, CAUSE_TIMER_EXPIRY);
|
||
isdn_event_handle(pid, ISDN_RELEASE_IND);
|
||
rel_B_chnl(pid);
|
||
isdn_set_cause(&isdn_sd_msg.msg_list.relComp.cause, CAUSE_TIMER_EXPIRY);
|
||
isdn_send_msg(pid, MSG_REL_COMP);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
}
|
||
}
|
||
break;
|
||
case CALL_RV_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t301) == 0)
|
||
{
|
||
pPort->w_time = 0;
|
||
isdn_log_err(pid, "[timeout]:t301 NT CALL RV STATE\r\n");
|
||
isdn_event_handle(pid, ISDN_TIMEOUT_IND);
|
||
}
|
||
break;
|
||
case IN_CALL_PROC_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t310) == 0)
|
||
{
|
||
pPort->w_time = 0;
|
||
isdn_log_err(pid, "[timeout]:t310 NT IN CALL PROC STATE\r\n");
|
||
isdn_event_handle(pid, ISDN_TIMEOUT_IND);
|
||
}
|
||
break;
|
||
case DISC_IND_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t305) == 0)
|
||
{
|
||
isdn_log_err(pid, "[timeout]:t305 NT DISC IND STATE\r\n");
|
||
isdn_set_cause(&isdn_sd_msg.msg_list.rel.cause, CAUSE_TIMER_EXPIRY);
|
||
nr_proc(pid);
|
||
pPort->fsm_state.cpc_state = REL_REQ_STATE;
|
||
}
|
||
break;
|
||
case REL_REQ_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t308) == 0)
|
||
{
|
||
pPort->w_time = 0;
|
||
if(pPort->timeout_fg == 0)
|
||
{
|
||
pPort->timeout_fg = 1;
|
||
isdn_log_err(pid, "[timeout]:t308 NT REL REQ STATE first timeout, resend REL\r\n");
|
||
isdn_set_cause(&isdn_sd_msg.msg_list.rel.cause, CAUSE_TIMER_EXPIRY);
|
||
isdn_send_msg(pid, MSG_REL);
|
||
}
|
||
else
|
||
{
|
||
isdn_log_err(pid, "[timeout]:t308 NT REL REQ STATE\r\n");
|
||
isdn_set_cause(&isdn_rv_msg.msg_list.relComp.cause, CAUSE_TIMER_EXPIRY);
|
||
isdn_event_handle(pid, ISDN_RELEASE_CNF); //error
|
||
rel_B_chnl(pid);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
}
|
||
}
|
||
break;
|
||
case OVERLAP_RV_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t304) == 0)
|
||
{
|
||
pPort->w_time = 0;
|
||
isdn_log_err(pid, "[timeout]:t304 NT OVERLAP RV STATE\r\n");
|
||
isdn_event_handle(pid, ISDN_TIMEOUT_IND);
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
static void isdn_cpc_lt_timer(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
switch(pPort->fsm_state.cpc_state)
|
||
{
|
||
case CALL_INIT_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t303) == 0)
|
||
{
|
||
pPort->w_time = 0;
|
||
if(pPort->timeout_fg == 0)
|
||
{
|
||
pPort->timeout_fg = 1;
|
||
isdn_log_err(pid, "[timeout]:t303 LT CALL INIT STATE, resend SETUP\r\n");
|
||
isdn_send_msg(pid, MSG_SETUP);
|
||
}
|
||
else
|
||
{
|
||
isdn_log_err(pid, "[timeout]:t303 LT CALL INIT STATE, second timeout, clear call!\r\n");
|
||
isdn_set_cause(&isdn_rv_msg.msg_list.rel.cause, CAUSE_TIMER_EXPIRY);
|
||
isdn_event_handle(pid, ISDN_RELEASE_IND);
|
||
rel_B_chnl(pid);
|
||
isdn_set_cause(&isdn_sd_msg.msg_list.relComp.cause, CAUSE_TIMER_EXPIRY);
|
||
isdn_send_msg(pid, MSG_REL_COMP);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
}
|
||
}
|
||
break;
|
||
case OVERLAP_SD_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t304) == 0)
|
||
{
|
||
pPort->w_time = 0; //stop t304 and start t305
|
||
isdn_log_err(pid, "[timeout]:t304 LT OVERLAP SD STATE\r\n");
|
||
isdn_event_handle(pid, ISDN_TIMEOUT_IND);
|
||
}
|
||
break;
|
||
case OUT_CALL_PROC_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t310) == 0)
|
||
{
|
||
pPort->w_time = 0; //stop t310 and start t305
|
||
isdn_log_err(pid, "[timeout]:t310 LT OUT CALL PROC STATE\r\n");
|
||
isdn_event_handle(pid, ISDN_TIMEOUT_IND);
|
||
}
|
||
break;
|
||
case CALL_DV_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t301) == 0)
|
||
{
|
||
pPort->w_time = 0;
|
||
isdn_log_err(pid, "[timeout]:t301 LT CALL DV STATE\r\n");
|
||
isdn_event_handle(pid, ISDN_TIMEOUT_IND);
|
||
}
|
||
break;
|
||
case CONN_REQ_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t313) == 0)
|
||
{
|
||
pPort->w_time = 0; //stop t313 and start t305
|
||
isdn_log_err(pid, "[timeout]:t313 LT CONN REQ STATE\r\n");
|
||
isdn_event_handle(pid, ISDN_TIMEOUT_IND);
|
||
}
|
||
break;
|
||
case DISC_REQ_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t305) == 0)
|
||
{
|
||
isdn_log_err(pid, "[timeout]:t305 LT DISC REQ STATE\r\n");
|
||
isdn_set_cause(&isdn_sd_msg.msg_list.rel.cause, CAUSE_TIMER_EXPIRY);
|
||
nr_proc(pid);
|
||
pPort->fsm_state.cpc_state = REL_REQ_STATE;
|
||
}
|
||
break;
|
||
case REL_REQ_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t308) == 0)
|
||
{
|
||
pPort->w_time = 0;
|
||
if(pPort->timeout_fg == 0)
|
||
{
|
||
pPort->timeout_fg = 1;
|
||
isdn_log_err(pid, "[timeout]:t308 LT REL REQ STATE, resend REL\r\n");
|
||
isdn_set_cause(&isdn_sd_msg.msg_list.rel.cause, CAUSE_TIMER_EXPIRY);
|
||
isdn_send_msg(pid, MSG_REL);
|
||
}
|
||
else
|
||
{
|
||
isdn_log_err(pid, "[timeout]:t308 LT REL REQ STATE\r\n");
|
||
isdn_set_cause(&isdn_rv_msg.msg_list.relComp.cause, CAUSE_TIMER_EXPIRY);
|
||
isdn_event_handle(pid, ISDN_RELEASE_CNF); //error
|
||
rel_B_chnl(pid);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
}
|
||
}
|
||
break;
|
||
case OVERLAP_RV_STATE:
|
||
// if((++(pPort->w_time)) % (isdn_timer_var.t302) == 0)
|
||
// {
|
||
// pPort->w_time = 0;
|
||
// isdn_log_err(pid, "[timeout]:t302 LT OVERLAP RV STATE\r\n");
|
||
// isdn_event_handle(pid, ISDN_TIMEOUT_IND);
|
||
// }
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
void isdn_cpc_timer(u32 pid)
|
||
{
|
||
int circuit_id = pid / ISDN_CIRCUIT_CIC;
|
||
const pal_circuit_struct *circuit_ptr = pal_circuit_ptr(circuit_id);
|
||
if(circuit_ptr == NULL)
|
||
return;
|
||
|
||
if(!(isdn_rs.port_pond[pid].timer_flag & CALLIN_FLAG) &&
|
||
!(isdn_rs.port_pond[pid].timer_flag & CALLOUT_FLAG))
|
||
return;
|
||
if(circuit_ptr->attrib.user_network_if)
|
||
isdn_cpc_lt_timer(pid);
|
||
else
|
||
isdn_cpc_nt_timer(pid);
|
||
}
|
||
|
||
void isdn_restart_timer(u32 pid)
|
||
{
|
||
int circuit_id, i, link_id, cic_range;
|
||
const pal_circuit_struct *circuit_ptr = NULL;
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
circuit_id = pid / ISDN_CIRCUIT_CIC;
|
||
circuit_ptr = pal_circuit_ptr(circuit_id);
|
||
if(circuit_ptr == NULL)
|
||
return;
|
||
|
||
link_id = circuit_ptr->attrib.link_id;
|
||
cic_range = circuit_ptr->attrib.cic_range;
|
||
if(cic_range == 24) //T1
|
||
cic_range++;
|
||
switch(pPort->cic_state.call_state)
|
||
{
|
||
case GLOBAL_RESTART_REQ_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t316) == 0)
|
||
{
|
||
pPort->w_time = 0;
|
||
if(pPort->timeout_fg == 2)
|
||
{
|
||
if(isdn_rs.link_pond[link_id].restart_clas == 0)
|
||
{
|
||
pid = find_port_by_cic(pPort->cic_val, circuit_id);
|
||
isdn_log_err(pid, "[timeout]:t316 GLOBAL RESTART REQ STATE\r\n");
|
||
isdn_event_handle(pid, ISDN_TIMEOUT_IND);
|
||
rel_B_chnl(pid);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
}
|
||
else
|
||
{
|
||
for(i = 1; i < cic_range; i++)
|
||
{
|
||
pid = circuit_id * ISDN_CIRCUIT_CIC + i;
|
||
pPort = &isdn_rs.port_pond[pid];
|
||
if(pPort->cic_val != 0)
|
||
{
|
||
isdn_log_err(pid, "[timeout]:t316 GLOBAL RESTART REQ STATE\r\n");
|
||
isdn_event_handle(pid, ISDN_TIMEOUT_IND);
|
||
rel_B_chnl(pid);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
pPort->timeout_fg++;
|
||
isdn_log_err(pid, "[timeout]:t316 GLOBAL RESTART REQ STATE, resend RESTART\r\n");
|
||
isdn_send_msg(pid, MSG_RESTART);
|
||
}
|
||
}
|
||
break;
|
||
case GLOBAL_RESTART_STATE:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t317) == 0)
|
||
{
|
||
pPort->w_time = 0;
|
||
if(isdn_rs.link_pond[link_id].restart_clas == 0)
|
||
{
|
||
pid = find_port_by_cic(pPort->cic_val, circuit_id);
|
||
isdn_log_err(pid, "[timeout]:t317 GLOBAL RESTART STATE\r\n");
|
||
isdn_event_handle(pid, ISDN_TIMEOUT_IND);
|
||
rel_B_chnl(pid);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
}
|
||
else
|
||
{
|
||
for(i = 1; i < cic_range; i++)
|
||
{
|
||
pid = circuit_id * ISDN_CIRCUIT_CIC + i;
|
||
pPort = &isdn_rs.port_pond[pid];
|
||
if(pPort->cic_val != 0)
|
||
{
|
||
isdn_log_err(pid, "[timeout]:t317 GLOBAL RESTART STATE\r\n");
|
||
isdn_event_handle(pid, ISDN_TIMEOUT_IND);
|
||
rel_B_chnl(pid);
|
||
rel_cr(pid);
|
||
isdn_cpc_clear(pPort);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
int isdn_event_handle(u32 pid, u8 primitive)
|
||
/*
|
||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>msc<EFBFBD>ϲ<EFBFBD><EFBFBD><EFBFBD>״̬<EFBFBD><EFBFBD>
|
||
*/
|
||
{
|
||
int offset, circuit_id;
|
||
Pst pst;
|
||
ISDN_EventHandle_struct *event_handle = NULL;
|
||
const pal_circuit_struct *circuit_ptr = NULL;
|
||
const pal_cg_struct *cg_ptr = NULL;
|
||
|
||
pst.sp_proc_id = pid;
|
||
pst.su_proc_id = isdn_rs.port_pond[pid].su_proc_id;
|
||
|
||
circuit_id = pid / ISDN_CIRCUIT_CIC;
|
||
offset = pid % ISDN_CIRCUIT_CIC;
|
||
circuit_ptr = pal_circuit_ptr(circuit_id);
|
||
if(circuit_ptr == NULL)
|
||
return ISDN_CM_FAILED;
|
||
|
||
if(circuit_ptr->attrib.cic_range == 32)
|
||
pst.cic = circuit_ptr->attrib.head_cic + offset;
|
||
else
|
||
pst.cic = circuit_ptr->attrib.head_cic + offset - 1;
|
||
pst.cg_id = circuit_ptr->cg_id;
|
||
cg_ptr = pal_cg_ptr(pst.cg_id);
|
||
if(cg_ptr == NULL)
|
||
return ISDN_CM_FAILED;
|
||
if(cg_ptr->attrib.protocol != PROTO_ISDN)
|
||
return ISDN_CM_FAILED;
|
||
|
||
pst.tg_id = cg_ptr->attrib.tg_id;
|
||
event_handle = (ISDN_EventHandle_struct *)pal_get_handler(pst.cg_id);
|
||
if(event_handle == NULL)
|
||
return ISDN_CM_FAILED;
|
||
|
||
switch(primitive)
|
||
{
|
||
case ISDN_SETUP_IND:
|
||
if(event_handle->h_isdn_setup_ind == NULL)
|
||
{
|
||
isdn_log_err(pid,"Setup indication handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_setup_ind\r\n");
|
||
event_handle->h_isdn_setup_ind(&pst, &(isdn_rv_msg.msg_list.setup));
|
||
isdn_rs.port_pond[pid].su_proc_id = pst.su_proc_id;
|
||
isdn_rs.port_pond[pid].trace_flag = pst.trace_flag;
|
||
break;
|
||
case ISDN_MORE_INFO_IND:
|
||
if(event_handle->h_isdn_minfo_ind == NULL)
|
||
{
|
||
isdn_log_err(pid,"More information indication handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_minfo_ind\r\n");
|
||
event_handle->h_isdn_minfo_ind(&pst, &(isdn_rv_msg.msg_list.setupAck));
|
||
break;
|
||
case ISDN_ALERT_IND:
|
||
if(event_handle->h_isdn_alert_ind == NULL)
|
||
{
|
||
isdn_log_err(pid,"Alert indication handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_alert_ind\r\n");
|
||
event_handle->h_isdn_alert_ind(&pst, &(isdn_rv_msg.msg_list.alert));
|
||
break;
|
||
case ISDN_SETUP_CNF:
|
||
if(event_handle->h_isdn_setup_cnf == NULL)
|
||
{
|
||
isdn_log_err(pid,"Setup confirm handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_setup_cnf\r\n");
|
||
event_handle->h_isdn_setup_cnf(&pst, &(isdn_rv_msg.msg_list.conn));
|
||
break;
|
||
case ISDN_RELEASE_IND:
|
||
if(event_handle->h_isdn_rel_ind == NULL)
|
||
{
|
||
isdn_log_err(pid,"Release indication handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_rel_ind\r\n");
|
||
event_handle->h_isdn_rel_ind(&pst, &(isdn_rv_msg.msg_list.rel));
|
||
break;
|
||
case ISDN_RELEASE_CNF:
|
||
if(event_handle->h_isdn_rel_cnf == NULL)
|
||
{
|
||
isdn_log_err(pid,"Release confirm handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_rel_cnf\r\n");
|
||
event_handle->h_isdn_rel_cnf(&pst, &(isdn_rv_msg.msg_list.relComp));
|
||
break;
|
||
case ISDN_STAT_IND:
|
||
if(event_handle->h_isdn_stat_ind == NULL)
|
||
{
|
||
isdn_log_err(pid,"Status indication handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_stat_ind\r\n");
|
||
event_handle->h_isdn_stat_ind(&pst, &(isdn_rv_msg.msg_list.status));
|
||
break;
|
||
case ISDN_RESTART_REQ:
|
||
if(event_handle->h_isdn_restart_req == NULL)
|
||
{
|
||
isdn_log_err(pid,"Restart request handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_restart_req\r\n");
|
||
event_handle->h_isdn_restart_req(&pst, &(isdn_rv_msg.msg_list.restart));
|
||
break;
|
||
case ISDN_RESTART_CNF:
|
||
if(event_handle->h_isdn_rest_cnf == NULL)
|
||
{
|
||
isdn_log_err(pid,"Restart confirm handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_rest_cnf\r\n");
|
||
event_handle->h_isdn_rest_cnf(&pst, &(isdn_rv_msg.msg_list.restAck));
|
||
break;
|
||
case ISDN_INFO_IND:
|
||
if(event_handle->h_isdn_info_ind == NULL)
|
||
{
|
||
isdn_log_err(pid,"Information indication handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_info_ind\r\n");
|
||
event_handle->h_isdn_info_ind(&pst, &(isdn_rv_msg.msg_list.info));
|
||
break;
|
||
case ISDN_PROG_IND:
|
||
if(event_handle->h_isdn_prog_ind == NULL)
|
||
{
|
||
isdn_log_err(pid,"Progress indication handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_prog_ind\r\n");
|
||
event_handle->h_isdn_prog_ind(&pst, &(isdn_rv_msg.msg_list.prog));
|
||
break;
|
||
case ISDN_NOTI_IND:
|
||
if(event_handle->h_isdn_noti_ind == NULL)
|
||
{
|
||
isdn_log_err(pid,"Notify indication handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_noti_ind\r\n");
|
||
event_handle->h_isdn_noti_ind(&pst, &(isdn_rv_msg.msg_list.noti));
|
||
break;
|
||
case ISDN_TIMEOUT_IND:
|
||
if(event_handle->h_isdn_timeout_ind == NULL)
|
||
{
|
||
isdn_log_err(pid,"Timeout indication handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_timeout_ind\r\n");
|
||
event_handle->h_isdn_timeout_ind(&pst);
|
||
break;
|
||
case ISDN_REATTEMPT_IND:
|
||
if(event_handle->h_isdn_reattempt_ind == NULL)
|
||
{
|
||
isdn_log_err(pid,"Reattempt indication handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_reattempt_ind\r\n");
|
||
event_handle->h_isdn_reattempt_ind(&pst);
|
||
break;
|
||
|
||
case ISDN_PROC_IND: //msc does not handle
|
||
/* if(event_handle->h_isdn_proc_ind == NULL)
|
||
{
|
||
isdn_log_err(pid,"Call proceeding indication handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_proc_ind\r\n");
|
||
event_handle->h_isdn_proc_ind(&pst, &(isdn_rv_msg.msg_list.callProc));
|
||
*/ break;
|
||
case ISDN_SETUP_COMP_IND:
|
||
break;
|
||
case ISDN_DISCONNECT_IND: //msc does not handle
|
||
if(event_handle->h_isdn_disc_ind == NULL)
|
||
{
|
||
isdn_log_err(pid,"Disconnect indication handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_disc_ind\r\n");
|
||
event_handle->h_isdn_disc_ind(&pst, &(isdn_rv_msg.msg_list.disc));
|
||
break;
|
||
|
||
case ISDN_SERVICE_IND:
|
||
if(event_handle->h_isdn_service_ind == NULL)
|
||
{
|
||
isdn_log_err(pid,"Service indication handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_service_ind\r\n");
|
||
event_handle->h_isdn_service_ind(&pst, &(isdn_rv_msg.msg_list.service));
|
||
isdn_rs.port_pond[pid].su_proc_id = pst.su_proc_id;
|
||
isdn_rs.port_pond[pid].trace_flag = pst.trace_flag;
|
||
break;
|
||
case ISDN_SERVICE_CNF:
|
||
if(event_handle->h_isdn_service_cnf == NULL)
|
||
{
|
||
isdn_log_err(pid,"Service confirm handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_service_cnf\r\n");
|
||
event_handle->h_isdn_service_cnf(&pst, &(isdn_rv_msg.msg_list.servAck));
|
||
break;
|
||
case ISDN_SER_TIMEOUT_IND:
|
||
if(event_handle->h_isdn_ser_timeout_ind == NULL)
|
||
{
|
||
isdn_log_err(pid,"Service timeout indication handle is not registered@%s\r\n", __FUNCTION__);
|
||
return ISDN_CM_FAILED;
|
||
}
|
||
isdn_trace_func(pid,"APP => function trace: isdn_ser_timeout_ind\r\n");
|
||
event_handle->h_isdn_ser_timeout_ind(&pst);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return ISDN_CM_OK;
|
||
}
|
||
|
||
|
||
void stuff_encode_m(u32 pid, IsdnMsgStr *ptr, int type)
|
||
{
|
||
ChgStat chg_stat;
|
||
ChnlId chnl_id;
|
||
|
||
chg_stat.pres = 1;
|
||
chg_stat.pref = 1;
|
||
chg_stat.new_stat = isdn_rs.port_pond[pid].cic_state.maintenance_state;
|
||
chnl_id.pres = 1;
|
||
chnl_id.b3.int_id_pre = 1;
|
||
chnl_id.b3.int_type = 1;
|
||
chnl_id.b3.pref_excl = 1;
|
||
chnl_id.b3.chnl_ind = 1;
|
||
chnl_id.b3.info_chnl_sel = 1;
|
||
chnl_id.b3.int_id = pid / ISDN_CIRCUIT_CIC;
|
||
chnl_id.b3.has_chnl = 1;
|
||
chnl_id.b3.code_stan = 0;
|
||
chnl_id.b3.num_map = 0;
|
||
chnl_id.b3.chnl_type = 3;
|
||
chnl_id.b3.chnl_num = pid % ISDN_CIRCUIT_CIC;
|
||
if(type == MSG_SERVICE)
|
||
{
|
||
memcpy(&ptr->msg_list.service.chg_stat, &chg_stat, sizeof(ChgStat));
|
||
memcpy(&ptr->msg_list.service.chnl_id, &chnl_id, sizeof(ChnlId));
|
||
}
|
||
else if(type == MSG_SERVICE_ACK)
|
||
{
|
||
memcpy(&ptr->msg_list.servAck.chg_stat, &chg_stat, sizeof(ChgStat));
|
||
memcpy(&ptr->msg_list.servAck.chnl_id, &chnl_id, sizeof(ChnlId));
|
||
}
|
||
}
|
||
|
||
//ansi isdn maintenance D-channel and B-channel
|
||
void service_dc_proc(u32 pid)
|
||
{
|
||
int circuit_id, link_id, cg_id, ds_0, ds_1;
|
||
int far_status;
|
||
const pal_circuit_struct *circuit_ptr = NULL;
|
||
const pal_cg_struct *cg_ptr = NULL;
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
circuit_id = pid / ISDN_CIRCUIT_CIC;
|
||
circuit_ptr = pal_circuit_ptr(circuit_id);
|
||
if(circuit_ptr == NULL)
|
||
return;
|
||
|
||
link_id = circuit_ptr->attrib.link_id;
|
||
cg_id = circuit_ptr->cg_id;
|
||
cg_ptr = pal_cg_ptr(cg_id);
|
||
if(cg_ptr == NULL)
|
||
return;
|
||
if(cg_ptr->attrib.protocol != PROTO_ISDN)
|
||
return;
|
||
|
||
ds_0 = cg_ptr->attrib.nfas.prim_link;
|
||
ds_1 = cg_ptr->attrib.nfas.backup_link;
|
||
far_status = isdn_rv_msg.msg_list.service.chg_stat.new_stat;
|
||
|
||
if(cg_ptr->attrib.variant == VARIANT_ANSI) //ANSI
|
||
{
|
||
switch(pPort->fsm_state.m_state)
|
||
{
|
||
case SERVICE_IDLE:
|
||
if(pPort->g_pri_cmd == ISDN_SERVICE_REQ)
|
||
{
|
||
pPort->g_pri_cmd = 0;
|
||
isdn_rs.link_pond[link_id].dc_status = DS_WAIT;
|
||
pPort->w_time = 0; //start t321
|
||
pPort->timer_flag |= DC_M_FLAG;
|
||
pPort->cic_state.maintenance_state = IN_SERVICE;
|
||
stuff_encode_m(pid, &isdn_sd_msg, MSG_SERVICE);
|
||
isdn_send_maintenance_msg(pid, MSG_SERVICE);
|
||
pPort->cic_state.maintenance_state = OUT_OF_SERVICE;
|
||
pPort->fsm_state.m_state = WAIT_SERVICE_ACK;
|
||
printf("service_dc_proc: wait service ack!\n");
|
||
}
|
||
else if(pPort->msg_cmd == MSG_SERVICE)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->callout_fg = 1;
|
||
if(link_id == ds_0)
|
||
{
|
||
if((isdn_rs.link_pond[ds_1].dc_status != DS_IS) &&
|
||
(isdn_rs.link_pond[link_id].lk3_status == LK_IS) &&
|
||
(far_status == IN_SERVICE))
|
||
{
|
||
isdn_rs.link_pond[link_id].dc_status = DS_IS;
|
||
pPort->cic_state.maintenance_state = IN_SERVICE;
|
||
stuff_encode_m(pid, &isdn_sd_msg, MSG_SERVICE_ACK);
|
||
isdn_send_maintenance_msg(pid, MSG_SERVICE_ACK);
|
||
pPort->fsm_state.m_state = SERVICE_IDLE;
|
||
}
|
||
}
|
||
else if(link_id == ds_1)
|
||
{
|
||
if(((isdn_rs.link_pond[ds_0].dc_status) == DS_OOS ||
|
||
(isdn_rs.link_pond[ds_0].dc_status == DS_STBY)) &&
|
||
(isdn_rs.link_pond[link_id].lk3_status == LK_IS) &&
|
||
(far_status == IN_SERVICE))
|
||
{
|
||
isdn_rs.link_pond[link_id].dc_status = DS_IS;
|
||
pPort->cic_state.maintenance_state = IN_SERVICE;
|
||
stuff_encode_m(pid, &isdn_sd_msg, MSG_SERVICE_ACK);
|
||
isdn_send_maintenance_msg(pid, MSG_SERVICE_ACK);
|
||
pPort->fsm_state.m_state = SERVICE_IDLE;
|
||
}
|
||
}
|
||
printf("service_dc_proc: receive service!\n");
|
||
}
|
||
if(pPort->msg_cmd == MSG_SERVICE_ACK) //timeout t321 TODO
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t321
|
||
if(far_status == IN_SERVICE)
|
||
{
|
||
isdn_rs.link_pond[link_id].dc_status = DS_IS;
|
||
pPort->cic_state.maintenance_state = IN_SERVICE;
|
||
}
|
||
else
|
||
{
|
||
isdn_rs.link_pond[link_id].dc_status = DS_STBY;
|
||
pPort->cic_state.maintenance_state = OUT_OF_SERVICE;
|
||
}
|
||
pPort->fsm_state.m_state = SERVICE_IDLE;
|
||
printf("service_dc_proc: receive service ack in service idle!\n");
|
||
}
|
||
break;
|
||
case WAIT_SERVICE_ACK:
|
||
if(pPort->msg_cmd == MSG_SERVICE_ACK)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t321
|
||
if(far_status == IN_SERVICE)
|
||
{
|
||
isdn_rs.link_pond[link_id].dc_status = DS_IS;
|
||
pPort->cic_state.maintenance_state = IN_SERVICE;
|
||
}
|
||
else
|
||
{
|
||
isdn_rs.link_pond[link_id].dc_status = DS_STBY;
|
||
pPort->cic_state.maintenance_state = OUT_OF_SERVICE;
|
||
}
|
||
pPort->fsm_state.m_state = SERVICE_IDLE;
|
||
printf("service_dc_proc: receive service ack!and enter service idle state\n");
|
||
}
|
||
else if(pPort->msg_cmd == MSG_SERVICE) //collision
|
||
{
|
||
if(!cg_ptr->attrib.priority)
|
||
{
|
||
pPort->w_time = 0; //stop t321
|
||
pPort->fsm_state.m_state = SERVICE_IDLE;
|
||
service_dc_proc(pid);
|
||
printf("service_dc_proc: collision, and renew the state with service idle to receive msg!\n");
|
||
}
|
||
else
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
isdn_log_err(pid, "service_dc_proc: discard receive msg!\r\n");
|
||
return;
|
||
}
|
||
}
|
||
break;
|
||
case RSP_SERVICE:
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
else //ITU
|
||
{
|
||
if(pPort->g_pri_cmd == ISDN_SERVICE_REQ)
|
||
{
|
||
pPort->g_pri_cmd = 0;
|
||
isdn_rs.link_pond[link_id].dc_status = DS_IS;
|
||
}
|
||
else if(isdn_rs.link_pond[link_id].lk3_status == LK_IS && isdn_rs.link_pond[link_id].dc_status != DS_IS)
|
||
{
|
||
isdn_rs.link_pond[link_id].dc_status = DS_STBY;
|
||
}
|
||
}
|
||
|
||
// if(isdn_rs.link_pond[link_id].dc_status == DS_OOS && isdn_rs.link_pond[link_id].lk3_status == LK_IS)
|
||
// isdn_rs.link_pond[link_id].dc_status = DS_STBY;
|
||
|
||
if(isdn_rs.link_pond[ds_0].dc_status == DS_IS && isdn_rs.link_pond[ds_1].dc_status == DS_IS)
|
||
isdn_rs.link_pond[ds_1].dc_status = DS_STBY;
|
||
else if(isdn_rs.link_pond[ds_0].dc_status == DS_STBY && isdn_rs.link_pond[ds_1].dc_status == DS_STBY)
|
||
isdn_rs.link_pond[ds_0].dc_status = DS_IS;
|
||
else if(isdn_rs.link_pond[ds_0].dc_status == DS_OOS && isdn_rs.link_pond[ds_1].dc_status == DS_STBY)
|
||
isdn_rs.link_pond[ds_1].dc_status = DS_IS;
|
||
else if(isdn_rs.link_pond[ds_0].dc_status == DS_STBY && isdn_rs.link_pond[ds_1].dc_status == DS_OOS)
|
||
isdn_rs.link_pond[ds_0].dc_status = DS_IS;
|
||
else if(isdn_rs.link_pond[ds_0].dc_status == DS_OOS && isdn_rs.link_pond[ds_1].dc_status == DS_OOS)
|
||
{
|
||
isdn_rs.link_pond[ds_0].dc_status = DS_MOOS;
|
||
isdn_rs.link_pond[ds_1].dc_status = DS_MOOS;
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
void service_bc_proc(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
const pal_cg_struct *cg_ptr = NULL;
|
||
const pal_circuit_struct *circuit_ptr = pal_circuit_ptr(pid / ISDN_CIRCUIT_CIC);
|
||
if(circuit_ptr == NULL)
|
||
return;
|
||
|
||
cg_ptr = pal_cg_ptr(circuit_ptr->cg_id);
|
||
if(cg_ptr == NULL)
|
||
return;
|
||
if(cg_ptr->attrib.protocol != PROTO_ISDN)
|
||
return;
|
||
|
||
switch(pPort->fsm_state.m_state)
|
||
{
|
||
case SERVICE_IDLE:
|
||
if(pPort->g_pri_cmd == ISDN_SERVICE_REQ)
|
||
{
|
||
pPort->g_pri_cmd = 0;
|
||
if(isdn_sd_msg.msg_list.service.chg_stat.new_stat != IN_SERVICE)
|
||
{
|
||
pPort->primitive_cmd = ISDN_RELEASE_REQ;
|
||
isdn_cpc_proc(pid);
|
||
}
|
||
pPort->w_time = 0; //start t3M1
|
||
pPort->timer_flag |= BC_M_FLAG;
|
||
isdn_send_maintenance_msg(pid, MSG_SERVICE);
|
||
pPort->cic_state.maintenance_state = isdn_sd_msg.msg_list.service.chg_stat.new_stat;
|
||
pPort->fsm_state.m_state = WAIT_SERVICE_ACK;
|
||
printf("service_bc_proc: wait service ack!\n");
|
||
}
|
||
else if(pPort->msg_cmd == MSG_SERVICE)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->callout_fg = 1;
|
||
pPort->cic_state.maintenance_state = isdn_rv_msg.msg_list.service.chg_stat.new_stat;
|
||
pPort->fsm_state.m_state = RSP_SERVICE;
|
||
printf("service_bc_proc: receive service!\n");
|
||
isdn_event_handle(pid, ISDN_SERVICE_IND); //indicate
|
||
}
|
||
else if(pPort->msg_cmd == MSG_SERVICE_ACK) //timeout t3M1
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
pPort->w_time = 0; //stop t3M1
|
||
pPort->cic_state.maintenance_state = isdn_rv_msg.msg_list.service.chg_stat.new_stat;
|
||
isdn_event_handle(pid, ISDN_SERVICE_CNF); //confirm
|
||
pPort->fsm_state.m_state = SERVICE_IDLE;
|
||
printf("service_bc_proc: receive service ack in service idle!\n");
|
||
}
|
||
break;
|
||
case WAIT_SERVICE_ACK:
|
||
if(pPort->msg_cmd == MSG_SERVICE_ACK)
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
isdn_event_handle(pid, ISDN_SERVICE_CNF); //confirm
|
||
pPort->fsm_state.m_state = SERVICE_IDLE;
|
||
printf("service_bc_proc: receive service ack!\n");
|
||
}
|
||
if(pPort->msg_cmd == MSG_SERVICE) //<2F><><EFBFBD><EFBFBD>service<63><65>ͻ TODO
|
||
{
|
||
if(!cg_ptr->attrib.priority)
|
||
{
|
||
pPort->w_time = 0;
|
||
pPort->cic_state.maintenance_state = ((pPort->cic_state.maintenance_state & 0x1) | (pPort->cic_state.maintenance_state >> 1)) ^ 0x1; //run back initial
|
||
pPort->fsm_state.m_state = SERVICE_IDLE;
|
||
isdn_event_handle(pid, ISDN_REATTEMPT_IND); //indicate
|
||
service_bc_proc(pid);
|
||
printf("service_bc_proc: collision, and renew the state with service idle to receive msg!\n");
|
||
}
|
||
else
|
||
{
|
||
pPort->msg_cmd = 0;
|
||
isdn_log_err(pid, "service_dc_proc: discard receive msg!\r\n");
|
||
return;
|
||
}
|
||
}
|
||
break;
|
||
case RSP_SERVICE:
|
||
if(pPort->g_pri_cmd == ISDN_SERVICE_RSP)
|
||
{
|
||
pPort->g_pri_cmd = 0;
|
||
pPort->fsm_state.m_state = SERVICE_IDLE;
|
||
pPort->cic_state.maintenance_state = isdn_sd_msg.msg_list.servAck.chg_stat.new_stat;
|
||
isdn_send_maintenance_msg(pid, MSG_SERVICE_ACK);
|
||
printf("service_bc_proc: response service!\n");
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
void service_dc_timer(u32 pid)
|
||
{
|
||
int link_id;
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
const pal_circuit_struct *circuit_ptr = pal_circuit_ptr(pid / ISDN_CIRCUIT_CIC);
|
||
if(circuit_ptr == NULL)
|
||
return;
|
||
|
||
link_id = circuit_ptr->attrib.link_id;
|
||
switch(pPort->fsm_state.m_state)
|
||
{
|
||
case WAIT_SERVICE_ACK:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t321) == 0)
|
||
{
|
||
pPort->w_time = 0; //stop t3M1
|
||
pPort->fsm_state.m_state = SERVICE_IDLE;
|
||
pPort->cic_state.maintenance_state = OUT_OF_SERVICE;
|
||
isdn_rs.link_pond[link_id].dc_status = DS_OOS;
|
||
isdn_log_err(pid, "service_dc_timer: t321 timeout!\r\n");
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
void service_bc_timer(u32 pid)
|
||
{
|
||
ISDN_Port_struct *pPort = &isdn_rs.port_pond[pid];
|
||
|
||
switch(pPort->fsm_state.m_state)
|
||
{
|
||
case WAIT_SERVICE_ACK:
|
||
if((++(pPort->w_time)) % (isdn_timer_var.t3M1) == 0)
|
||
{
|
||
pPort->w_time = 0; //stop t3M1
|
||
isdn_event_handle(pid, ISDN_SER_TIMEOUT_IND);
|
||
pPort->fsm_state.m_state = SERVICE_IDLE;
|
||
pPort->cic_state.maintenance_state = OUT_OF_SERVICE;
|
||
isdn_log_err(pid, "service_bc_timer: t3M1 timeout!\r\n");
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
void maintenance_timer(u32 pid)
|
||
{
|
||
if(isdn_rs.port_pond[pid].timer_flag & BC_M_FLAG)
|
||
service_bc_timer(pid);
|
||
if(isdn_rs.port_pond[pid].timer_flag & DC_M_FLAG)
|
||
service_dc_timer(pid);
|
||
}
|
||
|