Cygwin: pinfo: use stpcpy where appropriate
[newlib-cygwin.git] / winsup / cygwin / fhandler / serial.cc
blobe04f8f26321765f7f898f0d106d4f630fc7b6960
1 /* fhandler_serial.cc
4 This file is part of Cygwin.
6 This software is a copyrighted work licensed under the terms of the
7 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
8 details. */
10 #include "winsup.h"
11 #include <unistd.h>
12 #include <sys/param.h>
13 #include "cygerrno.h"
14 #include "security.h"
15 #include "path.h"
16 #include "fhandler.h"
17 #include "sigproc.h"
18 #include "pinfo.h"
19 #include <asm/socket.h>
20 #include <devioctl.h>
21 #include <ntddser.h>
22 #include "cygwait.h"
24 /**********************************************************************/
25 /* fhandler_serial */
27 fhandler_serial::fhandler_serial ()
28 : fhandler_base (), vmin_ (0), vtime_ (0), pgrp_ (myself->pgid)
30 need_fork_fixup (true);
33 void
34 fhandler_serial::raw_read (void *ptr, size_t& ulen)
36 OVERLAPPED ov = { 0 };
37 DWORD io_err;
38 COMSTAT st;
39 DWORD bytes_to_read, read_bytes;
40 ssize_t tot = 0;
42 if (ulen > SSIZE_MAX)
43 ulen = SSIZE_MAX;
44 if (ulen == 0)
45 return;
47 /* If MIN > 0 in blocking mode, we have to read at least VMIN chars,
48 otherwise we're in polling mode and there's no minimum chars. */
49 ssize_t minchars = (!is_nonblocking () && vmin_) ? MIN (vmin_, ulen) : 0;
51 debug_printf ("ulen %ld, vmin_ %u, vtime_ %u", ulen, vmin_, vtime_);
53 ov.hEvent = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
57 /* First check if chars are already in the inbound queue. */
58 if (!ClearCommError (get_handle (), &io_err, &st))
59 goto err;
60 /* FIXME: In case of I/O error, do we really want to bail out or is it
61 better just trying to pull through? */
62 if (io_err)
64 termios_printf ("error detected %x", io_err);
65 SetLastError (ERROR_IO_DEVICE);
66 goto err;
68 /* ReadFile only handles up to DWORD bytes. */
69 bytes_to_read = MIN (ulen, UINT32_MAX);
70 if (is_nonblocking ())
72 /* In O_NONBLOCK mode we just care for the number of chars already
73 in the inbound queue. */
74 if (!st.cbInQue)
75 break;
76 bytes_to_read = MIN (st.cbInQue, bytes_to_read);
78 else
80 /* If the number of chars in the inbound queue is sufficent
81 (minchars defines the minimum), set bytes_to_read accordingly
82 and don't wait. */
83 if (st.cbInQue && (ssize_t) st.cbInQue >= minchars)
84 bytes_to_read = MIN (st.cbInQue, bytes_to_read);
87 ResetEvent (ov.hEvent);
88 if (!ReadFile (get_handle (), ptr, bytes_to_read, &read_bytes, &ov))
90 if (GetLastError () != ERROR_IO_PENDING)
91 goto err;
92 if (is_nonblocking ())
94 CancelIo (get_handle ());
95 if (!GetOverlappedResult (get_handle (), &ov, &read_bytes,
96 TRUE))
97 goto err;
99 else
101 switch (cygwait (ov.hEvent))
103 default: /* Handle an error case from cygwait basically like
104 a cancel condition and see if we got "something" */
105 CancelIo (get_handle ());
106 fallthrough;
107 case WAIT_OBJECT_0:
108 if (!GetOverlappedResult (get_handle (), &ov, &read_bytes,
109 TRUE))
110 goto err;
111 debug_printf ("got %u bytes from ReadFile", read_bytes);
112 break;
113 case WAIT_SIGNALED:
114 CancelIo (get_handle ());
115 if (!GetOverlappedResult (get_handle (), &ov, &read_bytes,
116 TRUE))
117 goto err;
118 /* Only if no bytes read, return with EINTR. */
119 if (!tot && !read_bytes)
121 tot = -1;
122 set_sig_errno (EINTR);
123 debug_printf ("signal received, set EINTR");
125 else
126 debug_printf ("signal received but ignored");
127 goto out;
128 case WAIT_CANCELED:
129 CancelIo (get_handle ());
130 GetOverlappedResult (get_handle (), &ov, &read_bytes, TRUE);
131 debug_printf ("thread canceled");
132 pthread::static_cancel_self ();
133 /*NOTREACHED*/
137 tot += read_bytes;
138 ptr = (void *) ((caddr_t) ptr + read_bytes);
139 ulen -= read_bytes;
140 minchars -= read_bytes;
141 debug_printf ("vtime_ %u, vmin_ %u, read_bytes %u, tot %D",
142 vtime_, vmin_, read_bytes, tot);
143 continue;
145 err:
146 debug_printf ("err %E");
147 if (GetLastError () != ERROR_OPERATION_ABORTED)
149 if (tot == 0)
151 tot = -1;
152 __seterrno ();
154 break;
157 /* ALL of these are required to loop:
159 Still room in user space buffer
160 AND still a minchars requirement (implies blocking mode)
161 AND vtime_ is not set. */
162 while (ulen > 0 && minchars > 0 && vtime_ == 0);
164 out:
165 CloseHandle (ov.hEvent);
166 ulen = (size_t) tot;
167 if (is_nonblocking () && ulen == 0)
169 ulen = (size_t) -1;
170 set_errno (EAGAIN);
174 /* Cover function to WriteFile to provide Posix interface and semantics
175 (as much as possible). */
176 ssize_t
177 fhandler_serial::raw_write (const void *ptr, size_t len)
179 DWORD bytes_written;
180 OVERLAPPED write_status;
182 memset (&write_status, 0, sizeof (write_status));
183 write_status.hEvent = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
184 ProtectHandle (write_status.hEvent);
186 for (;;)
188 if (WriteFile (get_handle (), ptr, len, &bytes_written, &write_status))
189 break;
191 switch (GetLastError ())
193 case ERROR_OPERATION_ABORTED:
194 DWORD ev;
195 if (!ClearCommError (get_handle (), &ev, NULL))
196 goto err;
197 if (ev)
198 termios_printf ("error detected %x", ev);
199 continue;
200 case ERROR_IO_PENDING:
201 break;
202 default:
203 goto err;
206 if (!is_nonblocking ())
208 switch (cygwait (write_status.hEvent))
210 case WAIT_OBJECT_0:
211 break;
212 case WAIT_SIGNALED:
213 PurgeComm (get_handle (), PURGE_TXABORT);
214 set_sig_errno (EINTR);
215 ForceCloseHandle (write_status.hEvent);
216 return -1;
217 case WAIT_CANCELED:
218 PurgeComm (get_handle (), PURGE_TXABORT);
219 pthread::static_cancel_self ();
220 /*NOTREACHED*/
221 default:
222 goto err;
225 if (!GetOverlappedResult (get_handle (), &write_status, &bytes_written, TRUE))
226 goto err;
228 break;
231 ForceCloseHandle (write_status.hEvent);
233 return bytes_written;
235 err:
236 __seterrno ();
237 ForceCloseHandle (write_status.hEvent);
238 return -1;
242 fhandler_serial::init (HANDLE f, DWORD flags, mode_t bin)
244 return open (flags, bin & (O_BINARY | O_TEXT));
248 fhandler_serial::open (int flags, mode_t mode)
250 int res;
251 COMMTIMEOUTS to;
253 syscall_printf ("fhandler_serial::open (%s, %y, 0%o)",
254 get_name (), flags, mode);
256 if (!fhandler_base::open (flags, mode))
257 return 0;
259 res = 1;
261 SetCommMask (get_handle (), EV_RXCHAR);
263 memset (&to, 0, sizeof (to));
264 SetCommTimeouts (get_handle (), &to);
266 /* Reset serial port to known state of 9600-8-1-no flow control
267 on open for better behavior under Win 95.
269 FIXME: This should only be done when explicitly opening the com
270 port. It should not be reset if an fd is inherited.
271 Using __progname in this way, to determine how far along in the
272 initialization we are, is really a terrible kludge and should
273 be fixed ASAP.
275 if (reset_com && __progname)
277 DCB state;
278 GetCommState (get_handle (), &state);
279 syscall_printf ("setting initial state on %s (reset_com %d)",
280 get_name (), reset_com);
281 state.BaudRate = CBR_9600;
282 state.ByteSize = 8;
283 state.StopBits = ONESTOPBIT;
284 state.Parity = NOPARITY; /* FIXME: correct default? */
285 state.fBinary = TRUE; /* binary xfer */
286 state.EofChar = 0; /* no end-of-data in binary mode */
287 state.fNull = FALSE; /* don't discard nulls in binary mode */
288 state.fParity = FALSE; /* ignore parity errors */
289 state.fErrorChar = FALSE;
290 state.fTXContinueOnXoff = TRUE; /* separate TX and RX flow control */
291 state.fOutX = FALSE; /* disable transmission flow control */
292 state.fInX = FALSE; /* disable reception flow control */
293 state.XonChar = 0x11;
294 state.XoffChar = 0x13;
295 state.fOutxDsrFlow = FALSE; /* disable DSR flow control */
296 state.fRtsControl = RTS_CONTROL_ENABLE; /* ignore lead control except
297 DTR */
298 state.fOutxCtsFlow = FALSE; /* disable output flow control */
299 state.fDtrControl = DTR_CONTROL_ENABLE; /* assert DTR */
300 state.fDsrSensitivity = FALSE; /* don't assert DSR */
301 state.fAbortOnError = TRUE;
302 if (!SetCommState (get_handle (), &state))
303 system_printf ("couldn't set initial state for %s, %E", get_name ());
306 SetCommMask (get_handle (), EV_RXCHAR);
307 set_open_status ();
308 syscall_printf ("%p = fhandler_serial::open (%s, %y, 0%o)",
309 res, get_name (), flags, mode);
310 return res;
313 /* tcsendbreak: POSIX 7.2.2.1 */
314 /* Break for 250-500 milliseconds if duration == 0 */
315 /* Otherwise, units for duration are undefined */
317 fhandler_serial::tcsendbreak (int duration)
319 unsigned int sleeptime = 300000;
321 if (duration > 0)
322 sleeptime *= duration;
324 if (SetCommBreak (get_handle ()) == 0)
325 return -1;
327 /* FIXME: need to send zero bits during duration */
328 usleep (sleeptime);
330 if (ClearCommBreak (get_handle ()) == 0)
331 return -1;
333 syscall_printf ("0 = fhandler_serial:tcsendbreak (%d)", duration);
335 return 0;
338 /* tcdrain: POSIX 7.2.2.1 */
340 fhandler_serial::tcdrain ()
342 if (FlushFileBuffers (get_handle ()) == 0)
343 return -1;
345 return 0;
348 /* tcflow: POSIX 7.2.2.1 */
350 fhandler_serial::tcflow (int action)
352 DWORD win32action = 0;
353 DCB dcb;
354 char xchar;
356 termios_printf ("action %d", action);
358 switch (action)
360 case TCOOFF:
361 win32action = SETXOFF;
362 break;
363 case TCOON:
364 win32action = SETXON;
365 break;
366 case TCION:
367 case TCIOFF:
368 if (GetCommState (get_handle (), &dcb) == 0)
369 return -1;
370 if (action == TCION)
371 xchar = (dcb.XonChar ? dcb.XonChar : 0x11);
372 else
373 xchar = (dcb.XoffChar ? dcb.XoffChar : 0x13);
374 if (TransmitCommChar (get_handle (), xchar) == 0)
375 return -1;
376 return 0;
377 break;
378 default:
379 return -1;
380 break;
383 if (EscapeCommFunction (get_handle (), win32action) == 0)
384 return -1;
386 return 0;
390 /* switch_modem_lines: set or clear RTS and/or DTR */
392 fhandler_serial::switch_modem_lines (int set, int clr)
394 if ((set & (TIOCM_RTS | TIOCM_DTR)) || (clr & (TIOCM_RTS | TIOCM_DTR)))
396 DCB dcb;
398 memset(&dcb,0,sizeof(dcb));
399 dcb.DCBlength = sizeof(dcb);
401 if (!GetCommState(get_handle(), &dcb))
403 __seterrno ();
404 return -1;
407 if (set & TIOCM_RTS)
408 dcb.fRtsControl = RTS_CONTROL_ENABLE;
409 else
410 if (clr & TIOCM_RTS)
411 dcb.fRtsControl = RTS_CONTROL_DISABLE;
413 if (set & TIOCM_DTR)
414 dcb.fDtrControl = DTR_CONTROL_ENABLE;
415 else
416 if (clr & TIOCM_DTR)
417 dcb.fDtrControl = DTR_CONTROL_DISABLE;
419 if (!SetCommState(get_handle(), &dcb))
421 __seterrno ();
422 return -1;
426 return 0;
429 /* ioctl: */
431 fhandler_serial::ioctl (unsigned int cmd, void *buf)
433 int res = 0;
435 # define ibuf ((int) (intptr_t) buf)
436 # define ipbuf (*(int *) buf)
438 DWORD ev;
439 COMSTAT st;
440 if (!ClearCommError (get_handle (), &ev, &st))
442 __seterrno ();
443 res = -1;
445 else
446 switch (cmd)
448 case TCFLSH:
449 res = tcflush (ibuf);
450 break;
451 case TIOCMGET:
452 DWORD modem_lines;
453 if (!GetCommModemStatus (get_handle (), &modem_lines))
455 __seterrno ();
456 res = -1;
458 else
460 ipbuf = 0;
461 if (modem_lines & MS_CTS_ON)
462 ipbuf |= TIOCM_CTS;
463 if (modem_lines & MS_DSR_ON)
464 ipbuf |= TIOCM_DSR;
465 if (modem_lines & MS_RING_ON)
466 ipbuf |= TIOCM_RI;
467 if (modem_lines & MS_RLSD_ON)
468 ipbuf |= TIOCM_CD;
470 DWORD cb;
471 DWORD mcr;
472 if (!DeviceIoControl (get_handle (), IOCTL_SERIAL_GET_DTRRTS,
473 NULL, 0, &mcr, 4, &cb, 0) || cb != 4)
474 ipbuf |= rts | dtr;
475 else
477 if (mcr & 2)
478 ipbuf |= TIOCM_RTS;
479 if (mcr & 1)
480 ipbuf |= TIOCM_DTR;
483 break;
484 case TIOCMSET:
485 if (switch_modem_lines (ipbuf, ~ipbuf))
486 res = -1;
487 break;
488 case TIOCMBIS:
489 if (switch_modem_lines (ipbuf, 0))
490 res = -1;
491 break;
492 case TIOCMBIC:
493 if (switch_modem_lines (0, ipbuf))
494 res = -1;
495 break;
496 case TIOCCBRK:
497 if (ClearCommBreak (get_handle ()) == 0)
499 __seterrno ();
500 res = -1;
502 break;
503 case TIOCSBRK:
504 if (SetCommBreak (get_handle ()) == 0)
506 __seterrno ();
507 res = -1;
509 break;
510 case TIOCINQ:
511 ipbuf = st.cbInQue;
512 break;
513 case TIOCGWINSZ:
514 ((struct winsize *) buf)->ws_row = 0;
515 ((struct winsize *) buf)->ws_col = 0;
516 break;
517 case FIONREAD:
518 set_errno (ENOTSUP);
519 res = -1;
520 break;
521 default:
522 res = fhandler_base::ioctl (cmd, buf);
523 break;
526 termios_printf ("%d = ioctl(%x, %p)", res, cmd, buf);
527 # undef ibuf
528 # undef ipbuf
529 return res;
532 /* tcflush: POSIX 7.2.2.1 */
534 fhandler_serial::tcflush (int queue)
536 DWORD flags;
538 switch (queue)
540 case TCOFLUSH:
541 flags = PURGE_TXABORT | PURGE_TXCLEAR;
542 break;
543 case TCIFLUSH:
544 flags = PURGE_RXABORT | PURGE_RXCLEAR;
545 break;
546 case TCIOFLUSH:
547 flags = PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR;
548 break;
549 default:
550 termios_printf ("Invalid tcflush queue %d", queue);
551 set_errno (EINVAL);
552 return -1;
555 if (!PurgeComm (get_handle (), flags))
557 __seterrno ();
558 return -1;
561 return 0;
564 /* tcsetattr: POSIX 7.2.1.1 */
566 fhandler_serial::tcsetattr (int action, const struct termios *t)
568 /* Possible actions:
569 TCSANOW: immediately change attributes.
570 TCSADRAIN: flush output, then change attributes.
571 TCSAFLUSH: flush output and discard input, then change attributes.
574 bool dropDTR = false;
575 COMMTIMEOUTS to;
576 DCB ostate, state;
577 int tmpDtr, tmpRts, res;
578 res = tmpDtr = tmpRts = 0;
580 termios_printf ("action %d", action);
581 if ((action == TCSADRAIN) || (action == TCSAFLUSH))
583 FlushFileBuffers (get_handle ());
584 termios_printf ("flushed file buffers");
586 if (action == TCSAFLUSH)
587 PurgeComm (get_handle (), (PURGE_RXABORT | PURGE_RXCLEAR));
589 /* get default/last comm state */
590 if (!GetCommState (get_handle (), &ostate))
591 return -1;
593 state = ostate;
595 /* -------------- Set baud rate ------------------ */
596 /* FIXME: WIN32 also has 14400, 56000, 128000, and 256000.
597 Unix also has 230400. */
599 switch (t->c_ospeed)
601 case B0:
602 /* Drop DTR - but leave DCB-resident bitrate as-is since
603 0 is an invalid bitrate in Win32 */
604 dropDTR = true;
605 break;
606 case B110:
607 state.BaudRate = CBR_110;
608 break;
609 case B300:
610 state.BaudRate = CBR_300;
611 break;
612 case B600:
613 state.BaudRate = CBR_600;
614 break;
615 case B1200:
616 state.BaudRate = CBR_1200;
617 break;
618 case B2400:
619 state.BaudRate = CBR_2400;
620 break;
621 case B4800:
622 state.BaudRate = CBR_4800;
623 break;
624 case B9600:
625 state.BaudRate = CBR_9600;
626 break;
627 case B19200:
628 state.BaudRate = CBR_19200;
629 break;
630 case B38400:
631 state.BaudRate = CBR_38400;
632 break;
633 case B57600:
634 state.BaudRate = CBR_57600;
635 break;
636 case B115200:
637 state.BaudRate = CBR_115200;
638 break;
639 case B128000:
640 state.BaudRate = CBR_128000;
641 break;
642 case B230400:
643 state.BaudRate = 230400 /* CBR_230400 - not defined */;
644 break;
645 case B256000:
646 state.BaudRate = CBR_256000;
647 break;
648 case B460800:
649 state.BaudRate = 460800 /* CBR_460800 - not defined */;
650 break;
651 case B500000:
652 state.BaudRate = 500000 /* CBR_500000 - not defined */;
653 break;
654 case B576000:
655 state.BaudRate = 576000 /* CBR_576000 - not defined */;
656 break;
657 case B921600:
658 state.BaudRate = 921600 /* CBR_921600 - not defined */;
659 break;
660 case B1000000:
661 state.BaudRate = 1000000 /* CBR_1000000 - not defined */;
662 break;
663 case B1152000:
664 state.BaudRate = 1152000 /* CBR_1152000 - not defined */;
665 break;
666 case B1500000:
667 state.BaudRate = 1500000 /* CBR_1500000 - not defined */;
668 break;
669 case B2000000:
670 state.BaudRate = 2000000 /* CBR_2000000 - not defined */;
671 break;
672 case B2500000:
673 state.BaudRate = 2500000 /* CBR_2500000 - not defined */;
674 break;
675 case B3000000:
676 state.BaudRate = 3000000 /* CBR_3000000 - not defined */;
677 break;
678 default:
679 /* Unsupported baud rate! */
680 termios_printf ("Invalid t->c_ospeed %u", t->c_ospeed);
681 set_errno (EINVAL);
682 return -1;
685 /* -------------- Set byte size ------------------ */
687 switch (t->c_cflag & CSIZE)
689 case CS5:
690 state.ByteSize = 5;
691 break;
692 case CS6:
693 state.ByteSize = 6;
694 break;
695 case CS7:
696 state.ByteSize = 7;
697 break;
698 case CS8:
699 state.ByteSize = 8;
700 break;
701 default:
702 /* Unsupported byte size! */
703 termios_printf ("Invalid t->c_cflag byte size %u",
704 t->c_cflag & CSIZE);
705 set_errno (EINVAL);
706 return -1;
709 /* -------------- Set stop bits ------------------ */
711 if (t->c_cflag & CSTOPB)
712 state.StopBits = TWOSTOPBITS;
713 else
714 state.StopBits = ONESTOPBIT;
716 /* -------------- Set parity ------------------ */
718 if (t->c_cflag & PARENB)
720 if(t->c_cflag & CMSPAR)
721 state.Parity = (t->c_cflag & PARODD) ? MARKPARITY : SPACEPARITY;
722 else
723 state.Parity = (t->c_cflag & PARODD) ? ODDPARITY : EVENPARITY;
725 else
726 state.Parity = NOPARITY;
728 state.fBinary = TRUE; /* Binary transfer */
729 state.EofChar = 0; /* No end-of-data in binary mode */
730 state.fNull = FALSE; /* Don't discard nulls in binary mode */
732 /* -------------- Parity errors ------------------ */
733 /* fParity combines the function of INPCK and NOT IGNPAR */
735 if ((t->c_iflag & INPCK) && !(t->c_iflag & IGNPAR))
736 state.fParity = TRUE; /* detect parity errors */
737 else
738 state.fParity = FALSE; /* ignore parity errors */
740 /* Only present in Win32, Unix has no equivalent */
741 state.fErrorChar = FALSE;
742 state.ErrorChar = 0;
744 /* -------------- Set software flow control ------------------ */
745 /* Set fTXContinueOnXoff to FALSE. This prevents the triggering of a
746 premature XON when the remote device interprets a received character
747 as XON (same as IXANY on the remote side). Otherwise, a TRUE
748 value separates the TX and RX functions. */
750 state.fTXContinueOnXoff = TRUE; /* separate TX and RX flow control */
752 /* Transmission flow control */
753 if (t->c_iflag & IXON)
754 state.fOutX = TRUE; /* enable */
755 else
756 state.fOutX = FALSE; /* disable */
758 /* Reception flow control */
759 if (t->c_iflag & IXOFF)
760 state.fInX = TRUE; /* enable */
761 else
762 state.fInX = FALSE; /* disable */
764 /* XoffLim and XonLim are left at default values */
766 state.XonChar = (t->c_cc[VSTART] ? t->c_cc[VSTART] : 0x11);
767 state.XoffChar = (t->c_cc[VSTOP] ? t->c_cc[VSTOP] : 0x13);
769 /* -------------- Set hardware flow control ------------------ */
771 /* Disable DSR flow control */
772 state.fOutxDsrFlow = FALSE;
774 /* Some old flavors of Unix automatically enabled hardware flow
775 control when software flow control was not enabled. Since newer
776 Unices tend to require explicit setting of hardware flow-control,
777 this is what we do. */
779 /* RTS/CTS flow control */
780 if (t->c_cflag & CRTSCTS)
781 { /* enable */
782 state.fOutxCtsFlow = TRUE;
783 state.fRtsControl = RTS_CONTROL_HANDSHAKE;
785 else
786 { /* disable */
787 state.fRtsControl = RTS_CONTROL_ENABLE;
788 state.fOutxCtsFlow = FALSE;
789 tmpRts = TIOCM_RTS;
792 if (t->c_cflag & CRTSXOFF)
793 state.fRtsControl = RTS_CONTROL_HANDSHAKE;
795 /* -------------- DTR ------------------ */
796 /* Assert DTR on device open */
798 state.fDtrControl = DTR_CONTROL_ENABLE;
800 /* -------------- DSR ------------------ */
801 /* Assert DSR at the device? */
803 if (t->c_cflag & CLOCAL)
804 state.fDsrSensitivity = FALSE; /* no */
805 else
806 state.fDsrSensitivity = TRUE; /* yes */
808 /* -------------- Error handling ------------------ */
809 /* Since read/write operations terminate upon error, we
810 will use ClearCommError() to resume. */
812 state.fAbortOnError = TRUE;
814 if ((memcmp (&ostate, &state, sizeof (state)) != 0)
815 && !SetCommState (get_handle (), &state))
817 /* SetCommState() failed, usually due to invalid DCB param.
818 Keep track of this so we can set errno to EINVAL later
819 and return failure */
820 termios_printf ("SetCommState() failed, %E");
821 __seterrno ();
822 res = -1;
825 rbinary ((t->c_iflag & IGNCR) ? false : true);
826 wbinary ((t->c_oflag & ONLCR) ? false : true);
828 if (dropDTR)
830 EscapeCommFunction (get_handle (), CLRDTR);
831 tmpDtr = 0;
833 else
835 /* FIXME: Sometimes when CLRDTR is set, setting
836 state.fDtrControl = DTR_CONTROL_ENABLE will fail. This
837 is a problem since a program might want to change some
838 parameters while DTR is still down. */
840 EscapeCommFunction (get_handle (), SETDTR);
841 tmpDtr = TIOCM_DTR;
844 rts = tmpRts;
845 dtr = tmpDtr;
847 /* The following documentation on was taken from "Linux Serial Programming
848 HOWTO". It explains how MIN (t->c_cc[VMIN] || vmin_) and TIME
849 (t->c_cc[VTIME] || vtime_) is to be used.
851 In non-canonical input processing mode, input is not assembled into
852 lines and input processing (erase, kill, delete, etc.) does not
853 occur. Two parameters control the behavior of this mode: c_cc[VTIME]
854 sets the character timer, and c_cc[VMIN] sets the minimum number of
855 characters to receive before satisfying the read.
857 If MIN > 0 and TIME = 0, MIN sets the number of characters to receive
858 before the read is satisfied. As TIME is zero, the timer is not used.
860 If MIN = 0 and TIME > 0, TIME serves as a timeout value. The read will
861 be satisfied if a single character is read, or TIME is exceeded (t =
862 TIME *0.1 s). If TIME is exceeded, no character will be returned.
864 If MIN > 0 and TIME > 0, TIME serves as an inter-character timer. The
865 read will be satisfied if MIN characters are received, or the time
866 between two characters exceeds TIME. The timer is restarted every time
867 a character is received and only becomes active after the first
868 character has been received.
870 If MIN = 0 and TIME = 0, read will be satisfied immediately. The
871 number of characters currently available, or the number of characters
872 requested will be returned. According to Antonino (see contributions),
873 you could issue a fcntl(fd, F_SETFL, FNDELAY); before reading to get
874 the same result.
877 if (t->c_lflag & ICANON)
879 vmin_ = 0;
880 vtime_ = 0;
882 else
884 vtime_ = t->c_cc[VTIME];
885 vmin_ = t->c_cc[VMIN];
888 debug_printf ("vtime %u, vmin %u", vtime_, vmin_);
890 memset (&to, 0, sizeof (to));
892 if ((vmin_ > 0) && (vtime_ == 0))
894 /* Returns immediately with whatever is in buffer on a ReadFile();
895 or blocks if nothing found. We will keep calling ReadFile(); until
896 vmin_ characters are read */
897 to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD;
898 to.ReadTotalTimeoutConstant = MAXDWORD - 1;
900 else if ((vmin_ == 0) && (vtime_ > 0))
902 /* set timeoout constant appropriately and we will only try to
903 read one character in ReadFile() */
904 to.ReadTotalTimeoutConstant = vtime_ * 100;
905 to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD;
907 else if ((vmin_ > 0) && (vtime_ > 0))
909 /* time applies to the interval time for this case */
910 to.ReadIntervalTimeout = vtime_ * 100;
912 else if ((vmin_ == 0) && (vtime_ == 0))
914 /* returns immediately with whatever is in buffer as per
915 Time-Outs docs in Win32 SDK API docs */
916 to.ReadIntervalTimeout = MAXDWORD;
919 debug_printf ("ReadTotalTimeoutConstant %u, ReadIntervalTimeout %u, "
920 "ReadTotalTimeoutMultiplier %u", to.ReadTotalTimeoutConstant,
921 to.ReadIntervalTimeout, to.ReadTotalTimeoutMultiplier);
923 if (!SetCommTimeouts(get_handle (), &to))
925 /* SetCommTimeouts() failed. Keep track of this so we
926 can set errno to EINVAL later and return failure */
927 termios_printf ("SetCommTimeouts() failed, %E");
928 __seterrno ();
929 res = -1;
932 return res;
935 /* tcgetattr: POSIX 7.2.1.1 */
937 fhandler_serial::tcgetattr (struct termios *t)
939 DCB state;
941 /* Get current Win32 comm state */
942 if (GetCommState (get_handle (), &state) == 0)
943 return -1;
945 /* for safety */
946 memset (t, 0, sizeof (*t));
948 t->c_cflag = 0;
949 /* -------------- Baud rate ------------------ */
950 switch (state.BaudRate)
952 case CBR_110:
953 t->c_ospeed = t->c_ispeed = B110;
954 break;
955 case CBR_300:
956 t->c_ospeed = t->c_ispeed = B300;
957 break;
958 case CBR_600:
959 t->c_ospeed = t->c_ispeed = B600;
960 break;
961 case CBR_1200:
962 t->c_ospeed = t->c_ispeed = B1200;
963 break;
964 case CBR_2400:
965 t->c_ospeed = t->c_ispeed = B2400;
966 break;
967 case CBR_4800:
968 t->c_ospeed = t->c_ispeed = B4800;
969 break;
970 case CBR_9600:
971 t->c_ospeed = t->c_ispeed = B9600;
972 break;
973 case CBR_19200:
974 t->c_ospeed = t->c_ispeed = B19200;
975 break;
976 case CBR_38400:
977 t->c_ospeed = t->c_ispeed = B38400;
978 break;
979 case CBR_57600:
980 t->c_ospeed = t->c_ispeed = B57600;
981 break;
982 case CBR_115200:
983 t->c_ospeed = t->c_ispeed = B115200;
984 break;
985 case CBR_128000:
986 t->c_ospeed = t->c_ispeed = B128000;
987 break;
988 case 230400: /* CBR_230400 - not defined */
989 t->c_ospeed = t->c_ispeed = B230400;
990 break;
991 case CBR_256000:
992 t->c_ospeed = t->c_ispeed = B256000;
993 break;
994 case 460800: /* CBR_460000 - not defined */
995 t->c_ospeed = t->c_ispeed = B460800;
996 break;
997 case 500000: /* CBR_500000 - not defined */
998 t->c_ospeed = t->c_ispeed = B500000;
999 break;
1000 case 576000: /* CBR_576000 - not defined */
1001 t->c_ospeed = t->c_ispeed = B576000;
1002 break;
1003 case 921600: /* CBR_921600 - not defined */
1004 t->c_ospeed = t->c_ispeed = B921600;
1005 break;
1006 case 1000000: /* CBR_1000000 - not defined */
1007 t->c_ospeed = t->c_ispeed = B1000000;
1008 break;
1009 case 1152000: /* CBR_1152000 - not defined */
1010 t->c_ospeed = t->c_ispeed = B1152000;
1011 break;
1012 case 1500000: /* CBR_1500000 - not defined */
1013 t->c_ospeed = t->c_ispeed = B1500000;
1014 break;
1015 case 2000000: /* CBR_2000000 - not defined */
1016 t->c_ospeed = t->c_ispeed = B2000000;
1017 break;
1018 case 2500000: /* CBR_2500000 - not defined */
1019 t->c_ospeed = t->c_ispeed = B2500000;
1020 break;
1021 case 3000000: /* CBR_3000000 - not defined */
1022 t->c_ospeed = t->c_ispeed = B3000000;
1023 break;
1024 default:
1025 /* Unsupported baud rate! */
1026 termios_printf ("Invalid baud rate %u", state.BaudRate);
1027 set_errno (EINVAL);
1028 return -1;
1031 /* -------------- Byte size ------------------ */
1033 switch (state.ByteSize)
1035 case 5:
1036 t->c_cflag |= CS5;
1037 break;
1038 case 6:
1039 t->c_cflag |= CS6;
1040 break;
1041 case 7:
1042 t->c_cflag |= CS7;
1043 break;
1044 case 8:
1045 t->c_cflag |= CS8;
1046 break;
1047 default:
1048 /* Unsupported byte size! */
1049 termios_printf ("Invalid byte size %u", state.ByteSize);
1050 set_errno (EINVAL);
1051 return -1;
1054 /* -------------- Stop bits ------------------ */
1056 if (state.StopBits == TWOSTOPBITS)
1057 t->c_cflag |= CSTOPB;
1059 /* -------------- Parity ------------------ */
1061 if (state.Parity == ODDPARITY)
1062 t->c_cflag |= (PARENB | PARODD);
1063 if (state.Parity == EVENPARITY)
1064 t->c_cflag |= PARENB;
1065 if (state.Parity == MARKPARITY)
1066 t->c_cflag |= (PARENB | PARODD | CMSPAR);
1067 if (state.Parity == SPACEPARITY)
1068 t->c_cflag |= (PARENB | CMSPAR);
1070 /* -------------- Parity errors ------------------ */
1072 /* fParity combines the function of INPCK and NOT IGNPAR */
1073 if (state.fParity)
1074 t->c_iflag |= INPCK;
1075 else
1076 t->c_iflag |= IGNPAR; /* not necessarily! */
1078 /* -------------- Software flow control ------------------ */
1080 /* transmission flow control */
1081 if (state.fOutX)
1082 t->c_iflag |= IXON;
1084 /* reception flow control */
1085 if (state.fInX)
1086 t->c_iflag |= IXOFF;
1088 t->c_cc[VSTART] = (state.XonChar ? state.XonChar : 0x11);
1089 t->c_cc[VSTOP] = (state.XoffChar ? state.XoffChar : 0x13);
1091 /* -------------- Hardware flow control ------------------ */
1092 /* Some old flavors of Unix automatically enabled hardware flow
1093 control when software flow control was not enabled. Since newer
1094 Unices tend to require explicit setting of hardware flow-control,
1095 this is what we do. */
1097 /* Input flow-control */
1098 if ((state.fRtsControl == RTS_CONTROL_HANDSHAKE) && state.fOutxCtsFlow)
1099 t->c_cflag |= CRTSCTS;
1100 if (state.fRtsControl == RTS_CONTROL_HANDSHAKE)
1101 t->c_cflag |= CRTSXOFF;
1103 /* -------------- CLOCAL --------------- */
1104 /* DSR is only lead toggled only by CLOCAL. Check it to see if
1105 CLOCAL was called. */
1106 /* FIXME: If tcsetattr() hasn't been called previously, this may
1107 give a false CLOCAL. */
1109 if (!state.fDsrSensitivity)
1110 t->c_cflag |= CLOCAL;
1112 /* FIXME: need to handle IGNCR */
1113 #if 0
1114 if (!rbinary ())
1115 t->c_iflag |= IGNCR;
1116 #endif
1118 if (!wbinary ())
1119 t->c_oflag |= ONLCR;
1121 t->c_cc[VTIME] = vtime_;
1122 t->c_cc[VMIN] = vmin_;
1124 debug_printf ("vmin_ %u, vtime_ %u", vmin_, vtime_);
1126 return 0;