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