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