diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 01a2b09e0..66f13c834 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,18 @@ +2002-07-22 Jacek Trzcinski + + * fhandler.h (class fhandler_serial): Add new members of + the class - rts,dtr and method ioctl(). Variables rts and dtr + important for Win 9x only. + * fhandler_serial.cc (fhandler_serial::open): Add initial setting + of dtr and rts. Important for Win 9x only. + (fhandler_serial::ioctl): New function. Implements commands TIOCMGET, + TIOCMSET and TIOCINQ. + (fhandler_serial::tcflush): Fixed found error. + (fhandler_serial::tcsetattr): Add settings of rts and dtr. Important + for Win 9x only. + * termios.h: Add new defines as a support for ioctl() function + on serial device. + 2002-07-20 Christopher Faylor * autoload.cc (LoadDLLprime): Add jmp call to allow streamlining of diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 164a892d1..17390bdc3 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -629,6 +629,8 @@ class fhandler_serial: public fhandler_base unsigned int vmin_; /* from termios */ unsigned int vtime_; /* from termios */ pid_t pgrp_; + int rts; /* for Windows 9x purposes only */ + int dtr; /* for Windows 9x purposes only */ public: int overlapped_armed; @@ -648,6 +650,7 @@ class fhandler_serial: public fhandler_base int tcsendbreak (int); int tcdrain (); int tcflow (int); + int ioctl (unsigned int cmd, void *); int tcsetattr (int a, const struct termios *t); int tcgetattr (struct termios *t); __off64_t lseek (__off64_t, int) { return 0; } diff --git a/winsup/cygwin/fhandler_serial.cc b/winsup/cygwin/fhandler_serial.cc index b5816a858..648805150 100644 --- a/winsup/cygwin/fhandler_serial.cc +++ b/winsup/cygwin/fhandler_serial.cc @@ -268,6 +268,23 @@ fhandler_serial::open (path_conv *, int flags, mode_t mode) system_printf ("couldn't set initial state for %s, %E", get_name ()); } + /* setting rts and dtr to known state so that ioctl() function with + request TIOCMGET could return correct value of RTS and DTR lines. + Important only for Win 9x systems */ + + if (wincap.is_winnt() == false) + { + if (EscapeCommFunction (get_handle (), SETDTR) == 0) + system_printf ("couldn't set initial state of DTR for %s, %E", get_name ()); + if (EscapeCommFunction (get_handle (), SETRTS) == 0) + system_printf ("couldn't set initial state of RTS for %s, %E", get_name ()); + + /* even though one of above functions fail I have to set rts and dtr + variables to initial value. */ + rts = TIOCM_RTS; + dtr = TIOCM_DTR; + } + SetCommMask (get_handle (), EV_RXCHAR); set_open_status (); syscall_printf ("%p = fhandler_serial::open (%s, %p, %p)", @@ -324,7 +341,7 @@ fhandler_serial::tcflow (int action) DWORD win32action = 0; DCB dcb; char xchar; - + termios_printf ("action %d", action); switch (action) @@ -358,6 +375,107 @@ fhandler_serial::tcflow (int action) return 0; } + +/* ioctl: */ +int +fhandler_serial::ioctl (unsigned int cmd, void *buffer) +{ + + DWORD ev; + COMSTAT st; + DWORD action; + DWORD modemLines; + DWORD mcr; + DWORD cbReturned; + bool result; + int modemStatus; + int request; + + request = *(int *) buffer; + action = 0; + modemStatus = 0; + if (!ClearCommError (get_handle (), &ev, &st)) + return -1; + switch (cmd) + { + case TIOCMGET: + if (GetCommModemStatus (get_handle (), &modemLines) == 0) + return -1; + if (modemLines & MS_CTS_ON) + modemStatus |= TIOCM_CTS; + if (modemLines & MS_DSR_ON) + modemStatus |= TIOCM_DSR; + if (modemLines & MS_RING_ON) + modemStatus |= TIOCM_RI; + if (modemLines & MS_RLSD_ON) + modemStatus |= TIOCM_CD; + if (wincap.is_winnt() == true) + { + + /* here is Windows NT or Windows 2000 part */ + result = DeviceIoControl (get_handle (), + 0x001B0078, + NULL, 0, &mcr, 4, &cbReturned, 0); + if (!result) + return -1; + if (cbReturned != 4) + return -1; + if (mcr & 2) + modemStatus |= TIOCM_RTS; + if (mcr & 1) + modemStatus |= TIOCM_DTR; + + } + else + { + + /* here is Windows 9x part */ + modemStatus |= rts | dtr; + + } + *(int *) buffer = modemStatus; + return 0; + case TIOCMSET: + if (request & TIOCM_RTS) + { + if (EscapeCommFunction (get_handle (), SETRTS) == 0) + return -1; + else + rts = TIOCM_RTS; + } + else + { + if (EscapeCommFunction (get_handle (), CLRRTS) == 0) + return -1; + else + rts = 0; + } + if (request & TIOCM_DTR) + { + if (EscapeCommFunction (get_handle (), SETDTR) == 0) + return -1; + else + dtr = TIOCM_DTR; + } + else + { + if (EscapeCommFunction (get_handle (), CLRDTR) == 0) + return -1; + else + dtr = 0; + } + return 0; + case TIOCINQ: + if (ev & CE_FRAME | ev & CE_IOE | ev & CE_OVERRUN | + ev & CE_RXOVER | ev & CE_RXPARITY) + return -1; + *(int *) buffer = st.cbInQue; + return 0; + default: + return -1; + } +} + /* tcflush: POSIX 7.2.2.1 */ int fhandler_serial::tcflush (int queue) @@ -395,6 +513,8 @@ fhandler_serial::tcsetattr (int action, const struct termios *t) COMMTIMEOUTS to; DCB ostate, state; unsigned int ovtime = vtime_, ovmin = vmin_; + int tmpDtr, tmpRts; + tmpDtr = tmpRts = 0; termios_printf ("action %d", action); if ((action == TCSADRAIN) || (action == TCSAFLUSH)) @@ -560,6 +680,7 @@ fhandler_serial::tcsetattr (int action, const struct termios *t) { /* disable */ state.fRtsControl = RTS_CONTROL_ENABLE; state.fOutxCtsFlow = FALSE; + tmpRts = TIOCM_RTS; } if (t->c_cflag & CRTSXOFF) @@ -592,7 +713,10 @@ fhandler_serial::tcsetattr (int action, const struct termios *t) set_w_binary ((t->c_oflag & ONLCR) ? 0 : 1); if (dropDTR == TRUE) - EscapeCommFunction (get_handle (), CLRDTR); + { + EscapeCommFunction (get_handle (), CLRDTR); + tmpDtr = 0; + } else { /* FIXME: Sometimes when CLRDTR is set, setting @@ -601,7 +725,11 @@ fhandler_serial::tcsetattr (int action, const struct termios *t) parameters while DTR is still down. */ EscapeCommFunction (get_handle (), SETDTR); + tmpDtr = TIOCM_DTR; } + + rts = tmpRts; + dtr = tmpDtr; /* The following documentation on was taken from "Linux Serial Programming diff --git a/winsup/cygwin/include/sys/termios.h b/winsup/cygwin/include/sys/termios.h index c37776111..20a84aa78 100644 --- a/winsup/cygwin/include/sys/termios.h +++ b/winsup/cygwin/include/sys/termios.h @@ -13,6 +13,26 @@ details. */ #ifndef _SYS_TERMIOS_H #define _SYS_TERMIOS_H +#define TIOCMGET 0x5415 +#define TIOCMSET 0x5418 +#define TIOCINQ 0x541B + +/* TIOCINQ is utilized instead of FIONREAD which has been +accupied for other purposes under CYGWIN. +Other UNIX ioctl requests has been omited because +effects of their work one can achive by standard +POSIX commands */ + + +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG + #define TCOOFF 0 #define TCOON 1 #define TCIOFF 2