00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "ArExport.h"
00028 #include "ariaOSDef.h"
00029 #include <sys/time.h>
00030 #include <termios.h>
00031 #include <unistd.h>
00032 #include <sys/types.h>
00033 #include <sys/stat.h>
00034 #include <sys/ioctl.h>
00035 #include <fcntl.h>
00036 #include <errno.h>
00037
00038 #include "ArSerialConnection.h"
00039 #include "ArLog.h"
00040 #include "ariaUtil.h"
00041
00042
00043 ArSerialConnection::ArSerialConnection()
00044 {
00045 myPort = -1;
00046 myPortName = "none";
00047 myBaudRate = 9600;
00048 myHardwareControl = false;
00049 myStatus = STATUS_NEVER_OPENED;
00050 myTakingTimeStamps = false;
00051 buildStrMap();
00052 }
00053
00054 ArSerialConnection::~ArSerialConnection()
00055 {
00056 if (myPort != -1)
00057 close();
00058 }
00059
00060 void ArSerialConnection::buildStrMap(void)
00061 {
00062 myStrMap[OPEN_COULD_NOT_OPEN_PORT] = "Could not open serial port.";
00063 myStrMap[OPEN_COULD_NOT_SET_UP_PORT] = "Could not set up serial port.";
00064 myStrMap[OPEN_INVALID_BAUD_RATE] = "Baud rate invalid, could not set baud on serial port.";
00065 myStrMap[OPEN_COULD_NOT_SET_BAUD] = "Could not set baud rate on serial port.";
00066 myStrMap[OPEN_ALREADY_OPEN] = "Serial port already open.";
00067 }
00068
00069 const char * ArSerialConnection::getOpenMessage(int messageNumber)
00070 {
00071 return myStrMap[messageNumber].c_str();
00072 }
00073
00074 int ArSerialConnection::internalOpen(void)
00075 {
00076 struct termios tio;
00077
00078 if (myStatus == STATUS_OPEN)
00079 {
00080 ArLog::log(ArLog::Terse, "ArSerialConnection::open: Serial port already open");
00081 return OPEN_ALREADY_OPEN;
00082 }
00083
00084
00085 if ((myPort = ::open(myPortName.c_str(),O_RDWR | O_NDELAY)) < 0)
00086 {
00087 ArLog::log(ArLog::Terse, "ArSerialConnection::open: Could not open serial port '%s'", myPortName.c_str());
00088 return OPEN_COULD_NOT_OPEN_PORT;
00089 }
00090
00091
00092 if (tcgetattr(myPort, &tio) != 0)
00093 {
00094 ArLog::log(ArLog::Terse, "ArSerialConnection::open: Could not get port data to set up port");
00095 close();
00096 myStatus = STATUS_OPEN_FAILED;
00097 return OPEN_COULD_NOT_SET_UP_PORT;
00098 }
00099
00100
00101 tio.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
00102
00103
00104 tio.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
00105
00106
00107 tio.c_cflag &= ~(CSIZE | PARENB);
00108
00109
00110 tio.c_cflag |= CS8;
00111
00112
00113 tio.c_oflag &= ~(OPOST);
00114
00115
00116 tio.c_cc[VTIME] = 0;
00117 tio.c_cc[VMIN] = 0;
00118
00119 if (tcsetattr(myPort,TCSAFLUSH,&tio) < 0)
00120 {
00121 ArLog::log(ArLog::Terse,
00122 "ArSerialConnection::open: Could not set up port");
00123 close();
00124 myStatus = STATUS_OPEN_FAILED;
00125 return OPEN_COULD_NOT_SET_UP_PORT;
00126 }
00127
00128 myStatus = STATUS_OPEN;
00129
00130 if (rateToBaud(myBaudRate) == -1)
00131 {
00132 ArLog::log(ArLog::Terse, "ArSerialConnection::open: Invalid baud rate.");
00133 close();
00134 myStatus = STATUS_OPEN_FAILED;
00135 return OPEN_INVALID_BAUD_RATE;
00136 }
00137
00138 if (!setBaud(myBaudRate))
00139 {
00140 ArLog::log(ArLog::Terse,
00141 "ArSerialConnection::open: Could not set baud rate.");
00142 close();
00143 myStatus = STATUS_OPEN_FAILED;
00144 return OPEN_COULD_NOT_SET_BAUD;
00145 }
00146
00147 if (!setHardwareControl(myHardwareControl))
00148 {
00149 ArLog::log(ArLog::Terse,
00150 "ArSerialConnection::open: Could not set hardware control.");
00151 close();
00152 myStatus = STATUS_OPEN_FAILED;
00153 return OPEN_COULD_NOT_SET_UP_PORT;
00154 }
00155
00156 ArLog::log(ArLog::Verbose, "ArSerialConnection::open: Successfully opened and configured serial port.");
00157 return 0;
00158 }
00159
00160 bool ArSerialConnection::openSimple(void)
00161 {
00162 if (internalOpen() == 0)
00163 return true;
00164 else
00165 return false;
00166 }
00167
00173 void ArSerialConnection::setPort(const char *port)
00174 {
00175 if (port == NULL)
00176 myPortName = "/dev/ttyS0";
00177 else
00178 myPortName = port;
00179 }
00180
00184 const char * ArSerialConnection::getPort(void)
00185 {
00186 return myPortName.c_str();
00187 }
00188
00195 int ArSerialConnection::open(const char *port)
00196 {
00197 setPort(port);
00198 return internalOpen();
00199 }
00200
00201 bool ArSerialConnection::close(void)
00202 {
00203 int ret;
00204
00205 myStatus = STATUS_CLOSED_NORMALLY;
00206 if (myPort == -1)
00207 return true;
00208
00209
00210 ret = ::close(myPort);
00211
00212 if (ret == 0)
00213 ArLog::log(ArLog::Verbose,
00214 "ArSerialConnection::close: Successfully closed serial port.");
00215 else
00216 ArLog::log(ArLog::Verbose,
00217 "ArSerialConnection::close: Unsuccessfully closed serial port.");
00218
00219 myPort = -1;
00220 if (ret == 0)
00221 return true;
00222 else
00223 return false;
00224 }
00225
00231 bool ArSerialConnection::setBaud(int rate)
00232 {
00233 struct termios tio;
00234 int baud;
00235
00236 myBaudRate = rate;
00237
00238 if (getStatus() != STATUS_OPEN)
00239 return true;
00240
00241 if ((baud = rateToBaud(myBaudRate)) == -1)
00242 return false;
00243
00244 if (tcgetattr(myPort, &tio) != 0)
00245 {
00246 ArLog::log(ArLog::Terse, "ArSerialConnection::setBaud: Could not get port data.");
00247 return false;
00248 }
00249
00250 if (cfsetospeed(&tio, baud))
00251 {
00252 ArLog::log(ArLog::Terse, "ArSerialConnection::setBaud: Could not set output baud rate on termios struct.");
00253 return false;
00254 }
00255
00256 if (cfsetispeed(&tio, baud))
00257 {
00258 ArLog::log(ArLog::Terse, "ArSerialConnection::setBaud: Could not set input baud rate on termios struct.");
00259 return false;
00260 }
00261
00262 if(tcsetattr(myPort,TCSAFLUSH,&tio) < 0)
00263 {
00264 ArLog::log(ArLog::Terse, "ArSerialConnection::setBaud: Could not set baud rate.");
00265 return false;
00266 }
00267
00268 startTimeStamping();
00269
00270 return true;
00271 }
00272
00273 void ArSerialConnection::startTimeStamping(void)
00274 {
00275 long baud;
00276 baud = myBaudRate;
00277 if (ioctl(myPort, TIOSTARTTIMESTAMP, &baud) != 0)
00278 myTakingTimeStamps = false;
00279 else
00280 myTakingTimeStamps = true;
00281 }
00282
00287 int ArSerialConnection::getBaud(void)
00288 {
00289 return myBaudRate;
00290 }
00291
00292 int ArSerialConnection::rateToBaud(int rate)
00293 {
00294 switch (rate) {
00295 case 300: return B300;
00296 case 1200: return B1200;
00297 case 1800: return B1800;
00298 case 2400: return B2400;
00299 case 4800: return B4800;
00300 case 9600: return B9600;
00301 case 19200: return B19200;
00302 case 38400: return B38400;
00303 case 57600: return B57600;
00304 case 115200: return B115200;
00305 default:
00306 ArLog::log(ArLog::Terse, "ArSerialConnection::rateToBaud: Did not know baud for rate %d.", rate);
00307 return -1;
00308 }
00309 }
00310
00311 int ArSerialConnection::baudToRate(int baud)
00312 {
00313 switch (baud) {
00314 case B300: return 300;
00315 case B1200: return 1200;
00316 case B1800: return 1800;
00317 case B2400: return 2400;
00318 case B4800: return 4800;
00319 case B9600: return 9600;
00320 case B19200: return 19200;
00321 case B38400: return 38400;
00322 case B57600: return 57600;
00323 case B115200: return 115200;
00324 default:
00325 ArLog::log(ArLog::Terse, "ArSerialConnection:baudToRate: Did not know rate for baud.");
00326 return -1;
00327 }
00328
00329 }
00330
00336 bool ArSerialConnection::setHardwareControl(bool hardwareControl)
00337 {
00338 struct termios tio;
00339
00340 myHardwareControl = hardwareControl;
00341
00342 if (getStatus() != STATUS_OPEN)
00343 return true;
00344
00345 tcgetattr(myPort, &tio);
00346
00347
00348 if (myHardwareControl)
00349 tio.c_cflag |= CRTSCTS;
00350 else
00351 tio.c_cflag &= ~CRTSCTS;
00352
00353 if(tcsetattr(myPort,TCSAFLUSH,&tio) < 0) {
00354 ArLog::log(ArLog::Terse, "ArSerialConnection::setHardwareControl: Could not set hardware control.");
00355 return false;
00356 }
00357
00358 return true;
00359 }
00360
00364 bool ArSerialConnection::getHardwareControl(void)
00365 {
00366 return myHardwareControl;
00367 }
00368
00369 int ArSerialConnection::write(const char *data, unsigned int size)
00370 {
00371 int n;
00372
00373
00374
00375
00376
00377
00378 if (myPort >= 0)
00379 {
00380 n = ::write(myPort, data, size);
00381 if (n == -1)
00382 {
00383 if (errno == EAGAIN)
00384 {
00385 usleep(10);
00386 n = ::write(myPort, data, size);
00387 if (n >= 0)
00388 return n;
00389 }
00390 ArLog::log(ArLog::Terse, "ArSerialConnection::write: Error on writing.");
00391 perror("ArSerialConnection::write:");
00392 }
00393 return n;
00394 }
00395 ArLog::log(ArLog::Terse, "ArSerialConnection::write: Connection invalid.");
00396 return -1;
00397 }
00398
00399 int ArSerialConnection::read(const char *data, unsigned int size,
00400 unsigned int msWait)
00401 {
00402 struct timeval tp;
00403 fd_set fdset;
00404 int n;
00405 long timeLeft;
00406 unsigned int bytesRead = 0;
00407 ArTime timeDone;
00408
00409 if (myPort >= 0)
00410 {
00411 if (msWait >= 0)
00412 {
00413 timeDone.setToNow();
00414 timeDone.addMSec(msWait);
00415 while ((timeLeft = timeDone.mSecTo()) >= 0)
00416 {
00417 tp.tv_sec = (timeLeft) / 1000;
00418 tp.tv_usec = (timeLeft % 1000) * 1000;
00419 FD_ZERO(&fdset);
00420 FD_SET(myPort,&fdset);
00421 if (select(myPort+1,&fdset,NULL,NULL,&tp) <= 0)
00422 return bytesRead;
00423 if ((n = ::read(myPort, const_cast<char *>(data)+bytesRead,
00424 size-bytesRead)) == -1)
00425 {
00426 ArLog::log(ArLog::Terse, "ArSerialConnection::read: Blocking read failed.");
00427 return bytesRead;
00428 }
00429 bytesRead += n;
00430 if (bytesRead >= size)
00431 return bytesRead;
00432 }
00433 return bytesRead;
00434 }
00435 else
00436 {
00437 n = ::read(myPort, const_cast<char *>(data), size);
00438 if (n == -1)
00439 ArLog::log(ArLog::Terse, "ArSerialConnection::read: Non-Blocking read failed.");
00440 return n;
00441 }
00442 }
00443 ArLog::log(ArLog::Terse, "ArSerialConnection::read: Connection invalid.");
00444 return -1;
00445 }
00446
00447 int ArSerialConnection::getStatus(void)
00448 {
00449 return myStatus;
00450 }
00451
00452 ArTime ArSerialConnection::getTimeRead(int index)
00453 {
00454 ArTime ret;
00455 struct timeval timeStamp;
00456 if (myPort <= 0)
00457 {
00458 ret.setToNow();
00459 return ret;
00460 }
00461
00462 if (myTakingTimeStamps)
00463 {
00464 timeStamp.tv_sec = index;
00465 if (ioctl(myPort, TIOGETTIMESTAMP, &timeStamp) == 0)
00466 {
00467 ret.setSec(timeStamp.tv_sec);
00468 ret.setMSec(timeStamp.tv_usec / 1000);
00469 }
00470 else
00471 ret.setToNow();
00472 }
00473 else
00474 ret.setToNow();
00475
00476 return ret;
00477 }
00478
00479 bool ArSerialConnection::isTimeStamping(void)
00480 {
00481 return myTakingTimeStamps;
00482 }
00483
00484
00485 bool ArSerialConnection::getCTS(void)
00486 {
00487 unsigned int value;
00488 if (ioctl(myPort, TIOCMGET, &value) == 0)
00489 {
00490 return (bool) (value & TIOCM_CTS);
00491 }
00492 else
00493 {
00494 perror("ioctl: TIOCMGET");
00495 return false;
00496 }
00497 }
00498
00499 bool ArSerialConnection::getDSR(void)
00500 {
00501 unsigned int value;
00502 if (ioctl(myPort, TIOCMGET, &value) == 0)
00503 {
00504 return (bool) (value & TIOCM_DSR);
00505 }
00506 else
00507 {
00508 perror("ioctl: TIOCMGET");
00509 return false;
00510 }
00511 }
00512
00513 bool ArSerialConnection::getDCD(void)
00514 {
00515 unsigned int value;
00516 if (ioctl(myPort, TIOCMGET, &value) == 0)
00517 {
00518 return (bool) (value & TIOCM_CAR);
00519 }
00520 else
00521 {
00522 perror("ioctl: TIOCMGET");
00523 return false;
00524 }
00525 }
00526
00527 bool ArSerialConnection::getRing(void)
00528 {
00529 unsigned int value;
00530 if (ioctl(myPort, TIOCMGET, &value) == 0)
00531 {
00532 return (bool) (value & TIOCM_RI);
00533 }
00534 else
00535 {
00536 perror("ioctl: TIOCMGET");
00537 return false;
00538 }
00539 }