Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

ArSerialConnection_WIN.cpp

00001 /*
00002 ActivMedia Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004,2005 ActivMedia Robotics, LLC
00004 
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 ActivMedia Robotics for information about a commercial version of ARIA at 
00022 robots@activmedia.com or 
00023 ActivMedia Robotics, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 
00025 */
00026 
00027 #include "ArExport.h"
00028 #include "ariaOSDef.h"
00029 #include "ArSerialConnection.h"
00030 #include "ArLog.h"
00031 #include "ariaUtil.h"
00032 
00033 
00034 ArSerialConnection::ArSerialConnection()
00035 {
00036   myPort = INVALID_HANDLE_VALUE;
00037   myBaudRate = 9600;
00038   myStatus = STATUS_NEVER_OPENED;
00039   myHardwareControl = false;
00040   buildStrMap();
00041 }
00042 
00043 ArSerialConnection::~ArSerialConnection()
00044 {
00045   if (myPort != INVALID_HANDLE_VALUE)
00046     close();
00047 }
00048 
00049 void ArSerialConnection::buildStrMap(void)
00050 {
00051   myStrMap[OPEN_COULD_NOT_OPEN_PORT] = "Could not open serial port.";
00052   myStrMap[OPEN_COULD_NOT_SET_UP_PORT] = "Could not set up serial port.";
00053   myStrMap[OPEN_INVALID_BAUD_RATE] = "Baud rate invalid, could not set baud on serial port.";
00054   myStrMap[OPEN_COULD_NOT_SET_BAUD] = "Could not set baud rate on serial port.";
00055   myStrMap[OPEN_ALREADY_OPEN] = "Serial port already open.";
00056 }
00057 
00058 const char * ArSerialConnection::getOpenMessage(int messageNumber)
00059 {
00060   return myStrMap[messageNumber].c_str();
00061 }
00062 
00063 bool ArSerialConnection::openSimple(void)
00064 {
00065   if (internalOpen() == 0)
00066     return true;
00067   else
00068     return false;
00069 }
00070 
00077 void ArSerialConnection::setPort(const char *port)
00078 {
00079   if (port == NULL)
00080     myPortName = "COM1";
00081   else
00082     myPortName = port;
00083 }
00084 
00088 const char * ArSerialConnection::getPort(void)
00089 {
00090   return myPortName.c_str();
00091 }
00092 
00099 int ArSerialConnection::open(const char *port)
00100 {
00101   setPort(port);
00102   return internalOpen();
00103 }
00104 
00105 
00106 
00107 int ArSerialConnection::internalOpen(void)
00108 {
00109   DCB dcb;
00110 
00111 
00112   if (myStatus == STATUS_OPEN) 
00113   {
00114     ArLog::log(ArLog::Terse, 
00115                "ArSerialConnection::open: Serial port already open");
00116     return OPEN_ALREADY_OPEN;
00117   }
00118 
00119   myPort = CreateFile(myPortName.c_str(),
00120                       GENERIC_READ | GENERIC_WRITE,
00121                       0,        /* exclusive access  */
00122                       NULL,     /* no security attrs */
00123                       OPEN_EXISTING,
00124                       0,
00125                       NULL );
00126 
00127   if (myPort == INVALID_HANDLE_VALUE) {
00128     ArLog::log(ArLog::Terse, 
00129                "ArSerialConnection::open: Could not open serial port '%s'",
00130                myPortName.c_str());
00131     return OPEN_COULD_NOT_OPEN_PORT;
00132   }
00133              
00134   if ( !GetCommState(myPort, &dcb) )
00135   {  
00136     ArLog::log(ArLog::Terse, 
00137                "ArSerialConnection::open: Could not get port data to set up port");
00138     close();
00139     myStatus = STATUS_OPEN_FAILED;
00140     return OPEN_COULD_NOT_SET_UP_PORT;
00141   }
00142   
00143   dcb.ByteSize = 8;
00144   dcb.Parity = NOPARITY;
00145   dcb.StopBits = ONESTOPBIT;
00146   dcb.fOutxCtsFlow = FALSE;
00147   dcb.fOutxDsrFlow = 0;
00148   dcb.fBinary = TRUE;
00149   dcb.fParity = FALSE;
00150   dcb.fNull = FALSE;
00151   dcb.fOutX = FALSE;
00152   dcb.fInX =  FALSE;
00153 
00154   if ( !SetCommState(myPort, &dcb) )
00155   {  
00156     ArLog::log(ArLog::Terse, 
00157                "ArSerialConnection::open: Could not set up port");
00158     close();
00159     myStatus = STATUS_OPEN_FAILED;
00160     return OPEN_COULD_NOT_SET_UP_PORT;
00161   }
00162 
00163   myStatus = STATUS_OPEN;
00164 
00165   if (!setBaud(myBaudRate)) 
00166   {
00167     ArLog::log(ArLog::Terse, 
00168                "ArSerialConnection::open: Could not set baud rate.");
00169     close();
00170     myStatus = STATUS_OPEN_FAILED;
00171     return OPEN_COULD_NOT_SET_BAUD;
00172   }
00173   
00174   if (!setHardwareControl(myHardwareControl)) 
00175   {
00176     ArLog::log(ArLog::Terse, 
00177                "ArSerialConnection::open: Could not set hardware control.");
00178     close();
00179     myStatus = STATUS_OPEN_FAILED;
00180     return OPEN_COULD_NOT_SET_UP_PORT;
00181   }
00182 
00183   ArLog::log(ArLog::Verbose,
00184              "ArSerialConnection::open: Successfully opened and configured serial port.");
00185   return 0;
00186 }
00187 
00188 
00189 
00190 bool ArSerialConnection::close(void)
00191 {
00192   bool ret;
00193 
00194   if (myPort == INVALID_HANDLE_VALUE)
00195     return true;
00196 
00197   /* disable event notification  */
00198   SetCommMask( myPort, 0 ) ;
00199   /* drop DTR   */
00200   EscapeCommFunction( myPort, CLRDTR ) ;
00201   /* purge any outstanding reads/writes and close device handle  */
00202   PurgeComm( myPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
00203 
00204   myStatus = STATUS_CLOSED_NORMALLY;
00205 
00206   ret = CloseHandle( myPort ) ;
00207   if (ret)
00208     ArLog::log(ArLog::Verbose,
00209                "ArSerialConnection::close: Successfully closed serial port.");
00210   else
00211     ArLog::log(ArLog::Verbose, 
00212                "ArSerialConnection::close: Unsuccessfully closed serial port.");
00213   myPort = (HANDLE) INVALID_HANDLE_VALUE;
00214   return ret;
00215 }
00216 
00217 int ArSerialConnection::getBaud(void)
00218 {
00219    return myBaudRate;
00220 }
00221 
00222 bool ArSerialConnection::setBaud(int baud)
00223 {
00224   DCB dcb;
00225   
00226   myBaudRate = baud;
00227 
00228   if (getStatus() != STATUS_OPEN)
00229     return true;
00230   
00231   if ( !GetCommState(myPort, &dcb) )
00232   {
00233     ArLog::log(ArLog::Terse, "ArSerialConnection::setBaud: Could not get port Data.");
00234     return false;
00235   }
00236 
00237   dcb.BaudRate = myBaudRate;
00238 
00239   if ( !SetCommState(myPort, &dcb) )
00240   {  
00241     ArLog::log(ArLog::Terse,
00242                "ArSerialConnection::setBaud: Could not set port Data.");
00243     return false;
00244   }  
00245 
00246   return true;
00247 }
00248 
00249 bool ArSerialConnection::getHardwareControl(void)
00250 {
00251   return myHardwareControl;
00252 }
00253 
00254 bool ArSerialConnection::setHardwareControl(bool hardwareControl)
00255 {
00256   DCB dcb;
00257 
00258   myHardwareControl = hardwareControl;
00259 
00260   if (getStatus() != STATUS_OPEN)
00261     return true;
00262  
00263   if ( !GetCommState(myPort, &dcb) )
00264   {
00265     ArLog::log(ArLog::Terse,
00266                "ArSerialConnection::setBaud: Could not get port Data.");
00267     return false;
00268   }
00269   
00270   if (myHardwareControl == 0) /* set control lines */
00271   {
00272     dcb.fRtsControl = RTS_CONTROL_ENABLE;
00273     dcb.fDtrControl = DTR_CONTROL_ENABLE;
00274   }
00275   else
00276   {
00277     dcb.fRtsControl = RTS_CONTROL_DISABLE;
00278     dcb.fDtrControl = DTR_CONTROL_DISABLE;
00279   }
00280 
00281   if ( !SetCommState(myPort, &dcb) )
00282   {  
00283     ArLog::log(ArLog::Terse, "ArSerialConnection::setBaud: Could not set port Data.");
00284     return false;
00285   }  
00286   
00287   return true;
00288 }
00289 
00290 int ArSerialConnection::write(const char *data, unsigned int size) 
00291 {
00292   unsigned long ret;
00293 
00294   if (myPort != INVALID_HANDLE_VALUE && myStatus == STATUS_OPEN) 
00295   {
00296     if (!WriteFile(myPort, data, size, &ret, NULL)) 
00297     {
00298       ArLog::log(ArLog::Terse, "ArSerialConnection::write: Error on writing.");
00299       perror("ArSerialConnection::write:");
00300       return -1;
00301     }
00302     return ret;
00303   }
00304   ArLog::log(ArLog::Terse, "ArSerialConnection::write: Connection invalid.");
00305   return -1;
00306 }
00307 
00308 int ArSerialConnection::read(const char *data, unsigned int size, 
00309                                       unsigned int msWait) 
00310 {
00311   COMSTAT stat;
00312   unsigned long ret;
00313   unsigned int numToRead;
00314   ArTime timeDone;
00315 
00316   if (myPort != INVALID_HANDLE_VALUE && myStatus == STATUS_OPEN)
00317   {
00318     if (msWait > 0)
00319     {
00320       timeDone.setToNow();
00321       timeDone.addMSec(msWait);
00322       while (timeDone.mSecTo() >= 0) 
00323       {
00324         if (!ClearCommError(myPort, &ret, &stat))
00325           return -1;
00326         if (stat.cbInQue < size)
00327           ArUtil::sleep(2);
00328         else
00329           break;
00330       }
00331     }
00332     if (!ClearCommError(myPort, &ret, &stat))
00333       return -1;
00334     if (stat.cbInQue == 0)
00335       return 0;
00336     if (stat.cbInQue > size)
00337       numToRead = size;
00338     else
00339       numToRead = stat.cbInQue;
00340     if (ReadFile( myPort, (void *)data, numToRead, &ret, NULL))
00341     {
00342       return (int)ret;
00343     }
00344     else 
00345     {
00346       ArLog::log(ArLog::Terse, "ArSerialConnection::read:  Read failed.");
00347       return -1;
00348     }
00349   }
00350   ArLog::log(ArLog::Terse, "ArSerialConnection::read: Connection invalid.");
00351   return -1;
00352 }
00353 
00354 
00355 int ArSerialConnection::getStatus(void)
00356 {
00357   return myStatus;
00358 }
00359 
00360 bool ArSerialConnection::isTimeStamping(void)
00361 {
00362   return false;
00363 }
00364 
00365 ArTime ArSerialConnection::getTimeRead(int index)
00366 {
00367   ArTime now;
00368   now.setToNow();
00369   return now;
00370 }
00371 
00372 bool ArSerialConnection::getCTS(void)
00373 {
00374   DWORD modemStat;
00375   if (GetCommModemStatus(myPort, &modemStat))
00376   {
00377     return (bool) (modemStat & MS_CTS_ON);
00378   }
00379   else
00380   {
00381     fprintf(stderr, "problem with GetCommModemStatus\n");
00382     return false;
00383   }
00384 } 
00385 
00386 bool ArSerialConnection::getDSR(void)
00387 {
00388   DWORD modemStat;
00389   if (GetCommModemStatus(myPort, &modemStat))
00390   {
00391     return (bool) (modemStat & MS_DSR_ON);
00392   }
00393   else
00394   {
00395     fprintf(stderr, "problem with GetCommModemStatus\n");
00396     return false;
00397   }
00398 } 
00399 
00400 bool ArSerialConnection::getDCD(void)
00401 {
00402   DWORD modemStat;
00403   if (GetCommModemStatus(myPort, &modemStat))
00404   {
00405     return (bool) (modemStat & MS_RLSD_ON);
00406   }
00407   else
00408   {
00409     fprintf(stderr, "problem with GetCommModemStatus\n");
00410     return false;
00411   }
00412 }
00413 
00414 bool ArSerialConnection::getRing(void)
00415 {
00416   DWORD modemStat;
00417   if (GetCommModemStatus(myPort, &modemStat))
00418   {
00419     return (bool) (modemStat & MS_RING_ON);
00420   }
00421   else
00422   {
00423     fprintf(stderr, "problem with GetCommModemStatus\n");
00424     return false;
00425   }
00426 }
00427 

Generated on Wed Oct 19 12:56:36 2005 for Aria by  doxygen 1.4.0