pcomm.cpp Source File

Main Page Compound List File List Header Files Sources Compound Members File Members

# pcomm.cpp

    00001 /*
    00002    Copyright (C) 1999 PolyWog and Javaman for Ghetto.Org
    00003    This file is part of the PCR-1000 API Library.
    00004
    00005    The PCR-1000 API Library is free software; you can redistribute it and/or
    00006    modify it under the terms of the GNU Library General Public License as
    00007    published by the Free Software Foundation; either version 2 of the
    00008    License, or (at your option) any later version.
    00009
    00010    The PCR-1000 API Library is distributed in the hope that it will be useful,
    00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013    Library General Public License for more details.
    00014
    00015    You should have received a copy of the GNU Library General Public
    00016    License along with the PCR-1000 API Library; see the file LICENSE.  If not,
    00017    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00018    Boston, MA 02111-1307, USA.
    00019  */
    00020
    00021 #if defined (SunOS) || defined (Irix)
    00022 #include <strings.h>
    00023 #else if defined (BSD) || defined (Linux)
    00024 #include <string.h>     /* bzero(), strcpy(), strcpy() etc... */
    00025 #endif
    00026 #include <assert.h> /* assert() */
    00027 #include "pcomm.h"
    00028
    00029 PComm :: PComm (char *pcrDev, tcflag_t baudRate, const char *name)
    00030 {
    00031     if (name==NULL) {
    00032         strcpy(int_name, "PComm_Obj");
    00033     } else {
    00034         strcpy(int_name, name);
    00035     }
    00036
    00037     callCount=0;
    00038     bzero(pcrDevice, sizeof(pcrDevice));
    00039     strncpy(pcrDevice, pcrDev, sizeof(pcrDevice)-1);
    00040     pcrSpeed = baudRate;
    00041
    00042     if (!PCOpen(pcrDev, baudRate))
    00043         { exit(-1); }
    00044
    00045 }
    00062 PComm :: ~PComm ()
    00063 {
    00064         PCClose();
    00065
    00066 #ifdef DEBUG_VER_
    00067     fprintf(stderr, "%s: Destroyed\n", int_name);
    00068 #endif // DEBUG_VER_ //
    00069 }
    00079 bool PComm :: PCOpen(const char *pcrDev, tcflag_t baudRate)
    00080 {
    00081
    00082     /* Open modem device for reading and writing and not as controlling tty
    00083        because we don't want to get killed if linenoise sends CTRL-C.  */
    00084     fd = open(pcrDev, O_RDWR | O_NOCTTY );
    00085     if (fd <0) {
    00086                 perror(pcrDev);
    00087                 return false;
    00088 #ifdef DEBUG_VER_
    00089         } else {
    00090                 fprintf(stderr, "PCOMM: PCOpen(%s, %ld): Success at %d\n",
    00091                         pcrDev, baudRate, fd);
    00092 #endif // DEBUG_VER_
    00093         }
    00094
    00095
    00096     oldtio      = new termios;
    00097     newtio      = new termios;
    00098
    00099
    00100         // functions necessary to initialise socket sets for
    00101         // use with the select() function(s).
    00102         timeOut = new timeval;
    00103         FDSet   = new fd_set;
    00104         // clear out that memory.
    00105         bzero(timeOut, sizeof(struct timeval));
    00106         bzero(FDSet, sizeof(fd_set));
    00107         // remove any socket descriptors if necessary
    00108         // and add socket 'fd' to the FDSet
    00109         FD_ZERO(FDSet);
    00110         FD_SET(fd, FDSet);
    00111         // set default timeout values to five seconds
    00112         timeOut->tv_sec  = 5;
    00113         timeOut->tv_usec = 0;
    00114         // now we should be ready to use the select() statement.
    00115         // just make sure that if the socket `fd' is closed
    00116         // to repopulate the fd_set and to call select with
    00117         // fd+1 as the first arg
    00118
    00119     tcgetattr(fd,oldtio); /* save current serial port settings */
    00120     bzero(newtio, sizeof(struct termios));
    00121
    00122     /*
    00123        BAUDRATE: Set bps rate. use cfsetispeed and cfsetospeed.
    00124        CLOCAL  : local connection, no modem contol
    00125        CREAD   : enable receiving characters
    00126        ~HUPCL  : dont reset DTR to low when program finishes
    00127        ~PARENB : dont enable parity bits
    00128        ~CSTOPB : no stop bits
    00129        ~CSIZE  :
    00130        CS8     : 8n1 (8bit,no parity,1 stopbit)
    00131      */
    00132     cfsetispeed( newtio, baudRate );
    00133     cfsetospeed( newtio, baudRate );
    00134     newtio->c_cflag |=  (CLOCAL | CREAD);
    00135     newtio->c_cflag &= ~HUPCL ;
    00136     newtio->c_cflag &= ~PARENB ;
    00137     newtio->c_cflag &= ~CSTOPB ;
    00138     newtio->c_cflag &= ~CSIZE;
    00139     newtio->c_cflag |= CS8;
    00140
    00141     /* ICANON  : enable canonical input disable all echo functionality,
    00142                  and don't send signals to calling program */
    00143     newtio->c_lflag |= ICANON;
    00144     newtio->c_lflag &= ~(ECHO | ECHOCTL);
    00145
    00146     /* Raw output.  */
    00147     newtio->c_oflag &= ~OPOST;
    00148
    00149     /* now clean the modem line and activate the settings for the port */
    00150     /* tcflush(fd, TCIFLUSH); */
    00151     tcsetattr(fd,TCSANOW,newtio);
    00152
    00153     return true;
    00154 }
    00173 void PComm :: PCClose()
    00174 {
    00175     close(fd);
    00176
    00177     /* restore the old port settings */
    00178     tcsetattr(fd,TCSANOW,oldtio);
    00179     delete oldtio;
    00180     delete newtio;
    00181
    00182     FD_ZERO(FDSet);
    00183     delete FDSet;
    00184     delete timeOut;
    00185
    00186 }
    00194 size_pc PComm :: PCTell(char *mesg)
    00195 {
    00196     #ifdef DEBUG_VER_
    00197     fprintf(stderr, "Tell: %s\n", mesg);
    00198     #endif /* DEBUG_VER_ */
    00199
    00200     return (Write(mesg));
    00201 }
    00217 size_pc PComm :: PCAsk(char *mesg)
    00218 {
    00219     #ifdef DEBUG_VER_2
    00220     fprintf(stderr, "Ask: %s\n", mesg);
    00221     assert(mesg!=0);
    00222     assert(strlen(mesg)==2);
    00223     #endif /* DEBUG_VER_ */
    00224
    00225     bzero(askBuf, sizeof(askBuf));
    00226     strcpy(askBuf, mesg);
    00227     strcat(askBuf, PCRQST);
    00228
    00229     return (Write(askBuf)-1);
    00230 }
    00251 size_pc PComm :: PCHear(char *mesg)
    00252 {
    00253     char *cut;
    00254
    00255     #ifdef DEBUG_VER_2
    00256     assert(mesg != 0);
    00257     fprintf(stderr, "PComm: PCHEAR \n");
    00258     #endif /* DEBUG_VER_ */
    00259
    00260     hearCtr=0;
    00261     bzero(hearBuf, sizeof(hearBuf));
    00262     bzero(mesg, sizeof(mesg));
    00263
    00264     hearCtr = Read(hearBuf);
    00265     cut=strpbrk(hearBuf, PCRECMD);
    00266     if (cut!=NULL) {
    00267         *cut=0;
    00268         hearCtr -= 2;
    00269     }
    00270
    00271     strcpy(mesg, hearBuf);
    00272
    00273     #ifdef DEBUG_VER_2
    00274     fprintf(stderr, "Hear: %s\n", mesg);
    00275     #endif /* DEBUG_VER_ */
    00276
    00277         if (errRead) {
    00278                 return (-1);
    00279         } else {
    00280                 return (hearCtr);
    00281         }
    00282
    00283 }
    00304 size_pc PComm :: PCRawWrite(char *mesg)
    00305 {
    00306
    00307     bzero(writeBuf, sizeof(writeBuf));
    00308     strcpy(writeBuf, mesg);
    00309
    00310     if (select(fd+1, NULL, FDSet, NULL, timeOut)) {
    00311         writeCtr = write(fd, writeBuf, strlen(writeBuf));
    00312     } else {
    00313 #ifdef DEBUG_VER_
    00314             fprintf(stderr, "PCRawWrite Time Out on socket %d\n", fd);
    00315 #endif // DEBUG_VER_
    00316         writeCtr = 0;
    00317     }
    00318
    00319     if ((unsigned)writeCtr!=strlen(writeBuf)) {
    00320         return (-1);
    00321     }
    00322
    00323     return writeCtr;
    00324
    00325 }
    00337 size_pc PComm :: PCRawRead(char *mesg)
    00338 {
    00339     readCtr = 1;
    00340
    00341     bzero(readBuf, sizeof(readBuf));
    00342     bzero(readBuf, sizeof(mesg));
    00343
    00344     while(readCtr==1) {
    00345         if (select(fd+1, FDSet, NULL, NULL, timeOut)) {
    00346                 readCtr= read(fd, readBuf, sizeof(readBuf));
    00347                 strcpy(mesg, readBuf);
    00348         } else {
    00349                 readCtr=(-1);
    00350 #ifdef DEBUG_VER_
    00351             fprintf(stderr, "PCRawRead Time Out on socket %d\n", fd);
    00352 #endif // DEBUG_VER_
    00353
    00354         }
    00355     }
    00356
    00357     return readCtr;
    00358 }
    00370 size_pc PComm :: Write(char *submesg)
    00371 {
    00372     int __writeCtr;
    00373
    00374     bzero(writeBuf, sizeof(writeBuf));
    00375     strcpy(writeBuf, submesg);
    00376     strcat(writeBuf, PCRECMD);
    00377
    00378     #ifdef DEBUG_VER_2
    00379     fprintf(stderr, "Write Attempt: %s\n", writeBuf);
    00380     #endif /* DEBUG_VER_ */
    00381
    00382     if (select(fd+1, NULL, FDSet, NULL, timeOut)) {
    00383                 __writeCtr=write(fd, writeBuf, strlen(writeBuf));
    00384     } else {
    00385 #ifdef DEBUG_VER_
    00386             fprintf(stderr, "Write() Time Out on socket %d\n", fd);
    00387 #endif // DEBUG_VER_
    00388             __writeCtr=0;
    00389     }
    00390
    00391     return (__writeCtr-2);
    00392 }
    00416 size_pc PComm :: Read(char *submesg)
    00417 {
    00418     readCtr=1;
    00419     int loopBreaker=0;
    00420
    00421 #ifdef DEBUG_VER_2
    00422     assert(submesg!=0);
    00423     fprintf(stderr, "PComm: READ");
    00424 #endif /* DEBUG_VER_ */
    00425
    00426     bzero(readBuf, sizeof(readBuf));
    00427     bzero(submesg, sizeof(submesg));
    00428
    00429     while((readCtr==1) && (loopBreaker<10)) {
    00430         if (select(fd+1, FDSet, NULL, NULL, timeOut)) {
    00431                 readCtr=read(fd, readBuf, sizeof(readBuf));
    00432                 // call Count keeps track of the number of
    00433                 // read()/writes() to the serial object
    00434                     countCall();
    00435                 loopBreaker++;
    00436         } else {
    00437 #ifdef DEBUG_VER_
    00438                 fprintf(stderr, "Read() Time Out on socket %d\n", fd);
    00439 #endif // DEBUG_VER_ //
    00440                     readCtr=1;
    00441                 errRead=true;
    00442                 loopBreaker++;
    00443         }
    00444     }
    00445
    00446     /*
    00447        Was there an error reading? ie: after five
    00448        loops, did we still read in new lines (in other
    00449        words, did the radio have nothing to tell us?)
    00450        Then we should have never been called, and set
    00451        errRead appropriately.
    00452      */
    00453     (readCtr==1)?(errRead=true):(errRead=false);
    00454
    00455     strcpy(submesg, readBuf);
    00456
    00457     #ifdef DEBUG_VER_2
    00458     fprintf(stderr, "\nRead: %i -  %s\n", readCtr, submesg);
    00459     #endif /* DEBUG_VER_ */
    00460
    00461     return readCtr;
    00462
    00463 }
    00496 void PComm :: resetCall()
    00497 {
    00498 #ifdef DEBUG_VER_2
    00499         fprintf(stderr, "PCOMM: resetCall() @ %d \n", callCount);
    00500 #endif DEBUG_VER_2
    00501         callCount=0;
    00502         int __readCounter=0;
    00503         int __loopbreaker=0;
    00504
    00505         PCClose();
    00506         PCOpen(pcrDevice, pcrSpeed);
    00507         bzero(callBuf, sizeof(callBuf));
    00508         strncpy(callBuf, PCRPWRON, sizeof(callBuf)-1);
    00509         strncat(callBuf, PCRECMD,  ((sizeof(callBuf))-(strlen(callBuf))-1));
    00510         if (select(fd+1, NULL, FDSet, NULL, timeOut)) {
    00511         write(fd, callBuf, strlen(callBuf));
    00512             if (select(fd+1, NULL, FDSet, NULL, timeOut)) {
    00513                 bzero(callBuf, sizeof(callBuf));
    00514                 while ((__readCounter==1) && (__loopbreaker<10)) {
    00515                     __readCounter = read(fd, callBuf, sizeof(callBuf));
    00516                     __loopbreaker++;
    00517                 }
    00518 #ifdef DEBUG_VER_
    00519             } else {
    00520                // we should never have gotten here, if so, we are fubar'd
    00521                // and should abort the program
    00522                 fprintf(stderr, "Read failed in PCOMM: resetCall()");
    00523                 fprintf(stderr, "***UNRECOVERABLE ERROR***");
    00524                 abort();
    00525 #endif // DEBUG_VER_
    00526             }
    00527 #ifdef DEBUG_VER_
    00528         } else {
    00529             // we should never have gotten here, if so, we are fubar'd
    00530             // and should abort the program
    00531                 fprintf(stderr, "Write failed in PCOMM: resetCall()");
    00532         fprintf(stderr, "***UNRECOVERABLE ERROR***");
    00533         abort();
    00534 #endif // DEBUG_VER_
    00535         }
    00536 }
    00564 void PComm :: countCall()
    00565 {
    00566         if (callCount<200) {
    00567                 callCount++;
    00568         } else {
    00569                 resetCall();
    00570         }
    00571
    00572 #ifdef DEBUG_VER_2
    00573         fprintf(stderr, "PCOMM: countCall() %d\n", callCount);
    00574 #endif // DEBUG_VER_
    00575 }