📄 smodlib.c
字号:
//************************************************************// smodlib.cpp - source file for voice manipulation library for// USR Sportster voice modem with speakerphone.//************************************************************#include "incall.h"// Timer flagModemStatus MState;GlobInit glb;void GlobInit::PrepareAll(){ struct sigaction act, oact; openlog( "gspk", LOG_CONS, LOG_DAEMON); // Enable signal handling for the child. act.sa_handler = timeout; sigemptyset( &act.sa_mask ); act.sa_flags = 0; #ifdef SA_RESTART act.sa_flags |= SA_RESTART; #endif if (sigaction( SIGALRM, &act, &oact) < 0) { syslog(LOG_CRIT,"Cannot catch SIGALRM"); return; }};void GlobInit::CloseAll(){ closelog();}int iTimedOut = 0;void timeout(int){ iTimedOut = 1;};//***************************************************************//***************************************************************//// class PortParam////***************************************************************//***************************************************************PortParam::PortParam(char* PName){ IsSetup = 0; PortName = NULL; if (PName == NULL) return; PortName = new char[strlen(PName) + 1]; strcpy(PortName, PName);};int PortParam::SetPortMode(int speed){ struct termios tdes; int fd; if (PortName == NULL) { syslog(LOG_CRIT,"Port name is not defined in PortParam::SetPortMode!"); return 0; } // Open port fd = open( PortName, O_RDWR | O_NONBLOCK); if (fd == -1) { syslog(LOG_CRIT,"Unable to open modem port:"); syslog(LOG_CRIT,PortName); return 0; } if (!isatty(fd)) { syslog(LOG_CRIT,"Specified device is not a terminal:"); syslog(LOG_CRIT,PortName); close(fd); return 0; } if (tcgetattr ( fd, &told ) < 0) { syslog(LOG_CRIT,"tcgetattr failure"); close(fd); return 0; } if (tcgetattr ( fd, &tdes ) < 0) { syslog(LOG_CRIT,"tcgetattr failure"); close(fd); return 0; } tdes.c_iflag = IGNBRK | IGNPAR; // BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | // IUCLC | IXON | IXANY | IXOFF | IMAXBEL tdes.c_oflag = 0; // OPOST | OLCUC | ONLCR | OCRNL | ONOCR | ONLRET | OFILL | // OFDEL | NLDLY | NL0 | NL1 | CRDLY | CR0 | CR1 | CR2 | CR3 | // TABDLY | TAB0 | TAB1 | TAB2 | TAB3 | XTABS | BSDLY | BS0 | // BS1 | VTDLY | VT0 | VT1 | FFDLY | FF0 | FF1 tdes.c_cflag = CS8 | HUPCL | CLOCAL | CRTSCTS | CREAD; // CBAUD | EXTA | EXTB | CSIZE | CS5 | CS6 | CS7 | CSTOPB | // CREAD | PARENB | PARODD | CIBAUD | switch (speed) { case 0: tdes.c_cflag |= B0; break; case 50: tdes.c_cflag |= B50; break; case 75: tdes.c_cflag |= B75; break; case 110: tdes.c_cflag |= B110; break; case 134: tdes.c_cflag |= B134; break; case 150: tdes.c_cflag |= B150; break; case 200: tdes.c_cflag |= B200; break; case 300: tdes.c_cflag |= B300; break; case 600: tdes.c_cflag |= B600; break; case 1200: tdes.c_cflag |= B1200; break; case 1800: tdes.c_cflag |= B1800; break; case 2400: tdes.c_cflag |= B2400; break; case 4800: tdes.c_cflag |= B4800; break; case 9600: tdes.c_cflag |= B9600; break; case 19200: tdes.c_cflag |= B19200; break; case 38400: tdes.c_cflag |= B38400; break;#ifdef B57600 case 57600: tdes.c_cflag |= B57600; break;#endif#ifdef B115200 case 115200: tdes.c_cflag |= B115200; break;#endif#ifdef B230400 case 230400: tdes.c_cflag |= B230400; break;#endif#ifdef B460800 case 460800: tdes.c_cflag |= B460800; break;#endif default: tdes.c_cflag |= B38400; break; }; tdes.c_lflag = 0; // ISIG | ICANON | XCASE | ECHO | ECHOE | ECHOK | ECHONL | // NOFLSH | TOSTOP | ECHOCTL | ECHOPRT | ECHOKE | FLUSHO | // PENDIN | IEXTEN if (tcsetattr ( fd, TCSANOW, &tdes ) < 0) { syslog(LOG_CRIT,"tcsetattr failure: Unable to set port settings!"); close(fd); return 0; } close(fd); IsSetup = 1; return 1;}; int PortParam::RestorePortMode(){ int fd; if (!IsSetup) return 1; if (PortName == NULL) { syslog(LOG_WARNING,"Port name is not defined in PortParam::RestorePortMode!"); return 0; } // Open port fd = open( PortName, O_RDWR | O_NONBLOCK); if (fd == -1) { syslog(LOG_WARNING,"Unable to open modem port:"); syslog(LOG_WARNING,PortName); return 0; } if (!isatty(fd)) { syslog(LOG_WARNING,"Specified device is not a terminal:"); syslog(LOG_WARNING,PortName); close(fd); return 0; } if (tcsetattr ( fd, TCSANOW, &told ) < 0) { syslog(LOG_CRIT,"tcsetattr failure: Unable to set port settings!"); close(fd); return 0; } close(fd); IsSetup = 0; return 1;};//***************************************************************//***************************************************************//// global functions////***************************************************************//***************************************************************char* memstr( char* where, char* what, int howmuch){ char* ptrf; int i,j; if (strlen(what) >= 1) { for (i = 0; i < howmuch; i++) { if (what[0] == where[i]) { // compare further... j = i + 1; ptrf = &(what[1]); while (*ptrf != '\0' && *ptrf == where[j] && j < howmuch ) ptrf++,j++; if (*ptrf == '\0') return &(where[i]); } } return NULL; } return where;}//***************************************************************//***************************************************************//// class VModem////***************************************************************//***************************************************************VModem::VModem(ConfigInfo* con) { if (con == NULL) { syslog(LOG_ERR, "Empty parameter passed into VModem!"); exit(-1); } conf = con; inData = 0; inDTMF = 0; inPubDTMF = 0; MsgExchTimeOut = 3; // Three seconds time out for now... StopChild = 0; ttyParm = new PortParam(conf->SerialPort);};int VModem::Init(ConfigInfo* con) { if (con == NULL) { syslog(LOG_ERR, "Empty parameter passed into VModem!"); return 0; } conf = con; inData = 0; inDTMF = 0; inPubDTMF = 0; MsgExchTimeOut = 3; // Three seconds time out for now... StopChild = 0; ttyParm = new PortParam(conf->SerialPort); return 1;};VModem::~VModem(){ if (isParent) { StopRead(); // kill the child process ttyParm->RestorePortMode(); } delete ttyParm;};//static VModem* TThis;//static void dispatchsig(int)//{// if (TThis) TThis->GotSignal();//};////static void finishchild(int)//{// if (TThis) TThis->GotSignal2();//};int VModem::InitRead(){// char buf[5]; // Buffer for the characters read from the port. // For now, read one at a time.// struct sigaction act, oact; // Set the port to more appropriate mode -- RAW!!!! if (ttyParm->SetPortMode(conf->PortSpeed) == 0) { return 0; } // Open port for reading... fd = open(conf->SerialPort, O_RDWR/* | O_NONBLOCK*/); if (fd == -1) { syslog(LOG_CRIT,"Unable to open modem port for reading"); return 0; } { struct termios tdes; if (tcgetattr ( fd, &tdes ) < 0) { syslog(LOG_CRIT,"tcgetattr failure"); close(fd); return 0; } tdes.c_iflag = IGNBRK | IGNPAR; tdes.c_oflag = 0; tdes.c_cflag = CS8 | HUPCL | CLOCAL | CRTSCTS | CREAD; switch (conf->PortSpeed) { case 0: tdes.c_cflag |= B0; break; case 50: tdes.c_cflag |= B50; break; case 75: tdes.c_cflag |= B75; break; case 110: tdes.c_cflag |= B110; break; case 134: tdes.c_cflag |= B134; break; case 150: tdes.c_cflag |= B150; break; case 200: tdes.c_cflag |= B200; break; case 300: tdes.c_cflag |= B300; break; case 600: tdes.c_cflag |= B600; break; case 1200: tdes.c_cflag |= B1200; break; case 1800: tdes.c_cflag |= B1800; break; case 2400: tdes.c_cflag |= B2400; break; case 4800: tdes.c_cflag |= B4800; break; case 9600: tdes.c_cflag |= B9600; break; case 19200: tdes.c_cflag |= B19200; break; case 38400: tdes.c_cflag |= B38400; break;#ifdef B57600 case 57600: tdes.c_cflag |= B57600; break;#endif#ifdef B115200 case 115200: tdes.c_cflag |= B115200; break;#endif#ifdef B230400 case 230400: tdes.c_cflag |= B230400; break;#endif#ifdef B460800 case 460800: tdes.c_cflag |= B460800; break;#endif default: tdes.c_cflag |= B38400; break; }; tdes.c_lflag = 0; if (tcsetattr ( fd, TCSANOW, &tdes ) < 0) { syslog(LOG_CRIT,"tcsetattr failure: Unable to set port settings!"); close(fd); return 0; } } return 1; // Create a pipe from the child to the parent -- this way we transfer info // received from the modem. Sorry for these complications, I just // want to empty the modem buffer as soon as possible.// if (pipe(pipeD) < 0) // {// syslog(LOG_CRIT,"Cannot create a pipe -- Geeeez I hope this is not DOS!");// return 0;// }//// TThis = this;//// // Create a thread that will always read the port.// ChildID = fork();// if (ChildID == -1) // {// syslog(LOG_CRIT,"Can't fork -- sorry!");// return 0;// }//// // If this is a parent// if (ChildID != 0)// {//// // Enable signal handling for the parent. // act.sa_handler = dispatchsig;// sigemptyset( &act.sa_mask );// act.sa_flags = 0;//// #ifdef SA_RESTART// act.sa_flags |= SA_RESTART;// #endif//// if (sigaction( SIGUSR1, &act, &oact) < 0) // {// syslog(LOG_CRIT,"Cannot catch SIGUSR1");// return 0;// }//// close(pipeD[1]);//// isParent = 1;// return 1;// }//// // Child closes receiving end ...// close(pipeD[0]);// isParent = 0;//// // Enable signal handling for the child. // act.sa_handler = finishchild;// sigemptyset( &act.sa_mask );// act.sa_flags = 0;//// #ifdef SA_INTERRUPT// act.sa_flags |= SA_INTERRUPT;// #endif//// if (sigaction( SIGINT, &act, &oact) < 0) // {// syslog(LOG_CRIT,"Cannot catch SIGINT");// return 0;// }//// ParentID = getppid();//// do // {// if (read(fd, buf, 1) == 1) // {// write(pipeD[1], buf, 1);// kill(ParentID, SIGUSR1);//// buf[1] = '\0';// //syslog(LOG_DEBUG, "Pushed into pipe:");// //syslog(LOG_DEBUG, buf );// }// } while (StopChild == 0);//// close(fd);// syslog(LOG_DEBUG,"Child terminates.");// exit(0);};void VModem::ReadFromPort(){ char buf[256]; int numread; int retval; fd_set rset; struct timeval tmdly; tmdly.tv_sec = 0; tmdly.tv_usec = 0; FD_ZERO(&rset); FD_SET(GetPortFD(), &rset); retval = select(1+GetPortFD(), &rset, NULL, NULL, &tmdly); if ( retval < 1 ) return; numread = read( GetPortFD(), buf, sizeof(buf)-1); if (numread > 0) { buf[numread] = '\0'; //syslog(LOG_DEBUG, "Got:"); //syslog(LOG_DEBUG, buf );//if (buf[0] == DLE)//putchar('*'); // Check for DTMF signals. // They always start with DLE if (LastRec == DLE) { memmove(&(buf[1]), buf, numread); numread++; buf[0] = DLE; } LastRec = DLE; for ( int i = 0; i < numread-1; i++ ) { if (buf[i] == DLE) { // DLE was detected! Decode it. if ( buf[i+1] == DLE ) // Received double DLE, just make it one { if ( i+2 == numread ) LastRec = 0; // Last DLE not to be counted memmove(&buf[i],&buf[i+1],numread - i - 1); numread--; } else // DTMF command, decode it. { DTMF[inDTMF] = buf[i+1]; inDTMF++; if ( numread - i - 2 > 0 ) // Remove DTMF from the data stream { memmove(&buf[i],&buf[i+2],numread - i - 2); i--; } numread = numread - 2; } } } if ( numread == 0) { LastRec = 0; return; } if ( buf[numread-1] != DLE ) LastRec = 0; if (LastRec == DLE) return; // We need to add received data to the buffer... // Check for overflow situation if ((unsigned int)(inData + numread + 2) > sizeof(Data)) { syslog(LOG_WARNING,"Incoming buffer overflow, ... truncating"); char* to = Data; char* from = Data + sizeof(Data)/2; for (unsigned int i = 0; i < sizeof(Data); i++) { *to++ = *from++; } inData -= sizeof(Data)/2; } for (int i = 0; i < numread; i++) { Data[inData++] = buf[i]; } }};// Execute sequence of commands. If some commands// times out, will repeat it up to three timesint VModem::ExecuteSequence( CommandSequence* CommandSeq ){ int retval; CommandSequence* cmd = CommandSeq; while( cmd ) { retval = 0; for (int i = 0; i < 3; i++) { if (MsgExchange(cmd->GetCommand(), cmd->GetAnswer()) >= 0) { retval = 1; break; } } if (!retval) return 0; cmd = cmd->GetNext(); } return 1;}int VModem::MsgExchange( char* MsgSnd, char* MsgExpect ){ PREP_ALARM; char newline[3] = {'\015','\012','\0'}; int ExchComplete = 0; char allbuf[256]; strcpy(allbuf, MsgSnd); strcat(allbuf, newline);// sigset_t usrmask, oldmask; FlushRecBuffer(); CHECK_ABORT_0; syslog(LOG_DEBUG,"Sending:"); syslog(LOG_DEBUG,MsgSnd);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -