extractedLnx/linux-2.6.9/drivers/isdn/hardware/eicon/message.c_facility_req.c
byte facility_req(dword Id, word Number, DIVA_CAPI_ADAPTER * a, PLCI * plci, APPL * appl, API_PARSE * msg)
{
word Info = 0;
word i = 0;
word selector;
word SSreq;
long relatedPLCIvalue;
DIVA_CAPI_ADAPTER * relatedadapter;
byte * SSparms = "";
byte RCparms[] = "\x05\x00\x00\x02\x00\x00";
byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
API_PARSE * parms;
API_PARSE ss_parms[11];
PLCI *rplci;
byte cai[15];
dword d;
API_PARSE dummy;
dbug(1,dprintf("facility_req"));
for(i=0;i<9;i++) ss_parms[i].length = 0;
parms = &msg[1];
if(!a)
{
dbug(1,dprintf("wrong Ctrl"));
Info = _WRONG_IDENTIFIER;
}
selector = READ_WORD(msg[0].info);
if(!Info)
{
switch(selector)
{
case SELECTOR_HANDSET:
Info = AdvCodecSupport(a, plci, appl, HOOK_SUPPORT);
break;
case SELECTOR_SU_SERV:
if(!msg[1].length)
{
Info = _WRONG_MESSAGE_FORMAT;
break;
}
SSreq = READ_WORD(&(msg[1].info[1]));
WRITE_WORD(&RCparms[1],SSreq);
SSparms = RCparms;
switch(SSreq)
{
case S_GET_SUPPORTED_SERVICES:
if((i=get_plci(a)))
{
rplci = &a->plci[i-1];
rplci->appl = appl;
add_p(rplci,CAI,"\x01\x80");
add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
sig_req(rplci,ASSIGN,DSIG_ID);
send_req(rplci);
}
else
{
WRITE_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
SSparms = (byte *)SSstruct;
break;
}
rplci->internal_command = GETSERV_REQ_PEND;
rplci->number = Number;
rplci->appl = appl;
sig_req(rplci,S_SUPPORTED,0);
send_req(rplci);
return FALSE;
break;
case S_LISTEN:
if(parms->length==7)
{
if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
{
dbug(1,dprintf("format wrong"));
Info = _WRONG_MESSAGE_FORMAT;
break;
}
}
else
{
Info = _WRONG_MESSAGE_FORMAT;
break;
}
a->Notification_Mask[appl->Id-1] = READ_DWORD(ss_parms[2].info);
if(a->Notification_Mask[appl->Id-1] & SMASK_MWI) /* MWI active? */
{
if((i=get_plci(a)))
{
rplci = &a->plci[i-1];
rplci->appl = appl;
add_p(rplci,CAI,"\x01\x80");
add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
sig_req(rplci,ASSIGN,DSIG_ID);
send_req(rplci);
}
else
{
break;
}
rplci->internal_command = GET_MWI_STATE;
rplci->number = Number;
sig_req(rplci,MWI_POLL,0);
send_req(rplci);
}
break;
case S_HOLD:
api_parse(&parms->info[1],(word)parms->length,"ws",ss_parms);
if(plci && plci->State && plci->SuppState==IDLE)
{
plci->SuppState = HOLD_REQUEST;
plci->command = C_HOLD_REQ;
add_s(plci,CAI,&ss_parms[1]);
sig_req(plci,CALL_HOLD,0);
send_req(plci);
return FALSE;
}
else Info = 0x3010; /* wrong state */
break;
case S_RETRIEVE:
if(plci && plci->State && plci->SuppState==CALL_HELD)
{
if(Id & EXT_CONTROLLER)
{
if(AdvCodecSupport(a, plci, appl, 0))
{
Info = 0x3010; /* wrong state */
break;
}
}
else plci->tel = 0;
plci->SuppState = RETRIEVE_REQUEST;
plci->command = C_RETRIEVE_REQ;
if(plci->spoofed_msg==SPOOFING_REQUIRED)
{
plci->spoofed_msg = CALL_RETRIEVE;
plci->internal_command = BLOCK_PLCI;
plci->command = 0;
dbug(1,dprintf("Spoof"));
return FALSE;
}
else
{
sig_req(plci,CALL_RETRIEVE,0);
send_req(plci);
return FALSE;
}
}
else Info = 0x3010; /* wrong state */
break;
case S_SUSPEND:
if(parms->length)
{
if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
{
dbug(1,dprintf("format wrong"));
Info = _WRONG_MESSAGE_FORMAT;
break;
}
}
if(plci && plci->State)
{
add_s(plci,CAI,&ss_parms[2]);
plci->command = SUSPEND_REQ;
sig_req(plci,SUSPEND,0);
plci->State = SUSPENDING;
send_req(plci);
}
else Info = 0x3010; /* wrong state */
break;
case S_RESUME:
if(!(i=get_plci(a)) )
{
Info = _OUT_OF_PLCI;
break;
}
rplci = &a->plci[i-1];
rplci->appl = appl;
rplci->number = Number;
rplci->tel = 0;
rplci->call_dir = CALL_DIR_OUT | CALL_DIR_ORIGINATE;
/* check 'external controller' bit for codec support */
if(Id & EXT_CONTROLLER)
{
if(AdvCodecSupport(a, rplci, appl, 0) )
{
rplci->Id = 0;
Info = 0x300A;
break;
}
}
if(parms->length)
{
if(api_parse(&parms->info[1],(word)parms->length,"wbs",ss_parms))
{
dbug(1,dprintf("format wrong"));
rplci->Id = 0;
Info = _WRONG_MESSAGE_FORMAT;
break;
}
}
dummy.length = 0;
dummy.info = "\x00";
add_b1(rplci, &dummy, 0, 0);
if (a->Info_Mask[appl->Id-1] & 0x200)
{
/* early B3 connect (CIP mask bit 9) no release after a disc */
add_p(rplci,LLI,"\x01\x01");
}
add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
sig_req(rplci,ASSIGN,DSIG_ID);
send_req(rplci);
add_s(rplci,CAI,&ss_parms[2]);
rplci->command = RESUME_REQ;
sig_req(rplci,RESUME,0);
rplci->State = RESUMING;
send_req(rplci);
break;
case S_CONF_BEGIN: /* Request */
case S_CONF_DROP:
case S_CONF_ISOLATE:
case S_CONF_REATTACH:
if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
{
dbug(1,dprintf("format wrong"));
Info = _WRONG_MESSAGE_FORMAT;
break;
}
if(plci && plci->State && ((plci->SuppState==IDLE)||(plci->SuppState==CALL_HELD)))
{
d = READ_DWORD(ss_parms[2].info);
if(d>=0x80)
{
dbug(1,dprintf("format wrong"));
Info = _WRONG_MESSAGE_FORMAT;
break;
}
plci->ptyState = (byte)SSreq;
plci->command = 0;
cai[0] = 2;
switch(SSreq)
{
case S_CONF_BEGIN:
cai[1] = CONF_BEGIN;
plci->internal_command = CONF_BEGIN_REQ_PEND;
break;
case S_CONF_DROP:
cai[1] = CONF_DROP;
plci->internal_command = CONF_DROP_REQ_PEND;
break;
case S_CONF_ISOLATE:
cai[1] = CONF_ISOLATE;
plci->internal_command = CONF_ISOLATE_REQ_PEND;
break;
case S_CONF_REATTACH:
cai[1] = CONF_REATTACH;
plci->internal_command = CONF_REATTACH_REQ_PEND;
break;
}
cai[2] = (byte)d; /* Conference Size resp. PartyId */
add_p(plci,CAI,cai);
sig_req(plci,S_SERVICE,0);
send_req(plci);
return FALSE;
}
else Info = 0x3010; /* wrong state */
break;
case S_ECT:
case S_3PTY_BEGIN:
case S_3PTY_END:
case S_CONF_ADD:
if(parms->length==7)
{
if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
{
dbug(1,dprintf("format wrong"));
Info = _WRONG_MESSAGE_FORMAT;
break;
}
}
else if(parms->length==8) /* workaround for the T-View-S */
{
if(api_parse(&parms->info[1],(word)parms->length,"wbdb",ss_parms))
{
dbug(1,dprintf("format wrong"));
Info = _WRONG_MESSAGE_FORMAT;
break;
}
}
else
{
Info = _WRONG_MESSAGE_FORMAT;
break;
}
if(!msg[1].length)
{
Info = _WRONG_MESSAGE_FORMAT;
break;
}
if (!plci)
{
Info = _WRONG_IDENTIFIER;
break;
}
relatedPLCIvalue = READ_DWORD(ss_parms[2].info);
relatedPLCIvalue &= 0x0000FFFF;
dbug(1,dprintf("PTY/ECT/addCONF,relPLCI=%lx",relatedPLCIvalue));
/* controller starts with 0 up to (max_adapter - 1) */
if (((relatedPLCIvalue & 0x7f) == 0)
|| (MapController ((byte)(relatedPLCIvalue & 0x7f)) == 0)
|| (MapController ((byte)(relatedPLCIvalue & 0x7f)) > max_adapter))
{
if(SSreq==S_3PTY_END)
{
dbug(1, dprintf("wrong Controller use 2nd PLCI=PLCI"));
rplci = plci;
}
else
{
Info = 0x3010; /* wrong state */
break;
}
}
else
{
relatedadapter = &adapter[MapController ((byte)(relatedPLCIvalue & 0x7f))-1];
relatedPLCIvalue >>=8;
/* find PLCI PTR*/
for(i=0,rplci=NULL;i<relatedadapter->max_plci;i++)
{
if(relatedadapter->plci[i].Id == (byte)relatedPLCIvalue)
{
rplci = &relatedadapter->plci[i];
}
}
if(!rplci || !relatedPLCIvalue)
{
if(SSreq==S_3PTY_END)
{
dbug(1, dprintf("use 2nd PLCI=PLCI"));
rplci = plci;
}
else
{
Info = 0x3010; /* wrong state */
break;
}
}
}
/*
dbug(1,dprintf("rplci:%x",rplci));
dbug(1,dprintf("plci:%x",plci));
dbug(1,dprintf("rplci->ptyState:%x",rplci->ptyState));
dbug(1,dprintf("plci->ptyState:%x",plci->ptyState));
dbug(1,dprintf("SSreq:%x",SSreq));
dbug(1,dprintf("rplci->internal_command:%x",rplci->internal_command));
dbug(1,dprintf("rplci->appl:%x",rplci->appl));
dbug(1,dprintf("rplci->Id:%x",rplci->Id));
*/
/* send PTY/ECT req, cannot check all states because of US stuff */
if( !rplci->internal_command && rplci->appl )
{
plci->command = 0;
rplci->relatedPTYPLCI = plci;
plci->relatedPTYPLCI = rplci;
rplci->ptyState = (byte)SSreq;
if(SSreq==S_ECT)
{
rplci->internal_command = ECT_REQ_PEND;
cai[1] = ECT_EXECUTE;
rplci->vswitchstate=0;
rplci->vsprot=0;
rplci->vsprotdialect=0;
plci->vswitchstate=0;
plci->vsprot=0;
plci->vsprotdialect=0;
}
else if(SSreq==S_CONF_ADD)
{
rplci->internal_command = CONF_ADD_REQ_PEND;
cai[1] = CONF_ADD;
}
else
{
rplci->internal_command = PTY_REQ_PEND;
cai[1] = (byte)(SSreq-3);
}
rplci->number = Number;
if(plci!=rplci) /* explicit invocation */
{
cai[0] = 2;
cai[2] = plci->Sig.Id;
dbug(1,dprintf("explicit invocation"));
}
else
{
dbug(1,dprintf("implicit invocation"));
cai[0] = 1;
}
add_p(rplci,CAI,cai);
sig_req(rplci,S_SERVICE,0);
send_req(rplci);
return FALSE;
}
else
{
dbug(0,dprintf("Wrong line"));
Info = 0x3010; /* wrong state */
break;
}
break;
case S_CALL_DEFLECTION:
if(api_parse(&parms->info[1],(word)parms->length,"wbwss",ss_parms))
{
dbug(1,dprintf("format wrong"));
Info = _WRONG_MESSAGE_FORMAT;
break;
}
if (!plci)
{
Info = _WRONG_IDENTIFIER;
break;
}
/* reuse unused screening indicator */
ss_parms[3].info[3] = (byte)READ_WORD(&(ss_parms[2].info[0]));
plci->command = 0;
plci->internal_command = CD_REQ_PEND;
appl->CDEnable = TRUE;
cai[0] = 1;
cai[1] = CALL_DEFLECTION;
add_p(plci,CAI,cai);
add_p(plci,CPN,ss_parms[3].info);
sig_req(plci,S_SERVICE,0);
send_req(plci);
return FALSE;
break;
case S_CALL_FORWARDING_START:
if(api_parse(&parms->info[1],(word)parms->length,"wbdwwsss",ss_parms))
{
dbug(1,dprintf("format wrong"));
Info = _WRONG_MESSAGE_FORMAT;
break;
}
if((i=get_plci(a)))
{
rplci = &a->plci[i-1];
rplci->appl = appl;
add_p(rplci,CAI,"\x01\x80");
add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
sig_req(rplci,ASSIGN,DSIG_ID);
send_req(rplci);
}
else
{
Info = _OUT_OF_PLCI;
break;
}
/* reuse unused screening indicator */
rplci->internal_command = CF_START_PEND;
rplci->appl = appl;
rplci->number = Number;
appl->S_Handle = READ_DWORD(&(ss_parms[2].info[0]));
cai[0] = 2;
cai[1] = 0x70|(byte)READ_WORD(&(ss_parms[3].info[0])); /* Function */
cai[2] = (byte)READ_WORD(&(ss_parms[4].info[0])); /* Basic Service */
add_p(rplci,CAI,cai);
add_p(rplci,OAD,ss_parms[5].info);
add_p(rplci,CPN,ss_parms[6].info);
sig_req(rplci,S_SERVICE,0);
send_req(rplci);
return FALSE;
break;
case S_INTERROGATE_DIVERSION:
case S_INTERROGATE_NUMBERS:
case S_CALL_FORWARDING_STOP:
case S_CCBS_REQUEST:
case S_CCBS_DEACTIVATE:
case S_CCBS_INTERROGATE:
switch(SSreq)
{
case S_INTERROGATE_NUMBERS:
if(api_parse(&parms->info[1],(word)parms->length,"wbd",ss_parms))
{
dbug(0,dprintf("format wrong"));
Info = _WRONG_MESSAGE_FORMAT;
}
break;
case S_CCBS_REQUEST:
case S_CCBS_DEACTIVATE:
if(api_parse(&parms->info[1],(word)parms->length,"wbdw",ss_parms))
{
dbug(0,dprintf("format wrong"));
Info = _WRONG_MESSAGE_FORMAT;
}
break;
case S_CCBS_INTERROGATE:
if(api_parse(&parms->info[1],(word)parms->length,"wbdws",ss_parms))
{
dbug(0,dprintf("format wrong"));
Info = _WRONG_MESSAGE_FORMAT;
}
break;
default:
if(api_parse(&parms->info[1],(word)parms->length,"wbdwws",ss_parms))
{
dbug(0,dprintf("format wrong"));
Info = _WRONG_MESSAGE_FORMAT;
break;
}
break;
}
if(Info) break;
if((i=get_plci(a)))
{
rplci = &a->plci[i-1];
switch(SSreq)
{
case S_INTERROGATE_DIVERSION: /* use cai with S_SERVICE below */
cai[1] = 0x60|(byte)READ_WORD(&(ss_parms[3].info[0])); /* Function */
rplci->internal_command = INTERR_DIVERSION_REQ_PEND; /* move to rplci if assigned */
break;
case S_INTERROGATE_NUMBERS: /* use cai with S_SERVICE below */
cai[1] = DIVERSION_INTERROGATE_NUM; /* Function */
rplci->internal_command = INTERR_NUMBERS_REQ_PEND; /* move to rplci if assigned */
break;
case S_CALL_FORWARDING_STOP:
rplci->internal_command = CF_STOP_PEND;
cai[1] = 0x80|(byte)READ_WORD(&(ss_parms[3].info[0])); /* Function */
break;
case S_CCBS_REQUEST:
cai[1] = CCBS_REQUEST;
rplci->internal_command = CCBS_REQUEST_REQ_PEND;
break;
case S_CCBS_DEACTIVATE:
cai[1] = CCBS_DEACTIVATE;
rplci->internal_command = CCBS_DEACTIVATE_REQ_PEND;
break;
case S_CCBS_INTERROGATE:
cai[1] = CCBS_INTERROGATE;
rplci->internal_command = CCBS_INTERROGATE_REQ_PEND;
break;
default:
cai[1] = 0;
break;
}
rplci->appl = appl;
rplci->number = Number;
add_p(rplci,CAI,"\x01\x80");
add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
sig_req(rplci,ASSIGN,DSIG_ID);
send_req(rplci);
}
else
{
Info = _OUT_OF_PLCI;
break;
}
appl->S_Handle = READ_DWORD(&(ss_parms[2].info[0]));
switch(SSreq)
{
case S_INTERROGATE_NUMBERS:
cai[0] = 1;
add_p(rplci,CAI,cai);
break;
case S_CCBS_REQUEST:
case S_CCBS_DEACTIVATE:
cai[0] = 3;
WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[3].info[0])));
add_p(rplci,CAI,cai);
break;
case S_CCBS_INTERROGATE:
cai[0] = 3;
WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[3].info[0])));
add_p(rplci,CAI,cai);
add_p(rplci,OAD,ss_parms[4].info);
break;
default:
cai[0] = 2;
cai[2] = (byte)READ_WORD(&(ss_parms[4].info[0])); /* Basic Service */
add_p(rplci,CAI,cai);
add_p(rplci,OAD,ss_parms[5].info);
break;
}
sig_req(rplci,S_SERVICE,0);
send_req(rplci);
return FALSE;
break;
case S_MWI_ACTIVATE:
if(api_parse(&parms->info[1],(word)parms->length,"wbwdwwwssss",ss_parms))
{
dbug(1,dprintf("format wrong"));
Info = _WRONG_MESSAGE_FORMAT;
break;
}
if(!plci)
{
if((i=get_plci(a)))
{
rplci = &a->plci[i-1];
rplci->appl = appl;
rplci->cr_enquiry=TRUE;
add_p(rplci,CAI,"\x01\x80");
add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
sig_req(rplci,ASSIGN,DSIG_ID);
send_req(rplci);
}
else
{
Info = _OUT_OF_PLCI;
break;
}
}
else
{
rplci = plci;
rplci->cr_enquiry=FALSE;
}
rplci->command = 0;
rplci->internal_command = MWI_ACTIVATE_REQ_PEND;
rplci->appl = appl;
rplci->number = Number;
cai[0] = 13;
cai[1] = ACTIVATION_MWI; /* Function */
WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
WRITE_DWORD(&cai[4],READ_DWORD(&(ss_parms[3].info[0]))); /* Number of Messages */
WRITE_WORD(&cai[8],READ_WORD(&(ss_parms[4].info[0]))); /* Message Status */
WRITE_WORD(&cai[10],READ_WORD(&(ss_parms[5].info[0]))); /* Message Reference */
WRITE_WORD(&cai[12],READ_WORD(&(ss_parms[6].info[0]))); /* Invocation Mode */
add_p(rplci,CAI,cai);
add_p(rplci,CPN,ss_parms[7].info); /* Receiving User Number */
add_p(rplci,OAD,ss_parms[8].info); /* Controlling User Number */
add_p(rplci,OSA,ss_parms[9].info); /* Controlling User Provided Number */
add_p(rplci,UID,ss_parms[10].info); /* Time */
sig_req(rplci,S_SERVICE,0);
send_req(rplci);
return FALSE;
case S_MWI_DEACTIVATE:
if(api_parse(&parms->info[1],(word)parms->length,"wbwwss",ss_parms))
{
dbug(1,dprintf("format wrong"));
Info = _WRONG_MESSAGE_FORMAT;
break;
}
if(!plci)
{
if((i=get_plci(a)))
{
rplci = &a->plci[i-1];
rplci->appl = appl;
rplci->cr_enquiry=TRUE;
add_p(rplci,CAI,"\x01\x80");
add_p(rplci,UID,"\x06\x43\x61\x70\x69\x32\x30");
sig_req(rplci,ASSIGN,DSIG_ID);
send_req(rplci);
}
else
{
Info = _OUT_OF_PLCI;
break;
}
}
else
{
rplci = plci;
rplci->cr_enquiry=FALSE;
}
rplci->command = 0;
rplci->internal_command = MWI_DEACTIVATE_REQ_PEND;
rplci->appl = appl;
rplci->number = Number;
cai[0] = 5;
cai[1] = DEACTIVATION_MWI; /* Function */
WRITE_WORD(&cai[2],READ_WORD(&(ss_parms[2].info[0]))); /* Basic Service */
WRITE_WORD(&cai[4],READ_WORD(&(ss_parms[3].info[0]))); /* Invocation Mode */
add_p(rplci,CAI,cai);
add_p(rplci,CPN,ss_parms[4].info); /* Receiving User Number */
add_p(rplci,OAD,ss_parms[5].info); /* Controlling User Number */
sig_req(rplci,S_SERVICE,0);
send_req(rplci);
return FALSE;
default:
Info = 0x300E; /* not supported */
break;
}
break; /* case SELECTOR_SU_SERV: end */
case SELECTOR_DTMF:
return (dtmf_request (Id, Number, a, plci, appl, msg));
case SELECTOR_LINE_INTERCONNECT:
return (mixer_request (Id, Number, a, plci, appl, msg));
case PRIV_SELECTOR_ECHO_CANCELLER:
appl->appl_flags |= APPL_FLAG_PRIV_EC_SPEC;
return (ec_request (Id, Number, a, plci, appl, msg));
case SELECTOR_ECHO_CANCELLER:
appl->appl_flags &= ~APPL_FLAG_PRIV_EC_SPEC;
return (ec_request (Id, Number, a, plci, appl, msg));
case SELECTOR_V42BIS:
default:
Info = _FACILITY_NOT_SUPPORTED;
break;
} /* end of switch(selector) */
}
dbug(1,dprintf("SendFacRc"));
sendf(appl,
_FACILITY_R|CONFIRM,
Id,
Number,
"wws",Info,selector,SSparms);
return FALSE;
}
Generated by GNU enscript 1.6.4.