TTY_IO.cpp

Go to the documentation of this file.
00001 // TTY_IO.cpp,v 4.56 2006/03/29 16:30:37 olli Exp
00002 
00003 #include "ace/TTY_IO.h"
00004 #include "ace/OS_NS_errno.h"
00005 #include "ace/OS_NS_string.h"
00006 #include "ace/OS_NS_strings.h"
00007 
00008 #if defined (ACE_HAS_TERMIOS)
00009 # include "ace/os_include/os_termios.h"
00010 #elif  defined (ACE_HAS_TERMIO)
00011 # include <termio.h>
00012 #endif
00013 
00014 ACE_RCSID (ace,
00015            TTY_IO,
00016            "TTY_IO.cpp,v 4.56 2006/03/29 16:30:37 olli Exp")
00017 
00018 #if defined (ACE_HAS_TERMIOS) || defined (ACE_HAS_TERMIO) || defined (ACE_WIN32)
00019 namespace
00020 {
00021   const char ACE_TTY_IO_ODD[]   = "odd";
00022   const char ACE_TTY_IO_EVEN[]  = "even";
00023 #if defined (ACE_WIN32)
00024   const char ACE_TTY_IO_MARK[]  = "mark";
00025   const char ACE_TTY_IO_SPACE[] = "space";
00026 #endif /* ACE_WIN32 */
00027 }
00028 #endif
00029 
00030 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00031 
00032 ACE_TTY_IO::Serial_Params::Serial_Params (void)
00033 {
00034   ACE_OS::memset (this, 0, sizeof *this);
00035 }
00036 
00037 // Interface for reading/writing serial device parameters
00038 
00039 int ACE_TTY_IO::control (Control_Mode cmd, Serial_Params *arg) const
00040 {
00041 #if defined (ACE_HAS_TERMIOS) || defined (ACE_HAS_TERMIO)
00042 
00043 #if defined (ACE_HAS_TERMIOS)
00044   struct termios devpar;
00045   speed_t newbaudrate = 0;
00046   if (tcgetattr (get_handle () , &devpar) == -1)
00047 #elif defined (TCGETS)
00048   struct termios devpar;
00049   unsigned int newbaudrate = 0;
00050   if (this->ACE_IO_SAP::control (TCGETS, static_cast<void*>(&devpar)) == -1)
00051 #elif defined (TCGETA)
00052   struct termio devpar;
00053   unsigned int newbaudrate = 0;
00054   if (this->ACE_IO_SAP::control (TCGETA, static_cast<void*>(&devpar)) == -1)
00055 #else
00056   errno = ENOSYS;
00057 #endif /* ACE_HAS_TERMIOS */
00058   return -1;
00059 
00060   switch (cmd)
00061     {
00062     case SETPARAMS:
00063       switch (arg->baudrate)
00064         {
00065 #if defined (B0)
00066         case 0:       newbaudrate = B0;       break;
00067 #endif /* B0 */
00068 #if defined (B50)
00069         case 50:      newbaudrate = B50;      break;
00070 #endif /* B50 */
00071 #if defined (B75)
00072         case 75:      newbaudrate = B75;      break;
00073 #endif /* B75 */
00074 #if defined (B110)
00075         case 110:     newbaudrate = B110;     break;
00076 #endif /* B110 */
00077 #if defined (B134)
00078         case 134:     newbaudrate = B134;     break;
00079 #endif /* B134 */
00080 #if defined (B150)
00081         case 150:     newbaudrate = B150;     break;
00082 #endif /* B150 */
00083 #if defined (B200)
00084         case 200:     newbaudrate = B200;     break;
00085 #endif /* B200 */
00086 #if defined (B300)
00087         case 300:     newbaudrate = B300;     break;
00088 #endif /* B300 */
00089 #if defined (B600)
00090         case 600:     newbaudrate = B600;     break;
00091 #endif /* B600 */
00092 #if defined (B1200)
00093         case 1200:    newbaudrate = B1200;    break;
00094 #endif /* B1200 */
00095 #if defined (B1800)
00096         case 1800:    newbaudrate = B1800;    break;
00097 #endif /* B1800 */
00098 #if defined (B2400)
00099         case 2400:    newbaudrate = B2400;    break;
00100 #endif /* B2400 */
00101 #if defined (B4800)
00102         case 4800:    newbaudrate = B4800;    break;
00103 #endif /* B4800 */
00104 #if defined (B9600)
00105         case 9600:    newbaudrate = B9600;    break;
00106 #endif /* B9600 */
00107 #if defined (B19200)
00108         case 19200:   newbaudrate = B19200;   break;
00109 #endif /* B19200 */
00110 #if defined (B38400)
00111         case 38400:   newbaudrate = B38400;   break;
00112 #endif /* B38400 */
00113 #if defined (B56000)
00114         case 56000:   newbaudrate = B56000;   break;
00115 #endif /* B56000 */
00116 #if defined (B57600)
00117         case 57600:   newbaudrate = B57600;   break;
00118 #endif /* B57600 */
00119 #if defined (B76800)
00120         case 76800:   newbaudrate = B76800;   break;
00121 #endif /* B76800 */
00122 #if defined (B115200)
00123         case 115200:  newbaudrate = B115200;  break;
00124 #endif /* B115200 */
00125 #if defined (B128000)
00126         case 128000:  newbaudrate = B128000;  break;
00127 #endif /* B128000 */
00128 #if defined (B153600)
00129         case 153600:  newbaudrate = B153600;  break;
00130 #endif /* B153600 */
00131 #if defined (B230400)
00132         case 230400:  newbaudrate = B230400;  break;
00133 #endif /* B230400 */
00134 #if defined (B307200)
00135         case 307200:  newbaudrate = B307200;  break;
00136 #endif /* B307200 */
00137 #if defined (B256000)
00138         case 256000:  newbaudrate = B256000;  break;
00139 #endif /* B256000 */
00140 #if defined (B460800)
00141         case 460800:  newbaudrate = B460800;  break;
00142 #endif /* B460800 */
00143 #if defined (B500000)
00144         case 500000:  newbaudrate = B500000;  break;
00145 #endif /* B500000 */
00146 #if defined (B576000)
00147         case 576000:  newbaudrate = B576000;  break;
00148 #endif /* B576000 */
00149 #if defined (B921600)
00150         case 921600:  newbaudrate = B921600;  break;
00151 #endif /* B921600 */
00152 #if defined (B1000000)
00153         case 1000000: newbaudrate = B1000000; break;
00154 #endif /* B1000000 */
00155 #if defined (B1152000)
00156         case 1152000: newbaudrate = B1152000; break;
00157 #endif /* B1152000 */
00158 #if defined (B1500000)
00159         case 1500000: newbaudrate = B1500000; break;
00160 #endif /* B1500000 */
00161 #if defined (B2000000)
00162         case 2000000: newbaudrate = B2000000; break;
00163 #endif /* B2000000 */
00164 #if defined (B2500000)
00165         case 2500000: newbaudrate = B2500000; break;
00166 #endif /* B2500000 */
00167 #if defined (B3000000)
00168         case 3000000: newbaudrate = B3000000; break;
00169 #endif /* B3000000 */
00170 #if defined (B3500000)
00171         case 3500000: newbaudrate = B3500000; break;
00172 #endif /* B3500000 */
00173 #if defined (B4000000)
00174         case 4000000: newbaudrate = B4000000; break;
00175 #endif /* B4000000 */
00176         default:
00177           return -1;
00178         }
00179 
00180 #if defined (ACE_HAS_TERMIOS)
00181       // Can you really have different input and output baud rates?!
00182       if (cfsetospeed (&devpar, newbaudrate) == -1)
00183         return -1;
00184       if (cfsetispeed (&devpar, newbaudrate) == -1)
00185         return -1;
00186 #else
00187       devpar.c_cflag &= ~CBAUD;
00188 # if defined (CBAUDEX)
00189       devpar.c_cflag &= ~CBAUDEX;
00190 # endif /* CBAUDEX */
00191       devpar.c_cflag |= newbaudrate;
00192 #endif /* ACE_HAS_TERMIOS */
00193 
00194       devpar.c_cflag &= ~CSIZE;
00195       switch (arg->databits)
00196         {
00197         case 5:
00198           devpar.c_cflag |= CS5;
00199           break;
00200         case 6:
00201           devpar.c_cflag |= CS6;
00202           break;
00203         case 7:
00204           devpar.c_cflag |= CS7;
00205           break;
00206         case 8:
00207           devpar.c_cflag |= CS8;
00208           break;
00209         default:
00210           return -1;
00211         }
00212 
00213       switch (arg->stopbits)
00214         {
00215         case 1:
00216           devpar.c_cflag &= ~CSTOPB;
00217           break;
00218         case 2:
00219           devpar.c_cflag |=  CSTOPB;
00220           break;
00221         default:
00222           return -1;
00223         }
00224 
00225       if (arg->parityenb && arg->paritymode)
00226         {
00227           devpar.c_cflag |=  PARENB;
00228           if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_ODD) == 0)
00229             devpar.c_cflag |=  PARODD;
00230           else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_EVEN) == 0)
00231             devpar.c_cflag &= ~PARODD;
00232           else
00233             return -1;
00234         }
00235       else
00236         {
00237           devpar.c_cflag &= ~PARENB;
00238         }
00239 
00240 #if defined (CNEW_RTSCTS)
00241       if ((arg->ctsenb) || (arg->rtsenb)) // Enable RTS/CTS protocol
00242         devpar.c_cflag |= CNEW_RTSCTS;
00243       else
00244         devpar.c_cflag &= ~CNEW_RTSCTS;
00245 #elif defined (CRTSCTS)
00246       if ((arg->ctsenb) || (arg->rtsenb)) // Enable RTS/CTS protocol
00247         devpar.c_cflag |= CRTSCTS;
00248       else
00249         devpar.c_cflag &= ~CRTSCTS;
00250 #endif /* NEW_RTSCTS || CRTSCTS */
00251 
00252 #if defined (CREAD)
00253       // Enable/disable receiver
00254       if (arg->rcvenb)
00255         devpar.c_cflag |= CREAD;
00256       else
00257         devpar.c_cflag &= ~CREAD;
00258 #endif /* CREAD */
00259 
00260 #if defined (HUPCL)
00261       // Cause DTR to drop after port close.
00262       devpar.c_cflag |= HUPCL;
00263 #endif /* HUPCL */
00264 
00265 #if defined (CLOCAL)
00266       // If device is not a modem set to local device.
00267       if (arg->modem)
00268         devpar.c_cflag &= ~CLOCAL;
00269       else
00270         devpar.c_cflag |= CLOCAL;
00271 #endif /* CLOCAL */
00272 
00273       devpar.c_iflag = IGNPAR | INPCK;
00274       if (arg->databits < 8)
00275         devpar.c_iflag |= ISTRIP;
00276 
00277 #if defined (IGNBRK)
00278       // If device is not a modem set to ignore break points
00279       if(arg->modem)
00280         devpar.c_iflag &= ~IGNBRK;
00281       else
00282         devpar.c_iflag |= IGNBRK;
00283 #endif /* IGNBRK */
00284 
00285 #if defined (IXOFF)
00286       // Enable/disable software flow control on input
00287       if (arg->xinenb)
00288         devpar.c_iflag |= IXOFF;
00289       else
00290         devpar.c_iflag &= ~IXOFF;
00291 #endif /* IXOFF */
00292 
00293 #if defined (IXON)
00294       // Enable/disable software flow control on output
00295       if (arg->xoutenb)
00296         devpar.c_iflag |= IXON;
00297       else
00298         devpar.c_iflag &= ~IXON;
00299 #endif /* IXON */
00300 
00301 #if defined (ICANON)
00302       // Enable noncanonical input processing mode
00303       devpar.c_lflag &= ~ICANON;
00304 #endif /* ICANON */
00305 
00306       if (arg->readtimeoutmsec < 0)
00307         {
00308           // Settings for infinite timeout.
00309           devpar.c_cc[VTIME] = 0;
00310           // In case of infinite timeout [VMIN] must be at least 1.
00311           if (arg->readmincharacters > UCHAR_MAX)
00312             devpar.c_cc[VMIN] = UCHAR_MAX;
00313           else if (arg->readmincharacters < 1)
00314             devpar.c_cc[VMIN] = 1;
00315           else
00316             devpar.c_cc[VMIN] = static_cast<unsigned char>(arg->readmincharacters);
00317         }
00318       else
00319         {
00320           devpar.c_cc[VTIME] = static_cast<unsigned char>(arg->readtimeoutmsec / 100);
00321 
00322           if (arg->readmincharacters > UCHAR_MAX)
00323             devpar.c_cc[VMIN] = UCHAR_MAX;
00324           else if (arg->readmincharacters < 1)
00325             devpar.c_cc[VMIN] = 0;
00326           else
00327             devpar.c_cc[VMIN] = static_cast<unsigned char>(arg->readmincharacters);
00328         }
00329 
00330 #if defined (TIOCMGET) && !defined (__Lynx__)
00331       // This sets serial port under LynxOS to non-functional state
00332       int status;
00333       this->ACE_IO_SAP::control (TIOCMGET, &status);
00334 
00335       if (arg->dtrdisable)
00336         status &= ~TIOCM_DTR;
00337       else
00338         status |=  TIOCM_DTR;
00339 
00340       this->ACE_IO_SAP::control (TIOCMSET, &status);
00341 #endif /* definded (TIOCMGET) */
00342 
00343 #if defined (ACE_HAS_TERMIOS)
00344       return tcsetattr (get_handle (), TCSANOW, &devpar);
00345 #elif defined (TCSETS)
00346       return this->ACE_IO_SAP::control (TCSETS, static_cast<void*>(&devpar));
00347 #elif defined (TCSETA)
00348       return this->ACE_IO_SAP::control (TCSETA, static_cast<void*>(&devpar));
00349 #else
00350       errno = ENOSYS;
00351       return -1;
00352 #endif /* ACE_HAS_TERMIOS */
00353 
00354     case GETPARAMS:
00355       return -1; // Not yet implemented.
00356     default:
00357       return -1; // Wrong cmd.
00358     }
00359 #elif defined (ACE_WIN32)
00360   switch (cmd)
00361     {
00362     case SETPARAMS:
00363       DCB dcb;
00364       dcb.DCBlength = sizeof dcb;
00365       if (!::GetCommState (this->get_handle (), &dcb))
00366         {
00367           ACE_OS::set_errno_to_last_error ();
00368           return -1;
00369         }
00370 
00371       dcb.BaudRate = arg->baudrate;
00372 
00373       switch (arg->databits)
00374         {
00375         case 4:
00376         case 5:
00377         case 6:
00378         case 7:
00379         case 8:
00380           dcb.ByteSize = arg->databits;
00381           break;
00382         default:
00383           return -1;
00384         }
00385 
00386       switch (arg->stopbits)
00387         {
00388         case 1:
00389           dcb.StopBits = ONESTOPBIT;
00390           break;
00391         case 2:
00392           dcb.StopBits = TWOSTOPBITS;
00393           break;
00394         default:
00395           return -1;
00396         }
00397 
00398       if (arg->parityenb && arg->paritymode)
00399         {
00400           dcb.fParity = TRUE;
00401           if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_ODD) == 0)
00402             dcb.Parity = ODDPARITY;
00403           else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_EVEN) == 0)
00404             dcb.Parity = EVENPARITY;
00405           else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_MARK) == 0)
00406             dcb.Parity = MARKPARITY;
00407           else if (ACE_OS::strcasecmp (arg->paritymode, ACE_TTY_IO_SPACE) == 0)
00408             dcb.Parity = SPACEPARITY;
00409           else
00410             dcb.Parity = NOPARITY;
00411         }
00412       else
00413         {
00414           dcb.fParity = FALSE;
00415           dcb.Parity = NOPARITY;
00416         }
00417 
00418       // Enable/disable RTS protocol.
00419       switch (arg->rtsenb)
00420         {
00421         case 1:
00422           dcb.fRtsControl = RTS_CONTROL_ENABLE;
00423           break;
00424         case 2:
00425           dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
00426           break;
00427         case 3:
00428           dcb.fRtsControl = RTS_CONTROL_TOGGLE;
00429           break;
00430         default:
00431           dcb.fRtsControl = RTS_CONTROL_DISABLE;
00432         }
00433 
00434       // Enable/disable CTS protocol.
00435       if (arg->ctsenb)
00436         dcb.fOutxCtsFlow = TRUE;
00437       else
00438         dcb.fOutxCtsFlow = FALSE;
00439 
00440       // Enable/disable DSR protocol.
00441       if (arg->dsrenb)
00442         dcb.fOutxDsrFlow = TRUE;
00443       else
00444         dcb.fOutxDsrFlow = FALSE;
00445 
00446       // Disable/enable DTR protocol
00447       if (arg->dtrdisable)
00448         dcb.fDtrControl = DTR_CONTROL_DISABLE;
00449       else
00450         dcb.fDtrControl = DTR_CONTROL_ENABLE;
00451 
00452       // Enable/disable software flow control on input
00453       if (arg->xinenb)
00454         dcb.fInX = TRUE;
00455       else
00456         dcb.fInX = FALSE;
00457 
00458       // Enable/disable software flow control on output
00459       if (arg->xoutenb)
00460         dcb.fOutX = TRUE;
00461       else
00462         dcb.fOutX = FALSE;
00463 
00464       // Always set limits unless set to negative to use default.
00465       if (arg->xonlim >= 0)
00466         dcb.XonLim  = static_cast<WORD>(arg->xonlim);
00467       if (arg->xofflim >= 0)
00468         dcb.XoffLim = static_cast<WORD>(arg->xofflim);
00469 
00470       dcb.fAbortOnError = FALSE;
00471       dcb.fErrorChar = FALSE;
00472       dcb.fNull = FALSE;
00473       dcb.fBinary = TRUE;
00474 
00475       if (!::SetCommState (this->get_handle (), &dcb))
00476         {
00477           ACE_OS::set_errno_to_last_error ();
00478           return -1;
00479         }
00480 
00481       COMMTIMEOUTS timeouts;
00482       if (!::GetCommTimeouts (this->get_handle(), &timeouts))
00483         {
00484           ACE_OS::set_errno_to_last_error ();
00485           return -1;
00486         }
00487 
00488       if (arg->readtimeoutmsec < 0)
00489         {
00490           // Settings for infinite timeout.
00491           timeouts.ReadIntervalTimeout        = 0;
00492           timeouts.ReadTotalTimeoutMultiplier = 0;
00493           timeouts.ReadTotalTimeoutConstant   = 0;
00494         }
00495       else if (arg->readtimeoutmsec == 0)
00496         {
00497           // Return immediately if no data in the input buffer.
00498           timeouts.ReadIntervalTimeout        = MAXDWORD;
00499           timeouts.ReadTotalTimeoutMultiplier = 0;
00500           timeouts.ReadTotalTimeoutConstant   = 0;
00501         }
00502       else
00503         {
00504           // Wait for specified timeout for char to arrive before returning.
00505           timeouts.ReadIntervalTimeout        = MAXDWORD;
00506           timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
00507           timeouts.ReadTotalTimeoutConstant   = arg->readtimeoutmsec;
00508         }
00509 
00510        if (!::SetCommTimeouts (this->get_handle (), &timeouts))
00511          {
00512            ACE_OS::set_errno_to_last_error ();
00513            return -1;
00514          }
00515 
00516        return 0;
00517 
00518     case GETPARAMS:
00519       ACE_NOTSUP_RETURN (-1); // Not yet implemented.
00520     default:
00521       return -1; // Wrong cmd.
00522 
00523     } // arg switch
00524 #else
00525   ACE_UNUSED_ARG (cmd);
00526   ACE_UNUSED_ARG (arg);
00527   ACE_NOTSUP_RETURN (-1);
00528 #endif /* ACE_HAS_TERMIOS || ACE_HAS_TERMIO */
00529 }
00530 
00531 #if defined (ACE_NEEDS_DEV_IO_CONVERSION)
00532 ACE_TTY_IO::operator ACE_DEV_IO &()
00533 {
00534   return static_cast<ACE_DEV_IO &>(*this);
00535 }
00536 #endif /* ACE_NEEDS_DEV_IO_CONVERSION */
00537 
00538 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 09:42:08 2006 for ACE by doxygen 1.3.6