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 "Serial.H"
00039 #include <iostream>
00040 #include <sys/types.h>
00041 #include <dirent.h>
00042 #include <unistd.h>
00043 #include <string>
00044 #include <stdio.h>
00045 #include <string.h>
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 Serial::Serial() :
00056 itsCmdDevName("/dev/ttyUSB0"),
00057 itsDeviceDescription(""),
00058 itsSearchPrefix("ttyUSB"),
00059 itsBaud(9600),
00060 itsCharBits(8),
00061 itsStopBits(1),
00062 itsUseParity(false),
00063 itsParityOdd(false),
00064 itsFlowHard(false),
00065 itsFlowSoft(false),
00066 itsRdTout(0),
00067 itsBlocking(true),
00068 itsSerialOk(false),
00069 dev(-1),
00070 itsDevName(""),
00071 serialErrno(serialErrSuccess)
00072 {
00073
00074 }
00075
00076
00077 void Serial::start()
00078 {
00079
00080
00081 printf("Looking Device Name [%s]\n",itsDevName.c_str());
00082 if(itsDevName != "")
00083 {
00084 printf("Opening %s", itsDevName.c_str());
00085 enablePort(itsDevName);
00086 } else if (itsDevName == "search") {
00087 printf("Searching for devices\n");
00088 itsCmdDevName = "";
00089
00090 DIR *directory_p;
00091 struct dirent *entry_p;
00092
00093
00094 directory_p = ::opendir ("/dev");
00095 if (directory_p == NULL)
00096 printf("Could Not Open /dev Directory!\n");
00097
00098
00099 while ((entry_p = ::readdir (directory_p)))
00100 {
00101 std::string entryName(entry_p->d_name);
00102 if(entryName.find(itsSearchPrefix.c_str()) != std::string::npos)
00103 {
00104
00105
00106
00107 enablePort("/dev/" + entryName);
00108 unsigned char cmd[1] = {0};
00109
00110 write(cmd,1);
00111 std::vector<unsigned char> deviceStringVec = readFrame(cmd[0], 255);
00112
00113 std::string deviceString(deviceStringVec.begin(), deviceStringVec.end());
00114 printf("%s : %s", entryName.c_str(), deviceString.c_str());
00115
00116 if(deviceString == itsDeviceDescription)
00117 {
00118 itsCmdDevName ="/dev/"+entryName;
00119 break;
00120 }
00121 }
00122
00123
00124 }
00125 (void) ::closedir (directory_p);
00126 if(itsCmdDevName == "")
00127 {
00128 printf("Could Not Find Serial Device Matching Descriptor (%s)\n", itsDeviceDescription.c_str());
00129 }
00130 } else {
00131 printf("Opening from cmd line %s\n", itsCmdDevName.c_str());
00132 enablePort(itsCmdDevName);
00133 }
00134 }
00135
00136
00137
00138 void Serial::enablePort(std::string DeviceName)
00139 {
00140 closePort();
00141 serialErrno = serialErrSuccess;
00142
00143 openPort(DeviceName);
00144 perror();
00145
00146 setSpeed(itsBaud);
00147 perror();
00148
00149 setFlowControl(itsFlowHard,
00150 itsFlowSoft);
00151 perror();
00152
00153 setCharBits(itsCharBits);
00154 perror();
00155
00156 setParity(itsUseParity,
00157 itsParityOdd);
00158 perror();
00159
00160 setBlocking(itsBlocking);
00161 perror();
00162 }
00163
00164
00165 #include <cstdio>
00166
00167 void Serial::stop()
00168 {
00169 closePort();
00170 }
00171
00172
00173 void Serial::closePort()
00174 {
00175 if(dev >= 0) {
00176
00177 close(dev);
00178 dev = -1; }
00179 }
00180
00181
00182 void Serial::configureSearch(const std::string DeviceDescription, const int speed, const std::string SearchPrefix, const char *format,
00183 const bool flowSoft, const bool flowHard,
00184 const int tout)
00185 {
00186 printf("Search for %s in speed %d\n",DeviceDescription.c_str(),speed);
00187 itsDevName = "search";
00188 itsDeviceDescription = DeviceDescription;
00189 itsSearchPrefix = SearchPrefix;
00190
00191
00192
00193 configure("", speed, format, flowSoft, flowHard, tout);
00194 }
00195
00196
00197 void Serial::configure(const char *dev, const int speed, const char *format,
00198 const bool flowSoft, const bool flowHard,
00199 const int tout)
00200 {
00201 itsDevName = dev;
00202
00203
00204 itsBaud = speed;
00205 itsFlowSoft = flowSoft;
00206 itsFlowHard = flowHard;
00207 itsRdTout = tout;
00208
00209 if (strlen(format) != 3) printf("Incorrect format string: %s", format);
00210
00211 switch(format[0]) {
00212 case '5': itsCharBits = 5; break;
00213 case '6': itsCharBits = 6; break;
00214 case '7': itsCharBits = 7; break;
00215 case '8': itsCharBits = 8; break;
00216 default: printf("Invalid charbits: %c (should be 5..8)", format[0]);
00217 }
00218
00219 switch(format[1]) {
00220 case 'N': itsUseParity = false; break;
00221 case 'E': itsUseParity = true; itsParityOdd = false; break;
00222 case 'O': itsUseParity = true; itsParityOdd = true; break;
00223 default: printf("Invalid parity: %c (should be N,E,O)", format[1]);
00224 }
00225
00226 switch(format[2]) {
00227 case '1': itsStopBits = (1); break;
00228 case '2': itsStopBits = (2); break;
00229 default: printf("Invalid stopbits: %c (should be 1..2)", format[2]);
00230 }
00231 }
00232
00233
00234 serialError Serial::setSpeed(const int speed)
00235 {
00236 struct termios options;
00237 unsigned int rate;
00238
00239 switch(speed)
00240 {
00241 case 115200:
00242 rate = B115200;
00243 break;
00244 case 57600:
00245 rate = B57600;
00246 break;
00247 case 38400:
00248 rate = B38400;
00249 break;
00250 case 19200:
00251 rate = B19200;
00252 break;
00253 case 9600:
00254 rate = B9600;
00255 break;
00256 case 4800:
00257 rate = B4800;
00258 break;
00259 case 2400:
00260 rate = B2400;
00261 break;
00262 case 1200:
00263 rate = B1200;
00264 break;
00265 case 600:
00266 rate = B600;
00267 break;
00268 case 300:
00269 rate = B300;
00270 break;
00271 case 110:
00272 rate = B110;
00273 break;
00274 case 0:
00275 rate = B0;
00276 break;
00277 default:
00278 return serialError(serialErrSpeedInvalid);
00279 }
00280
00281
00282 if(tcgetattr(dev, &options)==-1){
00283 serialErrno = serialErrTcGetAttrFailed;
00284 return serialErrno;
00285 }
00286
00287
00288 cfsetispeed(&options, rate);
00289 cfsetospeed(&options, rate);
00290
00291
00292 if( tcsetattr(dev, TCSANOW, &options) == -1){
00293 serialErrno = serialErrTcSetAttrFailed;
00294 return serialErrno;
00295 }
00296
00297 if( tcgetattr(dev, &options) == -1) {
00298 serialErrno = serialErrTcGetAttrFailed;
00299 return serialErrno;
00300 }
00301
00302
00303 itsBaud=speed;
00304
00305 return serialErrSuccess;
00306 }
00307
00308
00309
00310 serialError Serial::setFlowControl(const bool useHard, const bool useSoft)
00311 {
00312 termios options;
00313
00314 if( tcgetattr(dev, &options) == -1){
00315 serialErrno = serialErrTcGetAttrFailed;
00316 return serialErrno;
00317 }
00318
00319 options.c_cflag &= ~CRTSCTS;
00320 options.c_iflag &= ~(IXON | IXANY | IXOFF);
00321
00322 if (useSoft) options.c_iflag |= (IXON | IXANY | IXOFF);
00323 if (useHard) options.c_cflag |= CRTSCTS;
00324
00325 if(tcsetattr(dev, TCSANOW, &options) == -1){
00326 serialErrno = serialErrTcGetAttrFailed;
00327 return serialErrno;
00328 }
00329
00330
00331 itsFlowHard=useHard;
00332 itsFlowSoft=useSoft;
00333
00334 return serialErrSuccess;
00335 }
00336
00337
00338 serialError Serial::setCharBits(const int bits)
00339 {
00340 termios options;
00341
00342 if(tcgetattr(dev, &options)==-1){
00343 serialErrno = serialErrTcGetAttrFailed;
00344 return serialErrno;
00345 }
00346
00347 options.c_cflag &= ~CSIZE;
00348
00349 switch(bits)
00350 {
00351 case 5: options.c_cflag |= CS5; break;
00352 case 6: options.c_cflag |= CS6; break;
00353 case 7: options.c_cflag |= CS7; break;
00354 case 8: options.c_cflag |= CS8; break;
00355 default: return serialError(serialErrCharsizeInvalid);
00356 }
00357
00358 if( tcsetattr(dev, TCSANOW, &options) == -1 ){
00359 serialErrno = serialErrTcSetAttrFailed;
00360 return serialErrno;
00361 }
00362
00363
00364 itsCharBits=bits;
00365
00366 return serialErrSuccess;
00367 }
00368
00369
00370 serialError Serial::setParity(const bool useParity, const bool oddParity)
00371 {
00372 struct termios options;
00373
00374 if(tcgetattr(dev, &options)==-1){
00375 serialErrno = serialErrTcGetAttrFailed;
00376 return serialErrno;
00377 }
00378
00379 options.c_cflag &= ~(PARENB | PARODD);
00380 if (useParity)
00381 {
00382 if (oddParity)
00383 options.c_cflag |= (PARENB | PARODD);
00384 else
00385 options.c_cflag |= PARENB;
00386 }
00387
00388 if(tcsetattr(dev, TCSANOW, &options) == -1){
00389 serialErrno = serialErrTcSetAttrFailed;
00390 return serialErrno;
00391 }
00392
00393
00394 itsUseParity=useParity;
00395 itsParityOdd=oddParity;
00396
00397 return serialErrSuccess;
00398 }
00399
00400
00401 serialError Serial::setStopBits(const int bits)
00402 {
00403 struct termios options;
00404
00405 if(tcgetattr(dev, &options)==-1){
00406 serialErrno = serialErrTcGetAttrFailed;
00407 return serialErrno;
00408 }
00409
00410 options.c_cflag &= ~CSTOPB;
00411 if (bits == 2) options.c_cflag |= CSTOPB;
00412 else if (bits != 1) return serialError(serialErrStopbitsInvalid);
00413
00414 if(tcsetattr(dev, TCSANOW, &options) == -1){
00415 serialErrno = serialErrTcSetAttrFailed;
00416 return serialErrno;
00417 }
00418
00419
00420 itsStopBits=bits;
00421
00422 return serialErrSuccess;
00423 }
00424
00425
00426 serialError Serial::setBlocking(const bool blocking)
00427 {
00428 int flags = fcntl(dev, F_GETFL, 0);
00429 if (flags == -1) printf("Cannot get flags");
00430 if (blocking) flags &= (~O_NONBLOCK); else flags |= O_NONBLOCK;
00431 if (fcntl(dev, F_SETFL, flags) == -1) printf("Cannot set flags");
00432
00433 itsBlocking=blocking;
00434
00435 return serialErrSuccess;
00436 }
00437
00438
00439 void Serial::toggleDTR(const time_t ms)
00440 {
00441 struct termios tty, old;
00442 if(tcgetattr(dev, &tty) == -1 || tcgetattr(dev, &old) == -1){
00443 serialErrno = serialErrTcGetAttrFailed;
00444 }
00445
00446 cfsetospeed(&tty, B0);
00447 cfsetispeed(&tty, B0);
00448
00449 if(tcsetattr(dev, TCSANOW, &tty) == -1){
00450 serialErrno = serialErrTcSetAttrFailed;
00451 }
00452
00453 if(ms)
00454 usleep(ms*1000);
00455
00456 if(tcsetattr(dev, TCSANOW, &old) == -1){
00457 serialErrno = serialErrTcSetAttrFailed;
00458 }
00459 }
00460
00461
00462 void Serial::sendBreak(void)
00463 {
00464
00465 tcsendbreak(dev, 0);
00466 }
00467
00468
00469 serialError Serial::error(const serialError serialErrorNum)
00470 {
00471 serialErrno = serialErrorNum;
00472 return serialErrorNum;
00473 }
00474
00475
00476 int Serial::openPort(std::string DeviceName)
00477 {
00478
00479
00480 int fuser = 0;
00481
00482 if (fuser != 0 && DeviceName.compare("/dev/null") != 0)
00483 {
00484 printf("serial device %s is already in use by process pid=%d;\n"
00485 "\ttry using /dev/null or a different serial device instead",
00486 DeviceName.c_str(), int(fuser));
00487 }
00488
00489 int flags= O_RDWR | O_NOCTTY;
00490 termios options;
00491
00492
00493
00494 if (itsRdTout < 0) flags |= O_NDELAY;
00495
00496 printf("Opening port %s\n", DeviceName.c_str());
00497 dev = ::open(DeviceName.c_str(), flags);
00498 if (dev == -1) { serialErrno = serialErrOpenFailed; return dev; }
00499 printf("Done\n");
00500
00501
00502 if( tcgetattr(dev, &savedState) == -1 ){
00503 serialErrno = serialErrTcGetAttrFailed;
00504 return -1;
00505 }
00506
00507
00508 if( fcntl(dev, F_SETFL, 0) == -1 ){
00509 serialErrno = serialErrFcntlFailed;
00510 return -1;
00511 }
00512
00513 if(tcgetattr(dev, &options) == -1 ){
00514 serialErrno = serialErrTcGetAttrFailed;
00515 return -1;
00516 }
00517
00518
00519 options.c_cflag |= ( CLOCAL
00520 | CREAD );
00521
00522 options.c_iflag &= ~( IGNBRK
00523 | BRKINT
00524
00525 | PARMRK
00526 | ISTRIP
00527 | INLCR
00528 | IGNCR
00529 | ICRNL
00530 | IXON
00531 );
00532
00533
00534 options.c_oflag &= ~OPOST;
00535 options.c_lflag &= ~(ECHO
00536 | ECHONL
00537 | ICANON
00538 | ISIG
00539 | IEXTEN
00540 );
00541
00542
00543 if(itsRdTout > 0) {
00544 options.c_cc[VMIN] = 0;
00545 options.c_cc[VTIME] = itsRdTout;
00546 }
00547
00548 if( tcsetattr(dev, TCSANOW, &options) == -1){
00549 serialErrno = serialErrTcSetAttrFailed;
00550 return -1;
00551 }
00552 return dev;
00553 }
00554
00555
00556
00557 int Serial::read(void* buffer, const int nbytes)
00558 {
00559 int n = ::read(dev, buffer, nbytes);
00560 if(n==-1)
00561 serialErrno = serialErrReadFailed;
00562
00563 if(n==0)
00564 serialErrno = serialErrReadTimedOut;
00565
00566 return n;
00567 }
00568
00569
00570
00571 char Serial::read(void)
00572 {
00573 char ch;
00574
00575 this->read(&ch, 1);
00576
00577 return ch;
00578 }
00579
00580 std::vector<unsigned char> Serial::readFrame(const unsigned char frameStart, const unsigned char frameEnd, const int frameLength, const double timeout)
00581 {
00582
00583 std::vector<unsigned char> data;
00584 unsigned char buffer[1024];
00585
00586
00587
00588
00589 int bytesRead = read(buffer, 1024);
00590
00591 if(bytesRead > 0)
00592 {
00593
00594 if(frameStart!=buffer[0])
00595 return std::vector<unsigned char>();
00596 int framesize = buffer[1];
00597
00598 for(int i=0;i<framesize;i++)
00599 data.push_back(buffer[i+2]);
00600 return data;
00601
00602 }
00603 else
00604 {
00605 usleep(1000);
00606 printf("Read Fail\n");
00607
00608
00609
00610 return std::vector<unsigned char>();
00611 }
00612 }
00613
00614
00615
00616 int Serial::write(const void* buffer, const int nbytes)
00617 {
00618
00619
00620
00621 int n = ::write(dev, buffer, nbytes);
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 if(n==-1)
00635 serialErrno = serialErrWriteFailed;
00636
00637 return n;
00638 }
00639
00640
00641 int Serial::write(const unsigned char character)
00642 {
00643 return write(&character, 1);
00644 }
00645
00646
00647
00648 void Serial::flush(void)
00649 {
00650
00651 int status = tcflush(dev,TCIFLUSH);
00652 if(status != 0)
00653 printf("BAD SERIAL FLUSH");
00654
00655 }
00656
00657
00658 void Serial::perror(void)
00659 {
00660 switch(serialErrno)
00661 {
00662 case serialErrSuccess:
00663 printf("Serial::OK\n");
00664 return;
00665 case serialErrOpenNoTty:
00666 printf("Serial::Open() No TTY Failed");
00667 break;
00668 case serialErrOpenFailed:
00669 printf("Serial::Open() Failed");
00670 break;
00671 case serialErrSpeedInvalid:
00672 printf("Serial::setSpeed() Invalid Speed Param");
00673 break;
00674 case serialErrFlowInvalid:
00675 printf("Serial::setFlow() Invalid Flow Param");
00676 break;
00677 case serialErrParityInvalid:
00678 printf("Serial::setParity() Invalid parity Param");
00679 break;
00680 case serialErrCharsizeInvalid:
00681 printf("Serial::setCharSize() Invalid Char Size");
00682 break;
00683 case serialErrStopbitsInvalid:
00684 printf("Serial::setStopBits() Invalid Stop Bits");
00685 break;
00686 case serialErrOptionInvalid:
00687 printf("Serial::read() invalid option");
00688 break;
00689 case serialErrOutput:
00690 printf("Serial::read() err output");
00691 break;
00692 case serialErrReadFailed:
00693 printf("Serial::read() Failed");
00694 break;
00695 case serialErrReadTimedOut:
00696 printf("Serial::read() Timed Out");
00697 break;
00698 case serialErrWriteFailed:
00699 printf("Serial::Write() Failed");
00700 break;
00701 case serialErrFcntlFailed:
00702 printf("Serial::Fcntl() Failed");
00703 break;
00704 case serialErrTcGetAttrFailed:
00705 printf("Serial::tcgetattr() Failed");
00706 break;
00707 case serialErrTcSetAttrFailed:
00708 printf("Serial::tcsetattr() Failed");
00709 break;
00710 default:
00711 printf("Unknow error!");
00712 }
00713 }
00714
00715
00716
00717 Serial::~Serial(void)
00718 { }
00719
00720
00721
00722
00723
00724
00725
00726