1 // $Id: TTY_IO.cpp 82271 2008-07-09 09:23:03Z olli $
3 #include "ace/TTY_IO.h"
4 #include "ace/OS_NS_errno.h"
5 #include "ace/OS_NS_string.h"
6 #include "ace/OS_NS_strings.h"
8 #if defined (ACE_HAS_TERMIOS)
9 # include "ace/os_include/os_termios.h"
10 #elif defined (ACE_HAS_TERMIO)
16 "$Id: TTY_IO.cpp 82271 2008-07-09 09:23:03Z olli $")
20 const char ACE_TTY_IO_NONE
[] = "none";
21 #if defined (ACE_HAS_TERMIOS) || defined (ACE_HAS_TERMIO) || defined (ACE_WIN32)
22 const char ACE_TTY_IO_ODD
[] = "odd";
23 const char ACE_TTY_IO_EVEN
[] = "even";
25 #if defined (ACE_WIN32)
26 const char ACE_TTY_IO_MARK
[] = "mark";
27 const char ACE_TTY_IO_SPACE
[] = "space";
28 #endif /* ACE_WIN32 */
31 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
33 ACE_TTY_IO::Serial_Params::Serial_Params (void)
38 readmincharacters
= 0;
39 readtimeoutmsec
= 10000;
40 paritymode
= ACE_TTY_IO_NONE
;
53 // Interface for reading/writing serial device parameters
55 int ACE_TTY_IO::control (Control_Mode cmd
, Serial_Params
*arg
) const
57 #if defined (ACE_HAS_TERMIOS) || defined (ACE_HAS_TERMIO)
59 #if defined (ACE_HAS_TERMIOS)
60 struct termios devpar
;
61 speed_t newbaudrate
= 0;
62 if (tcgetattr (get_handle () , &devpar
) == -1)
63 #elif defined (TCGETS)
64 struct termios devpar
;
65 unsigned int newbaudrate
= 0;
66 if (this->ACE_IO_SAP::control (TCGETS
, static_cast<void*>(&devpar
)) == -1)
67 #elif defined (TCGETA)
69 unsigned int newbaudrate
= 0;
70 if (this->ACE_IO_SAP::control (TCGETA
, static_cast<void*>(&devpar
)) == -1)
73 #endif /* ACE_HAS_TERMIOS */
79 switch (arg
->baudrate
)
82 case 0: newbaudrate
= B0
; break;
85 case 50: newbaudrate
= B50
; break;
88 case 75: newbaudrate
= B75
; break;
91 case 110: newbaudrate
= B110
; break;
94 case 134: newbaudrate
= B134
; break;
97 case 150: newbaudrate
= B150
; break;
100 case 200: newbaudrate
= B200
; break;
103 case 300: newbaudrate
= B300
; break;
106 case 600: newbaudrate
= B600
; break;
109 case 1200: newbaudrate
= B1200
; break;
112 case 1800: newbaudrate
= B1800
; break;
115 case 2400: newbaudrate
= B2400
; break;
118 case 4800: newbaudrate
= B4800
; break;
121 case 9600: newbaudrate
= B9600
; break;
124 case 19200: newbaudrate
= B19200
; break;
127 case 38400: newbaudrate
= B38400
; break;
130 case 56000: newbaudrate
= B56000
; break;
133 case 57600: newbaudrate
= B57600
; break;
136 case 76800: newbaudrate
= B76800
; break;
138 #if defined (B115200)
139 case 115200: newbaudrate
= B115200
; break;
141 #if defined (B128000)
142 case 128000: newbaudrate
= B128000
; break;
144 #if defined (B153600)
145 case 153600: newbaudrate
= B153600
; break;
147 #if defined (B230400)
148 case 230400: newbaudrate
= B230400
; break;
150 #if defined (B307200)
151 case 307200: newbaudrate
= B307200
; break;
153 #if defined (B256000)
154 case 256000: newbaudrate
= B256000
; break;
156 #if defined (B460800)
157 case 460800: newbaudrate
= B460800
; break;
159 #if defined (B500000)
160 case 500000: newbaudrate
= B500000
; break;
162 #if defined (B576000)
163 case 576000: newbaudrate
= B576000
; break;
165 #if defined (B921600)
166 case 921600: newbaudrate
= B921600
; break;
168 #if defined (B1000000)
169 case 1000000: newbaudrate
= B1000000
; break;
170 #endif /* B1000000 */
171 #if defined (B1152000)
172 case 1152000: newbaudrate
= B1152000
; break;
173 #endif /* B1152000 */
174 #if defined (B1500000)
175 case 1500000: newbaudrate
= B1500000
; break;
176 #endif /* B1500000 */
177 #if defined (B2000000)
178 case 2000000: newbaudrate
= B2000000
; break;
179 #endif /* B2000000 */
180 #if defined (B2500000)
181 case 2500000: newbaudrate
= B2500000
; break;
182 #endif /* B2500000 */
183 #if defined (B3000000)
184 case 3000000: newbaudrate
= B3000000
; break;
185 #endif /* B3000000 */
186 #if defined (B3500000)
187 case 3500000: newbaudrate
= B3500000
; break;
188 #endif /* B3500000 */
189 #if defined (B4000000)
190 case 4000000: newbaudrate
= B4000000
; break;
191 #endif /* B4000000 */
196 #if defined (ACE_HAS_TERMIOS)
197 // Can you really have different input and output baud rates?!
198 if (cfsetospeed (&devpar
, newbaudrate
) == -1)
200 if (cfsetispeed (&devpar
, newbaudrate
) == -1)
203 devpar
.c_cflag
&= ~CBAUD
;
204 # if defined (CBAUDEX)
205 devpar
.c_cflag
&= ~CBAUDEX
;
206 # endif /* CBAUDEX */
207 devpar
.c_cflag
|= newbaudrate
;
208 #endif /* ACE_HAS_TERMIOS */
210 devpar
.c_cflag
&= ~CSIZE
;
211 switch (arg
->databits
)
214 devpar
.c_cflag
|= CS5
;
217 devpar
.c_cflag
|= CS6
;
220 devpar
.c_cflag
|= CS7
;
223 devpar
.c_cflag
|= CS8
;
229 switch (arg
->stopbits
)
232 devpar
.c_cflag
&= ~CSTOPB
;
235 devpar
.c_cflag
|= CSTOPB
;
243 if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_ODD
) == 0)
245 devpar
.c_cflag
|= PARENB
;
246 devpar
.c_cflag
|= PARODD
;
248 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_EVEN
) == 0)
250 devpar
.c_cflag
|= PARENB
;
251 devpar
.c_cflag
&= ~PARODD
;
253 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_NONE
) == 0)
254 devpar
.c_cflag
&= ~PARENB
;
260 devpar
.c_cflag
&= ~PARENB
;
263 #if defined (CNEW_RTSCTS)
264 if ((arg
->ctsenb
) || (arg
->rtsenb
)) // Enable RTS/CTS protocol
265 devpar
.c_cflag
|= CNEW_RTSCTS
;
267 devpar
.c_cflag
&= ~CNEW_RTSCTS
;
268 #elif defined (CRTSCTS)
269 if ((arg
->ctsenb
) || (arg
->rtsenb
)) // Enable RTS/CTS protocol
270 devpar
.c_cflag
|= CRTSCTS
;
272 devpar
.c_cflag
&= ~CRTSCTS
;
273 #endif /* NEW_RTSCTS || CRTSCTS */
276 // Enable/disable receiver
278 devpar
.c_cflag
|= CREAD
;
280 devpar
.c_cflag
&= ~CREAD
;
284 // Cause DTR to drop after port close.
285 devpar
.c_cflag
|= HUPCL
;
289 // If device is not a modem set to local device.
291 devpar
.c_cflag
&= ~CLOCAL
;
293 devpar
.c_cflag
|= CLOCAL
;
296 devpar
.c_iflag
= IGNPAR
| INPCK
;
297 if (arg
->databits
< 8)
298 devpar
.c_iflag
|= ISTRIP
;
301 // If device is not a modem set to ignore break points
303 devpar
.c_iflag
&= ~IGNBRK
;
305 devpar
.c_iflag
|= IGNBRK
;
309 // Enable/disable software flow control on input
311 devpar
.c_iflag
|= IXOFF
;
313 devpar
.c_iflag
&= ~IXOFF
;
317 // Enable/disable software flow control on output
319 devpar
.c_iflag
|= IXON
;
321 devpar
.c_iflag
&= ~IXON
;
325 // Enable noncanonical input processing mode
326 devpar
.c_lflag
&= ~ICANON
;
330 // Disable echoing of input characters
331 devpar
.c_lflag
&= ~ECHO
;
335 // Disable echoing erase chareacter as BS-SP-BS
336 devpar
.c_lflag
&= ~ECHOE
;
340 // Disable SIGINTR, SIGSUSP, SIGDSUSP and SIGQUIT signals
341 devpar
.c_lflag
&= ~ISIG
;
345 // Disable post-processing of output data
346 devpar
.c_oflag
&= ~OPOST
;
349 if (arg
->readtimeoutmsec
< 0)
351 // Settings for infinite timeout.
352 devpar
.c_cc
[VTIME
] = 0;
353 // In case of infinite timeout [VMIN] must be at least 1.
354 if (arg
->readmincharacters
> UCHAR_MAX
)
355 devpar
.c_cc
[VMIN
] = UCHAR_MAX
;
356 else if (arg
->readmincharacters
< 1)
357 devpar
.c_cc
[VMIN
] = 1;
359 devpar
.c_cc
[VMIN
] = static_cast<unsigned char>(arg
->readmincharacters
);
363 devpar
.c_cc
[VTIME
] = static_cast<unsigned char>(arg
->readtimeoutmsec
/ 100);
365 if (arg
->readmincharacters
> UCHAR_MAX
)
366 devpar
.c_cc
[VMIN
] = UCHAR_MAX
;
367 else if (arg
->readmincharacters
< 1)
368 devpar
.c_cc
[VMIN
] = 0;
370 devpar
.c_cc
[VMIN
] = static_cast<unsigned char>(arg
->readmincharacters
);
373 #if defined (TIOCMGET)
375 this->ACE_IO_SAP::control (TIOCMGET
, &status
);
378 status
&= ~TIOCM_DTR
;
382 this->ACE_IO_SAP::control (TIOCMSET
, &status
);
383 #endif /* definded (TIOCMGET) */
385 #if defined (ACE_HAS_TERMIOS)
386 return tcsetattr (get_handle (), TCSANOW
, &devpar
);
387 #elif defined (TCSETS)
388 return this->ACE_IO_SAP::control (TCSETS
, static_cast<void*>(&devpar
));
389 #elif defined (TCSETA)
390 return this->ACE_IO_SAP::control (TCSETA
, static_cast<void*>(&devpar
));
394 #endif /* ACE_HAS_TERMIOS */
397 return -1; // Not yet implemented.
399 return -1; // Wrong cmd.
401 #elif defined (ACE_WIN32)
406 dcb
.DCBlength
= sizeof dcb
;
407 if (!::GetCommState (this->get_handle (), &dcb
))
409 ACE_OS::set_errno_to_last_error ();
413 dcb
.BaudRate
= arg
->baudrate
;
415 switch (arg
->databits
)
422 dcb
.ByteSize
= arg
->databits
;
428 switch (arg
->stopbits
)
431 dcb
.StopBits
= ONESTOPBIT
;
434 dcb
.StopBits
= TWOSTOPBITS
;
443 if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_ODD
) == 0)
444 dcb
.Parity
= ODDPARITY
;
445 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_EVEN
) == 0)
446 dcb
.Parity
= EVENPARITY
;
447 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_NONE
) == 0)
448 dcb
.Parity
= NOPARITY
;
449 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_MARK
) == 0)
450 dcb
.Parity
= MARKPARITY
;
451 else if (ACE_OS::strcasecmp (arg
->paritymode
, ACE_TTY_IO_SPACE
) == 0)
452 dcb
.Parity
= SPACEPARITY
;
459 dcb
.Parity
= NOPARITY
;
462 // Enable/disable RTS protocol.
466 dcb
.fRtsControl
= RTS_CONTROL_ENABLE
;
469 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
472 dcb
.fRtsControl
= RTS_CONTROL_TOGGLE
;
475 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
478 // Enable/disable CTS protocol.
480 dcb
.fOutxCtsFlow
= TRUE
;
482 dcb
.fOutxCtsFlow
= FALSE
;
484 // Enable/disable DSR protocol.
486 dcb
.fOutxDsrFlow
= TRUE
;
488 dcb
.fOutxDsrFlow
= FALSE
;
490 // Disable/enable DTR protocol
492 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
494 dcb
.fDtrControl
= DTR_CONTROL_ENABLE
;
496 // Enable/disable software flow control on input
502 // Enable/disable software flow control on output
508 // Always set limits unless set to negative to use default.
509 if (arg
->xonlim
>= 0)
510 dcb
.XonLim
= static_cast<WORD
>(arg
->xonlim
);
511 if (arg
->xofflim
>= 0)
512 dcb
.XoffLim
= static_cast<WORD
>(arg
->xofflim
);
514 dcb
.fAbortOnError
= FALSE
;
515 dcb
.fErrorChar
= FALSE
;
519 if (!::SetCommState (this->get_handle (), &dcb
))
521 ACE_OS::set_errno_to_last_error ();
525 COMMTIMEOUTS timeouts
;
526 if (!::GetCommTimeouts (this->get_handle(), &timeouts
))
528 ACE_OS::set_errno_to_last_error ();
532 if (arg
->readtimeoutmsec
< 0)
534 // Settings for infinite timeout.
535 timeouts
.ReadIntervalTimeout
= 0;
536 timeouts
.ReadTotalTimeoutMultiplier
= 0;
537 timeouts
.ReadTotalTimeoutConstant
= 0;
539 else if (arg
->readtimeoutmsec
== 0)
541 // Return immediately if no data in the input buffer.
542 timeouts
.ReadIntervalTimeout
= MAXDWORD
;
543 timeouts
.ReadTotalTimeoutMultiplier
= 0;
544 timeouts
.ReadTotalTimeoutConstant
= 0;
548 // Wait for specified timeout for char to arrive before returning.
549 timeouts
.ReadIntervalTimeout
= MAXDWORD
;
550 timeouts
.ReadTotalTimeoutMultiplier
= MAXDWORD
;
551 timeouts
.ReadTotalTimeoutConstant
= arg
->readtimeoutmsec
;
554 if (!::SetCommTimeouts (this->get_handle (), &timeouts
))
556 ACE_OS::set_errno_to_last_error ();
563 ACE_NOTSUP_RETURN (-1); // Not yet implemented.
565 return -1; // Wrong cmd.
569 ACE_UNUSED_ARG (cmd
);
570 ACE_UNUSED_ARG (arg
);
571 ACE_NOTSUP_RETURN (-1);
572 #endif /* ACE_HAS_TERMIOS || ACE_HAS_TERMIO */
575 #if defined (ACE_NEEDS_DEV_IO_CONVERSION)
576 ACE_TTY_IO::operator ACE_DEV_IO
&()
578 return static_cast<ACE_DEV_IO
&>(*this);
580 #endif /* ACE_NEEDS_DEV_IO_CONVERSION */
582 ACE_END_VERSIONED_NAMESPACE_DECL