extractedLnx/linux-2.6.9/drivers/isdn/hardware/eicon/message.c_control_rc.c
void control_rc(PLCI * plci, byte req, byte rc, byte ch, byte global_req, byte nl_rc)
{
dword Id;
dword rId;
word Number;
word Info=0;
word i;
word ncci;
DIVA_CAPI_ADAPTER * a;
APPL * appl;
PLCI * rplci;
byte SSparms[] = "\x05\x00\x00\x02\x00\x00";
byte SSstruct[] = "\x09\x00\x00\x06\x00\x00\x00\x00\x00\x00";
if (!plci) {
dbug(0,dprintf("A: control_rc, no plci %02x:%02x:%02x:%02x:%02x", req, rc, ch, global_req, nl_rc));
return;
}
dbug(1,dprintf("req0_in/out=%d/%d",plci->req_in,plci->req_out));
if(plci->req_in!=plci->req_out)
{
if (nl_rc || (global_req != ASSIGN) || (rc == ASSIGN_OK))
{
dbug(1,dprintf("req_1return"));
return;
}
/* cancel outstanding request on the PLCI after SIG ASSIGN failure */
}
plci->req_in = plci->req_in_start = plci->req_out = 0;
dbug(1,dprintf("control_rc"));
appl = plci->appl;
a = plci->adapter;
ncci = a->ch_ncci[ch];
if(appl)
{
Id = (((dword)(ncci ? ncci : ch)) << 16) | ((word)plci->Id << 8) | a->Id;
if(plci->tel && plci->SuppState!=CALL_HELD) Id|=EXT_CONTROLLER;
Number = plci->number;
dbug(1,dprintf("Contr_RC-Id=%08lx,plci=%x,tel=%x, entity=0x%x, command=0x%x, int_command=0x%x",Id,plci->Id,plci->tel,plci->Sig.Id,plci->command,plci->internal_command));
dbug(1,dprintf("channels=0x%x",plci->channels));
if (plci_remove_check(plci))
return;
if(req==REMOVE && rc==ASSIGN_OK)
{
sig_req(plci,HANGUP,0);
sig_req(plci,REMOVE,0);
send_req(plci);
}
if(plci->command)
{
switch(plci->command)
{
case C_HOLD_REQ:
dbug(1,dprintf("HoldRC=0x%x",rc));
SSparms[1] = (byte)S_HOLD;
if(rc!=OK)
{
plci->SuppState = IDLE;
Info = 0x2001;
}
sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
break;
case C_RETRIEVE_REQ:
dbug(1,dprintf("RetrieveRC=0x%x",rc));
SSparms[1] = (byte)S_RETRIEVE;
if(rc!=OK)
{
plci->SuppState = CALL_HELD;
Info = 0x2001;
}
sendf(appl,_FACILITY_R|CONFIRM,Id,Number,"wws",Info,3,SSparms);
break;
case _INFO_R:
dbug(1,dprintf("InfoRC=0x%x",rc));
if(rc!=OK) Info=_WRONG_STATE;
sendf(appl,_INFO_R|CONFIRM,Id,Number,"w",Info);
break;
case _CONNECT_R:
dbug(1,dprintf("Connect_R=0x%x/0x%x/0x%x/0x%x",req,rc,global_req,nl_rc));
if (plci->State == INC_DIS_PENDING)
break;
if(plci->Sig.Id!=0xff)
{
if (((global_req == ASSIGN) && (rc != ASSIGN_OK))
|| (!nl_rc && (req == CALL_REQ) && (rc != OK)))
{
dbug(1,dprintf("No more IDs/Call_Req failed"));
sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
plci_remove(plci);
plci->State = IDLE;
break;
}
if(plci->State!=LOCAL_CONNECT)plci->State = OUTG_CON_PENDING;
sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
}
else /* D-ch activation */
{
if (rc != ASSIGN_OK)
{
dbug(1,dprintf("No more IDs/X.25 Call_Req failed"));
sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
plci_remove(plci);
plci->State = IDLE;
break;
}
sendf(appl,_CONNECT_R|CONFIRM,Id,Number,"w",0);
sendf(plci->appl,_CONNECT_ACTIVE_I,Id,0,"sss","","","");
plci->State = INC_ACT_PENDING;
}
break;
case _CONNECT_I|RESPONSE:
if (plci->State != INC_DIS_PENDING)
plci->State = INC_CON_ACCEPT;
break;
case _DISCONNECT_R:
if (plci->State == INC_DIS_PENDING)
break;
if(plci->Sig.Id!=0xff)
{
plci->State = OUTG_DIS_PENDING;
sendf(appl,_DISCONNECT_R|CONFIRM,Id,Number,"w",0);
}
break;
case SUSPEND_REQ:
break;
case RESUME_REQ:
break;
case _CONNECT_B3_R:
if(rc!=OK)
{
sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",_WRONG_IDENTIFIER);
break;
}
ncci = get_ncci (plci, ch, 0);
Id = (Id & 0xffff) | (((dword) ncci) << 16);
plci->channels++;
if(req==N_RESET)
{
a->ncci_state[ncci] = INC_ACT_PENDING;
sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
sendf(appl,_CONNECT_B3_ACTIVE_I,Id,0,"s","");
}
else
{
a->ncci_state[ncci] = OUTG_CON_PENDING;
sendf(appl,_CONNECT_B3_R|CONFIRM,Id,Number,"w",0);
}
break;
case _CONNECT_B3_I|RESPONSE:
break;
case _RESET_B3_R:
/* sendf(appl,_RESET_B3_R|CONFIRM,Id,Number,"w",0);*/
break;
case _DISCONNECT_B3_R:
sendf(appl,_DISCONNECT_B3_R|CONFIRM,Id,Number,"w",0);
break;
case _MANUFACTURER_R:
break;
case PERM_LIST_REQ:
if(rc!=OK)
{
Info = _WRONG_IDENTIFIER;
sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
plci_remove(plci);
}
else
sendf(plci->appl,_CONNECT_R|CONFIRM,Id,Number,"w",Info);
break;
default:
break;
}
plci->command = 0;
}
else if (plci->internal_command)
{
switch(plci->internal_command)
{
case BLOCK_PLCI:
return;
case GET_MWI_STATE:
if(rc==OK) /* command supported, wait for indication */
{
return;
}
plci_remove(plci);
break;
/* Get Supported Services */
case GETSERV_REQ_PEND:
if(rc==OK) /* command supported, wait for indication */
{
break;
}
WRITE_DWORD(&SSstruct[6], MASK_TERMINAL_PORTABILITY);
sendf(appl, _FACILITY_R|CONFIRM, Id, Number, "wws",0,3,SSstruct);
plci_remove(plci);
break;
case INTERR_DIVERSION_REQ_PEND: /* Interrogate Parameters */
case INTERR_NUMBERS_REQ_PEND:
case CF_START_PEND: /* Call Forwarding Start pending */
case CF_STOP_PEND: /* Call Forwarding Stop pending */
case CCBS_REQUEST_REQ_PEND:
case CCBS_DEACTIVATE_REQ_PEND:
case CCBS_INTERROGATE_REQ_PEND:
switch(plci->internal_command)
{
case INTERR_DIVERSION_REQ_PEND:
SSparms[1] = S_INTERROGATE_DIVERSION;
break;
case INTERR_NUMBERS_REQ_PEND:
SSparms[1] = S_INTERROGATE_NUMBERS;
break;
case CF_START_PEND:
SSparms[1] = S_CALL_FORWARDING_START;
break;
case CF_STOP_PEND:
SSparms[1] = S_CALL_FORWARDING_STOP;
break;
case CCBS_REQUEST_REQ_PEND:
SSparms[1] = S_CCBS_REQUEST;
break;
case CCBS_DEACTIVATE_REQ_PEND:
SSparms[1] = S_CCBS_DEACTIVATE;
break;
case CCBS_INTERROGATE_REQ_PEND:
SSparms[1] = S_CCBS_INTERROGATE;
break;
}
if(global_req==ASSIGN)
{
dbug(1,dprintf("AssignDiversion_RC=0x%x/0x%x",req,rc));
return;
}
if(!plci->appl) break;
if(rc==ISDN_GUARD_REJ)
{
Info = _CAPI_GUARD_ERROR;
}
else if(rc!=OK)
{
Info = _SUPPLEMENTARY_SERVICE_NOT_SUPPORTED;
}
sendf(plci->appl,_FACILITY_R|CONFIRM,Id&0x7,
plci->number,"wws",Info,(word)3,SSparms);
if(Info) plci_remove(plci);
break;
/* 3pty conference pending */
case PTY_REQ_PEND:
if(!plci->relatedPTYPLCI) break;
rplci = plci->relatedPTYPLCI;
SSparms[1] = plci->ptyState;
rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
if(rplci->tel) rId|=EXT_CONTROLLER;
if(rc!=OK)
{
Info = 0x300E; /* not supported */
plci->relatedPTYPLCI = NULL;
plci->ptyState = 0;
}
sendf(rplci->appl,
_FACILITY_R|CONFIRM,
rId,
plci->number,
"wws",Info,(word)3,SSparms);
break;
/* Explicit Call Transfer pending */
case ECT_REQ_PEND:
dbug(1,dprintf("ECT_RC=0x%x/0x%x",req,rc));
if(!plci->relatedPTYPLCI) break;
rplci = plci->relatedPTYPLCI;
SSparms[1] = S_ECT;
rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
if(rplci->tel) rId|=EXT_CONTROLLER;
if(rc!=OK)
{
Info = 0x300E; /* not supported */
plci->relatedPTYPLCI = NULL;
plci->ptyState = 0;
}
sendf(rplci->appl,
_FACILITY_R|CONFIRM,
rId,
plci->number,
"wws",Info,(word)3,SSparms);
break;
case _MANUFACTURER_R:
dbug(1,dprintf("_Manufacturer_R=0x%x/0x%x",req,rc));
if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
{
dbug(1,dprintf("No more IDs"));
sendf(appl,_MANUFACTURER_R|CONFIRM,Id,Number,"dww",_DI_MANU_ID,_MANUFACTURER_R,_OUT_OF_PLCI);
plci_remove(plci); /* after codec init, internal codec commands pending */
}
break;
case _CONNECT_R:
dbug(1,dprintf("_Connect_R=0x%x/0x%x",req,rc));
if ((global_req == ASSIGN) && (rc != ASSIGN_OK))
{
dbug(1,dprintf("No more IDs"));
sendf(appl,_CONNECT_R|CONFIRM,Id&0xffL,Number,"w",_OUT_OF_PLCI);
plci_remove(plci); /* after codec init, internal codec commands pending */
}
break;
case PERM_COD_HOOK: /* finished with Hook_Ind */
return;
case PERM_COD_CALL:
dbug(1,dprintf("***Codec Connect_Pending A, Rc = 0x%x",rc));
plci->internal_command = PERM_COD_CONN_PEND;
return;
case PERM_COD_ASSIGN:
dbug(1,dprintf("***Codec Assign A, Rc = 0x%x",rc));
if(rc!=ASSIGN_OK) break;
sig_req(plci,CALL_REQ,0);
send_req(plci);
plci->internal_command = PERM_COD_CALL;
return;
/* Null Call Reference Request pending */
case C_NCR_FAC_REQ:
dbug(1,dprintf("NCR_FAC=0x%x/0x%x",req,rc));
if(global_req==ASSIGN)
{
if(rc==ASSIGN_OK)
{
return;
}
else
{
sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
appl->NullCREnable = FALSE;
plci_remove(plci);
}
}
else if(req==NCR_FACILITY)
{
if(rc==OK)
{
sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",0);
}
else
{
sendf(appl,_INFO_R|CONFIRM,Id&0xf,Number,"w",_WRONG_STATE);
appl->NullCREnable = FALSE;
}
plci_remove(plci);
}
break;
case HOOK_ON_REQ:
if(plci->channels)
{
if(a->ncci_state[ncci]==CONNECTED)
{
a->ncci_state[ncci] = OUTG_DIS_PENDING;
cleanup_ncci_data (plci, ncci);
nl_req_ncci(plci,N_DISC,(byte)ncci);
}
break;
}
break;
case HOOK_OFF_REQ:
if (plci->State == INC_DIS_PENDING)
break;
sig_req(plci,CALL_REQ,0);
send_req(plci);
plci->State=OUTG_CON_PENDING;
break;
case MWI_ACTIVATE_REQ_PEND:
case MWI_DEACTIVATE_REQ_PEND:
if(global_req == ASSIGN && rc==ASSIGN_OK)
{
dbug(1,dprintf("MWI_REQ assigned"));
return;
}
else if(rc!=OK)
{
if(rc==WRONG_IE)
{
Info = 0x2007; /* Illegal message parameter coding */
dbug(1,dprintf("MWI_REQ invalid parameter"));
}
else
{
Info = 0x300B; /* not supported */
dbug(1,dprintf("MWI_REQ not supported"));
}
/* 0x3010: Request not allowed in this state */
WRITE_WORD(&SSparms[4],0x300E); /* SS not supported */
}
if(plci->internal_command==MWI_ACTIVATE_REQ_PEND)
{
WRITE_WORD(&SSparms[1],S_MWI_ACTIVATE);
}
else WRITE_WORD(&SSparms[1],S_MWI_DEACTIVATE);
if(plci->cr_enquiry)
{
sendf(plci->appl,
_FACILITY_R|CONFIRM,
Id&0xf,
plci->number,
"wws",Info,(word)3,SSparms);
if(rc!=OK) plci_remove(plci);
}
else
{
sendf(plci->appl,
_FACILITY_R|CONFIRM,
Id,
plci->number,
"wws",Info,(word)3,SSparms);
}
break;
case CONF_BEGIN_REQ_PEND:
case CONF_ADD_REQ_PEND:
case CONF_SPLIT_REQ_PEND:
case CONF_DROP_REQ_PEND:
case CONF_ISOLATE_REQ_PEND:
case CONF_REATTACH_REQ_PEND:
dbug(1,dprintf("CONF_RC=0x%x/0x%x",req,rc));
if((plci->internal_command==CONF_ADD_REQ_PEND)&&(!plci->relatedPTYPLCI)) break;
rplci = plci;
rId = Id;
switch(plci->internal_command)
{
case CONF_BEGIN_REQ_PEND:
SSparms[1] = S_CONF_BEGIN;
break;
case CONF_ADD_REQ_PEND:
SSparms[1] = S_CONF_ADD;
rplci = plci->relatedPTYPLCI;
rId = ((word)rplci->Id<<8)|rplci->adapter->Id;
break;
case CONF_SPLIT_REQ_PEND:
SSparms[1] = S_CONF_SPLIT;
break;
case CONF_DROP_REQ_PEND:
SSparms[1] = S_CONF_DROP;
break;
case CONF_ISOLATE_REQ_PEND:
SSparms[1] = S_CONF_ISOLATE;
break;
case CONF_REATTACH_REQ_PEND:
SSparms[1] = S_CONF_REATTACH;
break;
}
if(rc!=OK)
{
Info = 0x300E; /* not supported */
plci->relatedPTYPLCI = NULL;
plci->ptyState = 0;
}
sendf(rplci->appl,
_FACILITY_R|CONFIRM,
rId,
plci->number,
"wws",Info,(word)3,SSparms);
break;
case VSWITCH_REQ_PEND:
if(rc!=OK)
{
if(plci->relatedPTYPLCI)
{
plci->relatedPTYPLCI->vswitchstate=0;
plci->relatedPTYPLCI->vsprot=0;
plci->relatedPTYPLCI->vsprotdialect=0;
}
plci->vswitchstate=0;
plci->vsprot=0;
plci->vsprotdialect=0;
}
else
{
if(plci->relatedPTYPLCI &&
plci->vswitchstate==1 &&
plci->relatedPTYPLCI->vswitchstate==3) /* join complete */
plci->vswitchstate=3;
}
break;
/* Call Deflection Request pending (SSCT) */
case CD_REQ_PEND:
SSparms[1] = S_CALL_DEFLECTION;
if(rc!=OK)
{
Info = 0x300E; /* not supported */
plci->appl->CDEnable = 0;
}
sendf(plci->appl,_FACILITY_R|CONFIRM,Id,
plci->number,"wws",Info,(word)3,SSparms);
break;
case RTP_CONNECT_B3_REQ_COMMAND_2:
if (rc == OK)
{
ncci = get_ncci (plci, ch, 0);
Id = (Id & 0xffff) | (((dword) ncci) << 16);
plci->channels++;
a->ncci_state[ncci] = OUTG_CON_PENDING;
}
default:
if (plci->internal_command_queue[0])
{
(*(plci->internal_command_queue[0]))(Id, plci, rc);
if (plci->internal_command)
return;
}
break;
}
next_internal_command (Id, plci);
}
}
else /* appl==0 */
{
Id = ((word)plci->Id<<8)|plci->adapter->Id;
if(plci->tel) Id|=EXT_CONTROLLER;
switch(plci->internal_command)
{
case BLOCK_PLCI:
return;
case START_L1_SIG_ASSIGN_PEND:
case REM_L1_SIG_ASSIGN_PEND:
if(global_req == ASSIGN)
{
break;
}
else
{
dbug(1,dprintf("***L1 Req rem PLCI"));
plci->internal_command = 0;
sig_req(plci,REMOVE,0);
send_req(plci);
}
break;
/* Call Deflection Request pending, just no appl ptr assigned */
case CD_REQ_PEND:
SSparms[1] = S_CALL_DEFLECTION;
if(rc!=OK)
{
Info = 0x300E; /* not supported */
}
for(i=0; i<max_appl; i++)
{
if(application[i].CDEnable)
{
if(!application[i].Id) application[i].CDEnable = 0;
else
{
sendf(&application[i],_FACILITY_R|CONFIRM,Id,
plci->number,"wws",Info,(word)3,SSparms);
if(Info) application[i].CDEnable = 0;
}
}
}
plci->internal_command = 0;
break;
case PERM_COD_HOOK: /* finished with Hook_Ind */
return;
case PERM_COD_CALL:
plci->internal_command = PERM_COD_CONN_PEND;
dbug(1,dprintf("***Codec Connect_Pending, Rc = 0x%x",rc));
return;
case PERM_COD_ASSIGN:
dbug(1,dprintf("***Codec Assign, Rc = 0x%x",rc));
plci->internal_command = 0;
if(rc!=ASSIGN_OK) break;
plci->internal_command = PERM_COD_CALL;
sig_req(plci,CALL_REQ,0);
send_req(plci);
return;
case LISTEN_SIG_ASSIGN_PEND:
if(rc == ASSIGN_OK)
{
plci->internal_command = 0;
dbug(1,dprintf("ListenCheck, new SIG_ID = 0x%x",plci->Sig.Id));
add_p(plci,ESC,"\x02\x18\x00"); /* support call waiting */
sig_req(plci,INDICATE_REQ,0);
send_req(plci);
}
else
{
dbug(1,dprintf("ListenCheck failed (assignRc=0x%x)",rc));
a->listen_active--;
plci_remove(plci);
plci->State = IDLE;
}
break;
case USELAW_REQ:
if(global_req == ASSIGN)
{
if (rc==ASSIGN_OK)
{
sig_req(plci,LAW_REQ,0);
send_req(plci);
dbug(1,dprintf("Auto-Law assigned"));
}
else
{
dbug(1,dprintf("Auto-Law assign failed"));
a->automatic_law = 3;
plci->internal_command = 0;
a->automatic_lawPLCI = NULL;
}
break;
}
else if(req == LAW_REQ && rc==OK)
{
dbug(1,dprintf("Auto-Law initiated"));
a->automatic_law = 2;
plci->internal_command = 0;
}
else
{
dbug(1,dprintf("Auto-Law not supported"));
a->automatic_law = 3;
plci->internal_command = 0;
sig_req(plci,REMOVE,0);
send_req(plci);
a->automatic_lawPLCI = NULL;
}
break;
}
plci_remove_check(plci);
}
}
Generated by GNU enscript 1.6.4.