// FIXME this needs serious code review from people who know this stuff... public int updateFromTermios(Port port) throws Fail { Termios tios = port.m_Termios; int c_speed = tios.c_ospeed; int c_cflag = tios.c_cflag; int c_iflag = tios.c_iflag; int c_oflag = tios.c_oflag; if (c_speed != port.m_c_speed || c_cflag != port.m_c_cflag || c_iflag != port.m_c_iflag || c_oflag != port.m_c_oflag) { DCB dcb = port.m_DCB; if (!GetCommState(port.m_Comm, dcb)) port.fail(); dcb.DCBlength = dcb.size(); dcb.BaudRate = c_speed; if (tios.c_ospeed != tios.c_ispeed) log(0, "c_ospeed (%d) != c_ispeed (%d)\n", tios.c_ospeed, tios.c_ispeed); int flags = 0; // rxtx does: if ( s_termios->c_iflag & ISTRIP ) dcb.fBinary = FALSE; // but Winapi doc says fBinary always true flags |= fBinary; if ((c_cflag & PARENB) != 0) flags |= fParity; if ((c_iflag & IXON) != 0) flags |= fOutX; if ((c_iflag & IXOFF) != 0) flags |= fInX; if ((c_iflag & IXANY) != 0) flags |= fTXContinueOnXoff; if ((c_iflag & CRTSCTS) != 0) { flags |= fRtsControl; flags |= fOutxCtsFlow; } // Following have no corresponding functionality in unix termios // fOutxDsrFlow = 0x00000008; // fDtrControl = 0x00000030; // fDsrSensitivity = 0x00000040; // fErrorChar = 0x00000400; // fNull = 0x00000800; // fAbortOnError = 0x00004000; // fDummy2 = 0xFFFF8000; dcb.fFlags = flags; // Don't touch these, windows seems to use: XonLim 2048 XoffLim 512 and who am I to argue with // those // dcb.XonLim = 0; // dcb.XoffLim = 128; byte cs = 8; int csize = c_cflag & CSIZE; if (csize == CS5) cs = 5; if (csize == CS6) cs = 6; if (csize == CS7) cs = 7; if (csize == CS8) cs = 8; dcb.ByteSize = cs; if ((c_cflag & PARENB) != 0) { if ((c_cflag & PARODD) != 0 && (c_cflag & CMSPAR) != 0) dcb.Parity = MARKPARITY; else if ((c_cflag & PARODD) != 0) dcb.Parity = ODDPARITY; else if ((c_cflag & CMSPAR) != 0) dcb.Parity = SPACEPARITY; else dcb.Parity = EVENPARITY; } else dcb.Parity = NOPARITY; dcb.StopBits = (c_cflag & CSTOPB) != 0 ? TWOSTOPBITS : ONESTOPBIT; dcb.XonChar = tios.c_cc[ VSTART]; // In theory these could change but they only get updated if the // baudrate/char size changes so this could be a time bomb dcb.XoffChar = tios.c_cc[ VSTOP]; // In practice in PJC these are never changed so updating on the first pass is // enough dcb.ErrorChar = 0; // rxtx has some thing like // if ( EV_BREAK|EV_CTS|EV_DSR|EV_ERR|EV_RING | ( EV_RLSD & EV_RXFLAG ) // ) // dcb.EvtChar = '\n'; // else // dcb.EvtChar = '\0'; // But those are all defines so there is something fishy there? dcb.EvtChar = '\n'; dcb.EofChar = tios.c_cc[VEOF]; if (!SetCommState(port.m_Comm, dcb)) port.fail(); port.m_c_speed = c_speed; port.m_c_cflag = c_cflag; port.m_c_iflag = c_iflag; port.m_c_oflag = c_oflag; } int vmin = port.m_Termios.c_cc[VMIN] & 0xFF; int vtime = (port.m_Termios.c_cc[VTIME] & 0xFF) * 100; if (vmin != port.m_VMIN || vtime != port.m_VTIME) { COMMTIMEOUTS touts = port.m_Timeouts; // There are really no write timeouts in classic unix termios // FIXME test that we can still interrupt the tread touts.WriteTotalTimeoutConstant = 0; touts.WriteTotalTimeoutMultiplier = 0; if (vmin == 0 && vtime == 0) { // VMIN = 0 and VTIME = 0 => totally non blocking,if data is // available, return it, ie this is poll operation touts.ReadIntervalTimeout = MAXDWORD; touts.ReadTotalTimeoutConstant = 0; touts.ReadTotalTimeoutMultiplier = 0; } if (vmin == 0 && vtime > 0) { // VMIN = 0 and VTIME > 0 => timed read, return as soon as data is // available, VTIME = total time touts.ReadIntervalTimeout = 0; touts.ReadTotalTimeoutConstant = vtime; touts.ReadTotalTimeoutMultiplier = 0; } if (vmin > 0 && vtime > 0) { // VMIN > 0 and VTIME > 0 => blocks until VMIN chars has arrived or between chars expired, // note that this will block if nothing arrives touts.ReadIntervalTimeout = vtime; touts.ReadTotalTimeoutConstant = 0; touts.ReadTotalTimeoutMultiplier = 0; } if (vmin > 0 && vtime == 0) { // VMIN > 0 and VTIME = 0 => blocks until VMIN characters have been // received touts.ReadIntervalTimeout = 0; touts.ReadTotalTimeoutConstant = 0; touts.ReadTotalTimeoutMultiplier = 0; } if (!SetCommTimeouts(port.m_Comm, port.m_Timeouts)) port.fail(); port.m_VMIN = vmin; port.m_VTIME = vtime; log = log && log( 2, "vmin %d vtime %d ReadIntervalTimeout %d ReadTotalTimeoutConstant %d ReadTotalTimeoutMultiplier %d\n", vmin, vtime, touts.ReadIntervalTimeout, touts.ReadTotalTimeoutConstant, touts.ReadTotalTimeoutMultiplier); } return 0; }