850 lines
25 KiB
C
850 lines
25 KiB
C
/*--------------------------------------------------------------------------*\
|
|
|
|
MAIN.C 1995 AVM
|
|
|
|
This demo program shows how to use the CAPI 2.0 Development Kit.
|
|
When the program is started, it prompts for a number which will be
|
|
called from the CONNECT routine. After that there is the main loop where
|
|
the program handles CAPI and keystrokes.
|
|
Following is a list of available keys:
|
|
'l' Listen (CIP mask = 0x1FFF03FF) every service will be indicated
|
|
'L' Listen (CIP mask = 0x00000000) no incoming call will be indicated
|
|
Listen is sent to all available controllers
|
|
'c' Connect to specified number on slot 0
|
|
'C' Connect to specified number on slot 1
|
|
'd' Disconnect slot 0
|
|
'D' Disconnect slot 1
|
|
's' Send datablock with size "SendBlockSize" on slot 0
|
|
'S' Send datablock with size "SendBlockSize" on slot 1
|
|
'f' Transfer a file on slot 0
|
|
'F' Transfer a file on slot 1
|
|
'v' Receive a file on slot 0
|
|
'V' Receive a file on slot 1
|
|
'a' Accept incoming call on slot 0
|
|
'A' Accept incoming call on slot 1
|
|
'i' Ignore incoming call on slot 0
|
|
'I' Ignore incoming call on slot 1
|
|
'r' Reject incoming call on slot 0
|
|
'R' Reject incoming call on slot 1
|
|
|
|
Next is an example how to connect the local 2 B-channels:
|
|
!! This will cost the same as one telephone call !!
|
|
After the start press 'l' so that every incoming call will be indicated.
|
|
Press 'c' and the program asks for a number to call, then dials the number.
|
|
There should be an incoming call indication on slot 1. Press 'A' and the
|
|
program answers the call on the second slot. Now everytime you send data
|
|
with 's' or 'S' there must be an data indication on the opposite slot.
|
|
Disconnect the slot with 'd' or 'D'
|
|
|
|
\*--------------------------------------------------------------------------*/
|
|
#if !defined (NDEBUG)
|
|
#define DEBUG
|
|
#define CPROT
|
|
#endif
|
|
|
|
#include "os.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <signal.h>
|
|
#include <assert.h>
|
|
|
|
#include "capi20.h"
|
|
#include "c20msg.h"
|
|
#include "capi.h"
|
|
#include "connect.h"
|
|
#include "contr.h"
|
|
#include "data.h"
|
|
#include "id.h"
|
|
#include "init.h"
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
\*--------------------------------------------------------------------------*/
|
|
static char testblock[2048];
|
|
|
|
/*----- note: you may enter your own number here, but if you -----*/
|
|
/*----- supply a wrong number, some PBXs may reject the -----*/
|
|
/*----- CAPI messages containing the wrong number -----*/
|
|
/*----- e.g.: static char *CallingPartyNumber = "1234567"; -----*/
|
|
static char *CallingPartyNumber = NULL;
|
|
|
|
static char CalledPartyNumberArr[40];
|
|
|
|
#ifdef DEBUG
|
|
static char CAPI_PROT_BUF[CAPI_PROTOCOL_INIT_BUF_SIZE];
|
|
static char ProtocolFileName[80];
|
|
static FILE *ProtocolFile;
|
|
#endif
|
|
|
|
#define INVALID_SLOT -1
|
|
#define maxSlots 2 /*----- this demo program handles max. -----*/
|
|
/*----- two connections -----*/
|
|
static ConnectionID Slot[maxSlots];
|
|
|
|
|
|
#define B1PROTOCOL 0
|
|
#define B2PROTOCOL 0
|
|
#define B3PROTOCOL 0
|
|
#define B3CONFIGURATION NULL
|
|
|
|
|
|
#define QueueSize 8
|
|
|
|
typedef struct __DataElement {
|
|
char DATA[SendBlockSize];
|
|
unsigned short DATA_LENGTH;
|
|
unsigned SENT;
|
|
} _DataElement;
|
|
|
|
typedef struct __DataQueue {
|
|
_DataElement Element[QueueSize];
|
|
unsigned Head;
|
|
unsigned Tail;
|
|
unsigned Fill;
|
|
} _DataQueue;
|
|
|
|
_DataQueue Queue;
|
|
|
|
static unsigned FileTransfer = FALSE; /*----- signals if filetransfer is in progress -----*/
|
|
static unsigned FileReceive = FALSE; /*----- signals if filetransfer is in progress -----*/
|
|
static FILE *File;
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* Press_Key:
|
|
\*--------------------------------------------------------------------------*/
|
|
int Press_Key(void) {
|
|
int c;
|
|
|
|
if ((c = getch()) == 0)
|
|
c = getch()+256;
|
|
return c;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* GetSlot: returns the slotnumber of the ConnectionID or INVALID_SLOT
|
|
\*--------------------------------------------------------------------------*/
|
|
int GetSlot(ConnectionID Con) {
|
|
int x;
|
|
|
|
for (x=0; x<maxSlots; x++)
|
|
if (Slot[x] == Con) return x;
|
|
return INVALID_SLOT;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* AllocSlot: allocates one slot, if none free returns INVALID_SLOT
|
|
\*--------------------------------------------------------------------------*/
|
|
int AllocSlot(ConnectionID Con) {
|
|
int x;
|
|
|
|
for (x=0; x<maxSlots; x++)
|
|
if (Slot[x] == INVALID_CONNECTION_ID) {
|
|
Slot[x] = Con;
|
|
return x;
|
|
}
|
|
return INVALID_SLOT;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* FreeSlot: clear one slot
|
|
\*--------------------------------------------------------------------------*/
|
|
void FreeSlot(int index) {
|
|
Slot[index] = INVALID_CONNECTION_ID;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* MainDataAvailable: signals received data blocks
|
|
* This function is called after a DATA_B3_INDication is received. The flag
|
|
* DiscardData tells CAPI to free the memora area directly after the return
|
|
* of this function when set to TRUE (1) which is the preset. When the flag
|
|
* is set to FALSE (0) the data area MUST be freed later with ReleaseData.
|
|
* The datahandle identifies the memory area. When reaching 7 unconfirmed
|
|
* blocks, no more incoming data will be signaled until freeing at least
|
|
* one block.
|
|
\*--------------------------------------------------------------------------*/
|
|
void MainDataAvailable(ConnectionID Connection,
|
|
void __far *Data,
|
|
unsigned short DataLength,
|
|
unsigned short DataHandle,
|
|
int *DiscardData) {
|
|
|
|
assert (Connection != INVALID_CONNECTION_ID);
|
|
|
|
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** incoming data, slot %d ID %d, size %d , handle %u *****\n",
|
|
GetSlot(Connection), Connection, DataLength, DataHandle);
|
|
# endif
|
|
|
|
if ((FileReceive) && (File != NULL)) {
|
|
fwrite(Data, 1, DataLength, File);
|
|
}
|
|
*DiscardData = TRUE;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* MainDataConf: signals the successful sending of a datablock
|
|
* This function is called after receiving a DATA_B3_CONFirmation. CAPI signals
|
|
* that the datablock identified by DataHandle has been sent and the memory
|
|
* area may be freed. The DataHandle is the same as specified in SendBlock.
|
|
\*--------------------------------------------------------------------------*/
|
|
void MainDataConf(ConnectionID Connection,
|
|
unsigned short DataHandle,
|
|
unsigned short Info) {
|
|
|
|
assert (Connection != INVALID_CONNECTION_ID);
|
|
|
|
|
|
if (Info != 0) {
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** datablock slot %d ID %d handle %d NOT sent , error: 0x%04X *****\n",
|
|
GetSlot(Connection), Connection, DataHandle, Info);
|
|
# endif
|
|
return;
|
|
}
|
|
if (FileTransfer) {
|
|
|
|
assert (DataHandle == (unsigned short)Queue.Tail);
|
|
|
|
Queue.Element[Queue.Tail].SENT = FALSE;
|
|
if (++Queue.Tail >= QueueSize) Queue.Tail = 0;
|
|
Queue.Fill--;
|
|
}
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** datablock slot %d ID %d handle %d has been sent *****\n",
|
|
GetSlot(Connection), Connection, DataHandle);
|
|
# endif
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* MainStateChange: signals a state change on both B-channels (connected,
|
|
* disconnected). Whenever a channel changes his state this function is called
|
|
\*--------------------------------------------------------------------------*/
|
|
void MainStateChange(ConnectionID Connection,
|
|
ConnectionState State) {
|
|
int index;
|
|
|
|
assert (Connection != INVALID_CONNECTION_ID);
|
|
|
|
|
|
index = GetSlot(Connection);
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** state change slot %d ID %d: %s *****\n", index, Connection,
|
|
ConnectionStateString[State]);
|
|
# endif
|
|
if (State == Disconnected) {
|
|
FreeSlot(index);
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* MainIncomingCall: signals an incoming call
|
|
* This function will be executed if a CONNECT_INDication appears to
|
|
* inform the user.
|
|
\*--------------------------------------------------------------------------*/
|
|
void MainIncomingCall(ConnectionID Connection,
|
|
char *CallingPartyNumber) {
|
|
int index;
|
|
|
|
assert (Connection != INVALID_CONNECTION_ID);
|
|
|
|
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** incoming call ,ID %d, caller: \"%s\" *****\n",Connection,CallingPartyNumber);
|
|
# endif
|
|
index = AllocSlot(Connection);
|
|
|
|
if (index == INVALID_SLOT) {
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** no free slot available, rejecting call... *****\n");
|
|
# endif
|
|
AnswerCall(Connection, REJECT,0,0,0,NULL);
|
|
return;
|
|
}
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** call assigned to slot %d *****\n", index);
|
|
# endif
|
|
}
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* CAPI_PROT_HANDLE: This is a callback-function that has been specified
|
|
* with CAPI_PROTOCOL_INIT. The first parameter is a pointer to the protocol-
|
|
* message which is plain ASCII-text. The parameter t contains the type of
|
|
* the message which can be CAPI_PROTOCOL_HEADER (appears only once when
|
|
* calling CAPI_PROTOCOL_INIT), CAPI_PROTOCOL_MSG (the text contains a
|
|
* decoded CAPI-message) and CAPI_PROTOCOL_TXT (the buffers contains a debug
|
|
* message or a message sent with the function CAPI_PROTOCOL_TEXT).
|
|
* If the type of the message is CAPI_PROTOCOL_MSG, the last parameter contains
|
|
* a pointer to the decoded CAPI-message.
|
|
\*--------------------------------------------------------------------------*/
|
|
void CAPI_PROT_HANDLE(char *Message,
|
|
CAPI_PROTOCOL_TYP t,
|
|
CAPI_MESSAGE m) {
|
|
|
|
fprintf(ProtocolFile,"%s",Message);
|
|
if (t != CAPI_PROTOCOL_MSG)
|
|
puts(Message);
|
|
|
|
if (t == CAPI_PROTOCOL_MSG) {
|
|
_cmsg CMSG;
|
|
|
|
CAPI_MESSAGE_2_CMSG(&CMSG, m);
|
|
if ((FileTransfer || FileReceive) &&
|
|
(CMSG.Command == CAPI_DATA_B3) && (CMSG.Info == 0) &&
|
|
(CMSG.Reason == 0) && (CMSG.Reason_B3 == 0)) {
|
|
|
|
return;
|
|
}
|
|
puts(Message);
|
|
if (CMSG.Info != 0) {
|
|
printf("Info 0x%04X: %s\n",CMSG.Info,Decode_Info(CMSG.Info));
|
|
fprintf(ProtocolFile,"Info 0x%04X: %s\n",CMSG.Info,Decode_Info(CMSG.Info));
|
|
}
|
|
if (CMSG.Reason != 0) {
|
|
printf("Reason 0x%04X: %s\n",CMSG.Reason,Decode_Info(CMSG.Reason));
|
|
fprintf(ProtocolFile,"Reason 0x%04X: %s\n",CMSG.Reason,Decode_Info(CMSG.Reason));
|
|
}
|
|
if (CMSG.Reason_B3 != 0) {
|
|
printf("Reason_B3 0x%04X: %s\n",CMSG.Reason_B3,Decode_Info(CMSG.Reason_B3));
|
|
fprintf(ProtocolFile,"Reason_B3 0x%04X: %s\n",CMSG.Reason_B3,Decode_Info(CMSG.Reason_B3));
|
|
}
|
|
}
|
|
fflush(ProtocolFile);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* Prot_Init: Initialisation of the protocol
|
|
\*--------------------------------------------------------------------------*/
|
|
int Prot_Init(char *Filename) {
|
|
char *p;
|
|
|
|
strcpy(ProtocolFileName, Filename);
|
|
p = strrchr(ProtocolFileName, '.');
|
|
if (p) *p = '\0';
|
|
strcat(ProtocolFileName, ".prt");
|
|
|
|
if ((ProtocolFile=fopen(ProtocolFileName, "w"))==NULL) {
|
|
printf("Can't open protocol-file !!\n");
|
|
return FALSE;
|
|
}
|
|
CAPI_PROTOCOL_INIT(CAPI_PROT_BUF, CAPI_PROT_HANDLE);
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* The following _h functions are 'h'igh level functions for the ones
|
|
* implemented in CONNECT.C . The _h functions perform some parameter tests
|
|
* that would cause an assert on the low-level functions.
|
|
\*--------------------------------------------------------------------------*/
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* Connect_h: Asks for a number to call then executes 'Connect'
|
|
\*--------------------------------------------------------------------------*/
|
|
unsigned Connect_h(ConnectionID *Connection,
|
|
char *CallingPartyNumber,
|
|
unsigned long Service,
|
|
unsigned short B1Protocol,
|
|
unsigned short B2Protocol,
|
|
unsigned short B3Protocol,
|
|
unsigned char __far *B3Configuration) {
|
|
|
|
if (*Connection != INVALID_CONNECTION_ID) {
|
|
printf("Connect_h: Connection is already in use\n");
|
|
return 0xFFFF;
|
|
}
|
|
|
|
printf("Enter Number: ");
|
|
fflush (stdout);
|
|
gets(CalledPartyNumberArr);
|
|
|
|
return Connect(Connection,
|
|
CalledPartyNumberArr,
|
|
CallingPartyNumber,
|
|
Service,
|
|
B1Protocol,
|
|
B2Protocol,
|
|
B3Protocol,
|
|
B3Configuration);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* Disconnect_h: high level Disconnect
|
|
\*--------------------------------------------------------------------------*/
|
|
unsigned Disconnect_h(ConnectionID Connection) {
|
|
|
|
int index;
|
|
ConnectionState State;
|
|
|
|
if (Connection == INVALID_CONNECTION_ID) {
|
|
printf("Disconnect_h: ConnectionID is invalid\n");
|
|
return 0xFFFF;
|
|
}
|
|
State = GetState(Connection);
|
|
if ((State == Disconnected) || (State == D_DisconnectPending)) {
|
|
index = GetSlot(Connection);
|
|
printf("Disconnect_h: slot %d ID %d is disconnected\n",index, Connection);
|
|
return 0xFFFF;
|
|
}
|
|
return Disconnect(Connection);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* SendData_h: high level SendData
|
|
\*--------------------------------------------------------------------------*/
|
|
unsigned SendData_h(ConnectionID Connection,
|
|
void __far *Data,
|
|
unsigned short DataLength,
|
|
unsigned short DataHandle) {
|
|
|
|
int index;
|
|
ConnectionState State;
|
|
|
|
if (Connection == INVALID_CONNECTION_ID) {
|
|
printf("SendData_h: ConnectionID is invalid\n");
|
|
return 0xFFFF;
|
|
}
|
|
State = GetState(Connection);
|
|
if (State != Connected) {
|
|
index = GetSlot(Connection);
|
|
printf("SendData_h: slot %d ID %d is not connected\n",index, Connection);
|
|
return 0xFFFF;
|
|
}
|
|
return SendData(Connection, Data, DataLength, DataHandle);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* AnswerCall_h: high level AnswerCall
|
|
\*--------------------------------------------------------------------------*/
|
|
unsigned AnswerCall_h(ConnectionID Connection,
|
|
RejectValue Reject,
|
|
unsigned short B1Protocol,
|
|
unsigned short B2Protocol,
|
|
unsigned short B3Protocol,
|
|
unsigned char __far *B3Configuration) {
|
|
|
|
int index;
|
|
ConnectionState State;
|
|
|
|
if (Connection == INVALID_CONNECTION_ID) {
|
|
printf("AnswerCall_h: ConnectionID is invalid\n");
|
|
return 0xFFFF;
|
|
}
|
|
State = GetState(Connection);
|
|
if (State != D_ConnectPending) {
|
|
index = GetSlot(Connection);
|
|
printf("AnswerCall_h: slot %d ID %d is the wrong state for answering\n",index, Connection);
|
|
return 0xFFFF;
|
|
}
|
|
return AnswerCall(Connection,
|
|
Reject,
|
|
B1Protocol,
|
|
B2Protocol,
|
|
B3Protocol,
|
|
B3Configuration);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* InitQueue: resets the data queue
|
|
\*--------------------------------------------------------------------------*/
|
|
void InitQueue(void) {
|
|
unsigned x;
|
|
|
|
for (x=0; x<QueueSize; x++) {
|
|
Queue.Element[x].SENT = FALSE;
|
|
}
|
|
Queue.Head = 0;
|
|
Queue.Tail = 0;
|
|
Queue.Fill = 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* TransferData: sends datablocks from the queue to CAPI until a) all Blocks
|
|
* from the queue are sent or b) an error occurs. This functions trys to send
|
|
* the maximum of 7 unconfirmed datablocks to CAPI for maximum throughput.
|
|
\*--------------------------------------------------------------------------*/
|
|
void TransferData(int index) {
|
|
MESSAGE_EXCHANGE_ERROR error;
|
|
unsigned t;
|
|
|
|
if (Queue.Fill > 0) {
|
|
t = Queue.Tail;
|
|
do {
|
|
if (Queue.Element[t].SENT == FALSE) {
|
|
error = SendData(index,
|
|
(void __far *)Queue.Element[t].DATA,
|
|
Queue.Element[t].DATA_LENGTH,
|
|
(unsigned short)t);
|
|
|
|
if (error != 0) {
|
|
printf("Error transfering data: 0x%04X !!!",error);
|
|
break;
|
|
}
|
|
Queue.Element[t].SENT = TRUE;
|
|
}
|
|
if (++t >= QueueSize) t = 0;
|
|
} while (t != Queue.Head);
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* SendFile: Sends a file
|
|
\*--------------------------------------------------------------------------*/
|
|
unsigned SendFile(int index) {
|
|
|
|
char Filename[80];
|
|
unsigned count;
|
|
|
|
if (Slot[index] == INVALID_CONNECTION_ID) {
|
|
printf("SendFile: ConnectionID is invalid\n");
|
|
return 1;
|
|
}
|
|
if (GetState(Slot[index]) != Connected) {
|
|
printf("SendFile: slot %d ID %d is not connected\n",index, Slot[index]);
|
|
return 2;
|
|
}
|
|
printf("Enter Filename: ");
|
|
fflush (stdout);
|
|
gets(Filename);
|
|
|
|
File = fopen(Filename, "rb");
|
|
if (! File) {
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** file not found *****\n");
|
|
# endif
|
|
return 3;
|
|
}
|
|
InitQueue();
|
|
|
|
FileTransfer = TRUE;
|
|
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** Starting datatransfer on slot %d, press any key to stop *****\n",index);
|
|
CAPI_PROTOCOL_TEXT("***** there is no protocol output to the screen during transfer *****\n\n");
|
|
# endif
|
|
do {
|
|
|
|
if ((! feof(File)) && (Queue.Fill < 7)) { /*----- max. 7 outstanding blocks supported by CAPI -----*/
|
|
count = fread(&(Queue.Element[Queue.Head].DATA[0]), 1, SendBlockSize, File);
|
|
if (count > 0) {
|
|
Queue.Element[Queue.Head].DATA_LENGTH = (unsigned short)count;
|
|
if (++Queue.Head >= QueueSize) Queue.Head = 0;
|
|
Queue.Fill++;
|
|
}
|
|
}
|
|
if (GetState(Slot[index]) != Connected) {
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** connection broken *****\n");
|
|
# endif
|
|
break;
|
|
}
|
|
if (kbhit()) {
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** interrupted by user *****\n");
|
|
# endif
|
|
break;
|
|
}
|
|
TransferData(index);
|
|
Handle_CAPI_Msg();
|
|
} while (Queue.Fill > 0);
|
|
|
|
FileTransfer = FALSE;
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** End of filetransfer *****\n");
|
|
# endif
|
|
fclose(File);
|
|
return 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* ReceiveFile: Receives a file and writes it to disk
|
|
\*--------------------------------------------------------------------------*/
|
|
unsigned ReceiveFile(int index) {
|
|
|
|
char Filename[80];
|
|
|
|
if (Slot[index] == INVALID_CONNECTION_ID) {
|
|
printf("ReceiveFile: ConnectionID is invalid\n");
|
|
return 1;
|
|
}
|
|
if (GetState(Slot[index]) != Connected) {
|
|
printf("ReceiveFile: slot %d ID %d is not connected\n",index, Slot[index]);
|
|
return 2;
|
|
}
|
|
printf("Enter Filename where incoming data shall be saved: ");
|
|
fflush (stdout);
|
|
gets(Filename);
|
|
|
|
File = fopen(Filename, "wb");
|
|
if (! File) {
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** could not open file *****\n");
|
|
# endif
|
|
return 3;
|
|
}
|
|
InitQueue();
|
|
|
|
FileReceive = TRUE;
|
|
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** Waiting for data on slot %d, press any key to stop *****\n",index);
|
|
CAPI_PROTOCOL_TEXT("***** there is no protocol output to the screen during transfer *****\n");
|
|
# endif
|
|
do {
|
|
if (GetState(Slot[index]) != Connected) {
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** connection broken *****\n");
|
|
# endif
|
|
break;
|
|
}
|
|
Handle_CAPI_Msg();
|
|
} while (! kbhit());
|
|
|
|
getch();
|
|
FileReceive = FALSE;
|
|
# ifdef DEBUG
|
|
CAPI_PROTOCOL_TEXT("***** End of filetransfer *****\n");
|
|
# endif
|
|
fclose(File);
|
|
return 0;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*\
|
|
* PrintHelp: tell the user the options
|
|
\*---------------------------------------------------------------------------*/
|
|
static void PrintHelp (void) {
|
|
|
|
puts("\n\n");
|
|
puts("'ESC' Exit program");
|
|
puts("'l' Listen (CIP mask = 0x1FFF03FF) every service will be indicated");
|
|
puts("'L' Listen (CIP mask = 0x00000000) no incoming call will be indicated");
|
|
puts("'c'+'C' Connect, the specified number will be called");
|
|
puts("'d' Disconnect slot 0");
|
|
puts("'D' Disconnect slot 1");
|
|
puts("'s' Send datablock with size \"SendBlockSize\" on slot 0");
|
|
puts("'S' Send datablock with size \"SendBlockSize\" on slot 1");
|
|
puts("'f' Transfer a file on slot 0");
|
|
puts("'F' Transfer a file on slot 1");
|
|
puts("'v' Receive a file on slot 0");
|
|
puts("'V' Receive a file on slot 1");
|
|
puts("'a' Accept incoming call on slot 0");
|
|
puts("'A' Accept incoming call on slot 1");
|
|
puts("'i' Ignore incoming call on slot 0");
|
|
puts("'I' Ignore incoming call on slot 1");
|
|
puts("'r' Reject incoming call on slot 0");
|
|
puts("'R' Reject incoming call on slot 1");
|
|
puts("'?' Print this help screen");
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* HandleKeyStroke: Checks the keyboard
|
|
\*--------------------------------------------------------------------------*/
|
|
int HandleKeyStroke(void) {
|
|
int i;
|
|
|
|
#if defined (TARGET_NW)
|
|
delay(50); // the netware NLM has to be cooperative
|
|
#endif
|
|
if (kbhit()) {
|
|
i = Press_Key();
|
|
switch (i) {
|
|
case 'q':
|
|
case 27: { /*----- ESCAPE -----*/
|
|
printf("Exit program ? y/n ");
|
|
fflush (stdout);
|
|
i = Press_Key();
|
|
if ((i == 'y') || (i =='Y')) {
|
|
puts("Y");
|
|
return FALSE;
|
|
}
|
|
puts("N");
|
|
return TRUE;
|
|
}
|
|
case 'l':
|
|
Listen(ALL_SERVICES);
|
|
break;
|
|
case 'L':
|
|
Listen(NO_SERVICES);
|
|
break;
|
|
case 'c':
|
|
Connect_h(&Slot[0],
|
|
CallingPartyNumber,
|
|
DATA_TRANSFER,
|
|
B1PROTOCOL,
|
|
B2PROTOCOL,
|
|
B3PROTOCOL,
|
|
B3CONFIGURATION);
|
|
break;
|
|
case 'C':
|
|
Connect_h(&Slot[1],
|
|
CallingPartyNumber,
|
|
DATA_TRANSFER,
|
|
B1PROTOCOL,
|
|
B2PROTOCOL,
|
|
B3PROTOCOL,
|
|
B3CONFIGURATION);
|
|
break;
|
|
case 'd':
|
|
Disconnect_h(Slot[0]);
|
|
break;
|
|
case 'D':
|
|
Disconnect_h(Slot[1]);
|
|
break;
|
|
case 's':
|
|
SendData_h(Slot[0], (void __far *)&testblock, SendBlockSize, 1);
|
|
break;
|
|
case 'S':
|
|
SendData_h(Slot[1], (void __far *)&testblock, SendBlockSize, 1);
|
|
break;
|
|
case 'f':
|
|
SendFile(Slot[0]);
|
|
break;
|
|
case 'F':
|
|
SendFile(Slot[1]);
|
|
break;
|
|
case 'v':
|
|
ReceiveFile(Slot[0]);
|
|
break;
|
|
case 'V':
|
|
ReceiveFile(Slot[1]);
|
|
break;
|
|
case 'a':
|
|
AnswerCall_h(Slot[0],ACCEPT,B1PROTOCOL,B2PROTOCOL,B3PROTOCOL,NULL);
|
|
break;
|
|
case 'A':
|
|
AnswerCall_h(Slot[1],ACCEPT,B1PROTOCOL,B2PROTOCOL,B3PROTOCOL,NULL);
|
|
break;
|
|
case 'i':
|
|
AnswerCall_h(Slot[0],IGNORE,0,0,0,NULL);
|
|
break;
|
|
case 'I':
|
|
AnswerCall_h(Slot[1],IGNORE,0,0,0,NULL);
|
|
break;
|
|
case 'r':
|
|
AnswerCall_h(Slot[0],REJECT,0,0,0,NULL);
|
|
break;
|
|
case 'R':
|
|
AnswerCall_h(Slot[1],REJECT,0,0,0,NULL);
|
|
break;
|
|
case 'h':
|
|
case '?':
|
|
PrintHelp();
|
|
break;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* Interact: main loop, checks keystrokes and CAPI-messages
|
|
\*--------------------------------------------------------------------------*/
|
|
void Interact(void) {
|
|
int numController;
|
|
int BChannels, Contr;
|
|
|
|
|
|
numController = GetNumController ();
|
|
BChannels = 0;
|
|
for (Contr=1; Contr<=numController; Contr++)
|
|
BChannels += GetNumOfSupportedBChannels(Contr);
|
|
|
|
printf("Detected %i controllers with %i B-channels overall.\n",
|
|
numController, BChannels);
|
|
PrintHelp ();
|
|
|
|
do {
|
|
Handle_CAPI_Msg();
|
|
} while (HandleKeyStroke());
|
|
|
|
puts("\nProgram terminated\n");
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* Hangup: Disconnect both channels
|
|
\*--------------------------------------------------------------------------*/
|
|
void Hangup(void) {
|
|
int i;
|
|
|
|
|
|
if ((Slot[0] != INVALID_CONNECTION_ID) &&
|
|
(GetState(Slot[0]) != Disconnected) &&
|
|
(GetState(Slot[0]) != D_DisconnectPending))
|
|
Disconnect(Slot[0]);
|
|
|
|
if ((Slot[1] != INVALID_CONNECTION_ID) &&
|
|
(GetState(Slot[1]) != Disconnected) &&
|
|
(GetState(Slot[1]) != D_DisconnectPending))
|
|
Disconnect(Slot[1]);
|
|
|
|
do {
|
|
Handle_CAPI_Msg();
|
|
if (kbhit()) {
|
|
while (kbhit()) {
|
|
getch();
|
|
}
|
|
printf("Exit program ? y/n ");
|
|
fflush (stdout);
|
|
i = Press_Key();
|
|
if ((i == 'y') || (i =='Y')) {
|
|
puts("Y");
|
|
return;
|
|
}
|
|
puts("N");
|
|
}
|
|
}
|
|
while ((Slot[0] != INVALID_CONNECTION_ID) || (Slot[1] != INVALID_CONNECTION_ID));
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* ctrlchandler: exits on CTRL-C and CTRL-BREAK
|
|
\*--------------------------------------------------------------------------*/
|
|
void ctrlchandler(int sig)
|
|
{
|
|
signal( SIGINT, ctrlchandler );
|
|
exit(0);
|
|
sig = 0; /*----- suppress warning -----*/
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*\
|
|
* main: Init & exit functions
|
|
\*--------------------------------------------------------------------------*/
|
|
#ifdef DEBUG
|
|
int main(int ac, char *av[]) {
|
|
#else
|
|
int main(void) {
|
|
#endif
|
|
|
|
Slot[0] = INVALID_CONNECTION_ID;
|
|
Slot[1] = INVALID_CONNECTION_ID;
|
|
|
|
if (! RegisterCAPI ()) return 1;
|
|
atexit (ReleaseCAPI);
|
|
|
|
signal(SIGINT, ctrlchandler);
|
|
|
|
InitConnectionIDHandling ();
|
|
|
|
|
|
#ifdef DEBUG
|
|
if (! Prot_Init(av[ac-1])) return 2;
|
|
#endif
|
|
|
|
#ifdef __linux__
|
|
init_tty();
|
|
atexit (restore_tty);
|
|
#endif
|
|
|
|
Interact();
|
|
|
|
Hangup();
|
|
|
|
#ifdef DEBUG
|
|
fclose(ProtocolFile);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|