Serial.C

Go to the documentation of this file.
00001 /*!@file Devices/Serial.C class for interfacing with a serial port */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Nitin Dhavale <dhavale@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Devices/Serial.C $
00035 // $Id: Serial.C 14056 2010-09-28 00:12:03Z rand $
00036 //
00037 
00038 #include "Devices/Serial.H"
00039 #include "Util/Timer.H"
00040 #include "Component/OptionManager.H"
00041 #include "Util/log.H"
00042 #include "rutz/unixcall.h" // for rutz::unixcall::get_file_user_pid()
00043 #include <iostream>
00044 #include <sys/types.h>
00045 #include <dirent.h>
00046 #include <unistd.h>
00047 
00048 const ModelOptionCateg MOC_Serial= {
00049         MOC_SORTPRI_3, "Serial Port Related Options" };
00050 
00051 const ModelOptionDef OPT_DevName =
00052 { MODOPT_ARG(std::string), "DevName", &MOC_Serial, OPTEXP_CORE,
00053         "Device file",
00054         "serial-dev", '\0', "", "/dev/ttyUSB0" };
00055 
00056 // ######################################################################
00057 
00058 Serial::Serial(OptionManager& mgr,
00059                 const std::string& descrName,
00060                 const std::string& tagName) :
00061         ModelComponent(mgr, descrName, tagName),
00062         itsCmdDevName(&OPT_DevName, this, 0),
00063         itsDeviceDescription(tagName+"DeviceDescription", this, ""),
00064         itsSearchPrefix(tagName+"SearchPrefix", this, "ttyUSB"),
00065         itsBaud(tagName+"Baud", this, 9600),
00066         itsCharBits(tagName+"CharBits", this, 8),
00067         itsStopBits(tagName+"StopBits", this, 1),
00068         itsUseParity(tagName+"UseParity", this, false),
00069         itsParityOdd(tagName+"ParityOdd", this, false),
00070         itsFlowHard(tagName+"FlowHard", this, false),
00071         itsFlowSoft(tagName+"FlowSoft", this, false),
00072         itsRdTout(tagName+"ReadTimeout", this, 0),
00073         itsBlocking(tagName+"Blocking", this, true),
00074         itsSerialOk(tagName+"SerialOk", this, false),
00075         dev(-1),
00076         itsDevName(""),
00077         serialErrno(serialErrSuccess)
00078 {
00079 
00080 }
00081 
00082 // ######################################################################
00083 void Serial::start2()
00084 {
00085         //Check to see if we have a hardcoded device name. If so, then let's just
00086         //go ahead and enable that port. If
00087         LINFO("Looking Device Name [%s]",itsDevName.c_str());
00088         if(itsDevName != "")
00089         {
00090                 LINFO("Opening %s", itsDevName.c_str());
00091                 enablePort(itsDevName);
00092         } else if (itsDevName == "search") {
00093                 LINFO("Searching for devices");
00094                 itsCmdDevName.setVal("");
00095 
00096                 DIR *directory_p;
00097                 struct dirent *entry_p;
00098 
00099                 //Open the device directory to search for devices whose names match the search prefix
00100                 directory_p = ::opendir ("/dev");
00101                 if (directory_p == NULL)
00102                         LFATAL("Could Not Open /dev Directory!");
00103 
00104                 //Iterate through the directory entries
00105                 while ((entry_p = ::readdir (directory_p)))
00106                 {
00107                         std::string entryName(entry_p->d_name);
00108                         if(entryName.find(itsSearchPrefix.getVal().c_str()) != std::string::npos)
00109                         {//If the directory entry name matches our search prefix, then let's try configuring a serial
00110                                 //port on that device, sending it an identity request command (0x00), and comparing the result
00111                                 //with our required device description
00112 
00113                                 enablePort("/dev/" + entryName);
00114                                 unsigned char cmd[1] = {0};
00115 
00116                                 write(cmd,1);
00117                                 std::vector<unsigned char> deviceStringVec = readFrame(cmd[0], 255);
00118 
00119                                 std::string deviceString(deviceStringVec.begin(), deviceStringVec.end());
00120                                 LINFO("%s : %s", entryName.c_str(), deviceString.c_str());
00121 
00122                                 if(deviceString == itsDeviceDescription.getVal())
00123                                 {
00124                                         itsCmdDevName.setVal("/dev/"+entryName);
00125                                         break;
00126                                 }
00127                         }
00128 
00129 
00130                 }
00131                 (void) ::closedir (directory_p);
00132                 if(itsCmdDevName.getVal() == "")
00133                 {
00134                         LFATAL("Could Not Find Serial Device Matching Descriptor (%s)", itsDeviceDescription.getVal().c_str());
00135                 }
00136         } else {
00137                 LINFO("Opening from cmd line %s", itsCmdDevName.getVal().c_str());
00138                 enablePort(itsCmdDevName.getVal());
00139         }
00140 }
00141 
00142 
00143 // ######################################################################
00144 void Serial::enablePort(std::string DeviceName)
00145 {
00146         closePort();
00147         serialErrno = serialErrSuccess;      // clear the error flag
00148 
00149         openPort(DeviceName);                // open the device
00150         perror();
00151 
00152         setSpeed(itsBaud.getVal());          // Set the baud rate
00153         perror();
00154 
00155         setFlowControl(itsFlowHard.getVal(),
00156                         itsFlowSoft.getVal());           // Set flow control
00157         perror();
00158 
00159         setCharBits(itsCharBits.getVal());   // set no of bits in a char
00160         perror();
00161 
00162         setParity(itsUseParity.getVal(),
00163                         itsParityOdd.getVal());          // Set even or odd parity
00164         perror();
00165 
00166         setBlocking(itsBlocking.getVal());   // blocking mode?
00167         perror();
00168 }
00169 
00170 
00171 #include <cstdio>
00172 // ######################################################################
00173 void Serial::stop2()
00174 {
00175         closePort();
00176 }
00177 
00178 // ######################################################################
00179 void Serial::closePort()
00180 {
00181         if(dev >= 0) {
00182                 //sendBreak();
00183                 close(dev);
00184                 dev = -1; }
00185 }
00186 
00187 // ######################################################################
00188 void Serial::configureSearch(const std::string DeviceDescription, const int speed, const std::string SearchPrefix, const char *format,
00189                 const bool flowSoft, const bool flowHard,
00190                 const int tout)
00191 {
00192         LINFO("Search for %s in speed %d",DeviceDescription.c_str(),speed);
00193         itsDevName = "search";
00194         itsDeviceDescription.setVal(DeviceDescription);
00195         itsSearchPrefix.setVal(SearchPrefix);
00196         //enable serch
00197         //configure("search", speed, format, flowSoft, flowHard, tout);
00198         //Bypass search
00199         configure("", speed, format, flowSoft, flowHard, tout);
00200 }
00201 
00202 // ######################################################################
00203 void Serial::configure(const char *dev, const int speed, const char *format,
00204                 const bool flowSoft, const bool flowHard,
00205                 const int tout)
00206 {
00207         itsDevName = dev;
00208 
00209 
00210         itsBaud.setVal(speed);
00211         itsFlowSoft.setVal(flowSoft);
00212         itsFlowHard.setVal(flowHard);
00213         itsRdTout.setVal(tout);
00214 
00215         if (strlen(format) != 3) LFATAL("Incorrect format string: %s", format);
00216 
00217         switch(format[0]) {
00218                 case '5': itsCharBits.setVal(5); break;
00219                 case '6': itsCharBits.setVal(6); break;
00220                 case '7': itsCharBits.setVal(7); break;
00221                 case '8': itsCharBits.setVal(8); break;
00222                 default: LFATAL("Invalid charbits: %c (should be 5..8)", format[0]);
00223         }
00224 
00225         switch(format[1]) {
00226                 case 'N': itsUseParity.setVal(false); break;
00227                 case 'E': itsUseParity.setVal(true); itsParityOdd.setVal(false); break;
00228                 case 'O': itsUseParity.setVal(true); itsParityOdd.setVal(true); break;
00229                 default: LFATAL("Invalid parity: %c (should be N,E,O)", format[1]);
00230         }
00231 
00232         switch(format[2]) {
00233                 case '1': itsStopBits.setVal(1); break;
00234                 case '2': itsStopBits.setVal(2); break;
00235                 default: LFATAL("Invalid stopbits: %c (should be 1..2)", format[2]);
00236         }
00237 }
00238 
00239 // ######################################################################
00240 serialError Serial::setSpeed(const int speed)
00241 {
00242         struct termios options;
00243         unsigned int rate;
00244 
00245         switch(speed)
00246         {
00247                 case 230400:
00248                         rate = B230400;
00249                         break;
00250                 case 115200:
00251                         rate = B115200;
00252                         break;
00253                 case 57600:
00254                         rate = B57600;
00255                         break;
00256                 case 38400:
00257                         rate = B38400;
00258                         break;
00259                 case 19200:
00260                         rate = B19200;
00261                         break;
00262                 case 9600:
00263                         rate = B9600;
00264                         break;
00265                 case 4800:
00266                         rate = B4800;
00267                         break;
00268                 case 2400:
00269                         rate = B2400;
00270                         break;
00271                 case 1200:
00272                         rate = B1200;
00273                         break;
00274                 case 600:
00275                         rate = B600;
00276                         break;
00277                 case 300:
00278                         rate = B300;
00279                         break;
00280                 case 110:
00281                         rate = B110;
00282                         break;
00283                 case 0:
00284                         rate = B0;
00285                         break;
00286                 default:
00287                         return serialError(serialErrSpeedInvalid);
00288         }
00289 
00290         // get current options
00291         if(tcgetattr(dev, &options)==-1){
00292                 serialErrno = serialErrTcGetAttrFailed;
00293                 return serialErrno;
00294         }
00295 
00296         // set the speed
00297         cfsetispeed(&options, rate);
00298         cfsetospeed(&options, rate);
00299 
00300         // change the terminals parameter instantly
00301         if( tcsetattr(dev, TCSANOW, &options) == -1){
00302                 serialErrno = serialErrTcSetAttrFailed;
00303                 return serialErrno;
00304         }
00305 
00306         if( tcgetattr(dev, &options) == -1) {
00307                 serialErrno = serialErrTcGetAttrFailed;
00308                 return serialErrno;
00309         }
00310 
00311         // update our ModelParam:
00312         itsBaud.setVal(speed);
00313 
00314         return serialErrSuccess;
00315 }
00316 
00317 
00318 // ######################################################################
00319 serialError Serial::setFlowControl(const bool useHard, const bool useSoft)
00320 {
00321         termios options;
00322 
00323         if( tcgetattr(dev, &options) == -1){
00324                 serialErrno = serialErrTcGetAttrFailed;
00325                 return serialErrno;
00326         }
00327 
00328         options.c_cflag &= ~CRTSCTS;
00329         options.c_iflag &= ~(IXON | IXANY | IXOFF);
00330 
00331         if (useSoft) options.c_iflag |= (IXON | IXANY | IXOFF);
00332         if (useHard) options.c_cflag |= CRTSCTS;
00333 
00334         if(tcsetattr(dev, TCSANOW, &options) == -1){
00335                 serialErrno = serialErrTcGetAttrFailed;
00336                 return serialErrno;
00337         }
00338 
00339         // update our ModelParams:
00340         itsFlowHard.setVal(useHard);
00341         itsFlowSoft.setVal(useSoft);
00342 
00343         return serialErrSuccess;
00344 }
00345 
00346 // ######################################################################
00347 serialError Serial::setCharBits(const int bits)
00348 {
00349         termios options;
00350 
00351         if(tcgetattr(dev, &options)==-1){
00352                 serialErrno = serialErrTcGetAttrFailed;
00353                 return serialErrno;
00354         }
00355 
00356         options.c_cflag &= ~CSIZE; // mask off the 'size' bits
00357 
00358         switch(bits)
00359         {
00360                 case 5: options.c_cflag |= CS5; break;
00361                 case 6: options.c_cflag |= CS6; break;
00362                 case 7: options.c_cflag |= CS7; break;
00363                 case 8: options.c_cflag |= CS8; break;
00364                 default: return serialError(serialErrCharsizeInvalid);
00365         }
00366 
00367         if( tcsetattr(dev, TCSANOW, &options) == -1 ){
00368                 serialErrno = serialErrTcSetAttrFailed;
00369                 return serialErrno;
00370         }
00371 
00372         // update our ModelParam:
00373         itsCharBits.setVal(bits);
00374 
00375         return serialErrSuccess;
00376 }
00377 
00378 // ######################################################################
00379 serialError Serial::setParity(const bool useParity, const bool oddParity)
00380 {
00381         struct termios options;
00382 
00383         if(tcgetattr(dev, &options)==-1){
00384                 serialErrno = serialErrTcGetAttrFailed;
00385                 return serialErrno;
00386         }
00387 
00388         options.c_cflag &= ~(PARENB | PARODD);
00389         if (useParity)
00390         {
00391                 if (oddParity)
00392                         options.c_cflag |= (PARENB | PARODD);
00393                 else
00394                         options.c_cflag |= PARENB;
00395         }
00396 
00397         if(tcsetattr(dev, TCSANOW, &options) == -1){
00398                 serialErrno = serialErrTcSetAttrFailed;
00399                 return serialErrno;
00400         }
00401 
00402         // update our ModelParams:
00403         itsUseParity.setVal(useParity);
00404         itsParityOdd.setVal(oddParity);
00405 
00406         return serialErrSuccess;
00407 }
00408 
00409 // ######################################################################
00410 serialError Serial::setStopBits(const int bits)
00411 {
00412         struct termios options;
00413 
00414         if(tcgetattr(dev, &options)==-1){
00415                 serialErrno = serialErrTcGetAttrFailed;
00416                 return serialErrno;
00417         }
00418 
00419         options.c_cflag &= ~CSTOPB;
00420         if (bits == 2) options.c_cflag |= CSTOPB;
00421         else if (bits != 1) return serialError(serialErrStopbitsInvalid);
00422 
00423         if(tcsetattr(dev, TCSANOW, &options) == -1){
00424                 serialErrno = serialErrTcSetAttrFailed;
00425                 return serialErrno;
00426         }
00427 
00428         // update our ModelParam:
00429         itsStopBits.setVal(bits);
00430 
00431         return serialErrSuccess;
00432 }
00433 
00434 // ######################################################################
00435 serialError Serial::setBlocking(const bool blocking)
00436 {
00437         int flags = fcntl(dev, F_GETFL, 0);
00438         if (flags == -1) PLERROR("Cannot get flags");
00439         if (blocking) flags &= (~O_NONBLOCK); else flags |= O_NONBLOCK;
00440         if (fcntl(dev, F_SETFL, flags) == -1) PLERROR("Cannot set flags");
00441 
00442         itsBlocking.setVal(blocking);
00443 
00444         return serialErrSuccess;
00445 }
00446 
00447 // ######################################################################
00448 void Serial::toggleDTR(const time_t ms)
00449 {
00450         struct termios tty, old;
00451         if(tcgetattr(dev, &tty) == -1 || tcgetattr(dev, &old) == -1){
00452                 serialErrno = serialErrTcGetAttrFailed;
00453         }
00454 
00455         cfsetospeed(&tty, B0);
00456         cfsetispeed(&tty, B0);
00457 
00458         if(tcsetattr(dev, TCSANOW, &tty) == -1){
00459                 serialErrno = serialErrTcSetAttrFailed;
00460         }
00461 
00462         if(ms)
00463                 usleep(ms*1000);
00464 
00465         if(tcsetattr(dev, TCSANOW, &old) == -1){
00466                 serialErrno = serialErrTcSetAttrFailed;
00467         }
00468 }
00469 
00470 // ######################################################################
00471 void Serial::sendBreak(void)
00472 {
00473         // Send a Hangup to the port
00474         tcsendbreak(dev, 0);
00475 }
00476 
00477 // ######################################################################
00478 serialError Serial::error(const serialError serialErrorNum)
00479 {
00480         serialErrno = serialErrorNum;
00481         return serialErrorNum;
00482 }
00483 
00484 // ######################################################################
00485 int Serial::openPort(std::string DeviceName)
00486 {
00487         const pid_t fuser =
00488                 rutz::unixcall::get_file_user_pid(DeviceName.c_str());
00489 
00490         if (fuser != 0 && DeviceName.compare("/dev/null") != 0)
00491         {
00492                 LINFO("serial device %s is already in use by process pid=%d;\n"
00493                                 "\ttry using /dev/null or a different serial device instead",
00494                                 DeviceName.c_str(), int(fuser));
00495         }
00496 
00497         int flags= O_RDWR | O_NOCTTY;
00498         termios options;
00499 
00500         // don't set the flag if we are setting a timeout on
00501         // the descriptor
00502         if (itsRdTout.getVal() < 0) flags |= O_NDELAY;
00503 
00504         CLDEBUG("Opening port %s", DeviceName.c_str());
00505         dev = ::open(DeviceName.c_str(), flags);
00506         if (dev == -1) { serialErrno = serialErrOpenFailed; return dev; }
00507         LDEBUG("Done");
00508 
00509         // Save current state
00510         if( tcgetattr(dev, &savedState) == -1 ){
00511                 serialErrno = serialErrTcGetAttrFailed;
00512                 return -1;
00513         }
00514 
00515         // reset all the flags
00516         if( fcntl(dev, F_SETFL, 0) == -1 ){
00517                 serialErrno = serialErrFcntlFailed;
00518                 return -1;
00519         }
00520 
00521         if(tcgetattr(dev, &options) == -1 ){
00522                 serialErrno = serialErrTcGetAttrFailed;
00523                 return -1;
00524         }
00525 
00526         // get raw input from the port
00527         options.c_cflag |= ( CLOCAL     // ignore modem control lines
00528                         | CREAD ); // enable the receiver
00529 
00530         options.c_iflag &= ~(  IGNBRK    // ignore BREAK condition on input
00531                         | BRKINT  // If IGNBRK is not set, generate SIGINT
00532                         // on BREAK condition, else read BREAK as \0
00533                         | PARMRK
00534                         | ISTRIP  // strip off eighth bit
00535                         | INLCR   // donot translate NL to CR on input
00536                         | IGNCR   // ignore CR
00537                         | ICRNL   // translate CR to newline on input
00538                         | IXON    // disable XON/XOFF flow control on output
00539                         );
00540 
00541         // disable implementation-defined output processing
00542         options.c_oflag &= ~OPOST;
00543         options.c_lflag &= ~(ECHO  // dont echo i/p chars
00544                         | ECHONL // do not echo NL under any circumstance
00545                         | ICANON // disable cannonical mode
00546                         | ISIG   // do not signal for INTR, QUIT, SUSP etc
00547                         | IEXTEN // disable platform dependent i/p processing
00548                         );
00549 
00550         // set a timeout on the descriptor
00551         if(itsRdTout.getVal() > 0) {
00552                 options.c_cc[VMIN] = 0;
00553                 options.c_cc[VTIME] = itsRdTout.getVal();
00554         }
00555 
00556         if( tcsetattr(dev, TCSANOW, &options) == -1){
00557                 serialErrno = serialErrTcSetAttrFailed;
00558                 return -1;
00559         }
00560         return dev;
00561 }
00562 
00563 
00564 // ######################################################################
00565 int Serial::read(void* buffer, const int nbytes)
00566 {
00567         int n = ::read(dev, buffer, nbytes);
00568         if(n==-1)
00569                 serialErrno = serialErrReadFailed;
00570 
00571         if(n==0)
00572                 serialErrno = serialErrReadTimedOut;
00573 
00574         return n;
00575 }
00576 
00577 
00578 // ######################################################################
00579 char Serial::read(void)
00580 {
00581         char ch;
00582 
00583         this->read(&ch, 1);
00584 
00585         return ch;
00586 }
00587 
00588 std::vector<unsigned char> Serial::readFrame(const unsigned char frameStart, const unsigned char frameEnd, const int frameLength, const double timeout)
00589 {
00590 
00591         std::vector<unsigned char> data;
00592         unsigned char buffer[1024];
00593 
00594         Timer timer;
00595 
00596         unsigned int startPos  =  0;
00597         unsigned int currPos   =  0;
00598         int frameSize          = -1;
00599         bool done              = false;
00600         int startFrameOffset   = 2;
00601 
00602         if(frameLength > 0)
00603         {
00604                 frameSize = frameLength;
00605                 startFrameOffset = 1;
00606         }
00607 
00608         timer.reset();
00609         while(!done)
00610         {
00611                 //If we have reached the timeout, then just quit return an empty vector
00612                 if(timeout > 0 && timer.getSecs() > timeout)
00613                         return std::vector<unsigned char>();
00614 
00615                 //Read data into the data buffer
00616                 int bytesRead = read(buffer, 1024);
00617 
00618 
00619           //LINFO("Got %i bytes", bytesRead);
00620     //for(int i=0; i<bytesRead; i++)
00621                 //      printf("%i ", buffer[i]);
00622           //printf("\n");
00623           
00624 
00625                 if(bytesRead > 0)
00626                 {
00627                         //If we read some bytes, then let's append them onto the data buffer
00628                         std::vector<unsigned char> newData(buffer, buffer+bytesRead*(sizeof(buffer[0])));
00629                         data.insert(data.end(), newData.begin(), newData.end());
00630 
00631                         while(currPos < data.size())
00632                         {
00633                                 //If we have reached the timeout, then just quit return an empty vector
00634                                 if(timeout > 0 && timer.getSecs() > timeout)
00635                                         return std::vector<unsigned char>();
00636 
00637                                 if(data.at(startPos) != frameStart)
00638                                 { //Get the start byte position settled
00639                                         currPos++;
00640                                         startPos = currPos;
00641                                 }
00642                                 else
00643                                 { //Here, we already have our start byte
00644 
00645                                         if(frameLength == -1 && frameSize == -1 && (startPos+1 < data.size()) )
00646                                         { //Find the frame size if one was not supplied, and we haven't yet found it
00647                                                 frameSize = data.at(startPos+1);
00648                                                 currPos++;
00649                                         }
00650                                         else if(frameSize > -1 && data.size() <= currPos+frameSize+1)
00651                                         { //If we know our frame size, but our data buffer is not large enough,
00652                                                 //then just break and we will read more data at the top of the while loop
00653                                                 break;
00654                                         }
00655                                         else if(frameSize > -1 && data.size() > currPos+frameSize+1 && data.at(currPos+frameSize+1) != frameEnd)
00656                                         { //If we know our frame size, and have enough data, and our frame stop
00657                                                 //byte is not there, then we need to move our startPos hypothesis one
00658                                                 //byte forward and start the whole thing over again
00659                                                 if(frameLength == -1)
00660                                                         frameSize = -1;
00661                                                 startPos++;
00662                                                 currPos = startPos;
00663                                         }
00664                                         else if(frameSize > -1 && data.size() > currPos+frameSize+1 && data.at(currPos+frameSize+1) == frameEnd)
00665                                         { //All constraints satisfied - we have our frame
00666                                                 return std::vector<unsigned char>(data.begin()+startPos+startFrameOffset, data.begin()+startPos+startFrameOffset+frameSize);
00667                                         }
00668                                 }
00669                         }
00670                 }
00671                 else
00672                 { //If the serial read returned 0 bytes, then just wait for a bit before reading again
00673                         usleep(1000);
00674 
00675                         //If the timer has expired, then let's just return an empty vector
00676                         if(timer.getSecs() > timeout && timeout > 0)
00677                                 return std::vector<unsigned char>();
00678                 }
00679         }
00680         return std::vector<unsigned char>();
00681 }
00682 
00683 
00684 // ######################################################################
00685 int Serial::write(const void* buffer, const int nbytes)
00686 {
00687         //char c[3] = { 0xff, 0x01, 0xff };
00688         //::write(dev, c, 3);
00689 
00690         int n = ::write(dev, buffer, nbytes);
00691 
00692         /*
00693         //LINFO("----------------- WRITE --------------------");
00694         for(int i=0; i<n; ++i)
00695         {
00696         fprintf(stderr, "%02X ",
00697         (static_cast<const unsigned char*>(buffer)[i])&0xff);
00698         }
00699         fprintf(stderr,"\n");
00700         //LINFO("-------------------------------------------");
00701          */
00702 
00703         if(n==-1)
00704                 serialErrno = serialErrWriteFailed;
00705 
00706         return n;
00707 }
00708 
00709 // ######################################################################
00710 int Serial::write(const unsigned char character)
00711 {
00712         return write(&character, 1);
00713 }
00714 
00715 
00716 // ######################################################################
00717 void Serial::flush(void)
00718 {
00719         //Flush the input
00720         int status = tcflush(dev,TCIFLUSH);
00721         if(status != 0)
00722                 LERROR("BAD SERIAL FLUSH");
00723 
00724 }
00725 
00726 // ######################################################################
00727 void Serial::perror(void)
00728 {
00729         switch(serialErrno)
00730         {
00731                 case serialErrSuccess:
00732                         LERROR("Serial::OK");
00733                         return;
00734                 case serialErrOpenNoTty:
00735                         LERROR("Serial::Open() No TTY Failed");
00736                         break;
00737                 case serialErrOpenFailed:
00738                         LERROR("Serial::Open() Failed");
00739                         break;
00740                 case serialErrSpeedInvalid:
00741                         LERROR("Serial::setSpeed() Invalid Speed Param");
00742                         break;
00743                 case serialErrFlowInvalid:
00744                         LERROR("Serial::setFlow() Invalid Flow Param");
00745                         break;
00746                 case serialErrParityInvalid:
00747                         LERROR("Serial::setParity() Invalid parity Param");
00748                         break;
00749                 case serialErrCharsizeInvalid:
00750                         LERROR("Serial::setCharSize() Invalid Char Size");
00751                         break;
00752                 case serialErrStopbitsInvalid:
00753                         LERROR("Serial::setStopBits() Invalid Stop Bits");
00754                         break;
00755                 case serialErrOptionInvalid:
00756                         LERROR("Serial::read() invalid option");
00757                         break;
00758                 case serialErrOutput:
00759                         LERROR("Serial::read() err output");
00760                         break;
00761                 case serialErrReadFailed:
00762                         LERROR("Serial::read() Failed");
00763                         break;
00764                 case serialErrReadTimedOut:
00765                         LERROR("Serial::read() Timed Out");
00766                         break;
00767                 case serialErrWriteFailed:
00768                         LERROR("Serial::Write() Failed");
00769                         break;
00770                 case serialErrFcntlFailed:
00771                         LERROR("Serial::Fcntl() Failed");
00772                         break;
00773                 case serialErrTcGetAttrFailed:
00774                         LERROR("Serial::tcgetattr() Failed");
00775                         break;
00776                 case serialErrTcSetAttrFailed:
00777                         LERROR("Serial::tcsetattr() Failed");
00778                         break;
00779                 default:
00780                         LERROR("Unknow error!");
00781         }
00782 }
00783 
00784 
00785 // ######################################################################
00786 Serial::~Serial(void)
00787 {  }
00788 
00789 
00790 
00791 // ######################################################################
00792 /* So things look consistent in everyone's emacs... */
00793 /* Local Variables: */
00794 /* indent-tabs-mode: nil */
00795 /* End: */
Generated on Sun May 8 08:04:45 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3