Subversion Repositories HomeAutomation

Rev

Rev 270 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1.  /***************************************************************************
  2.                            rlserial.cpp  -  description
  3.                               -------------------
  4.      begin                : Sat Dec 21 2002
  5.      copyright            : (C) 2002 by Rainer Lehrig
  6.      email                : lehrig@t-online.de
  7.  
  8.      RMOS implementation:
  9.      Copyright            : (C) 2004 Zertrox GbR
  10.      Written by           : Alexander Feller
  11.      Email                : feller@zertrox.de
  12.   ***************************************************************************/
  13.  
  14.  /***************************************************************************
  15.   *                                                                         *
  16.   *   This library is free software; you can redistribute it and/or modify  *
  17.   *   it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as        *
  18.   *   published by the Free Software Foundation                             *
  19.   *                                                                         *
  20.   ***************************************************************************/
  21.  #include "rlserial.h"
  22.  
  23.  #ifdef unix
  24.  #include <stdio.h>
  25.  #include <sys/types.h>
  26.  #include <sys/stat.h>
  27.  #include <fcntl.h>
  28.  #include <termios.h>
  29.  #include <unistd.h>
  30.  #include <signal.h>
  31.  #endif
  32.  
  33.  #ifdef __VMS
  34.  #include <stdio.h>
  35.  #include <string.h>
  36.  #include <stdlib.h>
  37.  #include <starlet.h>
  38.  #include <descrip.h>
  39.  #include <lib$routines.h>
  40.  #include <ssdef.h>
  41.  #include <iodef.h>
  42.  #endif
  43.  
  44.  #ifdef _WIN32
  45.  #include <windows.h>
  46.  #include <stdio.h>
  47.  #endif
  48.  
  49.  #ifdef RM3
  50.  #include <stdio.h>
  51.  #include <stdlib.h>
  52.  #include <rmcomp.h>
  53.  #include <rmapi.h>
  54.  #include <rio.h>
  55.  #include <drvspec.h>
  56.  #include <rm3cav.h>
  57.  //#include <clean.h>
  58.  #include <rcinc.h>
  59.  #define RTS_TIME_WAIT 0x008     /* Verzoerungszeit fuer RTS - Signal      */
  60.  #endif
  61.  
  62.  #include "rlthread.h"
  63.  
  64.  /*
  65.  static void sighandler(int sig)
  66.  {
  67.    if(sig == SIGINT)
  68.    {
  69.      closeDevice();
  70.      closeDatabase();
  71.    }
  72.  }
  73.  */
  74.  
  75.  rlSerial::rlSerial()
  76.  {
  77.    ttysavefd = -1;
  78.    ttystate  = RESET;
  79.    fd        = -1;
  80.    trace     = 0;
  81.  }
  82.  
  83.  rlSerial::~rlSerial()
  84.  {
  85.    closeDevice();
  86.  }
  87.  
  88.  void rlSerial::setTrace(int on)
  89.  {
  90.    if(on == 1) trace = 1;
  91.    else        trace = 0;
  92.  }
  93.  
  94.  int rlSerial::openDevice(const char *devicename, int speed, int block, int rtscts, int bits, int stopbits, int parity)
  95.  {
  96.  #ifdef unix
  97.    struct termios buf;
  98.  
  99.    if(fd != -1) return -1;
  100.    fd = open(devicename, O_RDWR | O_NOCTTY | O_NDELAY);
  101.    if(fd < 0) { return -1; }
  102.  
  103.    //signal(SIGINT, sighandler);
  104.  
  105.    if(tcgetattr(fd, &save_termios) < 0) { return -1; }
  106.    buf = save_termios;
  107.    buf.c_cflag = speed | CLOCAL | CREAD;
  108.    if(rtscts   == 1)  buf.c_cflag |= CRTSCTS;
  109.    if(bits     == 7)  buf.c_cflag |= CS7;
  110.    else               buf.c_cflag |= CS8;
  111.    if(stopbits == 2)  buf.c_cflag |= CSTOPB;
  112.    if(parity == rlSerial::ODD)  buf.c_cflag |= (PARENB | PARODD);
  113.    if(parity == rlSerial::EVEN) buf.c_cflag |= PARENB;
  114.    buf.c_lflag = IEXTEN; //ICANON;
  115.    buf.c_oflag     = OPOST;
  116.    buf.c_cc[VMIN]  = 1;
  117.    buf.c_cc[VTIME] = 0;
  118.    buf.c_line      = 0;
  119.    buf.c_iflag     = IGNBRK | IGNPAR | IXANY;
  120.    if(tcsetattr(fd, TCSAFLUSH, &buf) < 0) { return -1; }
  121.    //if(tcsetattr(fd, TCSANOW, &buf) < 0) { return -1; }
  122.    ttystate = RAW;
  123.    ttysavefd = fd;
  124.    if(block == 1) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);
  125.    tcflush(fd,TCIOFLUSH);
  126.  #endif
  127.  
  128.  #ifdef __VMS
  129.    // Please set com parameters at DCL level
  130.    struct dsc$descriptor_s dsc;
  131.    int status;
  132.  
  133.    dsc.dsc$w_length  = strlen(devicename);
  134.    dsc.dsc$a_pointer = devicename;
  135.    dsc.dsc$b_class   = DSC$K_CLASS_S;
  136.    dsc.dsc$b_dtype   = DSC$K_DTYPE_T;
  137.    status = SYS$ASSIGN(&dsc,&vms_channel,0,0);
  138.    if(status != SS$_NORMAL) return -1;
  139.  #endif
  140.  
  141.  #ifdef _WIN32
  142.    DWORD ccsize;
  143.    COMMCONFIG cc;
  144.    int baudrate,ret;
  145.  
  146.    hdl = CreateFile(
  147.                     (LPCWSTR)devicename,                    // pointer to name of the file
  148.                     GENERIC_READ | GENERIC_WRITE,  // access (read-write) mode
  149.                     0,                             // share mode
  150.                     0,                             // pointer to security attributes
  151.                     OPEN_EXISTING,                 // how to create
  152.                     0,                             // not overlapped I/O
  153.                     0                              // handle to file with attributes to copy
  154.                    );
  155.    if(hdl == INVALID_HANDLE_VALUE)
  156.    {
  157.      printf("CreateFile(%s) failed\n",devicename);
  158.      return -1;
  159.    }
  160.  
  161.    baudrate = CBR_9600;
  162.    if(speed == B50     ) baudrate = 50;
  163.    if(speed == B75     ) baudrate = 75;
  164.    if(speed == B110    ) baudrate = CBR_110;
  165.    if(speed == B134    ) baudrate = 134;
  166.    if(speed == B150    ) baudrate = 150;
  167.    if(speed == B200    ) baudrate = 200;
  168.    if(speed == B300    ) baudrate = CBR_300;
  169.    if(speed == B600    ) baudrate = CBR_600;
  170.    if(speed == B1200   ) baudrate = CBR_1200;
  171.    if(speed == B1800   ) baudrate = 1800;
  172.    if(speed == B2400   ) baudrate = CBR_2400;
  173.    if(speed == B4800   ) baudrate = CBR_4800;
  174.    if(speed == B9600   ) baudrate = CBR_9600;
  175.    if(speed == B19200  ) baudrate = CBR_19200;
  176.    if(speed == B38400  ) baudrate = CBR_38400;
  177.    if(speed == B57600  ) baudrate = CBR_57600;
  178.    if(speed == B115200 ) baudrate = CBR_115200;
  179.    if(speed == B230400 ) baudrate = 230400;
  180.    if(speed == B460800 ) baudrate = 460800;
  181.    if(speed == B500000 ) baudrate = 500000;
  182.    if(speed == B576000 ) baudrate = 576000;
  183.    if(speed == B921600 ) baudrate = 921600;
  184.    if(speed == B1000000) baudrate = 1000000;
  185.    if(speed == B1152000) baudrate = 1152000;
  186.    if(speed == B1500000) baudrate = 1500000;
  187.    if(speed == B2000000) baudrate = 2000000;
  188.    if(speed == B2500000) baudrate = 2500000;
  189.    if(speed == B3000000) baudrate = 3000000;
  190.    if(speed == B3500000) baudrate = 3500000;
  191.    if(speed == B4000000) baudrate = 4000000;
  192.  
  193.    GetCommConfig(hdl,&cc,&ccsize);
  194.    //cc.dwSize            = sizeof(cc);  // size of structure
  195.    //cc.wVersion          = 1;           // version of structure
  196.    //cc.wReserved         = 0;           // reserved
  197.    //  DCB   dcb;                      // device-control block
  198.    cc.dcb.DCBlength     = sizeof(DCB); // sizeof(DCB)
  199.    cc.dcb.BaudRate      = baudrate;    // current baud rate
  200.    cc.dcb.fBinary       = 1;           // binary mode, no EOF check
  201.    cc.dcb.fParity       = 1;           // enable parity checking
  202.    cc.dcb.fOutxCtsFlow  = 0;           // CTS output flow control
  203.    if(rtscts == 1) cc.dcb.fOutxCtsFlow = 1;
  204.    cc.dcb.fOutxDsrFlow  = 0;           // DSR output flow control
  205.    cc.dcb.fDtrControl   = DTR_CONTROL_DISABLE;  // DTR flow control type
  206.    cc.dcb.fDsrSensitivity   = 0;       // DSR sensitivity
  207.    cc.dcb.fTXContinueOnXoff = 1;       // XOFF continues Tx
  208.    //cc.dcb.fOutX         = 0;           // XON/XOFF out flow control
  209.    //cc.dcb.fInX          = 0;           // XON/XOFF in flow control
  210.    //cc.dcb.fErrorChar    = 0;           // enable error replacement
  211.    cc.dcb.fNull         = 0;           // enable null stripping
  212.    cc.dcb.fRtsControl   = RTS_CONTROL_DISABLE;
  213.    if(rtscts == 1)  cc.dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;  // RTS flow control
  214.    cc.dcb.fAbortOnError = 0;           // abort reads/writes on error
  215.    //cc.dcb.fDummy2       = 0;           // reserved
  216.    //cc.dcb.wReserved     = 0;           // not currently used
  217.    //cc.dcb.XonLim        = 0;           // transmit XON threshold
  218.    //cc.dcb.XoffLim       = 0;           // transmit XOFF threshold
  219.    cc.dcb.ByteSize      = bits;        // number of bits/byte, 4-8
  220.    cc.dcb.Parity        = 0;           // 0-4=no,odd,even,mark,space
  221.    if(parity == rlSerial::ODD)    cc.dcb.Parity = 1;
  222.    if(parity == rlSerial::EVEN)   cc.dcb.Parity = 2;
  223.    cc.dcb.StopBits      = ONESTOPBIT;  // 0,1,2 = 1, 1.5, 2
  224.    if(stopbits==2) cc.dcb.StopBits = TWOSTOPBITS;
  225.    //cc.dcb.XonChar       = 0;           // Tx and Rx XON character
  226.    //cc.dcb.XoffChar      = 0;           // Tx and Rx XOFF character
  227.    //cc.dcb.ErrorChar     = 0;           // error replacement character
  228.    //cc.dcb.EofChar       = 0;           // end of input character
  229.    //cc.dcb.EvtChar       = 0;           // received event character
  230.    //cc.dcb.wReserved1    = 0;           // reserved; do not use
  231.    cc.dwProviderSubType = PST_RS232;   // type of provider-specific data
  232.    //cc.dwProviderOffset  = 0;           // offset of provider-specific data
  233.    //cc.dwProviderSize    = 0;           // size of provider-specific data
  234.    //cc.wcProviderData[0] = 0;           // provider-specific data
  235.  
  236.    ret = SetCommConfig(hdl,&cc,sizeof(cc));
  237.    if(ret == 0)
  238.    {
  239.      printf("SetCommConfig ret=%d devicename=%s LastError=%d\n",ret,devicename,GetLastError());
  240.      return -1;
  241.    }
  242.  #endif
  243.  
  244.  #ifdef RM3
  245.    RmEntryStruct    CatEntry;        /* Struktur der Deiviceinformationen              */
  246.    int              iStatus;         /* Rckgabewert                                    */
  247.    RmIOStatusStruct DrvSts;          /* Struktur der Rckgabewerte fr RmIO - Funktion   */
  248.    RmBytParmStruct  PBlock;          /* Parameterstruktur fr RmIO - Funktion           */
  249.    static UCD_BYT_PORT Ucd_byt_drv;  /* Struktur zum Setzen der UCD - Werte            */
  250.    ushort           uTimeBd;         /* Timing - Wert der �ertragungsgeschwindigkeit   */
  251.    uint             uMode;           /* Portsteuerungsparameter                        */
  252.    unsigned char    cByte;           /* Byte - Parameter                               */
  253.                                      /* Timing = 748800 / Baudrate;                    */
  254.                                      /**************************************************/
  255.    char byt_com[32];
  256.                                      
  257.    /* COM1=0x3F8 COM2=0x2F8 - Port Adresse           */
  258.    if     (strcmp(devicename,"COM1") == 0)
  259.    {
  260.      strcpy(byt_com,"BYT_COM1");
  261.      com = 0x3f8;
  262.    }
  263.    else if(strcmp(devicename,"COM2") == 0)
  264.    {
  265.      strcpy(byt_com,"BYT_COM2");
  266.      com = 0x2f8;
  267.    }
  268.    else
  269.    {
  270.      printf("Error: devicename=%s unknown\n",devicename);
  271.      return -1;
  272.    }  
  273.    //printf("Open COM port - inside\n");
  274.  
  275.    /*
  276.    * Device und Unit - Id auslesen
  277.    */
  278.    if( RmGetEntry( RM_WAIT, byt_com, &CatEntry ) != RM_OK ) /* RM_CONTINUE */
  279.    {
  280.      printf( "Error: %s device not found\n", byt_com);
  281.      return -1;
  282.    }
  283.  
  284.    device = (int) ((ushort) CatEntry.ide);
  285.    unit   = (int) CatEntry.id;
  286.  
  287.    /*
  288.    * Ger� reservieren
  289.    */
  290.    if( RmIO( BYT_RESERVE, (unsigned)(device), (unsigned)(unit), 0u, 0u, &DrvSts, &PBlock ) < 0 )
  291.    {
  292.      printf( "Error: Unable to reserve %s device\n", byt_com);
  293.      return -1;
  294.    }
  295.  
  296.    /*
  297.    * Baudrate ausrechnen
  298.    */
  299.    baudrate = 9600;
  300.    if(speed == B50     ) baudrate = 50;
  301.    if(speed == B75     ) baudrate = 75;
  302.    if(speed == B110    ) baudrate = 110;
  303.    if(speed == B134    ) baudrate = 134;
  304.    if(speed == B150    ) baudrate = 150;
  305.    if(speed == B200    ) baudrate = 200;
  306.    if(speed == B300    ) baudrate = 300;
  307.    if(speed == B600    ) baudrate = 600;
  308.    if(speed == B1200   ) baudrate = 1200;
  309.    if(speed == B1800   ) baudrate = 1800;
  310.    if(speed == B2400   ) baudrate = 2400;
  311.    if(speed == B4800   ) baudrate = 4800;
  312.    if(speed == B9600   ) baudrate = 9600;
  313.    if(speed == B19200  ) baudrate = 19200;
  314.    if(speed == B38400  ) baudrate = 38400;
  315.    if(speed == B57600  ) baudrate = 57600;
  316.    if(speed == B115200 ) baudrate = 115200;
  317.    if(speed == B230400 ) baudrate = 230400;
  318.    if(speed == B460800 ) baudrate = 460800;
  319.    if(speed == B500000 ) baudrate = 500000;
  320.    if(speed == B576000 ) baudrate = 576000;
  321.    if(speed == B921600 ) baudrate = 921600;
  322.    if(speed == B1000000) baudrate = 1000000;
  323.    if(speed == B1152000) baudrate = 1152000;
  324.    if(speed == B1500000) baudrate = 1500000;
  325.    if(speed == B2000000) baudrate = 2000000;
  326.    if(speed == B2500000) baudrate = 2500000;
  327.    if(speed == B3000000) baudrate = 3000000;
  328.    if(speed == B3500000) baudrate = 3500000;
  329.    if(speed == B4000000) baudrate = 4000000;
  330.    uTimeBd = 748800 / baudrate;
  331.  
  332.    /*
  333.    * Portsteuerungsparameter setzen
  334.    */
  335.    uMode = 0x1000 | DATA_8 | STOP_1 | NOPARITY;
  336.  
  337.    /*
  338.    * UCD des seriellen Ports auslesen
  339.    */
  340.    PBlock.string = 0;
  341.    PBlock.strlen = 0;
  342.    PBlock.buffer = (char *)&Ucd_byt_drv;
  343.    PBlock.timlen = sizeof(UCD_BYT_PORT);
  344.    PBlock.status = 0;
  345.  
  346.    iStatus = RmIO( BYT_CREATE_NEW, (unsigned)(device), (unsigned)(unit), 0u, 0u, &DrvSts, &PBlock );
  347.  
  348.    /*
  349.     * Modus �dern
  350.     */
  351.    Ucd_byt_drv.mobyte[5] |= (ushort) (uMode & 0xFFu);
  352.  
  353.    /*
  354.     * Timeout setzen
  355.     */
  356.    Ucd_byt_drv.header.timout = timeout;
  357.  
  358.    /*
  359.     * Werte zuweisen
  360.     */
  361.    PBlock.string = (char*) &Ucd_byt_drv;
  362.    PBlock.strlen = sizeof(UCD_BYT_PORT);
  363.    PBlock.buffer = 0;
  364.    PBlock.timlen = 0;
  365.    PBlock.status = 0;
  366.  
  367.    iStatus = RmIO( BYT_CREATE_NEW, (unsigned)(device), (unsigned)(unit), 0u, 0u, &DrvSts, &PBlock );
  368.  
  369.    /*
  370.     * Register 0 und 1 zum Schreiben freigeben
  371.     */
  372.    cByte = inbyte( com + 0x03 );
  373.    outbyte( com + 0x03, (unsigned char)(cByte | 0x80) );
  374.  
  375.    /*
  376.     * Baudrate setzen
  377.     */
  378.    outbyte( com + 0x00, (ushort) LOW  (uTimeBd) );
  379.    outbyte( com + 0x01, (ushort) HIGH (uTimeBd) );
  380.  
  381.    /*
  382.     * Register 0 und 1 sperren
  383.     */
  384.    outbyte( com + 0x03, cByte );
  385.  
  386.    if( iStatus ) printf( "BYT_CREATE_NEW (set ucb): Error status = %X\n", iStatus );
  387.  #endif
  388.    
  389.    return 0;
  390.  }
  391.  
  392.  int rlSerial::readChar()
  393.  {
  394.  #ifdef unix
  395.    int  ret;
  396.    unsigned char buf[2];
  397.  
  398.    if(fd == -1) return -1;
  399.    ret = read(fd,buf,1);
  400.    if(ret == 1) return buf[0];
  401.    if(ret == 0) return -2;
  402.    return -1;
  403.  #endif
  404.  
  405.  #ifdef __VMS
  406.    unsigned char buf[2];
  407.  
  408.    if(readBlock(buf, 1) < 0) return -1;
  409.    return buf[0];
  410.  #endif
  411.  
  412.  #ifdef _WIN32
  413.    BOOL ret;
  414.    unsigned char buf[2];
  415.    unsigned long len;
  416.  
  417.    ret = ReadFile(
  418.                   hdl,  // handle of file to read
  419.                   buf,  // pointer to buffer that receives data
  420.                   1,    // number of bytes to read
  421.                   &len, // pointer to number of bytes read
  422.                   NULL  // pointer to structure for data
  423.                  );
  424.    if(len > 0)
  425.    {
  426.      if(trace == 1) printf("readChar %d\n",(int) buf[0]);
  427.      return buf[0];
  428.    }
  429.    return -1;
  430.  #endif
  431.  
  432.  #ifdef RM3
  433.    int ret;
  434.    unsigned char buf[2];
  435.    
  436.    ret = readBlock(buf,1);
  437.    if(ret < 0) return ret;
  438.    return buf[0];
  439.  #endif
  440.  }
  441.  
  442.  int rlSerial::writeChar(unsigned char uchar)
  443.  {
  444.  #ifdef unix
  445.    int ret;
  446.    if(fd == -1) return -1;
  447.    if(trace == 1) printf("writeChar %d\n",(int)uchar);
  448.    ret = write(fd,&uchar,1);
  449.    if(ret < 0) return -1;
  450.    //tcflush(fd, TCIOFLUSH);
  451.    return ret;
  452.  #endif
  453.  
  454.  #ifdef __VMS
  455.    int  status;
  456.    IOSB iosb;
  457.  
  458.    status = SYS$QIOW(0,vms_channel,IO$_WRITEVBLK | IO$M_CANCTRLO | IO$M_NOFORMAT,
  459.                      &iosb,0,0,&uchar,1,0,0,0,0);
  460.    if(status != SS$_NORMAL) return -1;
  461.    return 1;
  462.  #endif
  463.  
  464.  #ifdef _WIN32
  465.    BOOL ret;
  466.    unsigned long len;
  467.  
  468.    if(trace == 1) printf("writeChar %d\n",(int)uchar);
  469.    ret = WriteFile(
  470.                    hdl,    // handle to file to write to
  471.                    &uchar, // pointer to data to write to file
  472.                    1,      // number of bytes to write
  473.                    &len,   // pointer to number of bytes written
  474.                    NULL    // pointer to structure for overlapped I/O
  475.                   );
  476.  
  477.    if(ret) return (int) len;
  478.    return -1;
  479.  #endif
  480.  
  481.  #ifdef RM3
  482.    return writeBlock(&uchar, 1);
  483.  #endif
  484.  }
  485.  
  486.  int rlSerial::readBlock(unsigned char *buf, int len)
  487.  {
  488.  #ifdef unix
  489.    int c;
  490.  
  491.    for(int i=0; i<len; i++)
  492.    {
  493.      c = readChar();
  494.      if(c < 0) return c;
  495.      buf[i] = (unsigned char) c;
  496.    }
  497.    return len;
  498.  #endif
  499.  
  500.  #ifdef __VMS
  501.    int   status;
  502.    int   timeout = 1; // second
  503.    short iosb[4];
  504.  
  505.    status = SYS$QIOW(0,vms_channel,
  506.                      IO$_READVBLK | IO$M_NOFILTR | IO$M_NOECHO | IO$M_TIMED,
  507.                      iosb,0,0,buf,len,timeout,0,0,0);
  508.    if(status != SS$_NORMAL) return -1;
  509.    len=iosb[1];
  510.    if(iosb[2] != 0)
  511.    {
  512.      len++;
  513.      buf[len] = iosb[2];
  514.    }
  515.    return len;
  516.  #endif
  517.  
  518.  #ifdef _WIN32
  519.    BOOL ret;
  520.    unsigned long retlen;
  521.  
  522.    ret = ReadFile(
  523.                   hdl,     // handle of file to read
  524.                   buf,     // pointer to buffer that receives data
  525.                   len,     // number of bytes to read
  526.                   &retlen, // pointer to number of bytes read
  527.                   NULL     // pointer to structure for data
  528.                  );
  529.    if(retlen > 0)
  530.    {
  531.      if(trace == 1) printf("readBlock retlen=%d\n",retlen);
  532.      return (int) retlen;
  533.    }
  534.    return -1;
  535.  #endif
  536.  
  537.  #ifdef RM3
  538.    RmBytParmStruct  PBlock;    /* Parameterstruktur fr RmIO - Funktion          */
  539.    RmIOStatusStruct DrvSts;    /* Struktur der Rckgabewerte fr RmIO - Funktion */
  540.    int              iStatus;   /* Rckgabewert                                   */
  541.    int              i;         /* Schleifenz�ler                                */
  542.                                /**************************************************/
  543.  
  544.    /*
  545.     * Schreibparameter setzen
  546.     */
  547.    PBlock.string = 0;
  548.    PBlock.strlen = 0;
  549.    PBlock.buffer = (char*)buf;
  550.    PBlock.timlen = len;
  551.    PBlock.status = 0;
  552.  
  553.    /*
  554.     * Lesevorgang einleiten
  555.     */
  556.    iStatus = RmIO( BYT_POLL_XBUF_WAIT, (unsigned)device, (unsigned)unit, 0u, 0u, &DrvSts, &PBlock );
  557.  
  558.    if( iStatus ) printf( "BYT_POLL_XBUF_WAIT (set ucb): Error status = %X\n", iStatus );
  559.  
  560.    if( !iStatus ) return len;
  561.    return -1;
  562.  #endif
  563.  }
  564.  
  565.  int rlSerial::writeBlock(const unsigned char *buf, int len)
  566.  {
  567.  #ifdef unix
  568.    int ret;
  569.  
  570.    if(fd == -1) return -1;
  571.    if(trace == 1)
  572.    {
  573.      printf("writeBlock:");
  574.      for(int i=0; i<len; i++) printf(" %d",(int) buf[i]);
  575.      printf("\n");
  576.    }
  577.    ret = write(fd,buf,len);
  578.    //tcflush(fd, TCIOFLUSH);
  579.    return ret;
  580.  #endif
  581.  
  582.  #ifdef __VMS
  583.    int  status;
  584.    IOSB iosb;
  585.  
  586.  
  587.    status = SYS$QIOW(0,vms_channel,IO$_WRITEVBLK | IO$M_CANCTRLO | IO$M_NOFORMAT,
  588.                      &iosb,0,0,buf,len,0,0,0,0);
  589.    if(status != SS$_NORMAL) return -1;
  590.    return len;
  591.  #endif
  592.  
  593.  #ifdef _WIN32
  594.    BOOL ret;
  595.    unsigned long retlen;
  596.  
  597.    if(trace == 1)
  598.    {
  599.      printf("writeBlock:");
  600.      for(int i=0; i<len; i++) printf(" %d",(int) buf[i]);
  601.      printf("\n");
  602.    }
  603.    retlen = len;
  604.    ret = WriteFile(
  605.                    hdl,     // handle to file to write to
  606.                    buf,     // pointer to data to write to file
  607.                    len,     // number of bytes to write
  608.                    &retlen, // pointer to number of bytes written
  609.                    NULL     // pointer to structure for overlapped I/O
  610.                   );
  611.  
  612.    if(ret) return (int) retlen;
  613.    return -1;
  614.  #endif
  615.  
  616.  #ifdef RM3
  617.    RmBytParmStruct  PBlock;    /* Parameterstruktur fr RmIO - Funktion          */
  618.    RmIOStatusStruct DrvSts;    /* Struktur der Rckgabewerte fr RmIO - Funktion  */
  619.    unsigned char    cByte;     /* Rckgabewert von ibyte - Funktion              */
  620.    int              iStatus;   /* Rckgabewert                                   */
  621.    int              i;         /* Schleifenz�ler                                */
  622.                                /**************************************************/
  623.  
  624.    /*
  625.     * Schreibparameter setzen
  626.     */
  627.    PBlock.string = (char*)buf;
  628.    PBlock.strlen = len;
  629.    PBlock.buffer = 0;
  630.    PBlock.timlen = 0;
  631.    PBlock.status = 0;
  632.  
  633.    /******************************************************
  634.     *                                                    *
  635.     * Toggle mode wird emuliert indem an dieser Stelle   *
  636.     * RTS-Signal gesetzt und sp�er wieder gel�cht wird   *
  637.     *                                                    *
  638.     ******************************************************/
  639.  
  640.    cByte = inbyte( com + 0x04u );
  641.    outbyte( com + 0x04, (unsigned char)(cByte | 0x02u) );
  642.  
  643.    /*
  644.     * Schreibvorgang einleiten
  645.     */
  646.    iStatus = RmIO( BYT_WRITE_WAIT, (unsigned)device, (unsigned)unit, 0u, 0u, &DrvSts, &PBlock );
  647.  
  648.    /******************************************************************
  649.     *                                                                *
  650.     * 8ms warten.Bei der Aenderung der Uebertragungsgeschwindigkeit, *
  651.     * sollte dieser Wert angepasst werden. Hier fuer 9600            *
  652.     *                                                                *
  653.     ******************************************************************/
  654.    RmPauseTask((RTS_TIME_WAIT*9600)/baudrate);
  655.  
  656.    /*
  657.     * RTS-Signal l�chen
  658.     */
  659.    outbyte( com + 0x04, (unsigned char)(cByte & 0xFDu) );
  660.  
  661.    if( iStatus ) printf( "BYT_WRITE_WAIT (write block): Error status = %X\n", iStatus );
  662.  
  663.    if( !iStatus ) return len;
  664.    return -1;
  665.  #endif
  666.  }
  667.  
  668.  int rlSerial::readLine(unsigned char *buf, int maxlen)
  669.  {
  670.    int i,c,ret;
  671.  
  672.    if(maxlen <= 1) return -1;
  673.    ret = 0;
  674.    buf[maxlen-1] = '\0';
  675.    for(i=0; i<maxlen-2; i++)
  676.    {
  677.      ret = i;
  678.      c = readChar();
  679.      if(c < 0)
  680.      {
  681.        buf[i] = '\0';
  682.        ret = c;
  683.        break;
  684.      }
  685.      buf[i] = (unsigned char) c;
  686.      if(c < ' ')
  687.      {
  688.        buf[i+1] = '\0';
  689.        break;
  690.      }
  691.    }
  692.    return ret;
  693.  }
  694.  
  695.  int rlSerial::select(int timeout)
  696.  {
  697.  #ifdef unix
  698.    struct timeval timout;
  699.    fd_set wset,rset,eset;
  700.    int    ret,maxfdp1;
  701.  
  702.    if(timeout <= 0) return 1;
  703.    /* setup sockets to read */
  704.    maxfdp1 = fd+1;
  705.    FD_ZERO(&rset);
  706.    FD_SET (fd,&rset);
  707.    FD_ZERO(&wset);
  708.    FD_ZERO(&eset);
  709.    timout.tv_sec  = timeout / 1000;
  710.    timout.tv_usec = timeout % 1000;
  711.  
  712.    ret = ::select(maxfdp1,&rset,&wset,&eset,&timout);
  713.    if(ret == 0) return 0; /* timeout */
  714.    return 1;
  715.  #endif
  716.  
  717.  #ifdef __VMS
  718.    return 1;
  719.  #endif
  720.  
  721.  #ifdef _WIN32
  722.    COMMTIMEOUTS ctimeout;
  723.  
  724.    ctimeout.ReadIntervalTimeout          = timeout;
  725.    ctimeout.ReadTotalTimeoutMultiplier   = 1;
  726.    ctimeout.ReadTotalTimeoutConstant     = timeout;
  727.    ctimeout.WriteTotalTimeoutMultiplier  = 1;
  728.    ctimeout.WriteTotalTimeoutConstant    = timeout;
  729.  
  730.    SetCommTimeouts(hdl, &ctimeout);
  731.    return 1;
  732.  #endif
  733.  
  734.  #ifdef RM3
  735.    return 1;
  736.  #endif
  737.  }
  738.  
  739.  int rlSerial::closeDevice()
  740.  {
  741.  #ifdef unix
  742.    if(fd == -1) return -1;
  743.    //if(::tcsetattr(fd,TCSAFLUSH,&save_termios) < 0) return -1;
  744.    if(::tcsetattr(fd,TCSANOW,&save_termios) < 0) return -1;
  745.    ::close(fd);
  746.    ttystate = RESET;
  747.    fd = -1;
  748.    return 0;
  749.  #endif
  750.  
  751.  #ifdef __VMS
  752.    sys$dassgn(vms_channel);
  753.    return 0;
  754.  #endif
  755.  
  756.  #ifdef _WIN32
  757.    CloseHandle(hdl);
  758.    return 0;
  759.  #endif
  760.  
  761.  #ifdef RM3
  762.    RmBytParmStruct  PBlock;    /* Parameterstruktur fr RmIO - Funktion          */
  763.    RmIOStatusStruct DrvSts;    /* Struktur der Rckgabewerte fr RmIO - Funktion */
  764.                                /**************************************************/
  765.    if( RmIO( BYT_RELEASE, (unsigned)(device), (unsigned)(unit), 0u, 0u, &DrvSts, &PBlock ) < 0 )
  766.    {
  767.      printf( "Error: Unable to release device. device: %i, unit: %i\n",device, unit );
  768.      return -1;
  769.    }
  770.    return 0;
  771.  #endif
  772.  }
  773.