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
00028
00029
00030
00031
00032
00033
00034
00035
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"
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
00086
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
00100 directory_p = ::opendir ("/dev");
00101 if (directory_p == NULL)
00102 LFATAL("Could Not Open /dev Directory!");
00103
00104
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 {
00110
00111
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;
00148
00149 openPort(DeviceName);
00150 perror();
00151
00152 setSpeed(itsBaud.getVal());
00153 perror();
00154
00155 setFlowControl(itsFlowHard.getVal(),
00156 itsFlowSoft.getVal());
00157 perror();
00158
00159 setCharBits(itsCharBits.getVal());
00160 perror();
00161
00162 setParity(itsUseParity.getVal(),
00163 itsParityOdd.getVal());
00164 perror();
00165
00166 setBlocking(itsBlocking.getVal());
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
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
00197
00198
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
00291 if(tcgetattr(dev, &options)==-1){
00292 serialErrno = serialErrTcGetAttrFailed;
00293 return serialErrno;
00294 }
00295
00296
00297 cfsetispeed(&options, rate);
00298 cfsetospeed(&options, rate);
00299
00300
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
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
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;
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
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
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
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
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
00501
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
00510 if( tcgetattr(dev, &savedState) == -1 ){
00511 serialErrno = serialErrTcGetAttrFailed;
00512 return -1;
00513 }
00514
00515
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
00527 options.c_cflag |= ( CLOCAL
00528 | CREAD );
00529
00530 options.c_iflag &= ~( IGNBRK
00531 | BRKINT
00532
00533 | PARMRK
00534 | ISTRIP
00535 | INLCR
00536 | IGNCR
00537 | ICRNL
00538 | IXON
00539 );
00540
00541
00542 options.c_oflag &= ~OPOST;
00543 options.c_lflag &= ~(ECHO
00544 | ECHONL
00545 | ICANON
00546 | ISIG
00547 | IEXTEN
00548 );
00549
00550
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
00612 if(timeout > 0 && timer.getSecs() > timeout)
00613 return std::vector<unsigned char>();
00614
00615
00616 int bytesRead = read(buffer, 1024);
00617
00618
00619
00620
00621
00622
00623
00624
00625 if(bytesRead > 0)
00626 {
00627
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
00634 if(timeout > 0 && timer.getSecs() > timeout)
00635 return std::vector<unsigned char>();
00636
00637 if(data.at(startPos) != frameStart)
00638 {
00639 currPos++;
00640 startPos = currPos;
00641 }
00642 else
00643 {
00644
00645 if(frameLength == -1 && frameSize == -1 && (startPos+1 < data.size()) )
00646 {
00647 frameSize = data.at(startPos+1);
00648 currPos++;
00649 }
00650 else if(frameSize > -1 && data.size() <= currPos+frameSize+1)
00651 {
00652
00653 break;
00654 }
00655 else if(frameSize > -1 && data.size() > currPos+frameSize+1 && data.at(currPos+frameSize+1) != frameEnd)
00656 {
00657
00658
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 {
00666 return std::vector<unsigned char>(data.begin()+startPos+startFrameOffset, data.begin()+startPos+startFrameOffset+frameSize);
00667 }
00668 }
00669 }
00670 }
00671 else
00672 {
00673 usleep(1000);
00674
00675
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
00688
00689
00690 int n = ::write(dev, buffer, nbytes);
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
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
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
00793
00794
00795