/*--------------------------------------------------------------------------*\ FAXMAIN.C Version 1.1 1995 AVM 's'+'S' Send fax 'r'+'R' Receive fax \*--------------------------------------------------------------------------*/ #if !defined (NDEBUG) #define DEBUG #define CPROT #endif #include #ifndef __linux__ #include #endif #include #include #include #include #include #include "capi20.h" #include "c20msg.h" #include "capi.h" #include "connect.h" #include "contr.h" #include "data.h" #include "id.h" #include "init.h" #include "fax.h" #ifdef __linux__ #include "linuti.h" #endif /*--------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------*/ /*----- 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 4 #define B2PROTOCOL 4 #define B3PROTOCOL 4 #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; unsigned short FaxResolution = FAX_STANDARD_RESOLUTION; /*--------------------------------------------------------------------------*\ * 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= QueueSize) Queue.Tail = 0; Queue.Fill--; } CAPI_PROTOCOL_TEXT("***** datablock slot %d ID %d handle %d has been sent *****\n", GetSlot(Connection), Connection, DataHandle); } /*--------------------------------------------------------------------------*\ * 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); CAPI_PROTOCOL_TEXT("***** state change slot %d ID %d: %s *****\n", index, Connection, ConnectionStateString[State]); 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; B3_PROTO_FAXG3 B3conf; assert (Connection != INVALID_CONNECTION_ID); CAPI_PROTOCOL_TEXT("***** incoming call ,ID %d, caller: \"%s\" *****\n",Connection,CallingPartyNumber); index = AllocSlot(Connection); SetupB3Config( &B3conf, FAX_SFF_FORMAT, FaxResolution); if (index == INVALID_SLOT) { CAPI_PROTOCOL_TEXT("***** no free slot available, rejecting call... *****\n"); AnswerCall(Connection, REJECT, 4, 4, 4, (_cstruct)&B3conf); return; } CAPI_PROTOCOL_TEXT("***** call assigned to slot %d *****\n", index); AnswerCall(Connection, ACCEPT, 4, 4, 4, (_cstruct)&B3conf); } #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)); } } } /*--------------------------------------------------------------------------*\ * 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"); */ strcpy(ProtocolFileName, "/tmp/isdnsend.prot"); 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 to call: "); 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 \*--------------------------------------------------------------------------*/ void InitQueue(void) { unsigned x; for (x=0; x 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 !!!\n",error); break; } Queue.Element[t].SENT = TRUE; } if (++t >= QueueSize) t = 0; } while (t != Queue.Head); } } int GiveFreeSlot(void) { int i; for(i=0; i 0) { Queue.Element[Queue.Head].DATA_LENGTH = (unsigned short)count; if (++Queue.Head >= QueueSize) Queue.Head = 0; Queue.Fill++; } } if (GetState(Slot[SlotNr]) != Connected) { CAPI_PROTOCOL_TEXT("***** connection broken *****\n"); break; } #ifdef WITH_KBHIT if (kbhit()) { getch(); CAPI_PROTOCOL_TEXT("***** interrupted by user *****\n"); break; } #endif TransferData(SlotNr); Handle_CAPI_Msg(); } while (!feof(File)); Disconnect_h(Slot[SlotNr]); while ((Slot[SlotNr] != INVALID_CONNECTION_ID) && (GetState(Slot[SlotNr]) != Disconnected)) { Handle_CAPI_Msg(); #ifdef WITH_KBHIT if (kbhit()) { getch(); CAPI_PROTOCOL_TEXT("***** interrupted by user *****\n"); return 1; } #endif }; FileTransfer = FALSE; CAPI_PROTOCOL_TEXT("***** End of transfer *****\n"); fclose(File); return 2; } /*--------------------------------------------------------------------------*\ * ReceiveFax: Waits for incoming data and stores it to disk \*--------------------------------------------------------------------------*/ unsigned ReceiveFax(int SlotNr) { char Filename[80]; char *p; printf("The default extension for the FAX-data is .sff\n"); printf("Enter Filename where incoming data shall be saved: "); fflush (stdout); gets(Filename); p = strchr(Filename, '.'); if (p) *p = '\0'; strcat(Filename, ".sff"); File = fopen(Filename, "wb"); if (! File) { CAPI_PROTOCOL_TEXT("***** could not open file: \"%s\" *****\n",Filename); return 3; } printf("opening file: \"%s\"\n\n",Filename); InitQueue(); FileReceive = TRUE; CAPI_PROTOCOL_TEXT("***** Waiting for data , press any key to stop *****\n"); CAPI_PROTOCOL_TEXT("***** there is no protocol output to the screen during transfer *****\n"); printf("JIM, vor listen\n"); Listen(0x1FFF03FF); printf("JIM, nach listen\n"); while (GetState(Slot[SlotNr]) != Connected) { Handle_CAPI_Msg(); #ifdef WITH_KBHIT if (kbhit()) { getch(); CAPI_PROTOCOL_TEXT("***** interrupted by user *****\n"); fclose(File); FileReceive = FALSE; return 0; } #endif } printf("JIM, nach 1. while\n"); while (GetState(Slot[SlotNr]) != INVAL_STATE) { Handle_CAPI_Msg(); #ifdef WITH_KBHIT if (kbhit()) { getch(); CAPI_PROTOCOL_TEXT("***** interrupted by user *****\n"); FileReceive = FALSE; fclose(File); return 0; } #endif } FileReceive = FALSE; CAPI_PROTOCOL_TEXT("***** End of FAX-receive *****\n"); fclose(File); return 0; } void ShowChannels(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\n", numController, BChannels); */ } /*--------------------------------------------------------------------------*\ * ValidSlots: Check if connections are not completely closed yet \*--------------------------------------------------------------------------*/ int ValidSlots(void) { int i; for(i=0; i0; i--) if (string[i] == ':') break; strcpy(filename, &string[i+1]); } else if (memcmp(string, "number:", 7) == 0) strcpy(number, &string[7]); else if (memcmp(string, "resolution:", 11) == 0) { if (memcmp(&string[11], "196", 3)==0) // HIRES mode FaxResolution = FAX_HIGH_RESOLUTION; else FaxResolution = FAX_STANDARD_RESOLUTION; } } fclose(fp); } #ifdef DEBUG void CloseProtFile(void) { CAPI_PROTOCOL_TEXT("***** In exit routine *****\n"); fclose(ProtocolFile); } #endif // char number[256], faxID[256]; void HandleConfig(char *deviceID) { FILE *fp; char string[1024]; char number[256], faxID[256]; number[0] = faxID[0] = 0; sprintf(string, "etc/config.%s", deviceID); if ((fp=fopen(string, "r")) == NULL) { CAPI_PROTOCOL_TEXT("***** CAN'T OPEN filename=>%s< *****\n", string); return; } while (fgets(string, sizeof(string), fp) != NULL) { if (string[0]) string[strlen(string)-1] = 0; if (memcmp(string, "FAXNumber:", 10) == 0) { int i; CAPI_PROTOCOL_TEXT("GOT TOKEN>%s<\n", string); for (i=strlen(string)-1; i>0; i--) if ((!isdigit(string[i])) && (string[i] != '.') && (string[i] != '+')) break; strcpy(number, &string[i+1]); } else if (memcmp(string, "LocalIdentifier:", 16) == 0) { int i, j; CAPI_PROTOCOL_TEXT("GOT TOKEN>%s<\n", string); for (i=strlen(string)-1; i>0; i--) if (string[i] == '"') break; for (j=i-1; j>0; j--) if (string[j] == '"') break; if ((i-j) > 1) { memcpy(faxID, &string[j+1], i-j-1); faxID[i-j-1] = 0; } } else CAPI_PROTOCOL_TEXT("UNKNOWN TOKEN>%s<\n", string); } CAPI_PROTOCOL_TEXT("***** faxID=>%s< number=>%s< Resolution=>%d< *****\n", faxID, number, FaxResolution); SetB3Headline(faxID, number); // SetB3Headline("OSIcom NT via Linux", "+49 4261 9749 180"); /* if (faxID[0]) strcpy(headLine, faxID); if (number[0]) strcpy(stationID, number); */ fclose(fp); } /*--------------------------------------------------------------------------*\ * main: Init & exit functions \*--------------------------------------------------------------------------*/ int main(int argc, char *argv[]) { int i, ret; char filename[1024], number[256], configfile[1024], deviceID[256], job[1024]; filename[0] = number[0] = configfile[0] = deviceID[0] = job[0] = 0; if (argc == 1) { printf("fxsend -f filename -d number \n"); exit(0); } #ifdef DEBUG if (! Prot_Init(argv[argc-1])) exit(0); atexit (CloseProtFile); #endif for (i=1; i%s< number=>%s< *****\n", filename, number); if ((filename[0]==0) || (number[0]==0)) return 1; HandleConfig(deviceID); ret = SendFax(filename, number); // ret = ReceiveFax(0); Hangup(); #ifdef DEBUG CAPI_PROTOCOL_TEXT("***** Normal durchgelaufen *****\n"); // fclose(ProtocolFile); #endif exit (ret); }