#include <TTY_IO.h>
Inheritance diagram for ACE_TTY_IO:
Public Types | |
enum | Control_Mode { SETPARAMS, GETPARAMS } |
Public Member Functions | |
int | control (Control_Mode cmd, Serial_Params *arg) const |
This class represents an example interface for a specific device (a serial line). It extends the capability of the underlying DEV_IO class by adding a control method that takes a special structure (Serial_Params) as argument to allow a comfortable user interface (away from that annoying termios structure, which is very specific to UNIX).
Definition at line 36 of file TTY_IO.h.
|
Definition at line 39 of file TTY_IO.h.
|
|
Interface for reading/writing serial device parameters. Definition at line 56 of file TTY_IO.cpp. References ACE_NOTSUP_RETURN, ACE_TTY_IO_EVEN, ACE_TTY_IO_MARK, ACE_TTY_IO_NONE, ACE_TTY_IO_ODD, ACE_TTY_IO_SPACE, ACE_TTY_IO::Serial_Params::baudrate, ACE_IO_SAP::control(), ACE_TTY_IO::Serial_Params::ctsenb, ACE_TTY_IO::Serial_Params::databits, ACE_TTY_IO::Serial_Params::dsrenb, ACE_TTY_IO::Serial_Params::dtrdisable, ENOSYS, ACE_IO_SAP::get_handle(), GETPARAMS, ACE_TTY_IO::Serial_Params::modem, ACE_TTY_IO::Serial_Params::parityenb, ACE_TTY_IO::Serial_Params::paritymode, ACE_TTY_IO::Serial_Params::rcvenb, ACE_TTY_IO::Serial_Params::readmincharacters, ACE_TTY_IO::Serial_Params::readtimeoutmsec, ACE_TTY_IO::Serial_Params::rtsenb, ACE_OS::set_errno_to_last_error(), SETPARAMS, ACE_TTY_IO::Serial_Params::stopbits, ACE_OS::strcasecmp(), ACE_TTY_IO::Serial_Params::xinenb, ACE_TTY_IO::Serial_Params::xofflim, ACE_TTY_IO::Serial_Params::xonlim, and ACE_TTY_IO::Serial_Params::xoutenb.
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 /* ACE_HAS_TERMIOS */ 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 /* B0 */ 00085 #if defined (B50) 00086 case 50: newbaudrate = B50; break; 00087 #endif /* B50 */ 00088 #if defined (B75) 00089 case 75: newbaudrate = B75; break; 00090 #endif /* B75 */ 00091 #if defined (B110) 00092 case 110: newbaudrate = B110; break; 00093 #endif /* B110 */ 00094 #if defined (B134) 00095 case 134: newbaudrate = B134; break; 00096 #endif /* B134 */ 00097 #if defined (B150) 00098 case 150: newbaudrate = B150; break; 00099 #endif /* B150 */ 00100 #if defined (B200) 00101 case 200: newbaudrate = B200; break; 00102 #endif /* B200 */ 00103 #if defined (B300) 00104 case 300: newbaudrate = B300; break; 00105 #endif /* B300 */ 00106 #if defined (B600) 00107 case 600: newbaudrate = B600; break; 00108 #endif /* B600 */ 00109 #if defined (B1200) 00110 case 1200: newbaudrate = B1200; break; 00111 #endif /* B1200 */ 00112 #if defined (B1800) 00113 case 1800: newbaudrate = B1800; break; 00114 #endif /* B1800 */ 00115 #if defined (B2400) 00116 case 2400: newbaudrate = B2400; break; 00117 #endif /* B2400 */ 00118 #if defined (B4800) 00119 case 4800: newbaudrate = B4800; break; 00120 #endif /* B4800 */ 00121 #if defined (B9600) 00122 case 9600: newbaudrate = B9600; break; 00123 #endif /* B9600 */ 00124 #if defined (B19200) 00125 case 19200: newbaudrate = B19200; break; 00126 #endif /* B19200 */ 00127 #if defined (B38400) 00128 case 38400: newbaudrate = B38400; break; 00129 #endif /* B38400 */ 00130 #if defined (B56000) 00131 case 56000: newbaudrate = B56000; break; 00132 #endif /* B56000 */ 00133 #if defined (B57600) 00134 case 57600: newbaudrate = B57600; break; 00135 #endif /* B57600 */ 00136 #if defined (B76800) 00137 case 76800: newbaudrate = B76800; break; 00138 #endif /* B76800 */ 00139 #if defined (B115200) 00140 case 115200: newbaudrate = B115200; break; 00141 #endif /* B115200 */ 00142 #if defined (B128000) 00143 case 128000: newbaudrate = B128000; break; 00144 #endif /* B128000 */ 00145 #if defined (B153600) 00146 case 153600: newbaudrate = B153600; break; 00147 #endif /* B153600 */ 00148 #if defined (B230400) 00149 case 230400: newbaudrate = B230400; break; 00150 #endif /* B230400 */ 00151 #if defined (B307200) 00152 case 307200: newbaudrate = B307200; break; 00153 #endif /* B307200 */ 00154 #if defined (B256000) 00155 case 256000: newbaudrate = B256000; break; 00156 #endif /* B256000 */ 00157 #if defined (B460800) 00158 case 460800: newbaudrate = B460800; break; 00159 #endif /* B460800 */ 00160 #if defined (B500000) 00161 case 500000: newbaudrate = B500000; break; 00162 #endif /* B500000 */ 00163 #if defined (B576000) 00164 case 576000: newbaudrate = B576000; break; 00165 #endif /* B576000 */ 00166 #if defined (B921600) 00167 case 921600: newbaudrate = B921600; break; 00168 #endif /* B921600 */ 00169 #if defined (B1000000) 00170 case 1000000: newbaudrate = B1000000; break; 00171 #endif /* B1000000 */ 00172 #if defined (B1152000) 00173 case 1152000: newbaudrate = B1152000; break; 00174 #endif /* B1152000 */ 00175 #if defined (B1500000) 00176 case 1500000: newbaudrate = B1500000; break; 00177 #endif /* B1500000 */ 00178 #if defined (B2000000) 00179 case 2000000: newbaudrate = B2000000; break; 00180 #endif /* B2000000 */ 00181 #if defined (B2500000) 00182 case 2500000: newbaudrate = B2500000; break; 00183 #endif /* B2500000 */ 00184 #if defined (B3000000) 00185 case 3000000: newbaudrate = B3000000; break; 00186 #endif /* B3000000 */ 00187 #if defined (B3500000) 00188 case 3500000: newbaudrate = B3500000; break; 00189 #endif /* B3500000 */ 00190 #if defined (B4000000) 00191 case 4000000: newbaudrate = B4000000; break; 00192 #endif /* B4000000 */ 00193 default: 00194 return -1; 00195 } 00196 00197 #if defined (ACE_HAS_TERMIOS) 00198 // Can you really have different input and output baud rates?! 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 /* CBAUDEX */ 00208 devpar.c_cflag |= newbaudrate; 00209 #endif /* ACE_HAS_TERMIOS */ 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)) // Enable RTS/CTS protocol 00266 devpar.c_cflag |= CNEW_RTSCTS; 00267 else 00268 devpar.c_cflag &= ~CNEW_RTSCTS; 00269 #elif defined (CRTSCTS) 00270 if ((arg->ctsenb) || (arg->rtsenb)) // Enable RTS/CTS protocol 00271 devpar.c_cflag |= CRTSCTS; 00272 else 00273 devpar.c_cflag &= ~CRTSCTS; 00274 #endif /* NEW_RTSCTS || CRTSCTS */ 00275 00276 #if defined (CREAD) 00277 // Enable/disable receiver 00278 if (arg->rcvenb) 00279 devpar.c_cflag |= CREAD; 00280 else 00281 devpar.c_cflag &= ~CREAD; 00282 #endif /* CREAD */ 00283 00284 #if defined (HUPCL) 00285 // Cause DTR to drop after port close. 00286 devpar.c_cflag |= HUPCL; 00287 #endif /* HUPCL */ 00288 00289 #if defined (CLOCAL) 00290 // If device is not a modem set to local device. 00291 if (arg->modem) 00292 devpar.c_cflag &= ~CLOCAL; 00293 else 00294 devpar.c_cflag |= CLOCAL; 00295 #endif /* CLOCAL */ 00296 00297 devpar.c_iflag = IGNPAR | INPCK; 00298 if (arg->databits < 8) 00299 devpar.c_iflag |= ISTRIP; 00300 00301 #if defined (IGNBRK) 00302 // If device is not a modem set to ignore break points 00303 if(arg->modem) 00304 devpar.c_iflag &= ~IGNBRK; 00305 else 00306 devpar.c_iflag |= IGNBRK; 00307 #endif /* IGNBRK */ 00308 00309 #if defined (IXOFF) 00310 // Enable/disable software flow control on input 00311 if (arg->xinenb) 00312 devpar.c_iflag |= IXOFF; 00313 else 00314 devpar.c_iflag &= ~IXOFF; 00315 #endif /* IXOFF */ 00316 00317 #if defined (IXON) 00318 // Enable/disable software flow control on output 00319 if (arg->xoutenb) 00320 devpar.c_iflag |= IXON; 00321 else 00322 devpar.c_iflag &= ~IXON; 00323 #endif /* IXON */ 00324 00325 #if defined (ICANON) 00326 // Enable noncanonical input processing mode 00327 devpar.c_lflag &= ~ICANON; 00328 #endif /* ICANON */ 00329 00330 #if defined (ECHO) 00331 // Disable echoing of input characters 00332 devpar.c_lflag &= ~ECHO; 00333 #endif /* ECHO */ 00334 00335 #if defined (ECHOE) 00336 // Disable echoing erase chareacter as BS-SP-BS 00337 devpar.c_lflag &= ~ECHOE; 00338 #endif /* ECHOE */ 00339 00340 #if defined (ISIG) 00341 // Disable SIGINTR, SIGSUSP, SIGDSUSP and SIGQUIT signals 00342 devpar.c_lflag &= ~ISIG; 00343 #endif /* ISIG */ 00344 00345 #if defined (OPOST) 00346 // Disable post-processing of output data 00347 devpar.c_oflag &= ~OPOST; 00348 #endif /* OPOST */ 00349 00350 if (arg->readtimeoutmsec < 0) 00351 { 00352 // Settings for infinite timeout. 00353 devpar.c_cc[VTIME] = 0; 00354 // In case of infinite timeout [VMIN] must be at least 1. 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 /* definded (TIOCMGET) */ 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 /* ACE_HAS_TERMIOS */ 00396 00397 case GETPARAMS: 00398 return -1; // Not yet implemented. 00399 default: 00400 return -1; // Wrong cmd. 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 // Enable/disable RTS protocol. 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 // Enable/disable CTS protocol. 00480 if (arg->ctsenb) 00481 dcb.fOutxCtsFlow = TRUE; 00482 else 00483 dcb.fOutxCtsFlow = FALSE; 00484 00485 // Enable/disable DSR protocol. 00486 if (arg->dsrenb) 00487 dcb.fOutxDsrFlow = TRUE; 00488 else 00489 dcb.fOutxDsrFlow = FALSE; 00490 00491 // Disable/enable DTR protocol 00492 if (arg->dtrdisable) 00493 dcb.fDtrControl = DTR_CONTROL_DISABLE; 00494 else 00495 dcb.fDtrControl = DTR_CONTROL_ENABLE; 00496 00497 // Enable/disable software flow control on input 00498 if (arg->xinenb) 00499 dcb.fInX = TRUE; 00500 else 00501 dcb.fInX = FALSE; 00502 00503 // Enable/disable software flow control on output 00504 if (arg->xoutenb) 00505 dcb.fOutX = TRUE; 00506 else 00507 dcb.fOutX = FALSE; 00508 00509 // Always set limits unless set to negative to use default. 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 // Settings for infinite timeout. 00536 timeouts.ReadIntervalTimeout = 0; 00537 timeouts.ReadTotalTimeoutMultiplier = 0; 00538 timeouts.ReadTotalTimeoutConstant = 0; 00539 } 00540 else if (arg->readtimeoutmsec == 0) 00541 { 00542 // Return immediately if no data in the input buffer. 00543 timeouts.ReadIntervalTimeout = MAXDWORD; 00544 timeouts.ReadTotalTimeoutMultiplier = 0; 00545 timeouts.ReadTotalTimeoutConstant = 0; 00546 } 00547 else 00548 { 00549 // Wait for specified timeout for char to arrive before returning. 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); // Not yet implemented. 00565 default: 00566 return -1; // Wrong cmd. 00567 00568 } // arg switch 00569 #else 00570 ACE_UNUSED_ARG (cmd); 00571 ACE_UNUSED_ARG (arg); 00572 ACE_NOTSUP_RETURN (-1); 00573 #endif /* ACE_HAS_TERMIOS || ACE_HAS_TERMIO */ 00574 } |