301 lines
9.7 KiB
C
301 lines
9.7 KiB
C
/*--------------------------------------------------------------------------*\
|
|
|
|
CAPI.C Version 1.1 1995 AVM
|
|
|
|
Implementation of CAPI state machine
|
|
|
|
\*--------------------------------------------------------------------------*/
|
|
#include <stdio.h>
|
|
|
|
#include "capi20.h"
|
|
#include "connect.h"
|
|
#include "data.h"
|
|
#include "init.h"
|
|
#include "capi.h"
|
|
#include "id.h"
|
|
|
|
#define BC NULL
|
|
#define LLC NULL
|
|
#define HLC NULL
|
|
#define B1Protokoll 1
|
|
#define B2Protokoll 1
|
|
#define B3Protokoll 0
|
|
#define B1Configuration NULL
|
|
#define B2Configuration NULL
|
|
#define B3Configuration NULL
|
|
#define Flags 0
|
|
#define NCPI (_cstruct)NULL
|
|
|
|
static _cmsg CMESSAGE;
|
|
static _cmsg __far *CMSG = &CMESSAGE; /*----- used in all requests and responses -----*/
|
|
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* SetState: Set the state internal and informs the user
|
|
\*--------------------------------------------------------------------------*/
|
|
static void ChangeState (ConnectionID Con,
|
|
ConnectionState State) {
|
|
|
|
SetState (Con, State);
|
|
/*----- signal the status change to the user -----*/
|
|
StateChange (Con, State);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* Handle_Indication: CAPI logic for all indications
|
|
\*--------------------------------------------------------------------------*/
|
|
void Handle_Indication(void) {
|
|
ConnectionID Connection;
|
|
|
|
switch (CMSG->Command) {
|
|
|
|
case CAPI_CONNECT:
|
|
Connection = GetConnectionByPLCI (CONNECT_IND_PLCI(CMSG));
|
|
if (Connection == INVALID_CONNECTION_ID) {
|
|
|
|
/*----- incoming call -----*/
|
|
Connection = AllocConnection();
|
|
if (Connection == INVALID_CONNECTION_ID) {
|
|
|
|
/*----- error no internal resources -----*/
|
|
/*----- reject call -----*/
|
|
CONNECT_RESP(CMSG, Appl_Id, CMSG->Messagenumber, CONNECT_IND_PLCI(CMSG), REJECT,
|
|
0, 0, 0, NULL, NULL, NULL,
|
|
NULL, NULL, NULL,
|
|
NULL, NULL, NULL, NULL);
|
|
return;
|
|
}
|
|
SetConnectionPLCI(Connection, CONNECT_IND_PLCI(CMSG));
|
|
}
|
|
|
|
SetCallingPartyNumberStruct (Connection, CONNECT_IND_CALLINGPARTYNUMBER(CMSG));
|
|
|
|
/*----- The ALERT_REQuest tells the caller that someone is listening -----*/
|
|
/*----- for incoming calls on the line. A new timeout of 2 minutes is set -----*/
|
|
/*----- Without the ALERT_REQuest a disconnect would be sent after -----*/
|
|
/*----- 4 seconds with the cause "no user responding" on the caller side -----*/
|
|
/*----- (Assumed that no CONNECT_RESPonse is sent in this time) -----*/
|
|
/*----- If the application -----*/
|
|
ALERT_REQ (CMSG, Appl_Id, 0, CONNECT_IND_PLCI(CMSG),
|
|
NULL, NULL, NULL, NULL);
|
|
|
|
/*----- inform the user application -----*/
|
|
SetState(Connection, D_ConnectPending);
|
|
IncomingCall(Connection, GetCallingPartyNumber (Connection));
|
|
|
|
ChangeState(Connection, D_ConnectPending);
|
|
/*----- signal incoming call to the user -----*/
|
|
return;
|
|
|
|
case CAPI_CONNECT_ACTIVE:
|
|
Connection = GetConnectionByPLCI (CONNECT_ACTIVE_IND_PLCI(CMSG));
|
|
CONNECT_ACTIVE_RESP(CMSG, Appl_Id, CMSG->Messagenumber, CONNECT_ACTIVE_IND_PLCI(CMSG));
|
|
ChangeState(Connection, D_Connected);
|
|
if (GetConnectionInitiator (Connection)) {
|
|
CONNECT_B3_REQ(CMSG, Appl_Id, 0, CONNECT_ACTIVE_IND_PLCI(CMSG), NCPI);
|
|
}
|
|
return;
|
|
|
|
case CAPI_CONNECT_B3:
|
|
Connection = GetConnectionByPLCI (CONNECT_B3_IND_NCCI(CMSG) & 0x0000FFFF);
|
|
SetConnectionNCCI (Connection, CONNECT_B3_IND_NCCI(CMSG));
|
|
CONNECT_B3_RESP(CMSG, Appl_Id, CMSG->Messagenumber, CONNECT_B3_IND_NCCI(CMSG), 0, NCPI);
|
|
ChangeState(Connection, B_ConnectPending);
|
|
return;
|
|
|
|
case CAPI_CONNECT_B3_ACTIVE:
|
|
Connection = GetConnectionByNCCI (CONNECT_B3_ACTIVE_IND_NCCI(CMSG));
|
|
SetConnectionInitiator (Connection, FALSE);
|
|
CONNECT_B3_ACTIVE_RESP(CMSG, Appl_Id, CMSG->Messagenumber, CONNECT_B3_ACTIVE_IND_NCCI(CMSG));
|
|
ChangeState(Connection, Connected);
|
|
return;
|
|
|
|
case CAPI_DISCONNECT_B3:
|
|
Connection = GetConnectionByNCCI(DISCONNECT_B3_IND_NCCI(CMSG));
|
|
SetConnectionNCCI (Connection, INVAL_NCCI);
|
|
DISCONNECT_B3_RESP(CMSG, Appl_Id, CMSG->Messagenumber, DISCONNECT_B3_IND_NCCI(CMSG));
|
|
ChangeState(Connection, D_Connected);
|
|
if (GetConnectionInitiator(Connection)) {
|
|
DISCONNECT_REQ(CMSG, Appl_Id, 0, GetConnectionPLCI(Connection), NULL, NULL, NULL, NULL);
|
|
}
|
|
return;
|
|
|
|
case CAPI_DISCONNECT:
|
|
DISCONNECT_RESP(CMSG, Appl_Id, CMSG->Messagenumber, DISCONNECT_IND_PLCI(CMSG));
|
|
Connection = GetConnectionByPLCI(DISCONNECT_IND_PLCI(CMSG));
|
|
if (Connection != INVALID_CONNECTION_ID) {
|
|
ChangeState(Connection, Disconnected);
|
|
FreeConnection(Connection);
|
|
}
|
|
return;
|
|
|
|
case CAPI_DATA_B3:
|
|
Connection = GetConnectionByNCCI(DATA_B3_IND_NCCI(CMSG));
|
|
if (CMSG->DataLength > 0) {
|
|
int DiscardData = TRUE;
|
|
|
|
DataAvailable(Connection,
|
|
(void __far *)DATA_B3_IND_DATA(CMSG),
|
|
DATA_B3_IND_DATALENGTH(CMSG),
|
|
DATA_B3_IND_DATAHANDLE(CMSG),
|
|
&DiscardData);
|
|
|
|
if (DiscardData)
|
|
/*----- let CAPI free the data area immediately -----*/
|
|
DATA_B3_RESP(CMSG, Appl_Id, CMSG->Messagenumber, DATA_B3_IND_NCCI(CMSG), DATA_B3_IND_DATAHANDLE(CMSG));
|
|
}
|
|
return;
|
|
|
|
case CAPI_INFO:
|
|
INFO_RESP(CMSG, Appl_Id, CMSG->Messagenumber, INFO_IND_PLCI(CMSG));
|
|
return;
|
|
|
|
default:
|
|
puts("Error: Indication not handled in function Handle_Indication");
|
|
return;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* Handle_Confirmation: CAPI logic for all confirmations
|
|
\*--------------------------------------------------------------------------*/
|
|
static void Handle_Confirmation(void) {
|
|
ConnectionID Connection;
|
|
|
|
if (CMSG->Info > 0x00FF) { /*----- Info's with value 0x00xx are only -----*/
|
|
/*----- warnings, the corresponding requests -----*/
|
|
/*----- have been processed -----*/
|
|
printf("Error: Info value 0x%x indicates error, function Handle_Confirmation\n", CMSG->Info);
|
|
|
|
/*----- This branch is executed if an error has occurred -----*/
|
|
|
|
switch (CMSG->Command) {
|
|
case CAPI_CONNECT:
|
|
Connection = CMSG->Messagenumber;
|
|
ChangeState (Connection, D_ConnectPending);
|
|
ChangeState (Connection, Disconnected);
|
|
FreeConnection(Connection);
|
|
break;
|
|
|
|
case CAPI_DATA_B3:
|
|
/*----- return the error value -----*/
|
|
Connection = GetConnectionByNCCI(DATA_B3_CONF_NCCI(CMSG));
|
|
DataConf(Connection, DATA_B3_CONF_DATAHANDLE(CMSG),
|
|
DATA_B3_CONF_INFO(CMSG));
|
|
break;
|
|
|
|
case CAPI_CONNECT_B3:
|
|
/*----- disconnect line -----*/
|
|
Connection = GetConnectionByPLCI(CONNECT_B3_CONF_NCCI(CMSG) & 0x0000FFFF);
|
|
if (Connection == INVALID_CONNECTION_ID)
|
|
puts("Error: invalid PLCI in CONNECT_B3_CONF in function Handle_Confirmation");
|
|
else
|
|
DISCONNECT_REQ(CMSG, Appl_Id, 0, GetConnectionPLCI(Connection), NULL, NULL, NULL, NULL);
|
|
break;
|
|
|
|
case CAPI_DISCONNECT:
|
|
Connection = GetConnectionByPLCI(DISCONNECT_CONF_PLCI(CMSG));
|
|
if (Connection == INVALID_CONNECTION_ID)
|
|
puts("Error: invalid PLCI in DISCONNECT_CONF in function Handle_Confirmation");
|
|
break;
|
|
|
|
case CAPI_DISCONNECT_B3:
|
|
Connection = GetConnectionByNCCI(DISCONNECT_B3_CONF_NCCI(CMSG));
|
|
if (Connection == INVALID_CONNECTION_ID)
|
|
puts("Error: invalid NCCI in DISCONNECT_B3_CONF in function Handle_Confirmation");
|
|
break;
|
|
case CAPI_LISTEN:
|
|
puts("Error: Info != 0 in LISTEN_CONF in function Handle_Confirmation");
|
|
break;
|
|
case CAPI_INFO:
|
|
puts("Error: Info != 0 in INFO_CONF in function Handle_Confirmation");
|
|
break;
|
|
case CAPI_ALERT:
|
|
puts("Error: Info != 0 in ALERT_CONF in function Handle_Confirmation");
|
|
break;
|
|
}
|
|
|
|
} else { /*----- no error -----*/
|
|
|
|
switch (CMSG->Command) {
|
|
case CAPI_CONNECT:
|
|
Connection = CMSG->Messagenumber;
|
|
SetConnectionPLCI(Connection, CONNECT_CONF_PLCI(CMSG));
|
|
SetConnectionInitiator(Connection, TRUE);
|
|
ChangeState(Connection, D_ConnectPending);
|
|
return;
|
|
|
|
case CAPI_CONNECT_B3:
|
|
Connection = GetConnectionByPLCI(CONNECT_B3_CONF_NCCI(CMSG) & 0x0000FFFF);
|
|
SetConnectionNCCI(Connection, CONNECT_B3_CONF_NCCI(CMSG));
|
|
ChangeState(Connection, B_ConnectPending);
|
|
return;
|
|
|
|
case CAPI_DISCONNECT:
|
|
Connection = GetConnectionByPLCI(DISCONNECT_CONF_PLCI(CMSG));
|
|
if (Connection != INVALID_CONNECTION_ID) {
|
|
ChangeState(Connection, D_DisconnectPending);
|
|
}
|
|
return;
|
|
|
|
case CAPI_DISCONNECT_B3:
|
|
Connection = GetConnectionByNCCI(DISCONNECT_B3_CONF_NCCI(CMSG));
|
|
SetConnectionInitiator(Connection, TRUE);
|
|
ChangeState(Connection, B_DisconnectPending);
|
|
return;
|
|
|
|
case CAPI_DATA_B3:
|
|
Connection = GetConnectionByNCCI(DATA_B3_CONF_NCCI(CMSG));
|
|
DataConf(Connection, DATA_B3_CONF_DATAHANDLE(CMSG),
|
|
DATA_B3_CONF_INFO(CMSG));
|
|
return;
|
|
case CAPI_LISTEN:
|
|
return;
|
|
case CAPI_INFO:
|
|
return;
|
|
case CAPI_ALERT:
|
|
return;
|
|
default:
|
|
puts("Error: Confirmation not handled in function Handle_Confirmation");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* Handle_CAPI_Msg: the main routine, checks for messages and handles them
|
|
\*--------------------------------------------------------------------------*/
|
|
void Handle_CAPI_Msg(void) {
|
|
MESSAGE_EXCHANGE_ERROR Info;
|
|
int count;
|
|
|
|
count=0;
|
|
do {
|
|
switch (Info = CAPI_GET_CMSG(CMSG, Appl_Id)) {
|
|
case 0x0000: /*----- a message has been read -----*/
|
|
switch (CMSG->Subcommand) {
|
|
case CAPI_CONF:
|
|
Handle_Confirmation();
|
|
break;
|
|
|
|
case CAPI_IND:
|
|
Handle_Indication();
|
|
break;
|
|
|
|
default: /*----- neither indication nor confirmation ???? -----*/
|
|
puts("Error: Unknown subcommand in function Handle_CAPI_Msg");
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case 0x1104:
|
|
return; /*----- messagequeue is empty -----*/
|
|
|
|
default:
|
|
puts("Error: CAPI_GET_CMSG returns Info != 0 in function Handle_CAPI_Msg");
|
|
return;
|
|
}
|
|
count++;
|
|
} while (count < 6); /*----- CAPI is checked maximal 5 times before returning -----*/
|
|
}
|