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 }