1 #include "ace/TTY_IO.h"
2 #include "ace/OS_NS_errno.h"
3 #include "ace/OS_NS_string.h"
4 #include "ace/OS_NS_strings.h"
6 #if defined (ACE_HAS_TERMIOS)
7 # include "ace/os_include/os_termios.h"
8 #elif defined (ACE_HAS_TERMIO)
14 const char ACE_TTY_IO_NONE
[] = "none";
15 #if defined (ACE_HAS_TERMIOS) || defined (ACE_HAS_TERMIO) || defined (ACE_WIN32)
16 const char ACE_TTY_IO_ODD
[] = "odd";
17 const char ACE_TTY_IO_EVEN
[] = "even";
19 #if defined (ACE_WIN32)
20 const char ACE_TTY_IO_MARK
[] = "mark";
21 const char ACE_TTY_IO_SPACE
[] = "space";
22 #endif /* ACE_WIN32 */
25 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
27 ACE_TTY_IO::ACE_TTY_IO ()
31 ACE_TTY_IO::Serial_Params::Serial_Params ()
36 readmincharacters
= 0;
37 readtimeoutmsec
= 10000;
38 paritymode
= ACE_TTY_IO_NONE
;
52 // Interface for reading/writing serial device parameters
54 int ACE_TTY_IO::control (Control_Mode cmd
, Serial_Params
*arg
) const
56 #if defined (ACE_HAS_TERMIOS) || defined (ACE_HAS_TERMIO)
58 #if defined (ACE_HAS_TERMIOS)
59 struct termios devpar
;
60 speed_t newbaudrate
= 0;
61 if (tcgetattr (get_handle () , &devpar
) == -1)
62 #elif defined (TCGETS)
63 struct termios devpar
;
64 unsigned int newbaudrate
= 0;
65 if (this->ACE_IO_SAP::control (TCGETS
, static_cast<void*>(&devpar
)) == -1)
66 #elif defined (TCGETA)
68 unsigned int newbaudrate
= 0;
69 if (this->ACE_IO_SAP::control (TCGETA
, static_cast<void*>(&devpar
)) == -1)
72 #endif /* ACE_HAS_TERMIOS */
78 switch (arg
->baudrate
)
81 case 0: newbaudrate
= B0
; break;
84 case 50: newbaudrate
= B50
; break;
87 case 75: newbaudrate
= B75
; break;
90 case 110: newbaudrate
= B110
; break;
93 case 134: newbaudrate
= B134
; break;
96 case 150: newbaudrate
= B150
; break;
99 case 200: newbaudrate
= B200
; break;
102 case 300: newbaudrate
= B300
; break;
105 case 600: newbaudrate
= B600
; break;
108 case 1200: newbaudrate
= B1200
; break;
111 case 1800: newbaudrate
= B1800
; break;
114 case 2400: newbaudrate
= B2400
; break;
117 case 4800: newbaudrate
= B4800
; break;
120 case 9600: newbaudrate
= B9600
; break;
123 case 19200: newbaudrate
= B19200
; break;
126 case 38400: newbaudrate
= B38400
; break;
129 case 56000: newbaudrate
= B56000
; break;
132 case 57600: newbaudrate
= B57600
; break;
135 case 76800: newbaudrate
= B76800
; break;
137 #if defined (B115200)
138 case 115200: newbaudrate
= B115200
; break;
140 #if defined (B128000)
141 case 128000: newbaudrate
= B128000
; break;
143 #if defined (B153600)
144 case 153600: newbaudrate
= B153600
; break;
146 #if defined (B230400)
147 case 230400: newbaudrate
= B230400
; break;
149 #if defined (B307200)
150 case 307200: newbaudrate
= B307200
; break;
152 #if defined (B256000)
153 case 256000: newbaudrate
= B256000
; break;
155 #if defined (B460800)
156 case 460800: newbaudrate
= B460800
; break;
158 #if defined (B500000)
159 case 500000: newbaudrate
= B500000
; break;
161 #if defined (B576000)
162 case 576000: newbaudrate
= B576000
; break;
164 #if defined (B921600)
165 case 921600: newbaudrate
= B921600
; break;
167 #if defined (B1000000)
168 case 1000000: newbaudrate
= B1000000
; break;
169 #endif /* B1000000 */
170 #if defined (B1152000)
171 case 1152000: newbaudrate
= B1152000
; break;
172 #endif /* B1152000 */
173 #if defined (B1500000)
174 case 1500000: newbaudrate
= B1500000
; break;
175 #endif /* B1500000 */
176 #if defined (B2000000)
177 case 2000000: newbaudrate
= B2000000
; break;
178 #endif /* B2000000 */
179 #if defined (B2500000)
180 case 2500000: newbaudrate
= B2500000
; break;
181 #endif /* B2500000 */
182 #if defined (B3000000)
183 case 3000000: newbaudrate
= B3000000
; break;
184 #endif /* B3000000 */
185 #if defined (B3500000)
186 case 3500000: newbaudrate
= B3500000
; break;
187 #endif /* B3500000 */
188 #if defined (B4000000)
189 case 4000000: newbaudrate
= B4000000
; break;
190 #endif /* B4000000 */
195 #if defined (ACE_HAS_TERMIOS)
196 // Can you really have different input and output baud rates?!
197 if (cfsetospeed (&devpar
, newbaudrate
) == -1)
199 if (cfsetispeed (&devpar
, newbaudrate
) == -1)
202 devpar
.c_cflag
&= ~CBAUD
;
203 # if defined (CBAUDEX)
204 devpar
.c_cflag
&= ~CBAUDEX
;
205 # endif /* CBAUDEX */
206 devpar
.c_cflag
|= newbaudrate
;
207 #endif /* ACE_HAS_TERMIOS */
209 devpar
.c_cflag
&= ~CSIZE
;
210 switch (arg
->databits
)
213 devpar
.c_cflag
|= CS5
;
216 devpar
.c_cflag
|= CS6
;
219 devpar
.c_cflag
|= CS7
;
222 devpar
.c_cflag
|= CS8
;
228 switch (arg
->stopbits
)
231 devpar
.c_cflag
&= ~CSTOPB
;
234 devpar
.c_cflag
|= CSTOPB
;
242 if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_ODD
) == 0)
244 devpar
.c_cflag
|= PARENB
;
245 devpar
.c_cflag
|= PARODD
;
246 devpar
.c_iflag
&= ~IGNPAR
;
248 devpar
.c_iflag
|= INPCK
| PARMRK
;
250 devpar
.c_iflag
&= ~(INPCK
| PARMRK
);
252 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_EVEN
) == 0)
254 devpar
.c_cflag
|= PARENB
;
255 devpar
.c_cflag
&= ~PARODD
;
256 devpar
.c_iflag
&= ~IGNPAR
;
258 devpar
.c_iflag
|= INPCK
| PARMRK
;
260 devpar
.c_iflag
&= ~(INPCK
| PARMRK
);
262 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_NONE
) == 0)
264 devpar
.c_cflag
&= ~PARENB
;
273 devpar
.c_cflag
&= ~PARENB
;
276 #if defined (CNEW_RTSCTS)
277 if ((arg
->ctsenb
) || (arg
->rtsenb
)) // Enable RTS/CTS protocol
278 devpar
.c_cflag
|= CNEW_RTSCTS
;
280 devpar
.c_cflag
&= ~CNEW_RTSCTS
;
281 #elif defined (CRTSCTS)
282 if ((arg
->ctsenb
) || (arg
->rtsenb
)) // Enable RTS/CTS protocol
283 devpar
.c_cflag
|= CRTSCTS
;
285 devpar
.c_cflag
&= ~CRTSCTS
;
286 #endif /* NEW_RTSCTS || CRTSCTS */
289 // Enable/disable receiver
291 devpar
.c_cflag
|= CREAD
;
293 devpar
.c_cflag
&= ~CREAD
;
297 // Cause DTR to drop after port close.
298 devpar
.c_cflag
|= HUPCL
;
302 // If device is not a modem set to local device.
304 devpar
.c_cflag
&= ~CLOCAL
;
306 devpar
.c_cflag
|= CLOCAL
;
309 if (arg
->databits
< 8)
310 devpar
.c_iflag
|= ISTRIP
;
312 devpar
.c_iflag
&= ~ISTRIP
;
315 // If device is not a modem set to ignore break points
317 devpar
.c_iflag
&= ~IGNBRK
;
319 devpar
.c_iflag
|= IGNBRK
;
323 // Enable/disable software flow control on input
325 devpar
.c_iflag
|= IXOFF
;
327 devpar
.c_iflag
&= ~IXOFF
;
331 // Enable/disable software flow control on output
333 devpar
.c_iflag
|= IXON
;
335 devpar
.c_iflag
&= ~IXON
;
339 // Enable noncanonical input processing mode
340 devpar
.c_lflag
&= ~ICANON
;
344 // Disable echoing of input characters
345 devpar
.c_lflag
&= ~ECHO
;
349 // Disable echoing erase chareacter as BS-SP-BS
350 devpar
.c_lflag
&= ~ECHOE
;
354 // Disable SIGINTR, SIGSUSP, SIGDSUSP and SIGQUIT signals
355 devpar
.c_lflag
&= ~ISIG
;
359 // Do not discard CR characters
360 devpar
.c_iflag
&= ~IGNCR
;
364 // Disable CR to NL conversion
365 devpar
.c_iflag
&= ~ICRNL
;
369 // Disable NL to CR conversion
370 devpar
.c_iflag
&= ~INLCR
;
374 // Disable post-processing of output data
375 devpar
.c_oflag
&= ~OPOST
;
378 if (arg
->readtimeoutmsec
< 0)
380 // Settings for infinite timeout.
381 devpar
.c_cc
[VTIME
] = 0;
382 // In case of infinite timeout [VMIN] must be at least 1.
383 if (arg
->readmincharacters
> UCHAR_MAX
)
384 devpar
.c_cc
[VMIN
] = UCHAR_MAX
;
385 else if (arg
->readmincharacters
< 1)
386 devpar
.c_cc
[VMIN
] = 1;
388 devpar
.c_cc
[VMIN
] = static_cast<unsigned char>(arg
->readmincharacters
);
392 devpar
.c_cc
[VTIME
] = static_cast<unsigned char>(arg
->readtimeoutmsec
/ 100);
394 if (arg
->readmincharacters
> UCHAR_MAX
)
395 devpar
.c_cc
[VMIN
] = UCHAR_MAX
;
396 else if (arg
->readmincharacters
< 1)
397 devpar
.c_cc
[VMIN
] = 0;
399 devpar
.c_cc
[VMIN
] = static_cast<unsigned char>(arg
->readmincharacters
);
402 #if defined (TIOCMGET)
404 this->ACE_IO_SAP::control (TIOCMGET
, &status
);
407 status
&= ~TIOCM_DTR
;
411 this->ACE_IO_SAP::control (TIOCMSET
, &status
);
412 #endif /* definded (TIOCMGET) */
414 #if defined (ACE_HAS_TERMIOS)
415 return tcsetattr (get_handle (), TCSANOW
, &devpar
);
416 #elif defined (TCSETS)
417 return this->ACE_IO_SAP::control (TCSETS
, static_cast<void*>(&devpar
));
418 #elif defined (TCSETA)
419 return this->ACE_IO_SAP::control (TCSETA
, static_cast<void*>(&devpar
));
423 #endif /* ACE_HAS_TERMIOS */
426 return -1; // Not yet implemented.
428 return -1; // Wrong cmd.
430 #elif defined (ACE_WIN32)
432 dcb
.DCBlength
= sizeof dcb
;
433 if (!::GetCommState (this->get_handle (), &dcb
))
435 ACE_OS::set_errno_to_last_error ();
439 COMMTIMEOUTS timeouts
;
440 if (!::GetCommTimeouts (this->get_handle(), &timeouts
))
442 ACE_OS::set_errno_to_last_error ();
449 dcb
.BaudRate
= arg
->baudrate
;
451 switch (arg
->databits
)
458 dcb
.ByteSize
= arg
->databits
;
464 switch (arg
->stopbits
)
467 dcb
.StopBits
= ONESTOPBIT
;
470 dcb
.StopBits
= TWOSTOPBITS
;
479 if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_ODD
) == 0)
480 dcb
.Parity
= ODDPARITY
;
481 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_EVEN
) == 0)
482 dcb
.Parity
= EVENPARITY
;
483 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_NONE
) == 0)
484 dcb
.Parity
= NOPARITY
;
485 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_MARK
) == 0)
486 dcb
.Parity
= MARKPARITY
;
487 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_SPACE
) == 0)
488 dcb
.Parity
= SPACEPARITY
;
495 dcb
.Parity
= NOPARITY
;
498 // Enable/disable RTS protocol.
502 dcb
.fRtsControl
= RTS_CONTROL_ENABLE
;
505 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
508 dcb
.fRtsControl
= RTS_CONTROL_TOGGLE
;
511 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
514 // Enable/disable CTS protocol.
516 dcb
.fOutxCtsFlow
= TRUE
;
518 dcb
.fOutxCtsFlow
= FALSE
;
520 // Enable/disable DSR protocol.
522 dcb
.fOutxDsrFlow
= TRUE
;
524 dcb
.fOutxDsrFlow
= FALSE
;
526 // Disable/enable DTR protocol
528 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
530 dcb
.fDtrControl
= DTR_CONTROL_ENABLE
;
532 // Enable/disable software flow control on input
538 // Enable/disable software flow control on output
544 // Always set limits unless set to negative to use default.
545 if (arg
->xonlim
>= 0)
546 dcb
.XonLim
= static_cast<WORD
>(arg
->xonlim
);
547 if (arg
->xofflim
>= 0)
548 dcb
.XoffLim
= static_cast<WORD
>(arg
->xofflim
);
550 dcb
.fAbortOnError
= FALSE
;
551 dcb
.fErrorChar
= FALSE
;
555 if (!::SetCommState (this->get_handle (), &dcb
))
557 ACE_OS::set_errno_to_last_error ();
561 if (arg
->readtimeoutmsec
< 0)
563 // Settings for infinite timeout.
564 timeouts
.ReadIntervalTimeout
= 0;
565 timeouts
.ReadTotalTimeoutMultiplier
= 0;
566 timeouts
.ReadTotalTimeoutConstant
= 0;
568 else if (arg
->readtimeoutmsec
== 0)
570 // Return immediately if no data in the input buffer.
571 timeouts
.ReadIntervalTimeout
= MAXDWORD
;
572 timeouts
.ReadTotalTimeoutMultiplier
= 0;
573 timeouts
.ReadTotalTimeoutConstant
= 0;
577 // Wait for specified timeout for char to arrive before returning.
578 timeouts
.ReadIntervalTimeout
= MAXDWORD
;
579 timeouts
.ReadTotalTimeoutMultiplier
= MAXDWORD
;
580 timeouts
.ReadTotalTimeoutConstant
= arg
->readtimeoutmsec
;
583 if (!::SetCommTimeouts (this->get_handle (), &timeouts
))
585 ACE_OS::set_errno_to_last_error ();
592 arg
->baudrate
= dcb
.BaudRate
;
594 switch (dcb
.ByteSize
)
601 arg
->databits
= dcb
.ByteSize
;
607 switch (dcb
.StopBits
)
621 arg
->paritymode
= ACE_TTY_IO_NONE
;
628 arg
->paritymode
= ACE_TTY_IO_ODD
;
631 arg
->paritymode
= ACE_TTY_IO_EVEN
;
634 arg
->paritymode
= ACE_TTY_IO_NONE
;
637 arg
->paritymode
= ACE_TTY_IO_MARK
;
640 arg
->paritymode
= ACE_TTY_IO_SPACE
;
647 // Enable/disable RTS protocol.
648 switch (dcb
.fRtsControl
)
650 case RTS_CONTROL_ENABLE
:
653 case RTS_CONTROL_HANDSHAKE
:
656 case RTS_CONTROL_TOGGLE
:
659 case RTS_CONTROL_DISABLE
:
666 // Enable/disable CTS protocol.
667 if (dcb
.fOutxCtsFlow
)
672 // Enable/disable DSR protocol.
673 if (dcb
.fOutxDsrFlow
)
678 // Disable/enable DTR protocol
679 // Attention: DTR_CONTROL_HANDSHAKE is not supported.
680 switch (dcb
.fDtrControl
)
682 case DTR_CONTROL_DISABLE
:
683 arg
->dtrdisable
= true;
685 case DTR_CONTROL_ENABLE
:
686 arg
->dtrdisable
= false;
692 // Enable/disable software flow control on input
698 // Enable/disable software flow control on output
702 arg
->xoutenb
= false;
704 arg
->xonlim
= static_cast<int>(dcb
.XonLim
);
705 arg
->xofflim
= static_cast<int>(dcb
.XoffLim
);
707 if (timeouts
.ReadIntervalTimeout
== 0 &&
708 timeouts
.ReadTotalTimeoutMultiplier
== 0 &&
709 timeouts
.ReadTotalTimeoutConstant
== 0)
710 arg
->readtimeoutmsec
= -1;
712 arg
->readtimeoutmsec
= timeouts
.ReadTotalTimeoutConstant
;
717 return -1; // Wrong cmd.
721 ACE_UNUSED_ARG (cmd
);
722 ACE_UNUSED_ARG (arg
);
723 ACE_NOTSUP_RETURN (-1);
724 #endif /* ACE_HAS_TERMIOS || ACE_HAS_TERMIO */
727 ACE_END_VERSIONED_NAMESPACE_DECL