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

ArSerialConnection_WIN.cpp

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

Generated on Tue Feb 20 10:51:41 2007 for Aria by  doxygen 1.4.0