extractedLnx/linux-2.6.9/drivers/isdn/hardware/eicon/message.c_sig_ind.c
void sig_ind(PLCI * plci)
{
dword x_Id;
dword Id;
dword rId;
word Number = 0;
word i;
word cip;
dword cip_mask;
byte *ie;
DIVA_CAPI_ADAPTER * a;
API_PARSE saved_parms[MAX_MSG_PARMS+1];
#define MAXPARMSIDS 31
byte * parms[MAXPARMSIDS];
byte * add_i[4];
byte * multi_fac_parms[MAX_MULTI_IE];
byte * multi_pi_parms [MAX_MULTI_IE];
byte * multi_ssext_parms [MAX_MULTI_IE];
byte * multi_CiPN_parms [MAX_MULTI_IE];
byte * multi_vswitch_parms [MAX_MULTI_IE];
byte ai_len;
byte *esc_chi = "";
byte *esc_law = "";
byte *pty_cai = "";
byte *esc_cr = "";
byte *esc_profile = "";
byte facility[256];
PLCI * tplci = NULL;
byte chi[] = "\x02\x18\x01";
byte voice_cai[] = "\x06\x14\x00\x00\x00\x00\x08";
byte resume_cau[] = "\x05\x05\x00\x02\x00\x00";
/* ESC_MSGTYPE must be the last but one message, a new IE has to be */
/* included before the ESC_MSGTYPE and MAXPARMSIDS has to be incremented */
/* SMSG is situated at the end because its 0 (for compatibility reasons */
/* (see Info_Mask Bit 4, first IE. then the message type) */
word parms_id[] =
{MAXPARMSIDS, CPN, 0xff, DSA, OSA, BC, LLC, HLC, ESC_CAUSE, DSP, DT, CHA,
UUI, CONG_RR, CONG_RNR, ESC_CHI, KEY, CHI, CAU, ESC_LAW,
RDN, RDX, CONN_NR, RIN, NI, CAI, ESC_CR,
CST, ESC_PROFILE, 0xff, ESC_MSGTYPE, SMSG};
/* 14 FTY repl by ESC_CHI */
/* 18 PI repl by ESC_LAW */
/* removed OAD changed to 0xff for future use, OAD is multiIE now */
word multi_fac_id[] = {1, FTY};
word multi_pi_id[] = {1, PI};
word multi_CiPN_id[] = {1, OAD};
word multi_ssext_id[] = {1, ESC_SSEXT};
word multi_vswitch_id[] = {1, ESC_VSWITCH};
byte * cau;
word ncci;
byte SS_Ind[] = "\x05\x02\x00\x02\x00\x00"; /* Hold_Ind struct*/
byte CF_Ind[] = "\x09\x02\x00\x06\x00\x00\x00\x00\x00\x00";
byte Interr_Err_Ind[] = "\x0a\x02\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
byte CONF_Ind[] = "\x09\x16\x00\x06\x00\x00\0x00\0x00\0x00\0x00";
byte force_mt_info = FALSE;
byte dir;
dword d;
word w;
a = plci->adapter;
Id = ((word)plci->Id<<8)|a->Id;
WRITE_WORD(&SS_Ind[4],0x0000);
if (plci->sig_remove_id)
{
plci->Sig.RNR = 2; /* discard */
dbug(1,dprintf("SIG discard while remove pending"));
return;
}
if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
dbug(1,dprintf("SigInd-Id=%08lx,plci=%x,tel=%x,state=0x%x,channels=%d,Discflowcl=%d",
Id,plci->Id,plci->tel,plci->State,plci->channels,plci->hangup_flow_ctrl_timer));
if(plci->Sig.Ind==CALL_HOLD_ACK && plci->channels)
{
plci->Sig.RNR = 1;
return;
}
if(plci->Sig.Ind==HANGUP && plci->channels)
{
plci->Sig.RNR = 1;
plci->hangup_flow_ctrl_timer++;
/* recover the network layer after timeout */
if(plci->hangup_flow_ctrl_timer==100)
{
dbug(1,dprintf("Exceptional disc"));
plci->Sig.RNR = 0;
plci->hangup_flow_ctrl_timer = 0;
for (ncci = 1; ncci < MAX_NCCI+1; ncci++)
{
if (a->ncci_plci[ncci] == plci->Id)
{
cleanup_ncci_data (plci, ncci);
if(plci->channels)plci->channels--;
if (plci->appl)
sendf(plci->appl,_DISCONNECT_B3_I, (((dword) ncci) << 16) | Id,0,"ws",0,"");
}
}
if (plci->appl)
sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
plci_remove(plci);
plci->State=IDLE;
}
return;
}
/* do first parse the info with no OAD in, because OAD will be converted */
/* first the multiple facility IE, then mult. progress ind. */
/* then the parameters for the info_ind + conn_ind */
IndParse(plci,multi_fac_id,multi_fac_parms,MAX_MULTI_IE);
IndParse(plci,multi_pi_id,multi_pi_parms,MAX_MULTI_IE);
IndParse(plci,multi_ssext_id,multi_ssext_parms,MAX_MULTI_IE);
IndParse(plci,multi_vswitch_id,multi_vswitch_parms,MAX_MULTI_IE);
IndParse(plci,parms_id,parms,0);
IndParse(plci,multi_CiPN_id,multi_CiPN_parms,MAX_MULTI_IE);
esc_chi = parms[14];
esc_law = parms[18];
pty_cai = parms[24];
esc_cr = parms[25];
esc_profile = parms[27];
if(esc_cr[0] && plci)
{
if(plci->cr_enquiry && plci->appl)
{
plci->cr_enquiry = FALSE;
/* d = MANU_ID */
/* w = m_command */
/* b = total length */
/* b = indication type */
/* b = length of all IEs */
/* b = IE1 */
/* S = IE1 length + cont. */
/* b = IE2 */
/* S = IE2 lenght + cont. */
sendf(plci->appl,
_MANUFACTURER_I,
Id,
0,
"dwbbbbSbS",_DI_MANU_ID,plci->m_command,
2+1+1+esc_cr[0]+1+1+esc_law[0],plci->Sig.Ind,1+1+esc_cr[0]+1+1+esc_law[0],ESC,esc_cr,ESC,esc_law);
}
}
/* create the additional info structure */
add_i[1] = parms[15]; /* KEY of additional info */
add_i[2] = parms[11]; /* UUI of additional info */
ai_len = AddInfo(add_i,multi_fac_parms, esc_chi, facility);
/* the ESC_LAW indicates if u-Law or a-Law is actually used by the card */
/* indication returns by the card if requested by the function */
/* AutomaticLaw() after driver init */
if (a->automatic_law<4)
{
if(esc_law[0]){
if(esc_law[2]){
dbug(0,dprintf("u-Law selected"));
a->u_law = 1;
}
else {
dbug(0,dprintf("a-Law selected"));
a->u_law = 0;
}
a->automatic_law = 4;
if(plci==a->automatic_lawPLCI) {
plci->internal_command = 0;
sig_req(plci,REMOVE,0);
send_req(plci);
a->automatic_lawPLCI = NULL;
}
}
if (esc_profile[0])
{
dbug (1, dprintf ("[%06x] CardProfile: %lx %lx %lx %lx %lx",
UnMapController (a->Id), READ_DWORD (&esc_profile[6]),
READ_DWORD (&esc_profile[10]), READ_DWORD (&esc_profile[14]),
READ_DWORD (&esc_profile[18]), READ_DWORD (&esc_profile[46])));
a->profile.Global_Options &= 0x000000ffL;
a->profile.B1_Protocols &= 0x000003ffL;
a->profile.B2_Protocols &= 0x00001fdfL;
a->profile.B3_Protocols &= 0x000000b7L;
a->profile.Global_Options &= READ_DWORD (&esc_profile[6]) |
GL_BCHANNEL_OPERATION_SUPPORTED;
a->profile.B1_Protocols &= READ_DWORD (&esc_profile[10]);
a->profile.B2_Protocols &= READ_DWORD (&esc_profile[14]);
a->profile.B3_Protocols &= READ_DWORD (&esc_profile[18]);
a->manufacturer_features = READ_DWORD (&esc_profile[46]);
a->man_profile.private_options = 0;
if (a->manufacturer_features & MANUFACTURER_FEATURE_ECHO_CANCELLER)
{
a->man_profile.private_options |= 1L << PRIVATE_ECHO_CANCELLER;
a->profile.Global_Options |= GL_ECHO_CANCELLER_SUPPORTED;
}
if (a->manufacturer_features & MANUFACTURER_FEATURE_RTP)
a->man_profile.private_options |= 1L << PRIVATE_RTP;
a->man_profile.rtp_primary_payloads = READ_DWORD (&esc_profile[50]);
a->man_profile.rtp_additional_payloads = READ_DWORD (&esc_profile[54]);
if (a->manufacturer_features & MANUFACTURER_FEATURE_T38)
a->man_profile.private_options |= 1L << PRIVATE_T38;
if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_SUB_SEP_PWD)
a->man_profile.private_options |= 1L << PRIVATE_FAX_SUB_SEP_PWD;
if (a->manufacturer_features & MANUFACTURER_FEATURE_V18)
a->man_profile.private_options |= 1L << PRIVATE_V18;
if (a->manufacturer_features & MANUFACTURER_FEATURE_DTMF_TONE)
a->man_profile.private_options |= 1L << PRIVATE_DTMF_TONE;
if (a->manufacturer_features & MANUFACTURER_FEATURE_PIAFS)
a->man_profile.private_options |= 1L << PRIVATE_PIAFS;
if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_PAPER_FORMATS)
a->man_profile.private_options |= 1L << PRIVATE_FAX_PAPER_FORMATS;
if (a->manufacturer_features & MANUFACTURER_FEATURE_VOWN)
a->man_profile.private_options |= 1L << PRIVATE_VOWN;
if (a->manufacturer_features & MANUFACTURER_FEATURE_FAX_NONSTANDARD)
a->man_profile.private_options |= 1L << PRIVATE_FAX_NONSTANDARD;
}
else
{
a->profile.Global_Options &= 0x0000007fL;
a->profile.B1_Protocols &= 0x000003dfL;
a->profile.B2_Protocols &= 0x00001adfL;
a->profile.B3_Protocols &= 0x000000b7L;
a->manufacturer_features &= MANUFACTURER_FEATURE_HARDDTMF;
}
if (a->manufacturer_features & (MANUFACTURER_FEATURE_HARDDTMF |
MANUFACTURER_FEATURE_SOFTDTMF_SEND | MANUFACTURER_FEATURE_SOFTDTMF_RECEIVE))
{
a->profile.Global_Options |= GL_DTMF_SUPPORTED;
}
a->manufacturer_features &= ~MANUFACTURER_FEATURE_OOB_CHANNEL;
dbug (1, dprintf ("[%06x] Profile: %lx %lx %lx %lx %lx",
UnMapController (a->Id), a->profile.Global_Options,
a->profile.B1_Protocols, a->profile.B2_Protocols,
a->profile.B3_Protocols, a->manufacturer_features));
}
/* codec plci for the handset/hook state support is just an internal id */
if(plci!=a->AdvCodecPLCI)
{
force_mt_info = SendMultiIE(plci,Id,multi_fac_parms, FTY, 0x20, 0);
force_mt_info |= SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, 0);
SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
SendInfo(plci,Id, parms, force_mt_info);
VSwitchReqInd(plci,Id,multi_vswitch_parms);
}
/* switch the codec to the b-channel */
if(esc_chi[0] && plci && !plci->SuppState){
plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
mixer_set_bchannel_id_esc (plci, plci->b_channel);
dbug(1,dprintf("storeChannel=0x%x",plci->b_channel));
if(plci->tel==ADV_VOICE && plci->appl) {
SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
}
}
if(plci->appl) Number = plci->appl->Number++;
switch(plci->Sig.Ind) {
/* Response to Get_Supported_Services request */
case S_SUPPORTED:
dbug(1,dprintf("S_Supported"));
if(!plci->appl) break;
if(pty_cai[0]==4)
{
WRITE_DWORD(&CF_Ind[6],READ_DWORD(&pty_cai[1]) );
}
else
{
WRITE_DWORD(&CF_Ind[6],MASK_TERMINAL_PORTABILITY | MASK_HOLD_RETRIEVE);
}
WRITE_WORD (&CF_Ind[1], 0);
WRITE_WORD (&CF_Ind[4], 0);
sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,plci->number, "wws",0,3,CF_Ind);
plci_remove(plci);
break;
/* Supplementary Service rejected */
case S_SERVICE_REJ:
dbug(1,dprintf("S_Reject=0x%x",pty_cai[5]));
if(!pty_cai[0]) break;
switch (pty_cai[5])
{
case ECT_EXECUTE:
case THREE_PTY_END:
case THREE_PTY_BEGIN:
if(!plci->relatedPTYPLCI) break;
tplci = plci->relatedPTYPLCI;
rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
if(tplci->tel) rId|=EXT_CONTROLLER;
if(pty_cai[5]==ECT_EXECUTE)
{
WRITE_WORD(&SS_Ind[1],S_ECT);
plci->vswitchstate=0;
plci->relatedPTYPLCI->vswitchstate=0;
}
else
{
WRITE_WORD(&SS_Ind[1],pty_cai[5]+3);
}
if(pty_cai[2]!=0xff)
{
WRITE_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
}
else
{
WRITE_WORD(&SS_Ind[4],0x300E);
}
plci->relatedPTYPLCI = NULL;
plci->ptyState = 0;
sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
break;
case CALL_DEFLECTION:
if(pty_cai[2]!=0xff)
{
WRITE_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
}
else
{
WRITE_WORD(&SS_Ind[4],0x300E);
}
WRITE_WORD(&SS_Ind[1],pty_cai[5]);
for(i=0; i<max_appl; i++)
{
if(application[i].CDEnable)
{
if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
application[i].CDEnable = FALSE;
}
}
break;
case DEACTIVATION_DIVERSION:
case ACTIVATION_DIVERSION:
case DIVERSION_INTERROGATE_CFU:
case DIVERSION_INTERROGATE_CFB:
case DIVERSION_INTERROGATE_CFNR:
case DIVERSION_INTERROGATE_NUM:
case CCBS_REQUEST:
case CCBS_DEACTIVATE:
case CCBS_INTERROGATE:
if(!plci->appl) break;
if(pty_cai[2]!=0xff)
{
WRITE_WORD(&Interr_Err_Ind[4],0x3600|(word)pty_cai[2]);
}
else
{
WRITE_WORD(&Interr_Err_Ind[4],0x300E);
}
switch (pty_cai[5])
{
case DEACTIVATION_DIVERSION:
dbug(1,dprintf("Deact_Div"));
Interr_Err_Ind[0]=0x9;
Interr_Err_Ind[3]=0x6;
WRITE_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_STOP);
break;
case ACTIVATION_DIVERSION:
dbug(1,dprintf("Act_Div"));
Interr_Err_Ind[0]=0x9;
Interr_Err_Ind[3]=0x6;
WRITE_WORD(&Interr_Err_Ind[1],S_CALL_FORWARDING_START);
break;
case DIVERSION_INTERROGATE_CFU:
case DIVERSION_INTERROGATE_CFB:
case DIVERSION_INTERROGATE_CFNR:
dbug(1,dprintf("Interr_Div"));
Interr_Err_Ind[0]=0xa;
Interr_Err_Ind[3]=0x7;
WRITE_WORD(&Interr_Err_Ind[1],S_INTERROGATE_DIVERSION);
break;
case DIVERSION_INTERROGATE_NUM:
dbug(1,dprintf("Interr_Num"));
Interr_Err_Ind[0]=0xa;
Interr_Err_Ind[3]=0x7;
WRITE_WORD(&Interr_Err_Ind[1],S_INTERROGATE_NUMBERS);
break;
case CCBS_REQUEST:
dbug(1,dprintf("CCBS Request"));
Interr_Err_Ind[0]=0xd;
Interr_Err_Ind[3]=0xa;
WRITE_WORD(&Interr_Err_Ind[1],S_CCBS_REQUEST);
break;
case CCBS_DEACTIVATE:
dbug(1,dprintf("CCBS Deactivate"));
Interr_Err_Ind[0]=0x9;
Interr_Err_Ind[3]=0x6;
WRITE_WORD(&Interr_Err_Ind[1],S_CCBS_DEACTIVATE);
break;
case CCBS_INTERROGATE:
dbug(1,dprintf("CCBS Interrogate"));
Interr_Err_Ind[0]=0xb;
Interr_Err_Ind[3]=0x8;
WRITE_WORD(&Interr_Err_Ind[1],S_CCBS_INTERROGATE);
break;
}
WRITE_DWORD(&Interr_Err_Ind[6],plci->appl->S_Handle);
sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, Interr_Err_Ind);
plci_remove(plci);
break;
case ACTIVATION_MWI:
case DEACTIVATION_MWI:
if(pty_cai[5]==ACTIVATION_MWI)
{
WRITE_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
}
else WRITE_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
if(pty_cai[2]!=0xff)
{
WRITE_WORD(&SS_Ind[4],0x3600|(word)pty_cai[2]);
}
else
{
WRITE_WORD(&SS_Ind[4],0x300E);
}
if(plci->cr_enquiry)
{
sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
plci_remove(plci);
}
else
{
sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
}
break;
case CONF_ADD: /* ERROR */
case CONF_BEGIN:
case CONF_DROP:
case CONF_ISOLATE:
case CONF_REATTACH:
CONF_Ind[0]=9;
CONF_Ind[3]=6;
switch(pty_cai[5])
{
case CONF_BEGIN:
WRITE_WORD(&CONF_Ind[1],S_CONF_BEGIN);
plci->ptyState = 0;
break;
case CONF_DROP:
CONF_Ind[0]=5;
CONF_Ind[3]=2;
WRITE_WORD(&CONF_Ind[1],S_CONF_DROP);
plci->ptyState = CONNECTED;
break;
case CONF_ISOLATE:
CONF_Ind[0]=5;
CONF_Ind[3]=2;
WRITE_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
plci->ptyState = CONNECTED;
break;
case CONF_REATTACH:
CONF_Ind[0]=5;
CONF_Ind[3]=2;
WRITE_WORD(&CONF_Ind[1],S_CONF_REATTACH);
plci->ptyState = CONNECTED;
break;
case CONF_ADD:
WRITE_WORD(&CONF_Ind[1],S_CONF_ADD);
plci->relatedPTYPLCI = NULL;
tplci=plci->relatedPTYPLCI;
if(tplci) tplci->ptyState = CONNECTED;
plci->ptyState = CONNECTED;
break;
}
if(pty_cai[2]!=0xff)
{
WRITE_WORD(&CONF_Ind[4],0x3600|(word)pty_cai[2]);
}
else
{
WRITE_WORD(&CONF_Ind[4],0x3303); /* Time-out: network did not respond
within the required time */
}
WRITE_DWORD(&CONF_Ind[6],0x0);
sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
break;
}
break;
/* Supplementary Service indicates success */
case S_SERVICE:
dbug(1,dprintf("Service_Ind"));
WRITE_WORD (&CF_Ind[4], 0);
switch (pty_cai[5])
{
case THREE_PTY_END:
case THREE_PTY_BEGIN:
case ECT_EXECUTE:
if(!plci->relatedPTYPLCI) break;
tplci = plci->relatedPTYPLCI;
rId = ( (word)tplci->Id<<8)|tplci->adapter->Id;
if(tplci->tel) rId|=EXT_CONTROLLER;
if(pty_cai[5]==ECT_EXECUTE)
{
WRITE_WORD(&SS_Ind[1],S_ECT);
if(plci->vswitchstate!=3)
{
plci->ptyState = IDLE;
plci->relatedPTYPLCI = NULL;
plci->ptyState = 0;
}
dbug(1,dprintf("ECT OK"));
sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
}
else
{
switch (plci->ptyState)
{
case S_3PTY_BEGIN:
plci->ptyState = CONNECTED;
dbug(1,dprintf("3PTY ON"));
break;
case S_3PTY_END:
plci->ptyState = IDLE;
plci->relatedPTYPLCI = NULL;
plci->ptyState = 0;
dbug(1,dprintf("3PTY OFF"));
break;
}
WRITE_WORD(&SS_Ind[1],pty_cai[5]+3);
sendf(tplci->appl,_FACILITY_I,rId,0,"ws",3, SS_Ind);
}
break;
case CALL_DEFLECTION:
WRITE_WORD(&SS_Ind[1],pty_cai[5]);
for(i=0; i<max_appl; i++)
{
if(application[i].CDEnable)
{
if(application[i].Id) sendf(&application[i],_FACILITY_I,Id,0,"ws",3, SS_Ind);
application[i].CDEnable = FALSE;
}
}
break;
case DEACTIVATION_DIVERSION:
case ACTIVATION_DIVERSION:
if(!plci->appl) break;
WRITE_WORD(&CF_Ind[1],pty_cai[5]+2);
WRITE_DWORD(&CF_Ind[6],plci->appl->S_Handle);
sendf(plci->appl,_FACILITY_I,Id&0x7,0,"ws",3, CF_Ind);
plci_remove(plci);
break;
case DIVERSION_INTERROGATE_CFU:
case DIVERSION_INTERROGATE_CFB:
case DIVERSION_INTERROGATE_CFNR:
case DIVERSION_INTERROGATE_NUM:
case CCBS_REQUEST:
case CCBS_DEACTIVATE:
case CCBS_INTERROGATE:
if(!plci->appl) break;
switch (pty_cai[5])
{
case DIVERSION_INTERROGATE_CFU:
case DIVERSION_INTERROGATE_CFB:
case DIVERSION_INTERROGATE_CFNR:
dbug(1,dprintf("Interr_Div"));
WRITE_WORD(&pty_cai[1],S_INTERROGATE_DIVERSION);
pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
break;
case DIVERSION_INTERROGATE_NUM:
dbug(1,dprintf("Interr_Num"));
WRITE_WORD(&pty_cai[1],S_INTERROGATE_NUMBERS);
pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
break;
case CCBS_REQUEST:
dbug(1,dprintf("CCBS Request"));
WRITE_WORD(&pty_cai[1],S_CCBS_REQUEST);
pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
break;
case CCBS_DEACTIVATE:
dbug(1,dprintf("CCBS Deactivate"));
WRITE_WORD(&pty_cai[1],S_CCBS_DEACTIVATE);
pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
break;
case CCBS_INTERROGATE:
dbug(1,dprintf("CCBS Interrogate"));
WRITE_WORD(&pty_cai[1],S_CCBS_INTERROGATE);
pty_cai[3]=pty_cai[0]-3; /* Supplementary Service-specific parameter len */
break;
}
WRITE_WORD(&pty_cai[4],0); /* Supplementary Service Reason */
WRITE_DWORD(&pty_cai[6],plci->appl->S_Handle);
sendf(plci->appl,_FACILITY_I,Id&0x7,0,"wS",3, pty_cai);
plci_remove(plci);
break;
case ACTIVATION_MWI:
case DEACTIVATION_MWI:
if(pty_cai[5]==ACTIVATION_MWI)
{
WRITE_WORD(&SS_Ind[1],S_MWI_ACTIVATE);
}
else WRITE_WORD(&SS_Ind[1],S_MWI_DEACTIVATE);
if(plci->cr_enquiry)
{
sendf(plci->appl,_FACILITY_I,Id&0xf,0,"ws",3, SS_Ind);
plci_remove(plci);
}
else
{
sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
}
break;
case MWI_INDICATION:
if(pty_cai[0]>=0x12)
{
WRITE_WORD(&pty_cai[3],S_MWI_INDICATE);
pty_cai[2]=pty_cai[0]-2; /* len Parameter */
pty_cai[5]=pty_cai[0]-5; /* Supplementary Service-specific parameter len */
if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_MWI))
{
if(plci->internal_command==GET_MWI_STATE) /* result on Message Waiting Listen */
{
sendf(plci->appl,_FACILITY_I,Id&0xf,0,"wS",3, &pty_cai[2]);
plci_remove(plci);
return;
}
else sendf(plci->appl,_FACILITY_I,Id,0,"wS",3, &pty_cai[2]);
pty_cai[0]=0;
}
else
{
for(i=0; i<max_appl; i++)
{
if(a->Notification_Mask[i]&SMASK_MWI)
{
sendf(&application[i],_FACILITY_I,Id&0x7,0,"wS",3, &pty_cai[2]);
pty_cai[0]=0;
}
}
}
if(!pty_cai[0])
{ /* acknowledge */
facility[2]= 0; /* returncode */
}
else facility[2]= 0xff;
}
else
{
/* reject */
facility[2]= 0xff; /* returncode */
}
facility[0]= 2;
facility[1]= MWI_RESPONSE; /* Function */
add_p(plci,CAI,facility);
add_p(plci,ESC,multi_ssext_parms[0]); /* remembered parameter -> only one possible */
sig_req(plci,S_SERVICE,0);
send_req(plci);
plci->command = 0;
next_internal_command (Id, plci);
break;
case CONF_ADD: /* OK */
case CONF_BEGIN:
case CONF_DROP:
case CONF_ISOLATE:
case CONF_REATTACH:
case CONF_PARTYDISC:
CONF_Ind[0]=9;
CONF_Ind[3]=6;
switch(pty_cai[5])
{
case CONF_BEGIN:
WRITE_WORD(&CONF_Ind[1],S_CONF_BEGIN);
if(pty_cai[0]==6)
{
d=pty_cai[6];
WRITE_DWORD(&CONF_Ind[6],d); /* PartyID */
}
else
{
WRITE_DWORD(&CONF_Ind[6],0x0);
}
break;
case CONF_ISOLATE:
WRITE_WORD(&CONF_Ind[1],S_CONF_ISOLATE);
CONF_Ind[0]=5;
CONF_Ind[3]=2;
break;
case CONF_REATTACH:
WRITE_WORD(&CONF_Ind[1],S_CONF_REATTACH);
CONF_Ind[0]=5;
CONF_Ind[3]=2;
break;
case CONF_DROP:
WRITE_WORD(&CONF_Ind[1],S_CONF_DROP);
CONF_Ind[0]=5;
CONF_Ind[3]=2;
break;
case CONF_ADD:
WRITE_WORD(&CONF_Ind[1],S_CONF_ADD);
d=pty_cai[6];
WRITE_DWORD(&CONF_Ind[6],d); /* PartyID */
tplci=plci->relatedPTYPLCI;
if(tplci) tplci->ptyState = CONNECTED;
break;
case CONF_PARTYDISC:
CONF_Ind[0]=7;
CONF_Ind[3]=4;
WRITE_WORD(&CONF_Ind[1],S_CONF_PARTYDISC);
d=pty_cai[6];
WRITE_DWORD(&CONF_Ind[4],d); /* PartyID */
break;
}
plci->ptyState = CONNECTED;
sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
break;
case CCBS_INFO_RETAIN:
case CCBS_ERASECALLLINKAGEID:
case CCBS_STOP_ALERTING:
CONF_Ind[0]=5;
CONF_Ind[3]=2;
switch(pty_cai[5])
{
case CCBS_INFO_RETAIN:
WRITE_WORD(&CONF_Ind[1],S_CCBS_INFO_RETAIN);
break;
case CCBS_STOP_ALERTING:
WRITE_WORD(&CONF_Ind[1],S_CCBS_STOP_ALERTING);
break;
case CCBS_ERASECALLLINKAGEID:
WRITE_WORD(&CONF_Ind[1],S_CCBS_ERASECALLLINKAGEID);
CONF_Ind[0]=7;
CONF_Ind[3]=4;
CONF_Ind[6]=0;
CONF_Ind[7]=0;
break;
}
w=pty_cai[6];
WRITE_WORD(&CONF_Ind[4],w); /* PartyID */
if(plci->appl && (a->Notification_Mask[plci->appl->Id-1]&SMASK_CCBS))
{
sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, CONF_Ind);
}
else
{
for(i=0; i<max_appl; i++)
if(a->Notification_Mask[i]&SMASK_CCBS)
sendf(&application[i],_FACILITY_I,Id&0x7,0,"ws",3, CONF_Ind);
}
break;
}
break;
case CALL_HOLD_REJ:
cau = parms[7];
if(cau)
{
i = _L3_CAUSE | cau[2];
if(cau[2]==0) i = 0x3603;
}
else
{
i = 0x3603;
}
WRITE_WORD(&SS_Ind[1],S_HOLD);
WRITE_WORD(&SS_Ind[4],i);
if(plci->SuppState == HOLD_REQUEST)
{
plci->SuppState = IDLE;
sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
}
break;
case CALL_HOLD_ACK:
if(plci->SuppState == HOLD_REQUEST)
{
plci->SuppState = CALL_HELD;
CodecIdCheck(a, plci);
start_internal_command (Id, plci, hold_save_command);
}
break;
case CALL_RETRIEVE_REJ:
cau = parms[7];
if(cau)
{
i = _L3_CAUSE | cau[2];
if(cau[2]==0) i = 0x3603;
}
else
{
i = 0x3603;
}
WRITE_WORD(&SS_Ind[1],S_RETRIEVE);
WRITE_WORD(&SS_Ind[4],i);
if(plci->SuppState == RETRIEVE_REQUEST)
{
plci->SuppState = CALL_HELD;
CodecIdCheck(a, plci);
sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
}
break;
case CALL_RETRIEVE_ACK:
WRITE_WORD(&SS_Ind[1],S_RETRIEVE);
if(plci->SuppState == RETRIEVE_REQUEST)
{
plci->SuppState = IDLE;
plci->call_dir |= CALL_DIR_FORCE_OUTG_NL;
plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
if(plci->tel)
{
mixer_set_bchannel_id_esc (plci, plci->b_channel);
dbug(1,dprintf("RetrChannel=0x%x",plci->b_channel));
SetVoiceChannel(a->AdvCodecPLCI, esc_chi, a);
if(plci->B2_prot==B2_TRANSPARENT && plci->B3_prot==B3_TRANSPARENT)
{
dbug(1,dprintf("Get B-ch"));
start_internal_command (Id, plci, retrieve_restore_command);
}
else
sendf(plci->appl,_FACILITY_I,Id,0,"ws",3, SS_Ind);
}
else
start_internal_command (Id, plci, retrieve_restore_command);
}
break;
case INDICATE_IND:
if(plci->State != LISTENING) {
sig_req(plci,HANGUP,0);
send_req(plci);
break;
}
cip = find_cip(a,parms[4],parms[6]);
cip_mask = 1L<<cip;
dbug(1,dprintf("cip=%d,cip_mask=%lx",cip,cip_mask));
clear_c_ind_mask (plci);
if (!remove_started && !a->adapter_disabled)
{
set_c_ind_mask_bit (plci, MAX_APPL);
group_optimization(a, plci);
for(i=0; i<max_appl; i++) {
if(application[i].Id
&& (a->CIP_Mask[i]&1 || a->CIP_Mask[i]&cip_mask)
&& CPN_filter_ok(parms[0],a,i)
&& test_group_ind_mask_bit (plci, i) ) {
dbug(1,dprintf("storedcip_mask[%d]=0x%lx",i,a->CIP_Mask[i] ));
set_c_ind_mask_bit (plci, i);
dump_c_ind_mask (plci);
plci->State = INC_CON_PENDING;
plci->call_dir = (plci->call_dir & ~(CALL_DIR_OUT | CALL_DIR_ORIGINATE)) |
CALL_DIR_IN | CALL_DIR_ANSWER;
if(esc_chi[0]) {
plci->b_channel = esc_chi[esc_chi[0]]&0x1f;
mixer_set_bchannel_id_esc (plci, plci->b_channel);
}
/* if a listen on the ext controller is done, check if hook states */
/* are supported or if just a on board codec must be activated */
if(a->codec_listen[i] && !a->AdvSignalPLCI) {
if(a->profile.Global_Options & HANDSET)
plci->tel = ADV_VOICE;
else if(a->profile.Global_Options & ON_BOARD_CODEC)
plci->tel = CODEC;
if(plci->tel) Id|=EXT_CONTROLLER;
a->codec_listen[i] = plci;
}
sendf(&application[i],_CONNECT_I,Id,0,
"wSSSSSSSbSSSSS", cip, /* CIP */
parms[0], /* CalledPartyNumber */
multi_CiPN_parms[0], /* CallingPartyNumber */
parms[2], /* CalledPartySubad */
parms[3], /* CallingPartySubad */
parms[4], /* BearerCapability */
parms[5], /* LowLC */
parms[6], /* HighLC */
ai_len, /* nested struct add_i */
add_i[0], /* B channel info */
add_i[1], /* keypad facility */
add_i[2], /* user user data */
add_i[3], /* nested facility */
multi_CiPN_parms[1] /* second CiPN(SCR) */
);
SendSSExtInd(&application[i],
plci,
Id,
multi_ssext_parms);
SendSetupInfo(&application[i],
plci,
Id,
parms,
SendMultiIE(plci,Id,multi_pi_parms, PI, 0x210, TRUE));
}
}
clear_c_ind_mask_bit (plci, MAX_APPL);
dump_c_ind_mask (plci);
}
if(c_ind_mask_empty (plci)) {
sig_req(plci,HANGUP,0);
send_req(plci);
plci->State = IDLE;
}
plci->notifiedcall = 0;
a->listen_active--;
listen_check(a);
break;
case CALL_PEND_NOTIFY:
plci->notifiedcall = 1;
listen_check(a);
break;
case CALL_IND:
case CALL_CON:
if(plci->State==ADVANCED_VOICE_SIG || plci->State==ADVANCED_VOICE_NOSIG)
{
if(plci->internal_command==PERM_COD_CONN_PEND)
{
if(plci->State==ADVANCED_VOICE_NOSIG)
{
dbug(1,dprintf("***Codec OK"));
if(a->AdvSignalPLCI)
{
tplci = a->AdvSignalPLCI;
if(tplci->spoofed_msg)
{
dbug(1,dprintf("***Spoofed Msg(0x%x)",tplci->spoofed_msg));
tplci->command = 0;
tplci->internal_command = 0;
x_Id = ((word)tplci->Id<<8)|tplci->adapter->Id | 0x80;
switch (tplci->spoofed_msg)
{
case CALL_RES:
tplci->command = _CONNECT_I|RESPONSE;
api_load_msg (&tplci->saved_msg, saved_parms);
add_b1(tplci,&saved_parms[1],0,tplci->B1_facilities);
if (tplci->adapter->Info_Mask[tplci->appl->Id-1] & 0x200)
{
/* early B3 connect (CIP mask bit 9) no release after a disc */
add_p(tplci,LLI,"\x01\x01");
}
add_s(tplci, CONN_NR, &saved_parms[2]);
add_s(tplci, LLC, &saved_parms[4]);
add_ai(tplci, &saved_parms[5]);
tplci->State = INC_CON_ACCEPT;
sig_req(tplci, CALL_RES,0);
send_req(tplci);
break;
case AWAITING_SELECT_B:
dbug(1,dprintf("Select_B continue"));
start_internal_command (x_Id, tplci, select_b_command);
break;
case AWAITING_MANUF_CON: /* Get_Plci per Manufacturer_Req to ext controller */
if(!tplci->Sig.Id)
{
dbug(1,dprintf("No SigID!"));
sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
plci_remove(tplci);
break;
}
tplci->command = _MANUFACTURER_R;
api_load_msg (&tplci->saved_msg, saved_parms);
dir = saved_parms[2].info[0];
if(dir==1) {
sig_req(tplci,CALL_REQ,0);
}
else if(!dir){
sig_req(tplci,LISTEN_REQ,0);
}
send_req(tplci);
sendf(tplci->appl, _MANUFACTURER_R|CONFIRM,x_Id,tplci->number, "dww",_DI_MANU_ID,_MANUFACTURER_R,0);
break;
case (CALL_REQ|AWAITING_MANUF_CON):
sig_req(tplci,CALL_REQ,0);
send_req(tplci);
break;
case CALL_REQ:
if(!tplci->Sig.Id)
{
dbug(1,dprintf("No SigID!"));
sendf(tplci->appl,_CONNECT_R|CONFIRM,tplci->adapter->Id,0,"w",_OUT_OF_PLCI);
plci_remove(tplci);
break;
}
tplci->command = _CONNECT_R;
api_load_msg (&tplci->saved_msg, saved_parms);
add_s(tplci,CPN,&saved_parms[1]);
add_s(tplci,DSA,&saved_parms[3]);
add_ai(tplci,&saved_parms[9]);
sig_req(tplci,CALL_REQ,0);
send_req(tplci);
break;
case CALL_RETRIEVE:
tplci->command = C_RETRIEVE_REQ;
sig_req(tplci,CALL_RETRIEVE,0);
send_req(tplci);
break;
}
tplci->spoofed_msg = 0;
if (tplci->internal_command == 0)
next_internal_command (x_Id, tplci);
}
}
next_internal_command (Id, plci);
break;
}
dbug(1,dprintf("***Codec Hook Init Req"));
plci->internal_command = PERM_COD_HOOK;
add_p(plci,FTY,"\x01\x09"); /* Get Hook State*/
sig_req(plci,TEL_CTRL,0);
send_req(plci);
}
}
else if(plci->command != _MANUFACTURER_R /* old style permanent connect */
&& plci->State!=INC_ACT_PENDING)
{
mixer_set_bchannel_id_esc (plci, plci->b_channel);
if(plci->tel == ADV_VOICE && plci->SuppState == IDLE) /* with permanent codec switch on immediately */
{
chi[2] = plci->b_channel;
SetVoiceChannel(a->AdvCodecPLCI, chi, a);
}
sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"Sss",parms[21],"","");
plci->State = INC_ACT_PENDING;
}
break;
case TEL_CTRL:
Number = 0;
ie = multi_fac_parms[0]; /* inspect the facility hook indications */
if(plci->State==ADVANCED_VOICE_SIG && ie[0]){
switch (ie[1]&0x91) {
case 0x80: /* hook off */
case 0x81:
if(plci->internal_command==PERM_COD_HOOK)
{
dbug(1,dprintf("init:hook_off"));
plci->hook_state = ie[1];
next_internal_command (Id, plci);
break;
}
else /* ignore doubled hook indications */
{
if( ((plci->hook_state)&0xf0)==0x80)
{
dbug(1,dprintf("ignore hook"));
break;
}
plci->hook_state = ie[1]&0x91;
}
/* check for incoming call pending */
/* and signal '+'.Appl must decide */
/* with connect_res if call must */
/* accepted or not */
for(i=0, tplci=NULL;i<max_appl;i++){
if(a->codec_listen[i]
&& (a->codec_listen[i]->State==INC_CON_PENDING
||a->codec_listen[i]->State==INC_CON_ALERT) ){
tplci = a->codec_listen[i];
tplci->appl = &application[i];
}
}
/* no incoming call, do outgoing call */
/* and signal '+' if outg. setup */
if(!a->AdvSignalPLCI && !tplci){
if((i=get_plci(a))) {
a->AdvSignalPLCI = &a->plci[i-1];
tplci = a->AdvSignalPLCI;
tplci->tel = ADV_VOICE;
WRITE_WORD(&voice_cai[5],a->AdvSignalAppl->MaxDataLength);
if (a->Info_Mask[a->AdvSignalAppl->Id-1] & 0x200){
/* early B3 connect (CIP mask bit 9) no release after a disc */
add_p(tplci,LLI,"\x01\x01");
}
add_p(tplci, CAI, voice_cai);
add_p(tplci, OAD, a->TelOAD);
add_p(tplci, OSA, a->TelOSA);
add_p(tplci,SHIFT|6,NULL);
add_p(tplci,SIN,"\x02\x01\x00");
add_p(tplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
sig_req(tplci,ASSIGN,DSIG_ID);
a->AdvSignalPLCI->internal_command = HOOK_OFF_REQ;
a->AdvSignalPLCI->command = 0;
tplci->appl = a->AdvSignalAppl;
tplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
send_req(tplci);
}
}
if(!tplci) break;
Id = ((word)tplci->Id<<8)|a->Id;
Id|=EXT_CONTROLLER;
sendf(tplci->appl,
_FACILITY_I,
Id,
0,
"ws", (word)0, "\x01+");
break;
case 0x90: /* hook on */
case 0x91:
if(plci->internal_command==PERM_COD_HOOK)
{
dbug(1,dprintf("init:hook_on"));
plci->hook_state = ie[1]&0x91;
next_internal_command (Id, plci);
break;
}
else /* ignore doubled hook indications */
{
if( ((plci->hook_state)&0xf0)==0x90) break;
plci->hook_state = ie[1]&0x91;
}
/* hangup the adv. voice call and signal '-' to the appl */
if(a->AdvSignalPLCI) {
Id = ((word)a->AdvSignalPLCI->Id<<8)|a->Id;
if(plci->tel) Id|=EXT_CONTROLLER;
sendf(a->AdvSignalAppl,
_FACILITY_I,
Id,
0,
"ws", (word)0, "\x01-");
a->AdvSignalPLCI->internal_command = HOOK_ON_REQ;
a->AdvSignalPLCI->command = 0;
sig_req(a->AdvSignalPLCI,HANGUP,0);
send_req(a->AdvSignalPLCI);
}
break;
}
}
break;
case RESUME:
clear_c_ind_mask_bit (plci, (word)(plci->appl->Id-1));
WRITE_WORD(&resume_cau[4],GOOD);
sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
break;
case SUSPEND:
clear_c_ind_mask (plci);
if (plci->NL.Id && !plci->nl_remove_id) {
mixer_remove (plci);
nl_req_ncci(plci,REMOVE,0);
}
if (!plci->sig_remove_id) {
plci->internal_command = 0;
sig_req(plci,REMOVE,0);
}
send_req(plci);
if(!plci->channels) {
sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, "\x05\x04\x00\x02\x00\x00");
sendf(plci->appl, _DISCONNECT_I, Id, 0, "w", 0);
}
break;
case SUSPEND_REJ:
break;
case HANGUP:
plci->hangup_flow_ctrl_timer=0;
if(plci->manufacturer && plci->State==LOCAL_CONNECT) break;
cau = parms[7];
if(cau) {
i = _L3_CAUSE | cau[2];
if(cau[2]==0) i = 0;
else if(cau[2]==8) i = _L1_ERROR;
else if(cau[2]==9 || cau[2]==10) i = _L2_ERROR;
else if(cau[2]==5) i = _CAPI_GUARD_ERROR;
}
else {
i = _L3_ERROR;
}
if(plci->State==INC_CON_PENDING || plci->State==INC_CON_ALERT)
{
for(i=0; i<max_appl; i++)
{
if(test_c_ind_mask_bit (plci, i))
sendf(&application[i], _DISCONNECT_I, Id, 0, "w", 0);
}
}
else
{
clear_c_ind_mask (plci);
}
if(!plci->appl)
{
if (plci->State == LISTENING)
{
plci->notifiedcall=0;
a->listen_active--;
}
plci->State = INC_DIS_PENDING;
if(c_ind_mask_empty (plci))
{
plci->State = IDLE;
if (plci->NL.Id && !plci->nl_remove_id)
{
mixer_remove (plci);
nl_req_ncci(plci,REMOVE,0);
}
if (!plci->sig_remove_id)
{
plci->internal_command = 0;
sig_req(plci,REMOVE,0);
}
send_req(plci);
}
}
else
{
/* collision of DISCONNECT or CONNECT_RES with HANGUP can */
/* result in a second HANGUP! Don't generate another */
/* DISCONNECT */
if(plci->State!=IDLE && plci->State!=INC_DIS_PENDING)
{
if(plci->State==RESUMING)
{
WRITE_WORD(&resume_cau[4],i);
sendf(plci->appl,_FACILITY_I,Id,0,"ws", (word)3, resume_cau);
}
plci->State = INC_DIS_PENDING;
sendf(plci->appl,_DISCONNECT_I,Id,0,"w",i);
}
}
break;
case SSEXT_IND:
SendSSExtInd(NULL,plci,Id,multi_ssext_parms);
break;
case VSWITCH_REQ:
VSwitchReqInd(plci,Id,multi_vswitch_parms);
break;
case VSWITCH_IND:
if(plci->relatedPTYPLCI &&
plci->vswitchstate==3 &&
plci->relatedPTYPLCI->vswitchstate==3 &&
parms[MAXPARMSIDS-1][0])
{
add_p(plci->relatedPTYPLCI,SMSG,parms[MAXPARMSIDS-1]);
sig_req(plci->relatedPTYPLCI,VSWITCH_REQ,0);
send_req(plci->relatedPTYPLCI);
}
else VSwitchReqInd(plci,Id,multi_vswitch_parms);
break;
}
}
Generated by GNU enscript 1.6.4.