#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 39 of file TTY_IO.cpp. References ACE_NOTSUP_RETURN, ACE_TTY_IO_EVEN, ACE_TTY_IO_MARK, 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.
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 } |