SerialCom.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 * Software License Agreement (BSD License)
00004 *
00005 *  Copyright (c) 2011, LAR-DEM University of Aveiro.
00006 *  All rights reserved.
00007 *
00008 *  Redistribution and use in source and binary forms, with or without
00009 *  modification, are permitted provided that the following conditions
00010 *  are met:
00011 *
00012 *   * Redistributions of source code must retain the above copyright
00013 *     notice, this list of conditions and the following disclaimer.
00014 *   * Redistributions in binary form must reproduce the above
00015 *     copyright notice, this list of conditions and the following
00016 *     disclaimer in the documentation and/or other materials provided
00017 *     with the distribution.
00018 *   * Neither the name of the LAR-DEM University of Aveiro nor the names of its
00019 *     contributors may be used to endorse or promote products derived
00020 *     from this software without specific prior written permission.
00021 *
00022 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033 *  POSSIBILITY OF SUCH DAMAGE.
00034 *
00035 * based on the work of:
00036 * ISR University of Coimbra.
00037 * Gonçalo Cabrita on 01/10/2010
00038 *********************************************************************/
00039 
00045 #include <stdio.h>
00046 #include <string.h>
00047 #include <errno.h>
00048 #include <termios.h>
00049 #include <math.h>
00050 #include <poll.h>
00051 #include <signal.h>
00052 #include <fcntl.h>
00053 #include <iostream>
00054 #include <fstream>
00055 
00056 #include "serialcom/SerialCom.h"
00057 
00059 #define SERIAL_EXCEPT(except, msg, ...) \
00060 { \
00061     char buf[1000]; \
00062     snprintf(buf, 1000, msg " (in serialcom::SerialCom::%s)" , ##__VA_ARGS__, __FUNCTION__); \
00063     throw except(buf); \
00064 }
00065 
00066 serialcom::SerialCom::SerialCom() : fd_(-1)
00067 {
00068         stream_thread_ = NULL;
00069 }
00070 
00071 serialcom::SerialCom::~SerialCom()
00072 {
00073         if(portOpen()) close();
00074 }
00075 
00076 
00077 tcflag_t serialcom::SerialCom:: selectbaud(int baudrate_)
00078 {
00079  
00080   switch(baudrate_)
00081   {
00082     case(0):      return(B0);     //Hang up
00083     case(50):     return(B50);    //50 baud
00084     case(75):     return(B75);    //75 baud
00085     case(110):    return(B110);   //110 baud
00086     case(134):    return(B134);   //134.5 baud
00087     case(150):    return(B150);   //150 baud
00088     case(200):    return(B200);   //200 baud
00089     case(300):    return(B300);   //300 baud
00090     case(600):    return(B600);   //600 baud
00091     case(1200):   return(B1200);  //1200 baud
00092     case(1800):   return(B1800);  //1800 baud
00093     case(2400):   return(B2400);  //2400 baud
00094     case(4800):   return(B4800);  //4800 baud
00095     case(9600):   return(B9600);  //9600 baud
00096     case(19200):  return(B19200); //19200 baud
00097     case(38400):  return(B38400); //38400 baud
00098     case(57600):  return(B57600); 
00099     case(115200): return(B115200);
00100     case(230400): return(B230400);
00101     case(460800): return(B460800);
00102     case(500000): return(B500000);
00103     case(576000): return(B576000);
00104     default:
00105       return(B9600);
00106 
00107   }
00108 };
00109 
00110 bool serialcom::SerialCom:: config(int baudrate_, int databits_, int startbits_, int stopbits_, int parity_, int NLchar_)
00111 {
00112 
00113   tcflag_t DATABITS;
00114   tcflag_t PARITY;
00115   tcflag_t confipar;
00116   tcflag_t MAPCRNL;
00117   tcflag_t STOPBITS;
00118   
00119   int attribset, attribget;
00120  
00121   switch (databits_)
00122   {
00123     case(5): DATABITS = CS5; break; // 5 bits
00124     case(6): DATABITS = CS6; break;// 6 bits
00125     case(7): DATABITS = CS7; break;// 7 bits
00126     case(8): DATABITS = CS8; break; // 8 bits
00127     default:
00128        DATABITS = CS8;
00129   };
00130   
00131   switch (parity_)
00132   {
00133     case(EVEN):
00134       PARITY = PARENB; //Parity enable.
00135       PARITY &= ~PARODD; //even.
00136       confipar = INPCK | ISTRIP;
00137       break;
00138       
00139     case(ODD):
00140       PARITY =  PARENB; //Parity enable.
00141       PARITY |= PARODD; //Odd parity, else even.
00142       confipar = INPCK | ISTRIP;
00143       break;
00144       
00145     default:
00146       PARITY = 0;
00147       confipar = IGNPAR; // no parity check
00148       
00149   };
00150   
00151   switch (stopbits_)
00152   {
00153      case(1):
00154          default:
00155             STOPBITS = 0; //one stopbit
00156             break;
00157       case(2):
00158             STOPBITS = CSTOPB; //two stopbits
00159             break;
00160   };  //end of switch stop bits
00161 
00162   if (NLchar_ == 1) //CANONICAL
00163   {
00164     MAPCRNL = ICRNL; // map the carriage return to a line feed
00165     newParams.c_lflag = (ICANON & (~(ECHO))); // control mode local flags for canonical; input is line oriented, do not echo
00166   }
00167   else // RAW
00168   {
00169     MAPCRNL = 0;
00170     newParams.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // control mode local flags for raw input
00171   };
00172     
00173     
00174   attribget = tcgetattr(fd_, &ComParams); // get present serial communication parameters
00175 
00176   newParams.c_iflag =  confipar | MAPCRNL; // input mode
00177   
00178 //--------------------------------------------------
00179   newParams.c_oflag = 0; //output mode
00180 //--------------------------------------------------
00181 
00182   newParams.c_cflag = selectbaud(baudrate_) |
00183                                    DATABITS |
00184                                    STOPBITS |
00185                                      PARITY |
00186                                      CLOCAL |
00187                                      CREAD; //control mode
00188                                      
00189   //newParams.c_lflag &= ~( ECHO | ECHOE);
00190  
00191   newParams.c_cc[VTIME] = 0; /* second timeout - 0 disabled */
00192   newParams.c_cc[VMIN] = 0;  /* read 0 byte - 0 disabled */
00193 
00194   tcflush(fd_, TCIFLUSH);
00195   
00196   attribset = tcsetattr(fd_, TCSANOW, &newParams ); // set serial communication parameters 
00197   
00198   if(attribset == 0)
00199   {
00200     baud_ = baudrate_;
00201     databits = databits_;
00202     startbits = startbits_;
00203     stopbits = stopbits_;
00204     parity = parity_;
00205     return true;
00206   }
00207   else
00208   {
00209     SERIAL_EXCEPT(serialcom::Exception,"Set serial communication parameters failed:");
00210     return false;
00211   }
00212   
00213 };
00214 
00215 bool serialcom::SerialCom:: changebaudrate(int baudrate_)
00216 {
00217   int outset;
00218   int inset;
00219   int attribset;
00220   
00221   attribset = 0;
00222   
00223   outset = cfsetospeed(&newParams,(speed_t) selectbaud(baudrate_)); // output baud rate
00224   inset  = cfsetispeed(&newParams, (speed_t) selectbaud(baudrate_)); // input baud rate
00225   
00226   if((inset<0) || (outset<0))
00227   {
00228     SERIAL_EXCEPT(serialcom::Exception,"Setting baudrate failed");
00229   }
00230   
00231   tcflush(fd_, TCIFLUSH);
00232   attribset = tcsetattr(fd_,TCSANOW,&newParams); // set
00233   
00234   if(attribset<0)
00235   {
00236     SERIAL_EXCEPT(serialcom::Exception,"Set serial communication parameters failed:");
00237     return false;
00238   }
00239   
00240   return true;
00241 };
00242 
00243 
00244 void serialcom::SerialCom::open(const char * port_name, int baud_rate)
00245 {
00246         tcflag_t MAPCRNL;
00247         
00248         if(portOpen()) close();
00249   
00250         // Make IO non blocking. This way there are no race conditions that
00251         // cause blocking when a badly behaving process does a read at the same
00252         // time as us. Will need to switch to blocking for writes or errors
00253         // occur just after a replug event.
00254         fd_ = ::open(port_name, O_RDWR | O_NONBLOCK | O_NOCTTY);
00255 
00256         if(fd_ == -1)
00257         {
00258                 const char *extra_msg = "";
00259                 switch(errno)
00260                 {
00261                         case EACCES:
00262                         extra_msg = "You probably don't have premission to open the port for reading and writing.";
00263                         break;
00264 
00265                         case ENOENT:
00266                         extra_msg = "The requested port does not exist. Was the port name misspelled?";
00267                         break;
00268                 }
00269                 SERIAL_EXCEPT(serialcom::Exception, "Failed to open port: %s. %s (errno = %d). %s", port_name, strerror(errno), errno, extra_msg);
00270         }
00271         
00272         try
00273         {       
00274                 struct flock fl;
00275                 fl.l_type = F_WRLCK;
00276                 fl.l_whence = SEEK_SET;
00277                 fl.l_start = 0;
00278                 fl.l_len = 0;
00279                 fl.l_pid = getpid();
00280 
00281                 if(fcntl(fd_, F_SETLK, &fl) != 0)
00282                         SERIAL_EXCEPT(serialcom::Exception, "Device %s is already locked. Try 'lsof | grep %s' to find other processes that currently have the port open.", port_name, port_name);
00283 
00284                 // Settings for USB?
00285                 struct termios newtio;
00286                 tcgetattr(fd_, &newtio);
00287                 memset (&newtio.c_cc, 0, sizeof (newtio.c_cc));
00288                 newtio.c_cflag = CS8 | CLOCAL | CREAD;
00289 //              newtio.c_iflag = IGNPAR;  original
00290                 
00291 //rpascoal, because some PIC code is sending '\r'
00292                 //TODO rpascoal may need to be changed preferebly by using the config ()
00293                 MAPCRNL = ICRNL;
00294                 newtio.c_iflag = IGNPAR | MAPCRNL;
00295 // ---------------
00296                 
00297                 newtio.c_oflag = 0;
00298 //              newtio.c_lflag = 0;
00299 
00300 // rpascoal line oriented input
00301                 //TODO rpascoal may need to be changed preferebly by using the config ()
00302                 newtio.c_lflag = ICANON; // so that we don't cut settences when reading lines
00303 // -------------------------------------------------------
00304                 
00305                 cfsetspeed(&newtio, selectbaud(baud_rate));
00306                 baud_ = baud_rate;
00307 
00308                 // Activate new settings
00309                 tcflush(fd_, TCIFLUSH);
00310                 if(tcsetattr(fd_, TCSANOW, &newtio) < 0)
00311                         SERIAL_EXCEPT(serialcom::Exception, "Unable to set serial port attributes. The port you specified (%s) may not be a serial port.", port_name); 
00312                 usleep (200000);
00313         }
00314         catch(serialcom::Exception& e)
00315         {
00316                 // These exceptions mean something failed on open and we should close
00317                 if(fd_ != -1) ::close(fd_);
00318                 fd_ = -1;
00319                 throw e;
00320         }
00321 }
00322 
00323 void serialcom::SerialCom::close()
00324 {
00325         int retval = 0;
00326         
00327         retval = ::close(fd_);
00328 
00329         fd_ = -1;
00330 
00331         if(retval != 0)
00332                 SERIAL_EXCEPT(serialcom::Exception, "Failed to close port properly -- error = %d: %s\n", errno, strerror(errno));
00333 }
00334 
00335 int serialcom::SerialCom::write(const char * data, int length)
00336 {
00337         int len = length==-1 ? strlen(data) : length;
00338 
00339         // IO is currently non-blocking. This is what we want for the more serialcomon read case.
00340         int origflags = fcntl(fd_, F_GETFL, 0);
00341         fcntl(fd_, F_SETFL, origflags & ~O_NONBLOCK); // TODO: @todo can we make this all work in non-blocking?
00342         int retval = ::write(fd_, data, len);
00343         fcntl(fd_, F_SETFL, origflags | O_NONBLOCK);
00344 
00345         if(retval == len) return retval;
00346         else SERIAL_EXCEPT(serialcom::Exception, "write failed");
00347 }
00348 
00349 //created by jorge and procopio to be used with the xbee api lib
00350 bool serialcom::SerialCom::writebyte(uint8_t byte)
00351 {
00352         int written = 0;
00353         while (written != 1)
00354         {
00355                 written = ::write(fd_, &byte, 1); //to make sure we get the std write
00356                 if (written < 0)
00357                 {
00358                         return false;
00359                 }
00360 
00361                 usleep(1000);
00362         }
00363         return true;
00364 }
00365 
00366 //created by jorge and procopio to be used with the xbee api lib
00367 int serialcom :: SerialCom:: readbyte(uint8_t *read_byte)
00368 {
00369   //int read_result;
00370   //read_result = fgetc(datastream); // get a character from the stream
00371   char read_result;
00372   int ret;
00373   ret = ::read(fd_, &read_result, 1); //TODO rpascoal have to check that this is OK
00374   *read_byte = (uint8_t) read_result;
00375   
00376   //if(isindebugmode())
00377   //{
00378   //  printf("this was read %i\n",read_result);
00379   //};
00380   
00381   if (read_result == EOF) return false;
00382   return ret;
00383 }
00384 
00385 
00386 int serialcom::SerialCom::read(char * buffer, int max_length, int timeout)
00387 {
00388         int ret;
00389 
00390         struct pollfd ufd[1];
00391         int retval;
00392         ufd[0].fd = fd_;
00393         ufd[0].events = POLLIN;
00394 
00395         if(timeout == 0) timeout = -1; // For compatibility with former behavior, 0 means no timeout. For poll, negative means no timeout.
00396 
00397         if((retval = poll(ufd, 1, timeout)) < 0) SERIAL_EXCEPT(serialcom::Exception, "poll failed -- error = %d: %s", errno, strerror(errno));
00398 
00399         if(retval == 0) SERIAL_EXCEPT(serialcom::TimeoutException, "timeout reached");
00400                 
00401         if(ufd[0].revents & POLLERR) SERIAL_EXCEPT(serialcom::Exception, "error on socket, possibly unplugged");
00402                 
00403     ret = ::read(fd_, buffer, max_length);
00404                 
00405         if(ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK) SERIAL_EXCEPT(serialcom::Exception, "read failed");
00406         
00407         return ret;
00408 }
00409 
00410 int serialcom::SerialCom::readBytes(char * buffer, int length, int timeout)
00411 {
00412         int ret;
00413         int current = 0;
00414 
00415         struct pollfd ufd[1];
00416         int retval;
00417         ufd[0].fd = fd_;
00418         ufd[0].events = POLLIN;
00419 
00420         if(timeout == 0) timeout = -1; // For compatibility with former behavior, 0 means no timeout. For poll, negative means no timeout.
00421 
00422         while(current < length)
00423         {
00424                 if((retval = poll(ufd, 1, timeout)) < 0) SERIAL_EXCEPT(serialcom::Exception, "poll failed -- error = %d: %s", errno, strerror(errno));
00425 
00426                 if(retval == 0) SERIAL_EXCEPT(serialcom::TimeoutException, "timeout reached");
00427                 
00428                 if(ufd[0].revents & POLLERR) SERIAL_EXCEPT(serialcom::Exception, "error on socket, possibly unplugged");
00429                 
00430         ret = ::read(fd_, &buffer[current], length-current);
00431                 
00432                 if(ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK) SERIAL_EXCEPT(serialcom::Exception, "read failed");
00433 
00434                 current += ret;
00435         }
00436         return current;
00437 }
00438 
00439 int serialcom::SerialCom::readLine(char * buffer, int length, int timeout)
00440 {
00441         int ret;
00442         int current = 0;
00443 
00444         struct pollfd ufd[1];
00445         int retval;
00446         ufd[0].fd = fd_;
00447         ufd[0].events = POLLIN;
00448 
00449         if(timeout == 0) timeout = -1; // For compatibility with former behavior, 0 means no timeout. For poll, negative means no timeout.
00450 
00451         while(current < length-1)
00452         {
00453                 if(current > 0)
00454                         if(buffer[current-1] == '\n')
00455                                 return current;
00456 
00457                 if((retval = poll(ufd, 1, timeout)) < 0) SERIAL_EXCEPT(serialcom::Exception, "poll failed -- error = %d: %s", errno, strerror(errno));
00458 
00459                 if(retval == 0) SERIAL_EXCEPT(serialcom::TimeoutException, "timeout reached");
00460                 
00461                 if(ufd[0].revents & POLLERR) SERIAL_EXCEPT(serialcom::Exception, "error on socket, possibly unplugged");
00462                 
00463         ret = ::read(fd_, &buffer[current], length-current);
00464                 
00465                 if(ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK) SERIAL_EXCEPT(serialcom::Exception, "read failed");
00466 
00467                 current += ret;
00468         }
00469         SERIAL_EXCEPT(serialcom::Exception, "buffer filled without end of line being found");
00470 }
00471 using namespace std;
00472 bool serialcom::SerialCom::readLine(std::string& buffer)
00473 {
00474     int ret;
00475     struct pollfd ufd[1];
00476     int retval;
00477     ufd[0].fd = fd_;
00478     ufd[0].events = POLLIN;
00479     
00480     buffer.clear();
00481     
00482     int timeout=1;
00483     int c=0;
00484     
00485     while(1)
00486     {
00487         char ch;
00488         
00489         ret = readbyte((uint8_t*)&ch);
00490         
00491         if(ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
00492         {
00493           continue;
00494         }else if(ret==-1)
00495         {
00496 //        perror("cannot read");
00497           break;
00498         }
00499   
00500         if(ch=='\n')
00501           break;
00502         
00503         buffer.append(1,ch);
00504     }
00505     
00506     return true;
00507 }
00508 
00509 bool serialcom::SerialCom::readLine(std::string * buffer, int timeout)
00510 {
00511         int ret;
00512 
00513         struct pollfd ufd[1];
00514         int retval;
00515         ufd[0].fd = fd_;
00516         ufd[0].events = POLLIN;
00517 
00518         if(timeout == 0) timeout = -1; // For compatibility with former behavior, 0 means no timeout. For poll, negative means no timeout.
00519 
00520         buffer->clear();
00521         while(buffer->size() < buffer->max_size()/2)
00522         {
00523                 // Look for the end char
00524                 ret = buffer->find_first_of("\n");
00525 
00526                 //printf("test rpascoal %d 4\n", (int)ret);
00527                 if(ret == 0) // added because the code was getting stuck. This condition was not checked in cereal port.
00528                 {
00529                  buffer->erase(0,1);
00530                  ret = buffer->find_first_of("\n");
00531                 }
00532                 
00533                 if(ret > 0)
00534                 {
00535                         // If it is there clear everything after it and return
00536                         buffer->erase(ret); //rpascoal
00537                         //buffer->erase(ret+1, buffer->size()-ret-1); the original from cereal port was not clearing properly
00538         
00539                         //printf("test rpascoal %s \n", buffer->c_str());       
00540                         
00541                         return true;
00542                 }
00543 
00544                 if((retval = poll(ufd, 1, timeout)) < 0) SERIAL_EXCEPT(serialcom::Exception, "poll failed -- error = %d: %s", errno, strerror(errno));
00545 
00546                 if(retval == 0) SERIAL_EXCEPT(serialcom::TimeoutException, "timeout reached");
00547                 
00548                 if(ufd[0].revents & POLLERR) SERIAL_EXCEPT(serialcom::Exception, "error on socket, possibly unplugged");
00549                 
00550         char temp_buffer[128];
00551                 
00552         ret = ::read(fd_, temp_buffer, 128);
00553 
00554                 //temp_buffer[126] = 't';
00555                 //temp_buffer[127] = '\0';
00556                 //printf("test rpascoal %s 2\n", temp_buffer);
00557                 
00558                 if(ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK) SERIAL_EXCEPT(serialcom::Exception, "read failed");
00559         
00560                 // Append the new data to the buffer
00561         buffer->append(temp_buffer, ret);
00562 
00563                 //printf("test rpascoal %s 2\n", buffer->c_str());
00564                                 
00565                 //sleep(1);             
00566         }
00567         
00568         SERIAL_EXCEPT(serialcom::Exception, "buffer filled without end of line being found");
00569 }
00570 
00571 bool serialcom::SerialCom::readBetween(std::string * buffer, char start, char end, int timeout)
00572 {
00573         int ret;
00574 
00575         struct pollfd ufd[1];
00576         int retval;
00577         ufd[0].fd = fd_;
00578         ufd[0].events = POLLIN;
00579 
00580         if(timeout == 0) timeout = -1; // For compatibility with former behavior, 0 means no timeout. For poll, negative means no timeout.
00581 
00582         // Clear the buffer before we start
00583         buffer->clear();
00584         while(buffer->size() < buffer->max_size()/2)
00585         {
00586                 if((retval = poll(ufd, 1, timeout)) < 0) SERIAL_EXCEPT(serialcom::Exception, "poll failed -- error = %d: %s", errno, strerror(errno));
00587                 
00588                 if(retval == 0) SERIAL_EXCEPT(serialcom::TimeoutException, "timeout reached");
00589                 
00590                 if(ufd[0].revents & POLLERR) SERIAL_EXCEPT(serialcom::Exception, "error on socket, possibly unplugged");
00591                 
00592                 char temp_buffer[128];
00593                 ret = ::read(fd_, temp_buffer, 128);
00594         
00595                 if(ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK) SERIAL_EXCEPT(serialcom::Exception, "read failed");
00596         
00597                 // Append the new data to the buffer
00598                 buffer->append(temp_buffer, ret);
00599         
00600         // Look for the start char
00601         ret = buffer->find_first_of(start);
00602         // If it is not on the buffer, clear it
00603         if(ret == -1) buffer->clear();
00604         // If it is there, but not on the first position clear everything behind it
00605         else if(ret > 0) buffer->erase(0, ret);
00606                 
00607                 // Look for the end char
00608                 ret = buffer->find_first_of(end);
00609                 if(ret > 0)
00610                 {
00611                         // If it is there clear everything after it and return
00612                         buffer->erase(ret+1, buffer->size()-ret-1);
00613                         return true;
00614                 }
00615         }
00616         SERIAL_EXCEPT(serialcom::Exception, "buffer filled without reaching end of data stream");
00617 }
00618 
00619 int serialcom::SerialCom::flush()
00620 {
00621           int retval = tcflush(fd_, TCIOFLUSH);
00622           if(retval != 0) SERIAL_EXCEPT(serialcom::Exception, "tcflush failed");
00623           
00624           return retval;
00625 }
00626 
00627 bool serialcom::SerialCom::startReadStream(boost::function<void(char*, int)> f)
00628 {
00629         if(stream_thread_ != NULL) return false;
00630 
00631         stream_stopped_ = false;
00632         stream_paused_ = false;
00633         
00634         readCallback = f;
00635         
00636         stream_thread_ = new boost::thread(boost::bind(&serialcom::SerialCom::readThread, this));
00637         return true;
00638 }
00639 
00640 void serialcom::SerialCom::readThread()
00641 {
00642         char data[MAX_LENGTH];
00643         int ret;
00644 
00645         struct pollfd ufd[1];
00646         ufd[0].fd = fd_;
00647         ufd[0].events = POLLIN;
00648         
00649         while(!stream_stopped_)
00650         {
00651                 if(!stream_paused_)
00652                 {
00653                         if(poll(ufd, 1, 10) > 0)
00654                         {
00655                                 if(!(ufd[0].revents & POLLERR))
00656                                 {
00657                                         ret = ::read(fd_, data, MAX_LENGTH);
00658                                         if(ret>0)
00659                                         {
00660                                                 readCallback(data, ret);
00661                                         }
00662                                 }
00663                         }
00664                 }
00665         }
00666 }
00667 
00668 bool serialcom::SerialCom::startReadLineStream(boost::function<void(std::string*)> f)
00669 {
00670         if(stream_thread_ != NULL) return false;
00671 
00672         stream_stopped_ = false;
00673         stream_paused_ = false;
00674         
00675         readLineCallback = f;
00676                 
00677         stream_thread_ = new boost::thread(boost::bind(&serialcom::SerialCom::readLineThread, this));
00678         return true;
00679 }
00680 
00681 void serialcom::SerialCom::readLineThread()
00682 {
00683         std::string data;
00684         bool error = false;
00685 
00686         while(!stream_stopped_)
00687         {
00688                 
00689                 if(!stream_paused_)
00690                 {
00691                         error = false;
00692                         try{readLine(&data, 100); }
00693                         catch(serialcom::Exception& e)
00694                         { 
00695                                 error = true;
00696                         }
00697         
00698                         //printf("rpascoal data %s \n", data.c_str());                  
00699 
00700                         if(!error && data.size()>0) {readLineCallback(&data);};
00701                 }
00702         }
00703 }
00704 
00705 bool serialcom::SerialCom::startReadBetweenStream(boost::function<void(std::string*)> f, char start, char end)
00706 {
00707         if(stream_thread_ != NULL) return false;
00708 
00709         stream_stopped_ = false;
00710         stream_paused_ = false;
00711         
00712         readBetweenCallback = f;
00713         
00714         stream_thread_ = new boost::thread(boost::bind(&serialcom::SerialCom::readBetweenThread, this, start, end));
00715         return true;
00716 }
00717 
00718 void serialcom::SerialCom::readBetweenThread(char start, char end)
00719 {
00720         std::string data;
00721         bool error = false;
00722 
00723         while(!stream_stopped_)
00724         {
00725                 if(!stream_paused_)
00726                 {
00727                         error = false;
00728                         try{ readBetween(&data, start, end, 100); }
00729                         catch(serialcom::Exception& e)
00730                         { 
00731                                 error = true;
00732                         }
00733                         
00734                         if(!error && data.size()>0) readBetweenCallback(&data);
00735                 }
00736         }
00737 }
00738 
00739 void serialcom::SerialCom::stopStream()
00740 {
00741         stream_stopped_ = true;
00742         stream_thread_->join();
00743         
00744         delete stream_thread_;
00745         stream_thread_ = NULL;
00746 }
00747 
00748 void serialcom::SerialCom::pauseStream()
00749 {
00750         stream_paused_ = true;
00751 }
00752 
00753 void serialcom::SerialCom::resumeStream()
00754 {
00755         stream_paused_ = false;
00756 }
00757 
00758 // EOF


serialcom
Author(s): Ricardo Pascoal
autogenerated on Thu Nov 20 2014 11:35:58