serialport.cpp

Go to the documentation of this file.
00001 //======================================================================
00002 // File:        serialport.cpp
00003 // Author:      Matthias Toussaint
00004 // Created:     Sat Nov 25 13:49:23 CET 2006
00005 // Project:     QtDMM
00006 // Description: Encapsulation of serial port
00007 //----------------------------------------------------------------------
00008 // This file  may  be used under  the terms of  the GNU  General Public
00009 // License  version 2.0 as published   by the Free Software  Foundation
00010 // and appearing  in the file LICENSE.GPL included  in the packaging of
00011 // this file.
00012 // 
00013 // This file is provided AS IS with  NO WARRANTY OF ANY KIND, INCLUDING 
00014 // THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
00015 // PURPOSE.
00016 //----------------------------------------------------------------------
00017 // Copyright 2006 Matthias Toussaint
00018 //======================================================================
00019 
00020 #include <serialport.h>
00021 #include <errno.h>
00022 #include <ctype.h>
00023 #include <iostream>
00024 #include <util.h>
00025 
00026 SerialPort::SerialPort() : 
00027   Port()
00028 {
00029 }
00030 
00031 SerialPort::~SerialPort()
00032 {
00033   close();
00034 }
00035 
00036 Port::Error SerialPort::open( const std::string & config )
00037 {
00038   bool rts=false, dtr=false, dsr=false, cts=false;
00039   
00040   TokenList token = Util::tokenize( config, ":" );
00041   int tokenCnt = token.size();
00042   
00043   for (int i=5; i<tokenCnt; ++i)
00044   {
00045     for (unsigned j=0; j<token[i].size(); ++j) 
00046     {
00047       token[i][j] = toupper( token[i][j] );
00048     }
00049     if (token[i] == "RTS")      rts=true;
00050     else if (token[i] == "DTR") dtr=true;
00051     else if (token[i] == "DSR") dsr=true;
00052     else if (token[i] == "CTS") cts=true;
00053   }
00054   
00055   int baud; 
00056   if (!Util::fromString( &baud, token[1] )) return Port::SyntaxError;
00057   int bits; 
00058   if (!Util::fromString( &bits, token[2] )) return Port::SyntaxError;
00059   int stopBits; 
00060   if (!Util::fromString( &stopBits, token[4] )) return Port::SyntaxError;
00061   
00062   int parity = -1;
00063   
00064   if (token[3] == "N" || token[3] == "n") parity = 0;
00065   if (token[3] == "E" || token[3] == "e") parity = 1;
00066   if (token[3] == "O" || token[3] == "o") parity = 2;
00067   
00068   if (parity == -1) return Port::UnknownParity;
00069   if (stopBits != 1 && stopBits != 2) return Port::UnknownStopBits;
00070   
00071   tcflag_t cflag = CREAD | CLOCAL;
00072   
00073   if (stopBits == 2)
00074   {
00075     cflag |= CSTOPB;
00076   }
00077   
00078   switch (bits)
00079   {
00080     case 5:
00081       cflag |= CS5;
00082       break;
00083     case 6:
00084       cflag |= CS6;
00085       break;
00086     case 7:
00087       cflag |= CS7;
00088       break;
00089     case 8:
00090       cflag |= CS8;
00091       break;
00092     default:
00093       return Port::UnknownNumberOfBits;
00094   }
00095   
00096   switch (parity)
00097   {
00098     case 0: // None
00099       break;
00100     case 1: // Even
00101       cflag |= PARENB;
00102       break;
00103     case 2: // Odd
00104       cflag |= PARENB;
00105       cflag |= PARODD;
00106   }    
00107   
00108   struct termios attr;
00109   int            mdlns;
00110   
00111   memset( &attr, 0, sizeof( struct termios ) );
00112   
00113   m_handle = ::open( token[0].c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
00114   
00115   if (-1 == m_handle)
00116   {
00117     switch (errno) 
00118     {
00119       case EACCES:
00120         return Port::PermissionDenied;
00121       case ENXIO: 
00122       case ENODEV: 
00123       case ENOENT:
00124         return Port::NoSuchPort;
00125       default:  
00126         return Port::OpenError;
00127     }
00128   }
00129   
00130   fcntl( m_handle, F_SETFL, 0 );
00131   tcgetattr( m_handle, &m_oldSettings );
00132   
00133   attr.c_oflag = 0;
00134   attr.c_lflag = 0;
00135   attr.c_cflag = cflag;
00136   
00137   // According to Thomas Hoffman flags should be like this
00138   //
00139   if (0 == parity)          // Ignore parity errors
00140   {
00141     attr.c_iflag = IGNBRK | IGNPAR ;
00142   }
00143   else
00144   {
00145     attr.c_iflag = IGNBRK | INPCK | ISTRIP;
00146   }
00147   
00148   attr.c_cc[VTIME]= 0;
00149   attr.c_cc[VMIN]= 1;
00150   
00151   if (300 == baud)
00152   {
00153     cfsetospeed( &attr, B300 ); 
00154     cfsetispeed( &attr, B300 );
00155   }
00156   else if (600 == baud)
00157   {
00158     cfsetospeed( &attr, B600 ); 
00159     cfsetispeed( &attr, B600 );
00160   }
00161   else if (1200 == baud)
00162   {
00163     cfsetospeed( &attr, B1200 ); 
00164     cfsetispeed( &attr, B1200 );
00165   }
00166   else if (1800 == baud)
00167   {
00168     cfsetospeed( &attr, B1800 ); 
00169     cfsetispeed( &attr, B1800 );
00170   }
00171   else if (2400 == baud)
00172   {
00173     cfsetospeed( &attr, B2400 ); 
00174     cfsetispeed( &attr, B2400 );
00175   }
00176   else if (4800 == baud)
00177   {
00178     cfsetospeed( &attr, B4800 ); 
00179     cfsetispeed( &attr, B4800 );
00180   }
00181   else if (9600 == baud)
00182   {
00183     cfsetospeed( &attr, B9600 ); 
00184     cfsetispeed( &attr, B9600 );
00185   }
00186   else if (19200 == baud)
00187   {
00188     cfsetospeed( &attr, B19200 ); 
00189     cfsetispeed( &attr, B19200 );
00190   }
00191   else
00192   {
00193     cfsetospeed( &attr, B38400 ); 
00194     cfsetispeed( &attr, B38400 );
00195   }
00196   
00197   if (-1 == tcsetattr( m_handle, TCSANOW, &attr )) 
00198   {  
00199     goto config_error;
00200   }
00201   
00202   mdlns = 0;
00203   if (-1 == ioctl( m_handle, TIOCMGET, &mdlns )) 
00204   {
00205     goto config_error;
00206   }
00207 
00208   if (rts) mdlns |= TIOCM_RTS;
00209   else     mdlns &= ~TIOCM_RTS;
00210 
00211   if (dtr) mdlns |= TIOCM_DTR;
00212   else     mdlns &= ~TIOCM_DTR;
00213 
00214   if (dsr) mdlns |= TIOCM_DSR;
00215   else     mdlns &= ~TIOCM_DSR;
00216 
00217   if (cts) mdlns |= TIOCM_CTS;
00218   else     mdlns &= ~TIOCM_CTS;
00219   
00220   if (-1 == ioctl( m_handle, TIOCMSET, &mdlns )) 
00221   {
00222     goto config_error;
00223   }
00224   
00225   tcsetattr( m_handle, TCSAFLUSH, &attr );
00226 
00227   return Port::Ok;
00228   
00229 config_error:
00230   ::close(m_handle);
00231   m_handle = -1;
00232     
00233   return Port::ConfigError;
00234 }
00235 
00236 Port::Error SerialPort::close()
00237 {
00238   if (-1 != m_handle)
00239   {
00240     // restore
00241     ::tcsetattr( m_handle, TCSANOW, &m_oldSettings );
00242     ::close( m_handle );
00243     m_handle = -1;
00244   }
00245   
00246   return Port::Ok;
00247 }

Generated on Mon Jan 22 23:24:18 2007 for cdmm by  doxygen 1.4.6