Ejemplo n.º 1
0
  // 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;
  }