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/SerialAdvanced.H"
00039
00040 #include "Component/OptionManager.H"
00041 #include "Util/log.H"
00042 #include "rutz/unixcall.h"
00043
00044 #include <iostream>
00045
00046 const ModelOptionCateg MOC_SerialAdvanced = {
00047 MOC_SORTPRI_3, "Advanced Serial Port Related Options" };
00048
00049 const ModelOptionDef OPT_DevNameAdvanced =
00050 { MODOPT_ARG(std::string), "DevNameAdvanced", &MOC_SerialAdvanced, OPTEXP_CORE,
00051 "Device file",
00052 "serial-dev-advanced", '\0', "", "/dev/ttyS0" };
00053
00054 const ModelOptionDef OPT_Baud =
00055 { MODOPT_ARG(int), "Baud", &MOC_SerialAdvanced, OPTEXP_CORE,
00056 "Baud Rate",
00057 "serial-baud", '\0', "", "9600" };
00058
00059 const ModelOptionDef OPT_CharBits =
00060 { MODOPT_ARG(int), "CharBits", &MOC_SerialAdvanced, OPTEXP_CORE,
00061 "Number of bits per character",
00062 "serial-charbits", '\0', "", "8" };
00063
00064 const ModelOptionDef OPT_StopBits =
00065 { MODOPT_ARG(int), "StopBits", &MOC_SerialAdvanced, OPTEXP_CORE,
00066 "Number of stop bits",
00067 "serial-stopbits", '\0', "", "1" };
00068
00069 const ModelOptionDef OPT_UseParity =
00070 { MODOPT_ARG(bool), "UseParity", &MOC_SerialAdvanced, OPTEXP_CORE,
00071 "Use Parity?",
00072 "serial-parity", '\0', "true | false", "false" };
00073
00074 const ModelOptionDef OPT_ParityOdd =
00075 { MODOPT_ARG(bool), "ParityOdd", &MOC_SerialAdvanced, OPTEXP_CORE,
00076 "Use Odd Parity?",
00077 "serial-oddparity", '\0', "true | false", "false" };
00078
00079 const ModelOptionDef OPT_FlowHard =
00080 { MODOPT_ARG(bool), "FlowHard", &MOC_SerialAdvanced, OPTEXP_CORE,
00081 "Use Hardware Flow Control?",
00082 "serial-flowhard", '\0', "true | false", "false" };
00083
00084 const ModelOptionDef OPT_FlowSoft =
00085 { MODOPT_ARG(bool), "FlowSoft", &MOC_SerialAdvanced, OPTEXP_CORE,
00086 "Use Software Flow Control?",
00087 "serial-flowsoft", '\0', "true | false", "false" };
00088
00089 const ModelOptionDef OPT_RdTout =
00090 { MODOPT_ARG(int), "RdTout", &MOC_SerialAdvanced, OPTEXP_CORE,
00091 "Read Timeout",
00092 "serial-readtout", '\0', "", "-1" };
00093
00094 const ModelOptionDef OPT_Blocking =
00095 { MODOPT_ARG(bool), "Blocking", &MOC_SerialAdvanced, OPTEXP_CORE,
00096 "Use Blocking Mode?",
00097 "serial-blocking", '\0', "true | false", "true" };
00098
00099 const ModelOptionDef OPT_DevSearchDescriptor =
00100 { MODOPT_ARG(std::string), "DevSearchDesctriptor", &MOC_SerialAdvanced, OPTEXP_CORE,
00101 "Some of the serial devices in iLab will respond to a command of '0' with "
00102 "a framed string containing a device description. By setting this commmand line option, "
00103 "one can specify which such string to search for among all available serial devices. "
00104 "The DevName will then be set according to which available device with the correct string.",
00105 "dev-descriptor", '\0', "", "" };
00106
00107
00108
00109 SerialAdvanced::SerialAdvanced(OptionManager& mgr,
00110 const std::string& descrName,
00111 const std::string& tagName) :
00112 ModelComponent(mgr, descrName, tagName),
00113 dev(-1), serialErrno(serialErrSuccess),
00114 itsDevName(&OPT_DevNameAdvanced, this,0),
00115 itsBaud(&OPT_Baud, this, 0),
00116 itsCharBits(&OPT_CharBits, this, 0),
00117 itsStopBits(&OPT_StopBits, this, 0),
00118 itsUseParity(&OPT_UseParity, this, 0),
00119 itsParityOdd(&OPT_ParityOdd, this, 0),
00120 itsFlowHard(&OPT_FlowHard, this, 0),
00121 itsFlowSoft(&OPT_FlowSoft, this, 0),
00122 itsRdTout(&OPT_RdTout, this, 0),
00123 itsBlocking(&OPT_Blocking, this, 0),
00124 itsDevSearchDescriptor(&OPT_DevSearchDescriptor, this, 0)
00125 { }
00126
00127
00128 void SerialAdvanced::start2()
00129 {
00130 serialErrno = serialErrSuccess;
00131
00132 openPort();
00133 perror();
00134
00135 setSpeed(itsBaud.getVal());
00136 perror();
00137
00138 setFlowControl(itsFlowHard.getVal(),
00139 itsFlowSoft.getVal());
00140 perror();
00141
00142 setCharBits(itsCharBits.getVal());
00143 perror();
00144
00145 setParity(itsUseParity.getVal(),
00146 itsParityOdd.getVal());
00147 perror();
00148
00149 setBlocking(itsBlocking.getVal());
00150 perror();
00151 }
00152
00153 #include <cstdio>
00154
00155 void SerialAdvanced::stop2()
00156 {
00157 if(dev >= 0) {
00158
00159 fputs("closing...\n", stderr);
00160 close(dev);
00161 dev = -1; }
00162 }
00163
00164
00165 void SerialAdvanced::configure(const char *dev, const int speed, const char *format,
00166 const bool flowSoft, const bool flowHard,
00167 const int tout)
00168 {
00169 itsDevName.setVal(dev);
00170 itsBaud.setVal(speed);
00171 itsFlowSoft.setVal(flowSoft);
00172 itsFlowHard.setVal(flowHard);
00173 itsRdTout.setVal(tout);
00174
00175 if (strlen(format) != 3) LFATAL("Incorrect format string: %s", format);
00176
00177 switch(format[0]) {
00178 case '5': itsCharBits.setVal(5); break;
00179 case '6': itsCharBits.setVal(6); break;
00180 case '7': itsCharBits.setVal(7); break;
00181 case '8': itsCharBits.setVal(8); break;
00182 default: LFATAL("Invalid charbits: %c (should be 5..8)", format[0]);
00183 }
00184
00185 switch(format[1]) {
00186 case 'N': itsUseParity.setVal(false); break;
00187 case 'E': itsUseParity.setVal(true); itsParityOdd.setVal(false); break;
00188 case 'O': itsUseParity.setVal(true); itsParityOdd.setVal(true); break;
00189 default: LFATAL("Invalid parity: %c (should be N,E,O)", format[1]);
00190 }
00191
00192 switch(format[2]) {
00193 case '1': itsStopBits.setVal(1); break;
00194 case '2': itsStopBits.setVal(2); break;
00195 default: LFATAL("Invalid stopbits: %c (should be 1..2)", format[2]);
00196 }
00197 }
00198
00199
00200 serialError SerialAdvanced::setSpeed(const int speed)
00201 {
00202 struct termios options;
00203 unsigned int rate;
00204
00205 switch(speed)
00206 {
00207 case 115200:
00208 rate = B115200;
00209 break;
00210 case 57600:
00211 rate = B57600;
00212 break;
00213 case 38400:
00214 rate = B38400;
00215 break;
00216 case 19200:
00217 rate = B19200;
00218 break;
00219 case 9600:
00220 rate = B9600;
00221 break;
00222 case 4800:
00223 rate = B4800;
00224 break;
00225 case 2400:
00226 rate = B2400;
00227 break;
00228 case 1200:
00229 rate = B1200;
00230 break;
00231 case 600:
00232 rate = B600;
00233 break;
00234 case 300:
00235 rate = B300;
00236 break;
00237 case 110:
00238 rate = B110;
00239 break;
00240 case 0:
00241 rate = B0;
00242 break;
00243 default:
00244 return serialError(serialErrSpeedInvalid);
00245 }
00246
00247
00248 if(tcgetattr(dev, &options)==-1){
00249 serialErrno = serialErrTcGetAttrFailed;
00250 return serialErrno;
00251 }
00252
00253
00254 cfsetispeed(&options, rate);
00255 cfsetospeed(&options, rate);
00256
00257
00258 if( tcsetattr(dev, TCSANOW, &options) == -1){
00259 serialErrno = serialErrTcSetAttrFailed;
00260 return serialErrno;
00261 }
00262
00263 if( tcgetattr(dev, &options) == -1) {
00264 serialErrno = serialErrTcGetAttrFailed;
00265 return serialErrno;
00266 }
00267
00268
00269 itsBaud.setVal(speed);
00270
00271 return serialErrSuccess;
00272 }
00273
00274
00275
00276 serialError SerialAdvanced::setFlowControl(const bool useHard, const bool useSoft)
00277 {
00278 termios options;
00279
00280 if( tcgetattr(dev, &options) == -1){
00281 serialErrno = serialErrTcGetAttrFailed;
00282 return serialErrno;
00283 }
00284
00285 options.c_cflag &= ~CRTSCTS;
00286 options.c_iflag &= ~(IXON | IXANY | IXOFF);
00287
00288 if (useSoft) options.c_iflag |= (IXON | IXANY | IXOFF);
00289 if (useHard) options.c_cflag |= CRTSCTS;
00290
00291 if(tcsetattr(dev, TCSANOW, &options) == -1){
00292 serialErrno = serialErrTcGetAttrFailed;
00293 return serialErrno;
00294 }
00295
00296
00297 itsFlowHard.setVal(useHard);
00298 itsFlowSoft.setVal(useSoft);
00299
00300 return serialErrSuccess;
00301 }
00302
00303
00304 serialError SerialAdvanced::setCharBits(const int bits)
00305 {
00306 termios options;
00307
00308 if(tcgetattr(dev, &options)==-1){
00309 serialErrno = serialErrTcGetAttrFailed;
00310 return serialErrno;
00311 }
00312
00313 options.c_cflag &= ~CSIZE;
00314
00315 switch(bits)
00316 {
00317 case 5: options.c_cflag |= CS5; break;
00318 case 6: options.c_cflag |= CS6; break;
00319 case 7: options.c_cflag |= CS7; break;
00320 case 8: options.c_cflag |= CS8; break;
00321 default: return serialError(serialErrCharsizeInvalid);
00322 }
00323
00324 if( tcsetattr(dev, TCSANOW, &options) == -1 ){
00325 serialErrno = serialErrTcSetAttrFailed;
00326 return serialErrno;
00327 }
00328
00329
00330 itsCharBits.setVal(bits);
00331
00332 return serialErrSuccess;
00333 }
00334
00335
00336 serialError SerialAdvanced::setParity(const bool useParity, const bool oddParity)
00337 {
00338 struct termios options;
00339
00340 if(tcgetattr(dev, &options)==-1){
00341 serialErrno = serialErrTcGetAttrFailed;
00342 return serialErrno;
00343 }
00344
00345 options.c_cflag &= ~(PARENB | PARODD);
00346 if (useParity)
00347 {
00348 if (oddParity)
00349 options.c_cflag |= (PARENB | PARODD);
00350 else
00351 options.c_cflag |= PARENB;
00352 }
00353
00354 if(tcsetattr(dev, TCSANOW, &options) == -1){
00355 serialErrno = serialErrTcSetAttrFailed;
00356 return serialErrno;
00357 }
00358
00359
00360 itsUseParity.setVal(useParity);
00361 itsParityOdd.setVal(oddParity);
00362
00363 return serialErrSuccess;
00364 }
00365
00366
00367 serialError SerialAdvanced::setStopBits(const int bits)
00368 {
00369 struct termios options;
00370
00371 if(tcgetattr(dev, &options)==-1){
00372 serialErrno = serialErrTcGetAttrFailed;
00373 return serialErrno;
00374 }
00375
00376 options.c_cflag &= ~CSTOPB;
00377 if (bits == 2) options.c_cflag |= CSTOPB;
00378 else if (bits != 1) return serialError(serialErrStopbitsInvalid);
00379
00380 if(tcsetattr(dev, TCSANOW, &options) == -1){
00381 serialErrno = serialErrTcSetAttrFailed;
00382 return serialErrno;
00383 }
00384
00385
00386 itsStopBits.setVal(bits);
00387
00388 return serialErrSuccess;
00389 }
00390
00391
00392 serialError SerialAdvanced::setBlocking(const bool blocking)
00393 {
00394 int flags = fcntl(dev, F_GETFL, 0);
00395 if (flags == -1) PLERROR("Cannot get flags");
00396 if (blocking) flags &= (~O_NONBLOCK); else flags |= O_NONBLOCK;
00397 if (fcntl(dev, F_SETFL, flags) == -1) PLERROR("Cannot set flags");
00398
00399 itsBlocking.setVal(blocking);
00400
00401 return serialErrSuccess;
00402 }
00403
00404
00405 void SerialAdvanced::toggleDTR(const time_t ms)
00406 {
00407 struct termios tty, old;
00408 if(tcgetattr(dev, &tty) == -1 || tcgetattr(dev, &old) == -1){
00409 serialErrno = serialErrTcGetAttrFailed;
00410 }
00411
00412 cfsetospeed(&tty, B0);
00413 cfsetispeed(&tty, B0);
00414
00415 if(tcsetattr(dev, TCSANOW, &tty) == -1){
00416 serialErrno = serialErrTcSetAttrFailed;
00417 }
00418
00419 if(ms)
00420 usleep(ms*1000);
00421
00422 if(tcsetattr(dev, TCSANOW, &old) == -1){
00423 serialErrno = serialErrTcSetAttrFailed;
00424 }
00425 }
00426
00427
00428 void SerialAdvanced::sendBreak(void)
00429 {
00430
00431 tcsendbreak(dev, 0);
00432 }
00433
00434
00435 serialError SerialAdvanced::error(const serialError serialErrorNum)
00436 {
00437 serialErrno = serialErrorNum;
00438 return serialErrorNum;
00439 }
00440
00441
00442 int SerialAdvanced::openPort()
00443 {
00444 const pid_t fuser =
00445 rutz::unixcall::get_file_user_pid(itsDevName.getVal().c_str());
00446
00447 if (fuser != 0 && itsDevName.getVal().compare("/dev/null") != 0)
00448 {
00449 LFATAL("serial device %s is already in use by process pid=%d;\n"
00450 "\ttry using /dev/null or a different serial device instead",
00451 itsDevName.getVal().c_str(), int(fuser));
00452 }
00453
00454 int flags= O_RDWR | O_NOCTTY;
00455 termios options;
00456
00457
00458
00459 if (itsRdTout.getVal() < 0) flags |= O_NDELAY;
00460
00461 CLDEBUG("Opening port %s", itsDevName.getVal().c_str());
00462 dev = ::open(itsDevName.getVal().c_str(), flags);
00463 if (dev == -1) { serialErrno = serialErrOpenFailed; return dev; }
00464 LDEBUG("Done");
00465
00466
00467 if( tcgetattr(dev, &savedState) == -1 ){
00468 serialErrno = serialErrTcGetAttrFailed;
00469 return -1;
00470 }
00471
00472
00473 if( fcntl(dev, F_SETFL, 0) == -1 ){
00474 serialErrno = serialErrFcntlFailed;
00475 return -1;
00476 }
00477
00478 if(tcgetattr(dev, &options) == -1 ){
00479 serialErrno = serialErrTcGetAttrFailed;
00480 return -1;
00481 }
00482
00483
00484 options.c_cflag |= ( CLOCAL
00485 | CREAD );
00486
00487 options.c_iflag &= ~( IGNBRK
00488 | BRKINT
00489
00490 | PARMRK
00491 | ISTRIP
00492 | INLCR
00493 | IGNCR
00494 | ICRNL
00495 | IXON
00496 );
00497
00498
00499 options.c_oflag &= ~OPOST;
00500 options.c_lflag &= ~(ECHO
00501 | ECHONL
00502 | ICANON
00503 | ISIG
00504 | IEXTEN
00505 );
00506
00507
00508 if(itsRdTout.getVal() > 0) {
00509 options.c_cc[VMIN] = 0;
00510 options.c_cc[VTIME] = itsRdTout.getVal();
00511 }
00512
00513 if( tcsetattr(dev, TCSANOW, &options) == -1){
00514 serialErrno = serialErrTcSetAttrFailed;
00515 return -1;
00516 }
00517 return dev;
00518 }
00519
00520
00521
00522 int SerialAdvanced::read(void* buffer, const int nbytes)
00523 {
00524 int n = ::read(dev, buffer, nbytes);
00525
00526 if(n==-1)
00527 serialErrno = serialErrReadFailed;
00528
00529 if(n==0)
00530 serialErrno = serialErrReadTimedOut;
00531
00532 return n;
00533 }
00534
00535
00536
00537 char SerialAdvanced::read(void)
00538 {
00539 char ch;
00540
00541 this->read(&ch, 1);
00542
00543 return ch;
00544 }
00545
00546
00547
00548 int SerialAdvanced::write(const void* buffer, const int nbytes)
00549 {
00550
00551
00552
00553 int n = ::write(dev, buffer, nbytes);
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 if(n==-1)
00567 serialErrno = serialErrWriteFailed;
00568
00569 return n;
00570 }
00571
00572
00573
00574 void SerialAdvanced::perror(void)
00575 {
00576 const char* s=NULL;
00577 switch(serialErrno)
00578 {
00579 case serialErrSuccess:
00580 s = "Success";
00581 return;
00582 case serialErrOpenNoTty:
00583 s = "SerialAdvanced::Open() No TTY Failed";
00584 break;
00585 case serialErrOpenFailed:
00586 s = "SerialAdvanced::Open() Failed";
00587 break;
00588 case serialErrSpeedInvalid:
00589 s = "SerialAdvanced::setSpeed() Invalid Speed Param";
00590 break;
00591 case serialErrFlowInvalid:
00592 s = "SerialAdvanced::setFlow() Invalid Flow Param";
00593 break;
00594 case serialErrParityInvalid:
00595 s = "SerialAdvanced::setParity() Invalid parity Param";
00596 break;
00597 case serialErrCharsizeInvalid:
00598 s = "SerialAdvanced::setCharSize() Invalid Char Size";
00599 break;
00600 case serialErrStopbitsInvalid:
00601 s = "SerialAdvanced::setStopBits() Invalid Stop Bits";
00602 break;
00603 case serialErrOptionInvalid:
00604 break;
00605 case serialErrOutput:
00606 break;
00607 case serialErrReadFailed:
00608 s = "SerialAdvanced::read() Failed";
00609 break;
00610 case serialErrReadTimedOut:
00611 s = "SerialAdvanced::read() Timed Out";
00612 break;
00613 case serialErrWriteFailed:
00614 s = "SerialAdvanced::Write() Failed";
00615 break;
00616 case serialErrFcntlFailed:
00617 s = "SerialAdvanced::Fcntl() Failed";
00618 break;
00619 case serialErrTcGetAttrFailed:
00620 s = "SerialAdvanced::tcgetattr() Failed";
00621 break;
00622 case serialErrTcSetAttrFailed:
00623 s = "SerialAdvanced::tcsetattr() Failed";
00624 break;
00625 default:
00626 s = "Unknow error!";
00627 }
00628 LERROR("%s", s);
00629 }
00630
00631
00632
00633 SerialAdvanced::~SerialAdvanced(void)
00634 { }
00635
00636
00637
00638
00639
00640
00641
00642