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 }