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 (void)
31 ACE_TTY_IO::Serial_Params::Serial_Params (void)
36 readmincharacters
= 0;
37 readtimeoutmsec
= 10000;
38 paritymode
= ACE_TTY_IO_NONE
;
51 // Interface for reading/writing serial device parameters
53 int ACE_TTY_IO::control (Control_Mode cmd
, Serial_Params
*arg
) const
55 #if defined (ACE_HAS_TERMIOS) || defined (ACE_HAS_TERMIO)
57 #if defined (ACE_HAS_TERMIOS)
58 struct termios devpar
;
59 speed_t newbaudrate
= 0;
60 if (tcgetattr (get_handle () , &devpar
) == -1)
61 #elif defined (TCGETS)
62 struct termios devpar
;
63 unsigned int newbaudrate
= 0;
64 if (this->ACE_IO_SAP::control (TCGETS
, static_cast<void*>(&devpar
)) == -1)
65 #elif defined (TCGETA)
67 unsigned int newbaudrate
= 0;
68 if (this->ACE_IO_SAP::control (TCGETA
, static_cast<void*>(&devpar
)) == -1)
71 #endif /* ACE_HAS_TERMIOS */
77 switch (arg
->baudrate
)
80 case 0: newbaudrate
= B0
; break;
83 case 50: newbaudrate
= B50
; break;
86 case 75: newbaudrate
= B75
; break;
89 case 110: newbaudrate
= B110
; break;
92 case 134: newbaudrate
= B134
; break;
95 case 150: newbaudrate
= B150
; break;
98 case 200: newbaudrate
= B200
; break;
101 case 300: newbaudrate
= B300
; break;
104 case 600: newbaudrate
= B600
; break;
107 case 1200: newbaudrate
= B1200
; break;
110 case 1800: newbaudrate
= B1800
; break;
113 case 2400: newbaudrate
= B2400
; break;
116 case 4800: newbaudrate
= B4800
; break;
119 case 9600: newbaudrate
= B9600
; break;
122 case 19200: newbaudrate
= B19200
; break;
125 case 38400: newbaudrate
= B38400
; break;
128 case 56000: newbaudrate
= B56000
; break;
131 case 57600: newbaudrate
= B57600
; break;
134 case 76800: newbaudrate
= B76800
; break;
136 #if defined (B115200)
137 case 115200: newbaudrate
= B115200
; break;
139 #if defined (B128000)
140 case 128000: newbaudrate
= B128000
; break;
142 #if defined (B153600)
143 case 153600: newbaudrate
= B153600
; break;
145 #if defined (B230400)
146 case 230400: newbaudrate
= B230400
; break;
148 #if defined (B307200)
149 case 307200: newbaudrate
= B307200
; break;
151 #if defined (B256000)
152 case 256000: newbaudrate
= B256000
; break;
154 #if defined (B460800)
155 case 460800: newbaudrate
= B460800
; break;
157 #if defined (B500000)
158 case 500000: newbaudrate
= B500000
; break;
160 #if defined (B576000)
161 case 576000: newbaudrate
= B576000
; break;
163 #if defined (B921600)
164 case 921600: newbaudrate
= B921600
; break;
166 #if defined (B1000000)
167 case 1000000: newbaudrate
= B1000000
; break;
168 #endif /* B1000000 */
169 #if defined (B1152000)
170 case 1152000: newbaudrate
= B1152000
; break;
171 #endif /* B1152000 */
172 #if defined (B1500000)
173 case 1500000: newbaudrate
= B1500000
; break;
174 #endif /* B1500000 */
175 #if defined (B2000000)
176 case 2000000: newbaudrate
= B2000000
; break;
177 #endif /* B2000000 */
178 #if defined (B2500000)
179 case 2500000: newbaudrate
= B2500000
; break;
180 #endif /* B2500000 */
181 #if defined (B3000000)
182 case 3000000: newbaudrate
= B3000000
; break;
183 #endif /* B3000000 */
184 #if defined (B3500000)
185 case 3500000: newbaudrate
= B3500000
; break;
186 #endif /* B3500000 */
187 #if defined (B4000000)
188 case 4000000: newbaudrate
= B4000000
; break;
189 #endif /* B4000000 */
194 #if defined (ACE_HAS_TERMIOS)
195 // Can you really have different input and output baud rates?!
196 if (cfsetospeed (&devpar
, newbaudrate
) == -1)
198 if (cfsetispeed (&devpar
, newbaudrate
) == -1)
201 devpar
.c_cflag
&= ~CBAUD
;
202 # if defined (CBAUDEX)
203 devpar
.c_cflag
&= ~CBAUDEX
;
204 # endif /* CBAUDEX */
205 devpar
.c_cflag
|= newbaudrate
;
206 #endif /* ACE_HAS_TERMIOS */
208 devpar
.c_cflag
&= ~CSIZE
;
209 switch (arg
->databits
)
212 devpar
.c_cflag
|= CS5
;
215 devpar
.c_cflag
|= CS6
;
218 devpar
.c_cflag
|= CS7
;
221 devpar
.c_cflag
|= CS8
;
227 switch (arg
->stopbits
)
230 devpar
.c_cflag
&= ~CSTOPB
;
233 devpar
.c_cflag
|= CSTOPB
;
241 if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_ODD
) == 0)
243 devpar
.c_cflag
|= PARENB
;
244 devpar
.c_cflag
|= PARODD
;
245 devpar
.c_iflag
&= ~IGNPAR
;
246 devpar
.c_iflag
|= INPCK
| PARMRK
;
248 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_EVEN
) == 0)
250 devpar
.c_cflag
|= PARENB
;
251 devpar
.c_cflag
&= ~PARODD
;
252 devpar
.c_iflag
&= ~IGNPAR
;
253 devpar
.c_iflag
|= INPCK
| PARMRK
;
255 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_NONE
) == 0)
257 devpar
.c_cflag
&= ~PARENB
;
266 devpar
.c_cflag
&= ~PARENB
;
269 #if defined (CNEW_RTSCTS)
270 if ((arg
->ctsenb
) || (arg
->rtsenb
)) // Enable RTS/CTS protocol
271 devpar
.c_cflag
|= CNEW_RTSCTS
;
273 devpar
.c_cflag
&= ~CNEW_RTSCTS
;
274 #elif defined (CRTSCTS)
275 if ((arg
->ctsenb
) || (arg
->rtsenb
)) // Enable RTS/CTS protocol
276 devpar
.c_cflag
|= CRTSCTS
;
278 devpar
.c_cflag
&= ~CRTSCTS
;
279 #endif /* NEW_RTSCTS || CRTSCTS */
282 // Enable/disable receiver
284 devpar
.c_cflag
|= CREAD
;
286 devpar
.c_cflag
&= ~CREAD
;
290 // Cause DTR to drop after port close.
291 devpar
.c_cflag
|= HUPCL
;
295 // If device is not a modem set to local device.
297 devpar
.c_cflag
&= ~CLOCAL
;
299 devpar
.c_cflag
|= CLOCAL
;
302 if (arg
->databits
< 8)
303 devpar
.c_iflag
|= ISTRIP
;
306 // If device is not a modem set to ignore break points
308 devpar
.c_iflag
&= ~IGNBRK
;
310 devpar
.c_iflag
|= IGNBRK
;
314 // Enable/disable software flow control on input
316 devpar
.c_iflag
|= IXOFF
;
318 devpar
.c_iflag
&= ~IXOFF
;
322 // Enable/disable software flow control on output
324 devpar
.c_iflag
|= IXON
;
326 devpar
.c_iflag
&= ~IXON
;
330 // Enable noncanonical input processing mode
331 devpar
.c_lflag
&= ~ICANON
;
335 // Disable echoing of input characters
336 devpar
.c_lflag
&= ~ECHO
;
340 // Disable echoing erase chareacter as BS-SP-BS
341 devpar
.c_lflag
&= ~ECHOE
;
345 // Disable SIGINTR, SIGSUSP, SIGDSUSP and SIGQUIT signals
346 devpar
.c_lflag
&= ~ISIG
;
350 // Disable post-processing of output data
351 devpar
.c_oflag
&= ~OPOST
;
354 if (arg
->readtimeoutmsec
< 0)
356 // Settings for infinite timeout.
357 devpar
.c_cc
[VTIME
] = 0;
358 // In case of infinite timeout [VMIN] must be at least 1.
359 if (arg
->readmincharacters
> UCHAR_MAX
)
360 devpar
.c_cc
[VMIN
] = UCHAR_MAX
;
361 else if (arg
->readmincharacters
< 1)
362 devpar
.c_cc
[VMIN
] = 1;
364 devpar
.c_cc
[VMIN
] = static_cast<unsigned char>(arg
->readmincharacters
);
368 devpar
.c_cc
[VTIME
] = static_cast<unsigned char>(arg
->readtimeoutmsec
/ 100);
370 if (arg
->readmincharacters
> UCHAR_MAX
)
371 devpar
.c_cc
[VMIN
] = UCHAR_MAX
;
372 else if (arg
->readmincharacters
< 1)
373 devpar
.c_cc
[VMIN
] = 0;
375 devpar
.c_cc
[VMIN
] = static_cast<unsigned char>(arg
->readmincharacters
);
378 #if defined (TIOCMGET)
380 this->ACE_IO_SAP::control (TIOCMGET
, &status
);
383 status
&= ~TIOCM_DTR
;
387 this->ACE_IO_SAP::control (TIOCMSET
, &status
);
388 #endif /* definded (TIOCMGET) */
390 #if defined (ACE_HAS_TERMIOS)
391 return tcsetattr (get_handle (), TCSANOW
, &devpar
);
392 #elif defined (TCSETS)
393 return this->ACE_IO_SAP::control (TCSETS
, static_cast<void*>(&devpar
));
394 #elif defined (TCSETA)
395 return this->ACE_IO_SAP::control (TCSETA
, static_cast<void*>(&devpar
));
399 #endif /* ACE_HAS_TERMIOS */
402 return -1; // Not yet implemented.
404 return -1; // Wrong cmd.
406 #elif defined (ACE_WIN32)
408 dcb
.DCBlength
= sizeof dcb
;
409 if (!::GetCommState (this->get_handle (), &dcb
))
411 ACE_OS::set_errno_to_last_error ();
415 COMMTIMEOUTS timeouts
;
416 if (!::GetCommTimeouts (this->get_handle(), &timeouts
))
418 ACE_OS::set_errno_to_last_error ();
425 dcb
.BaudRate
= arg
->baudrate
;
427 switch (arg
->databits
)
434 dcb
.ByteSize
= arg
->databits
;
440 switch (arg
->stopbits
)
443 dcb
.StopBits
= ONESTOPBIT
;
446 dcb
.StopBits
= TWOSTOPBITS
;
455 if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_ODD
) == 0)
456 dcb
.Parity
= ODDPARITY
;
457 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_EVEN
) == 0)
458 dcb
.Parity
= EVENPARITY
;
459 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_NONE
) == 0)
460 dcb
.Parity
= NOPARITY
;
461 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_MARK
) == 0)
462 dcb
.Parity
= MARKPARITY
;
463 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_SPACE
) == 0)
464 dcb
.Parity
= SPACEPARITY
;
471 dcb
.Parity
= NOPARITY
;
474 // Enable/disable RTS protocol.
478 dcb
.fRtsControl
= RTS_CONTROL_ENABLE
;
481 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
484 dcb
.fRtsControl
= RTS_CONTROL_TOGGLE
;
487 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
490 // Enable/disable CTS protocol.
492 dcb
.fOutxCtsFlow
= TRUE
;
494 dcb
.fOutxCtsFlow
= FALSE
;
496 // Enable/disable DSR protocol.
498 dcb
.fOutxDsrFlow
= TRUE
;
500 dcb
.fOutxDsrFlow
= FALSE
;
502 // Disable/enable DTR protocol
504 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
506 dcb
.fDtrControl
= DTR_CONTROL_ENABLE
;
508 // Enable/disable software flow control on input
514 // Enable/disable software flow control on output
520 // Always set limits unless set to negative to use default.
521 if (arg
->xonlim
>= 0)
522 dcb
.XonLim
= static_cast<WORD
>(arg
->xonlim
);
523 if (arg
->xofflim
>= 0)
524 dcb
.XoffLim
= static_cast<WORD
>(arg
->xofflim
);
526 dcb
.fAbortOnError
= FALSE
;
527 dcb
.fErrorChar
= FALSE
;
531 if (!::SetCommState (this->get_handle (), &dcb
))
533 ACE_OS::set_errno_to_last_error ();
537 if (arg
->readtimeoutmsec
< 0)
539 // Settings for infinite timeout.
540 timeouts
.ReadIntervalTimeout
= 0;
541 timeouts
.ReadTotalTimeoutMultiplier
= 0;
542 timeouts
.ReadTotalTimeoutConstant
= 0;
544 else if (arg
->readtimeoutmsec
== 0)
546 // Return immediately if no data in the input buffer.
547 timeouts
.ReadIntervalTimeout
= MAXDWORD
;
548 timeouts
.ReadTotalTimeoutMultiplier
= 0;
549 timeouts
.ReadTotalTimeoutConstant
= 0;
553 // Wait for specified timeout for char to arrive before returning.
554 timeouts
.ReadIntervalTimeout
= MAXDWORD
;
555 timeouts
.ReadTotalTimeoutMultiplier
= MAXDWORD
;
556 timeouts
.ReadTotalTimeoutConstant
= arg
->readtimeoutmsec
;
559 if (!::SetCommTimeouts (this->get_handle (), &timeouts
))
561 ACE_OS::set_errno_to_last_error ();
568 arg
->baudrate
= dcb
.BaudRate
;
570 switch (dcb
.ByteSize
)
577 arg
->databits
= dcb
.ByteSize
;
583 switch (dcb
.StopBits
)
597 arg
->paritymode
= ACE_TTY_IO_NONE
;
604 arg
->paritymode
= ACE_TTY_IO_ODD
;
607 arg
->paritymode
= ACE_TTY_IO_EVEN
;
610 arg
->paritymode
= ACE_TTY_IO_NONE
;
613 arg
->paritymode
= ACE_TTY_IO_MARK
;
616 arg
->paritymode
= ACE_TTY_IO_SPACE
;
623 // Enable/disable RTS protocol.
624 switch (dcb
.fRtsControl
)
626 case RTS_CONTROL_ENABLE
:
629 case RTS_CONTROL_HANDSHAKE
:
632 case RTS_CONTROL_TOGGLE
:
635 case RTS_CONTROL_DISABLE
:
642 // Enable/disable CTS protocol.
643 if (dcb
.fOutxCtsFlow
)
648 // Enable/disable DSR protocol.
649 if (dcb
.fOutxDsrFlow
)
654 // Disable/enable DTR protocol
655 // Attention: DTR_CONTROL_HANDSHAKE is not supported.
656 switch (dcb
.fDtrControl
)
658 case DTR_CONTROL_DISABLE
:
659 arg
->dtrdisable
= true;
661 case DTR_CONTROL_ENABLE
:
662 arg
->dtrdisable
= false;
668 // Enable/disable software flow control on input
674 // Enable/disable software flow control on output
678 arg
->xoutenb
= false;
680 arg
->xonlim
= static_cast<int>(dcb
.XonLim
);
681 arg
->xofflim
= static_cast<int>(dcb
.XoffLim
);
683 if (timeouts
.ReadIntervalTimeout
== 0 &&
684 timeouts
.ReadTotalTimeoutMultiplier
== 0 &&
685 timeouts
.ReadTotalTimeoutConstant
== 0)
686 arg
->readtimeoutmsec
= -1;
688 arg
->readtimeoutmsec
= timeouts
.ReadTotalTimeoutConstant
;
693 return -1; // Wrong cmd.
697 ACE_UNUSED_ARG (cmd
);
698 ACE_UNUSED_ARG (arg
);
699 ACE_NOTSUP_RETURN (-1);
700 #endif /* ACE_HAS_TERMIOS || ACE_HAS_TERMIO */
703 #if defined (ACE_NEEDS_DEV_IO_CONVERSION)
704 ACE_TTY_IO::operator ACE_DEV_IO
&()
706 return static_cast<ACE_DEV_IO
&>(*this);
708 #endif /* ACE_NEEDS_DEV_IO_CONVERSION */
710 ACE_END_VERSIONED_NAMESPACE_DECL