OSDN Git Service

2012-01-06 Chris Sutcliffe <ir0nh34d@users.sf.net>
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / fhandler_serial.cc
1 /* fhandler_serial.cc
2
3    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4    2006, 2007, 2008, 2009, 2011 Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 #include "winsup.h"
13 #include <unistd.h>
14 #include "cygerrno.h"
15 #include "security.h"
16 #include "path.h"
17 #include "fhandler.h"
18 #include "sigproc.h"
19 #include "pinfo.h"
20 #include <asm/socket.h>
21 #include <ddk/ntddser.h>
22
23 /**********************************************************************/
24 /* fhandler_serial */
25
26 fhandler_serial::fhandler_serial ()
27   : fhandler_base (), vmin_ (0), vtime_ (0), pgrp_ (myself->pgid)
28 {
29   need_fork_fixup (true);
30 }
31
32 void
33 fhandler_serial::overlapped_setup ()
34 {
35   memset (&io_status, 0, sizeof (io_status));
36   io_status.hEvent = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
37   ProtectHandle (io_status.hEvent);
38   overlapped_armed = 0;
39 }
40
41 void __stdcall
42 fhandler_serial::raw_read (void *ptr, size_t& ulen)
43 {
44   int tot;
45   DWORD n;
46
47   size_t minchars = vmin_ ? min (vmin_, ulen) : ulen;
48
49   debug_printf ("ulen %d, vmin_ %d, vtime_ %d, hEvent %p", ulen, vmin_, vtime_,
50                 io_status.hEvent);
51   if (!overlapped_armed)
52     {
53       SetCommMask (get_handle (), EV_RXCHAR);
54       ResetEvent (io_status.hEvent);
55     }
56
57   for (n = 0, tot = 0; ulen; ulen -= n, ptr = (char *) ptr + n)
58     {
59       COMSTAT st;
60       DWORD inq = vmin_ ? minchars : vtime_ ? ulen : 1;
61
62       n = 0;
63
64       if (vtime_) // non-interruptible -- have to use kernel timeouts
65         overlapped_armed = -1;
66
67       if (!ClearCommError (get_handle (), &ev, &st))
68         goto err;
69       else if (ev)
70         termios_printf ("error detected %x", ev);
71       else if (st.cbInQue && !vtime_)
72         inq = st.cbInQue;
73       else if (!overlapped_armed)
74         {
75           if ((size_t) tot >= minchars)
76             break;
77           else if (WaitCommEvent (get_handle (), &ev, &io_status))
78             {
79               debug_printf ("WaitCommEvent succeeded: ev %x", ev);
80               if (!ev)
81                 continue;
82             }
83           else if (GetLastError () != ERROR_IO_PENDING)
84             goto err;
85           else if (is_nonblocking ())
86             {
87               PurgeComm (get_handle (), PURGE_RXABORT);
88               if (tot == 0)
89                 {
90                   tot = -1;
91                   set_errno (EAGAIN);
92                 }
93               goto out;
94             }
95           else
96             {
97               overlapped_armed = 1;
98               switch (cygwait (io_status.hEvent))
99                 {
100                 case WAIT_OBJECT_0:
101                   if (!GetOverlappedResult (get_handle (), &io_status, &n,
102                                             FALSE))
103                     goto err;
104                   debug_printf ("n %d, ev %x", n, ev);
105                   break;
106                 case WAIT_OBJECT_0 + 1:
107                   tot = -1;
108                   PurgeComm (get_handle (), PURGE_RXABORT);
109                   overlapped_armed = 0;
110                   set_sig_errno (EINTR);
111                   goto out;
112                 case WAIT_OBJECT_0 + 2:
113                   PurgeComm (get_handle (), PURGE_RXABORT);
114                   overlapped_armed = 0;
115                   pthread::static_cancel_self ();
116                   /*NOTREACHED*/
117                 default:
118                   goto err;
119                 }
120             }
121         }
122
123       overlapped_armed = 0;
124       ResetEvent (io_status.hEvent);
125       if (inq > ulen)
126         inq = ulen;
127       debug_printf ("inq %d", inq);
128       if (ReadFile (get_handle (), ptr, inq, &n, &io_status))
129         /* Got something */;
130       else if (GetLastError () != ERROR_IO_PENDING)
131         goto err;
132       else if (is_nonblocking ())
133         {
134           PurgeComm (get_handle (), PURGE_RXABORT);
135           if (tot == 0)
136             {
137               tot = -1;
138               set_errno (EAGAIN);
139             }
140           goto out;
141         }
142       else if (!GetOverlappedResult (get_handle (), &io_status, &n, TRUE))
143         goto err;
144
145       tot += n;
146       debug_printf ("vtime_ %d, vmin_ %d, n %d, tot %d", vtime_, vmin_, n, tot);
147       if (vtime_ || !vmin_ || !n)
148         break;
149       continue;
150
151     err:
152       debug_printf ("err %E");
153       if (GetLastError () != ERROR_OPERATION_ABORTED)
154         {
155           PurgeComm (get_handle (), PURGE_RXABORT);
156           tot = -1;
157           __seterrno ();
158           break;
159         }
160
161       n = 0;
162     }
163
164 out:
165   ulen = tot;
166 }
167
168 /* Cover function to WriteFile to provide Posix interface and semantics
169    (as much as possible).  */
170 ssize_t __stdcall
171 fhandler_serial::raw_write (const void *ptr, size_t len)
172 {
173   DWORD bytes_written;
174   OVERLAPPED write_status;
175
176   memset (&write_status, 0, sizeof (write_status));
177   write_status.hEvent = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
178   ProtectHandle (write_status.hEvent);
179
180   for (;;)
181     {
182       if (WriteFile (get_handle (), ptr, len, &bytes_written, &write_status))
183         break;
184
185       switch (GetLastError ())
186         {
187         case ERROR_OPERATION_ABORTED:
188           DWORD ev;
189           if (!ClearCommError (get_handle (), &ev, NULL))
190             goto err;
191           if (ev)
192             termios_printf ("error detected %x", ev);
193           continue;
194         case ERROR_IO_PENDING:
195           break;
196         default:
197           goto err;
198         }
199
200       if (!is_nonblocking ())
201         {
202           switch (cygwait (write_status.hEvent))
203             {
204             case WAIT_OBJECT_0:
205               break;
206             case WAIT_OBJECT_0 + 1:
207               PurgeComm (get_handle (), PURGE_TXABORT);
208               set_sig_errno (EINTR);
209               ForceCloseHandle (write_status.hEvent);
210               return -1;
211             case WAIT_OBJECT_0 + 2:
212               PurgeComm (get_handle (), PURGE_TXABORT);
213               pthread::static_cancel_self ();
214               /*NOTREACHED*/
215             default:
216               goto err;
217             }
218         }
219       if (!GetOverlappedResult (get_handle (), &write_status, &bytes_written, TRUE))
220         goto err;
221
222       break;
223     }
224
225   ForceCloseHandle (write_status.hEvent);
226
227   return bytes_written;
228
229 err:
230   __seterrno ();
231   ForceCloseHandle (write_status.hEvent);
232   return -1;
233 }
234
235 int
236 fhandler_serial::init (HANDLE f, DWORD flags, mode_t bin)
237 {
238   return open (flags, bin & (O_BINARY | O_TEXT));
239 }
240
241 int
242 fhandler_serial::open (int flags, mode_t mode)
243 {
244   int res;
245   COMMTIMEOUTS to;
246   extern BOOL reset_com;
247
248   syscall_printf ("fhandler_serial::open (%s, %p, %p)",
249                         get_name (), flags, mode);
250
251   if (!fhandler_base::open (flags, mode))
252     return 0;
253
254   res = 1;
255
256   SetCommMask (get_handle (), EV_RXCHAR);
257
258   overlapped_setup ();
259
260   memset (&to, 0, sizeof (to));
261   SetCommTimeouts (get_handle (), &to);
262
263   /* Reset serial port to known state of 9600-8-1-no flow control
264      on open for better behavior under Win 95.
265
266      FIXME:  This should only be done when explicitly opening the com
267      port.  It should not be reset if an fd is inherited.
268      Using __progname in this way, to determine how far along in the
269      initialization we are, is really a terrible kludge and should
270      be fixed ASAP.
271   */
272   if (reset_com && __progname)
273     {
274       DCB state;
275       GetCommState (get_handle (), &state);
276       syscall_printf ("setting initial state on %s (reset_com %d)",
277                       get_name (), reset_com);
278       state.BaudRate = CBR_9600;
279       state.ByteSize = 8;
280       state.StopBits = ONESTOPBIT;
281       state.Parity = NOPARITY; /* FIXME: correct default? */
282       state.fBinary = TRUE; /* binary xfer */
283       state.EofChar = 0; /* no end-of-data in binary mode */
284       state.fNull = FALSE; /* don't discard nulls in binary mode */
285       state.fParity = FALSE; /* ignore parity errors */
286       state.fErrorChar = FALSE;
287       state.fTXContinueOnXoff = TRUE; /* separate TX and RX flow control */
288       state.fOutX = FALSE; /* disable transmission flow control */
289       state.fInX = FALSE; /* disable reception flow control */
290       state.XonChar = 0x11;
291       state.XoffChar = 0x13;
292       state.fOutxDsrFlow = FALSE; /* disable DSR flow control */
293       state.fRtsControl = RTS_CONTROL_ENABLE; /* ignore lead control except
294                                                   DTR */
295       state.fOutxCtsFlow = FALSE; /* disable output flow control */
296       state.fDtrControl = DTR_CONTROL_ENABLE; /* assert DTR */
297       state.fDsrSensitivity = FALSE; /* don't assert DSR */
298       state.fAbortOnError = TRUE;
299       if (!SetCommState (get_handle (), &state))
300         system_printf ("couldn't set initial state for %s, %E", get_name ());
301     }
302
303   SetCommMask (get_handle (), EV_RXCHAR);
304   set_open_status ();
305   syscall_printf ("%p = fhandler_serial::open (%s, %p, %p)",
306                         res, get_name (), flags, mode);
307   return res;
308 }
309
310 int
311 fhandler_serial::close ()
312 {
313   ForceCloseHandle (io_status.hEvent);
314   return fhandler_base::close ();
315 }
316
317 /* tcsendbreak: POSIX 7.2.2.1 */
318 /* Break for 250-500 milliseconds if duration == 0 */
319 /* Otherwise, units for duration are undefined */
320 int
321 fhandler_serial::tcsendbreak (int duration)
322 {
323   unsigned int sleeptime = 300000;
324
325   if (duration > 0)
326     sleeptime *= duration;
327
328   if (SetCommBreak (get_handle ()) == 0)
329     return -1;
330
331   /* FIXME: need to send zero bits during duration */
332   usleep (sleeptime);
333
334   if (ClearCommBreak (get_handle ()) == 0)
335     return -1;
336
337   syscall_printf ("0 = fhandler_serial:tcsendbreak (%d)", duration);
338
339   return 0;
340 }
341
342 /* tcdrain: POSIX 7.2.2.1 */
343 int
344 fhandler_serial::tcdrain ()
345 {
346   if (FlushFileBuffers (get_handle ()) == 0)
347     return -1;
348
349   return 0;
350 }
351
352 /* tcflow: POSIX 7.2.2.1 */
353 int
354 fhandler_serial::tcflow (int action)
355 {
356   DWORD win32action = 0;
357   DCB dcb;
358   char xchar;
359
360   termios_printf ("action %d", action);
361
362   switch (action)
363     {
364     case TCOOFF:
365       win32action = SETXOFF;
366       break;
367     case TCOON:
368       win32action = SETXON;
369       break;
370     case TCION:
371     case TCIOFF:
372       if (GetCommState (get_handle (), &dcb) == 0)
373         return -1;
374       if (action == TCION)
375         xchar = (dcb.XonChar ? dcb.XonChar : 0x11);
376       else
377         xchar = (dcb.XoffChar ? dcb.XoffChar : 0x13);
378       if (TransmitCommChar (get_handle (), xchar) == 0)
379         return -1;
380       return 0;
381       break;
382     default:
383       return -1;
384       break;
385     }
386
387   if (EscapeCommFunction (get_handle (), win32action) == 0)
388     return -1;
389
390   return 0;
391 }
392
393
394 /* switch_modem_lines: set or clear RTS and/or DTR */
395 int
396 fhandler_serial::switch_modem_lines (int set, int clr)
397 {
398   int res = 0;
399
400   if (set & TIOCM_RTS)
401     {
402       if (EscapeCommFunction (get_handle (), SETRTS))
403         rts = TIOCM_RTS;
404       else
405         {
406           __seterrno ();
407           res = -1;
408         }
409     }
410   else if (clr & TIOCM_RTS)
411     {
412       if (EscapeCommFunction (get_handle (), CLRRTS))
413         rts = 0;
414       else
415         {
416           __seterrno ();
417           res = -1;
418         }
419     }
420   if (set & TIOCM_DTR)
421     {
422       if (EscapeCommFunction (get_handle (), SETDTR))
423         rts = TIOCM_DTR;
424       else
425         {
426           __seterrno ();
427           res = -1;
428         }
429     }
430   else if (clr & TIOCM_DTR)
431     {
432       if (EscapeCommFunction (get_handle (), CLRDTR))
433         rts = 0;
434       else
435         {
436           __seterrno ();
437           res = -1;
438         }
439     }
440
441   return res;
442 }
443
444 /* ioctl: */
445 int
446 fhandler_serial::ioctl (unsigned int cmd, void *buf)
447 {
448   int res = 0;
449
450 # define ibuf ((int) buf)
451 # define ipbuf (*(int *) buf)
452
453   DWORD ev;
454   COMSTAT st;
455   if (!ClearCommError (get_handle (), &ev, &st))
456     {
457       __seterrno ();
458       res = -1;
459     }
460   else
461     switch (cmd)
462       {
463       case TCFLSH:
464         res = tcflush (ibuf);
465         break;
466       case TIOCMGET:
467         DWORD modem_lines;
468         if (!GetCommModemStatus (get_handle (), &modem_lines))
469           {
470             __seterrno ();
471             res = -1;
472           }
473         else
474           {
475             ipbuf = 0;
476             if (modem_lines & MS_CTS_ON)
477               ipbuf |= TIOCM_CTS;
478             if (modem_lines & MS_DSR_ON)
479               ipbuf |= TIOCM_DSR;
480             if (modem_lines & MS_RING_ON)
481               ipbuf |= TIOCM_RI;
482             if (modem_lines & MS_RLSD_ON)
483               ipbuf |= TIOCM_CD;
484
485             DWORD cb;
486             DWORD mcr;
487             if (!DeviceIoControl (get_handle (), IOCTL_SERIAL_GET_DTRRTS,
488                                   NULL, 0, &mcr, 4, &cb, 0) || cb != 4)
489               ipbuf |= rts | dtr;
490             else
491               {
492                 if (mcr & 2)
493                   ipbuf |= TIOCM_RTS;
494                 if (mcr & 1)
495                   ipbuf |= TIOCM_DTR;
496               }
497           }
498         break;
499       case TIOCMSET:
500         if (switch_modem_lines (ipbuf, ~ipbuf))
501           res = -1;
502         break;
503       case TIOCMBIS:
504         if (switch_modem_lines (ipbuf, 0))
505           res = -1;
506         break;
507       case TIOCMBIC:
508         if (switch_modem_lines (0, ipbuf))
509           res = -1;
510         break;
511       case TIOCCBRK:
512         if (ClearCommBreak (get_handle ()) == 0)
513           {
514             __seterrno ();
515             res = -1;
516           }
517         break;
518       case TIOCSBRK:
519         if (SetCommBreak (get_handle ()) == 0)
520           {
521             __seterrno ();
522             res = -1;
523           }
524         break;
525      case TIOCINQ:
526        if (ev & CE_FRAME || ev & CE_IOE || ev & CE_OVERRUN || ev & CE_RXOVER
527            || ev & CE_RXPARITY)
528          {
529            set_errno (EINVAL);  /* FIXME: Use correct errno */
530            res = -1;
531          }
532        else
533          ipbuf = st.cbInQue;
534        break;
535      case TIOCGWINSZ:
536        ((struct winsize *) buf)->ws_row = 0;
537        ((struct winsize *) buf)->ws_col = 0;
538        break;
539      case FIONREAD:
540        set_errno (ENOTSUP);
541        res = -1;
542        break;
543      default:
544        res = fhandler_base::ioctl (cmd, buf);
545        break;
546      }
547
548   termios_printf ("%d = ioctl(%p, %p)", res, cmd, buf);
549 # undef ibuf
550 # undef ipbuf
551   return res;
552 }
553
554 /* tcflush: POSIX 7.2.2.1 */
555 int
556 fhandler_serial::tcflush (int queue)
557 {
558   DWORD flags;
559
560   switch (queue)
561     {
562     case TCOFLUSH:
563       flags = PURGE_TXABORT | PURGE_TXCLEAR;
564       break;
565     case TCIFLUSH:
566       flags = PURGE_RXABORT | PURGE_RXCLEAR;
567       break;
568     case TCIOFLUSH:
569       flags = PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR;
570       break;
571     default:
572       termios_printf ("Invalid tcflush queue %d", queue);
573       set_errno (EINVAL);
574       return -1;
575     }
576
577   if (!PurgeComm (get_handle (), flags))
578     {
579       __seterrno ();
580       return -1;
581     }
582
583   return 0;
584 }
585
586 /* tcsetattr: POSIX 7.2.1.1 */
587 int
588 fhandler_serial::tcsetattr (int action, const struct termios *t)
589 {
590   /* Possible actions:
591     TCSANOW:   immediately change attributes.
592     TCSADRAIN: flush output, then change attributes.
593     TCSAFLUSH: flush output and discard input, then change attributes.
594   */
595
596   bool dropDTR = false;
597   COMMTIMEOUTS to;
598   DCB ostate, state;
599   unsigned int ovtime = vtime_, ovmin = vmin_;
600   int tmpDtr, tmpRts, res;
601   res = tmpDtr = tmpRts = 0;
602
603   termios_printf ("action %d", action);
604   if ((action == TCSADRAIN) || (action == TCSAFLUSH))
605     {
606       FlushFileBuffers (get_handle ());
607       termios_printf ("flushed file buffers");
608     }
609   if (action == TCSAFLUSH)
610     PurgeComm (get_handle (), (PURGE_RXABORT | PURGE_RXCLEAR));
611
612   /* get default/last comm state */
613   if (!GetCommState (get_handle (), &ostate))
614     return -1;
615
616   state = ostate;
617
618   /* -------------- Set baud rate ------------------ */
619   /* FIXME: WIN32 also has 14400, 56000, 128000, and 256000.
620      Unix also has 230400. */
621
622   switch (t->c_ospeed)
623     {
624     case B0:
625       /* Drop DTR - but leave DCB-resident bitrate as-is since
626          0 is an invalid bitrate in Win32 */
627       dropDTR = true;
628       break;
629     case B110:
630       state.BaudRate = CBR_110;
631       break;
632     case B300:
633       state.BaudRate = CBR_300;
634       break;
635     case B600:
636       state.BaudRate = CBR_600;
637       break;
638     case B1200:
639       state.BaudRate = CBR_1200;
640       break;
641     case B2400:
642       state.BaudRate = CBR_2400;
643       break;
644     case B4800:
645       state.BaudRate = CBR_4800;
646       break;
647     case B9600:
648       state.BaudRate = CBR_9600;
649       break;
650     case B19200:
651       state.BaudRate = CBR_19200;
652       break;
653     case B38400:
654       state.BaudRate = CBR_38400;
655       break;
656     case B57600:
657       state.BaudRate = CBR_57600;
658       break;
659     case B115200:
660       state.BaudRate = CBR_115200;
661       break;
662     case B128000:
663       state.BaudRate = CBR_128000;
664       break;
665     case B230400:
666       state.BaudRate = 230400 /* CBR_230400 - not defined */;
667       break;
668     case B256000:
669       state.BaudRate = CBR_256000;
670       break;
671     case B460800:
672       state.BaudRate = 460800 /* CBR_460800 - not defined */;
673       break;
674     case B500000:
675       state.BaudRate = 500000 /* CBR_500000 - not defined */;
676       break;
677     case B576000:
678       state.BaudRate = 576000 /* CBR_576000 - not defined */;
679       break;
680     case B921600:
681       state.BaudRate = 921600 /* CBR_921600 - not defined */;
682       break;
683     case B1000000:
684       state.BaudRate = 1000000 /* CBR_1000000 - not defined */;
685       break;
686     case B1152000:
687       state.BaudRate = 1152000 /* CBR_1152000 - not defined */;
688       break;
689     case B1500000:
690       state.BaudRate = 1500000 /* CBR_1500000 - not defined */;
691       break;
692     case B2000000:
693       state.BaudRate = 2000000 /* CBR_2000000 - not defined */;
694       break;
695     case B2500000:
696       state.BaudRate = 2500000 /* CBR_2500000 - not defined */;
697       break;
698     case B3000000:
699       state.BaudRate = 3000000 /* CBR_3000000 - not defined */;
700       break;
701     default:
702       /* Unsupported baud rate! */
703       termios_printf ("Invalid t->c_ospeed %d", t->c_ospeed);
704       set_errno (EINVAL);
705       return -1;
706     }
707
708   /* -------------- Set byte size ------------------ */
709
710   switch (t->c_cflag & CSIZE)
711     {
712     case CS5:
713       state.ByteSize = 5;
714       break;
715     case CS6:
716       state.ByteSize = 6;
717       break;
718     case CS7:
719       state.ByteSize = 7;
720       break;
721     case CS8:
722       state.ByteSize = 8;
723       break;
724     default:
725       /* Unsupported byte size! */
726       termios_printf ("Invalid t->c_cflag byte size %d",
727                       t->c_cflag & CSIZE);
728       set_errno (EINVAL);
729       return -1;
730     }
731
732   /* -------------- Set stop bits ------------------ */
733
734   if (t->c_cflag & CSTOPB)
735     state.StopBits = TWOSTOPBITS;
736   else
737     state.StopBits = ONESTOPBIT;
738
739   /* -------------- Set parity ------------------ */
740
741   if (t->c_cflag & PARENB)
742     state.Parity = (t->c_cflag & PARODD) ? ODDPARITY : EVENPARITY;
743   else
744     state.Parity = NOPARITY;
745
746   state.fBinary = TRUE;     /* Binary transfer */
747   state.EofChar = 0;        /* No end-of-data in binary mode */
748   state.fNull = FALSE;      /* Don't discard nulls in binary mode */
749
750   /* -------------- Parity errors ------------------ */
751   /* fParity combines the function of INPCK and NOT IGNPAR */
752
753   if ((t->c_iflag & INPCK) && !(t->c_iflag & IGNPAR))
754     state.fParity = TRUE;   /* detect parity errors */
755   else
756     state.fParity = FALSE;  /* ignore parity errors */
757
758   /* Only present in Win32, Unix has no equivalent */
759   state.fErrorChar = FALSE;
760   state.ErrorChar = 0;
761
762   /* -------------- Set software flow control ------------------ */
763   /* Set fTXContinueOnXoff to FALSE.  This prevents the triggering of a
764      premature XON when the remote device interprets a received character
765      as XON (same as IXANY on the remote side).  Otherwise, a TRUE
766      value separates the TX and RX functions. */
767
768   state.fTXContinueOnXoff = TRUE;     /* separate TX and RX flow control */
769
770   /* Transmission flow control */
771   if (t->c_iflag & IXON)
772     state.fOutX = TRUE;   /* enable */
773   else
774     state.fOutX = FALSE;  /* disable */
775
776   /* Reception flow control */
777   if (t->c_iflag & IXOFF)
778     state.fInX = TRUE;    /* enable */
779   else
780     state.fInX = FALSE;   /* disable */
781
782   /* XoffLim and XonLim are left at default values */
783
784   state.XonChar = (t->c_cc[VSTART] ? t->c_cc[VSTART] : 0x11);
785   state.XoffChar = (t->c_cc[VSTOP] ? t->c_cc[VSTOP] : 0x13);
786
787   /* -------------- Set hardware flow control ------------------ */
788
789   /* Disable DSR flow control */
790   state.fOutxDsrFlow = FALSE;
791
792   /* Some old flavors of Unix automatically enabled hardware flow
793      control when software flow control was not enabled.  Since newer
794      Unices tend to require explicit setting of hardware flow-control,
795      this is what we do. */
796
797   /* RTS/CTS flow control */
798   if (t->c_cflag & CRTSCTS)
799     {                                                   /* enable */
800       state.fOutxCtsFlow = TRUE;
801       state.fRtsControl = RTS_CONTROL_HANDSHAKE;
802     }
803   else
804     {                                                   /* disable */
805       state.fRtsControl = RTS_CONTROL_ENABLE;
806       state.fOutxCtsFlow = FALSE;
807       tmpRts = TIOCM_RTS;
808     }
809
810   if (t->c_cflag & CRTSXOFF)
811     state.fRtsControl = RTS_CONTROL_HANDSHAKE;
812
813   /* -------------- DTR ------------------ */
814   /* Assert DTR on device open */
815
816   state.fDtrControl = DTR_CONTROL_ENABLE;
817
818   /* -------------- DSR ------------------ */
819   /* Assert DSR at the device? */
820
821   if (t->c_cflag & CLOCAL)
822     state.fDsrSensitivity = FALSE;  /* no */
823   else
824     state.fDsrSensitivity = TRUE;   /* yes */
825
826   /* -------------- Error handling ------------------ */
827   /* Since read/write operations terminate upon error, we
828      will use ClearCommError() to resume. */
829
830   state.fAbortOnError = TRUE;
831
832   if ((memcmp (&ostate, &state, sizeof (state)) != 0)
833       && !SetCommState (get_handle (), &state))
834     {
835       /* SetCommState() failed, usually due to invalid DCB param.
836          Keep track of this so we can set errno to EINVAL later
837          and return failure */
838       termios_printf ("SetCommState() failed, %E");
839       __seterrno ();
840       res = -1;
841     }
842
843   rbinary ((t->c_iflag & IGNCR) ? false : true);
844   wbinary ((t->c_oflag & ONLCR) ? false : true);
845
846   if (dropDTR)
847     {
848       EscapeCommFunction (get_handle (), CLRDTR);
849       tmpDtr = 0;
850     }
851   else
852     {
853       /* FIXME: Sometimes when CLRDTR is set, setting
854       state.fDtrControl = DTR_CONTROL_ENABLE will fail.  This
855       is a problem since a program might want to change some
856       parameters while DTR is still down. */
857
858       EscapeCommFunction (get_handle (), SETDTR);
859       tmpDtr = TIOCM_DTR;
860     }
861
862   rts = tmpRts;
863   dtr = tmpDtr;
864
865   /* The following documentation on was taken from "Linux Serial Programming
866   HOWTO".  It explains how MIN (t->c_cc[VMIN] || vmin_) and TIME
867   (t->c_cc[VTIME] || vtime_) is to be used.
868
869   In non-canonical input processing mode, input is not assembled into
870   lines and input processing (erase, kill, delete, etc.) does not
871   occur. Two parameters control the behavior of this mode: c_cc[VTIME]
872   sets the character timer, and c_cc[VMIN] sets the minimum number of
873   characters to receive before satisfying the read.
874
875   If MIN > 0 and TIME = 0, MIN sets the number of characters to receive
876   before the read is satisfied. As TIME is zero, the timer is not used.
877
878   If MIN = 0 and TIME > 0, TIME serves as a timeout value. The read will
879   be satisfied if a single character is read, or TIME is exceeded (t =
880   TIME *0.1 s). If TIME is exceeded, no character will be returned.
881
882   If MIN > 0 and TIME > 0, TIME serves as an inter-character timer. The
883   read will be satisfied if MIN characters are received, or the time
884   between two characters exceeds TIME. The timer is restarted every time
885   a character is received and only becomes active after the first
886   character has been received.
887
888   If MIN = 0 and TIME = 0, read will be satisfied immediately. The
889   number of characters currently available, or the number of characters
890   requested will be returned. According to Antonino (see contributions),
891   you could issue a fcntl(fd, F_SETFL, FNDELAY); before reading to get
892   the same result.
893   */
894
895   if (t->c_lflag & ICANON)
896     {
897       vmin_ = 0;
898       vtime_ = 0;
899     }
900   else
901     {
902       vtime_ = t->c_cc[VTIME] * 100;
903       vmin_ = t->c_cc[VMIN];
904     }
905
906   debug_printf ("vtime %d, vmin %d", vtime_, vmin_);
907
908   if (ovmin != vmin_ || ovtime != vtime_)
909   {
910     memset (&to, 0, sizeof (to));
911
912     if ((vmin_ > 0) && (vtime_ == 0))
913       {
914         /* Returns immediately with whatever is in buffer on a ReadFile();
915            or blocks if nothing found.  We will keep calling ReadFile(); until
916            vmin_ characters are read */
917         to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD;
918         to.ReadTotalTimeoutConstant = MAXDWORD - 1;
919       }
920     else if ((vmin_ == 0) && (vtime_ > 0))
921       {
922         /* set timeoout constant appropriately and we will only try to
923            read one character in ReadFile() */
924         to.ReadTotalTimeoutConstant = vtime_;
925         to.ReadIntervalTimeout = to.ReadTotalTimeoutMultiplier = MAXDWORD;
926       }
927     else if ((vmin_ > 0) && (vtime_ > 0))
928       {
929         /* time applies to the interval time for this case */
930         to.ReadIntervalTimeout = vtime_;
931       }
932     else if ((vmin_ == 0) && (vtime_ == 0))
933       {
934         /* returns immediately with whatever is in buffer as per
935            Time-Outs docs in Win32 SDK API docs */
936         to.ReadIntervalTimeout = MAXDWORD;
937       }
938
939     debug_printf ("ReadTotalTimeoutConstant %d, ReadIntervalTimeout %d, ReadTotalTimeoutMultiplier %d",
940                   to.ReadTotalTimeoutConstant, to.ReadIntervalTimeout, to.ReadTotalTimeoutMultiplier);
941
942     if (!SetCommTimeouts(get_handle (), &to))
943       {
944         /* SetCommTimeouts() failed. Keep track of this so we
945            can set errno to EINVAL later and return failure */
946         termios_printf ("SetCommTimeouts() failed, %E");
947         __seterrno ();
948         res = -1;
949       }
950   }
951
952   return res;
953 }
954
955 /* tcgetattr: POSIX 7.2.1.1 */
956 int
957 fhandler_serial::tcgetattr (struct termios *t)
958 {
959   DCB state;
960
961   /* Get current Win32 comm state */
962   if (GetCommState (get_handle (), &state) == 0)
963     return -1;
964
965   /* for safety */
966   memset (t, 0, sizeof (*t));
967
968   t->c_cflag = 0;
969   /* -------------- Baud rate ------------------ */
970   switch (state.BaudRate)
971     {
972     case CBR_110:
973         t->c_ospeed = t->c_ispeed = B110;
974         break;
975     case CBR_300:
976         t->c_ospeed = t->c_ispeed = B300;
977         break;
978     case CBR_600:
979         t->c_ospeed = t->c_ispeed = B600;
980         break;
981     case CBR_1200:
982         t->c_ospeed = t->c_ispeed = B1200;
983         break;
984     case CBR_2400:
985         t->c_ospeed = t->c_ispeed = B2400;
986         break;
987     case CBR_4800:
988         t->c_ospeed = t->c_ispeed = B4800;
989         break;
990     case CBR_9600:
991         t->c_ospeed = t->c_ispeed = B9600;
992         break;
993     case CBR_19200:
994         t->c_ospeed = t->c_ispeed = B19200;
995         break;
996     case CBR_38400:
997         t->c_ospeed = t->c_ispeed = B38400;
998         break;
999     case CBR_57600:
1000         t->c_ospeed = t->c_ispeed = B57600;
1001         break;
1002     case CBR_115200:
1003         t->c_ospeed = t->c_ispeed = B115200;
1004         break;
1005     case CBR_128000:
1006         t->c_ospeed = t->c_ispeed = B128000;
1007         break;
1008     case 230400: /* CBR_230400 - not defined */
1009         t->c_ospeed = t->c_ispeed = B230400;
1010         break;
1011     case CBR_256000:
1012         t->c_ospeed = t->c_ispeed = B256000;
1013         break;
1014     case 460800: /* CBR_460000 - not defined */
1015         t->c_ospeed = t->c_ispeed = B460800;
1016         break;
1017     case 500000: /* CBR_500000 - not defined */
1018         t->c_ospeed = t->c_ispeed = B500000;
1019         break;
1020     case 576000: /* CBR_576000 - not defined */
1021         t->c_ospeed = t->c_ispeed = B576000;
1022         break;
1023     case 921600: /* CBR_921600 - not defined */
1024         t->c_ospeed = t->c_ispeed = B921600;
1025         break;
1026     case 1000000: /* CBR_1000000 - not defined */
1027         t->c_ospeed = t->c_ispeed = B1000000;
1028         break;
1029     case 1152000: /* CBR_1152000 - not defined */
1030         t->c_ospeed = t->c_ispeed = B1152000;
1031         break;
1032     case 1500000: /* CBR_1500000 - not defined */
1033         t->c_ospeed = t->c_ispeed = B1500000;
1034         break;
1035     case 2000000: /* CBR_2000000 - not defined */
1036         t->c_ospeed = t->c_ispeed = B2000000;
1037         break;
1038     case 2500000: /* CBR_2500000 - not defined */
1039         t->c_ospeed = t->c_ispeed = B2500000;
1040         break;
1041     case 3000000: /* CBR_3000000 - not defined */
1042         t->c_ospeed = t->c_ispeed = B3000000;
1043         break;
1044     default:
1045         /* Unsupported baud rate! */
1046         termios_printf ("Invalid baud rate %d", state.BaudRate);
1047         set_errno (EINVAL);
1048         return -1;
1049     }
1050
1051   /* -------------- Byte size ------------------ */
1052
1053   switch (state.ByteSize)
1054     {
1055     case 5:
1056       t->c_cflag |= CS5;
1057       break;
1058     case 6:
1059       t->c_cflag |= CS6;
1060       break;
1061     case 7:
1062       t->c_cflag |= CS7;
1063       break;
1064     case 8:
1065       t->c_cflag |= CS8;
1066       break;
1067     default:
1068       /* Unsupported byte size! */
1069       termios_printf ("Invalid byte size %d", state.ByteSize);
1070       set_errno (EINVAL);
1071       return -1;
1072     }
1073
1074   /* -------------- Stop bits ------------------ */
1075
1076   if (state.StopBits == TWOSTOPBITS)
1077     t->c_cflag |= CSTOPB;
1078
1079   /* -------------- Parity ------------------ */
1080
1081   if (state.Parity == ODDPARITY)
1082     t->c_cflag |= (PARENB | PARODD);
1083   if (state.Parity == EVENPARITY)
1084     t->c_cflag |= PARENB;
1085
1086   /* -------------- Parity errors ------------------ */
1087
1088   /* fParity combines the function of INPCK and NOT IGNPAR */
1089   if (state.fParity)
1090     t->c_iflag |= INPCK;
1091   else
1092     t->c_iflag |= IGNPAR;       /* not necessarily! */
1093
1094   /* -------------- Software flow control ------------------ */
1095
1096   /* transmission flow control */
1097   if (state.fOutX)
1098     t->c_iflag |= IXON;
1099
1100   /* reception flow control */
1101   if (state.fInX)
1102     t->c_iflag |= IXOFF;
1103
1104   t->c_cc[VSTART] = (state.XonChar ? state.XonChar : 0x11);
1105   t->c_cc[VSTOP] = (state.XoffChar ? state.XoffChar : 0x13);
1106
1107   /* -------------- Hardware flow control ------------------ */
1108   /* Some old flavors of Unix automatically enabled hardware flow
1109      control when software flow control was not enabled.  Since newer
1110      Unices tend to require explicit setting of hardware flow-control,
1111      this is what we do. */
1112
1113   /* Input flow-control */
1114   if ((state.fRtsControl == RTS_CONTROL_HANDSHAKE) && state.fOutxCtsFlow)
1115     t->c_cflag |= CRTSCTS;
1116   if (state.fRtsControl == RTS_CONTROL_HANDSHAKE)
1117     t->c_cflag |= CRTSXOFF;
1118
1119   /* -------------- CLOCAL --------------- */
1120   /* DSR is only lead toggled only by CLOCAL.  Check it to see if
1121      CLOCAL was called. */
1122   /* FIXME: If tcsetattr() hasn't been called previously, this may
1123      give a false CLOCAL. */
1124
1125   if (!state.fDsrSensitivity)
1126     t->c_cflag |= CLOCAL;
1127
1128   /* FIXME: need to handle IGNCR */
1129 #if 0
1130   if (!rbinary ())
1131     t->c_iflag |= IGNCR;
1132 #endif
1133
1134   if (!wbinary ())
1135     t->c_oflag |= ONLCR;
1136
1137   t->c_cc[VTIME] = vtime_ / 100;
1138   t->c_cc[VMIN] = vmin_;
1139
1140   debug_printf ("vmin_ %d, vtime_ %d", vmin_, vtime_);
1141
1142   return 0;
1143 }
1144
1145 void
1146 fhandler_serial::fixup_after_fork (HANDLE parent)
1147 {
1148   if (close_on_exec ())
1149     fhandler_base::fixup_after_fork (parent);
1150   overlapped_setup ();
1151   debug_printf ("io_status.hEvent %p", io_status.hEvent);
1152 }
1153
1154 void
1155 fhandler_serial::fixup_after_exec ()
1156 {
1157   if (!close_on_exec ())
1158     overlapped_setup ();
1159   debug_printf ("io_status.hEvent %p, close_on_exec %d", io_status.hEvent, close_on_exec ());
1160 }
1161
1162 int
1163 fhandler_serial::dup (fhandler_base *child, int flags)
1164 {
1165   fhandler_serial *fhc = (fhandler_serial *) child;
1166   fhc->overlapped_setup ();
1167   return fhandler_base::dup (child, flags);
1168 }