Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

tty.C

Go to the documentation of this file.
00001 
00002 #define _INCLUDE_XOPEN_SOURCE
00003 /* -----------------------------  Ifdefs  ---------------------------------- */
00004 #include "std/config.H"
00005 #include "tty.H"
00006 
00007 #ifdef sgi
00008 #include <bstring.h>  /* sgi */
00009 #endif
00010 
00011 #ifdef sun
00012 #include <strings.h>  /* sun */
00013 #endif
00014 
00015 #ifndef aix
00016 #define TRUE 1
00017 #endif
00018 
00019 #define BIT(N, INT)          ((1 << N) & ((int)(INT)))
00020 #define brcase    break; case
00021 #define brdefault break; default
00022 
00023 int     TTYdebug = 0;
00024 typedef unsigned char byte;
00025 
00026 #ifndef WIN32
00027 extern "C" int (*SELECT)(int, fd_set *, fd_set *, fd_set *, timeval *) = select;
00028 
00029 extern "C" int Select(int maxfds, fd_set *reads, fd_set *writes, fd_set *errors,
00030      struct timeval *timeout)
00031    {
00032     struct timezone tz;
00033     struct timeval Timer1, Timer2;
00034     struct timeval timetogo;
00035     static fd_set readcopy;
00036     static fd_set writecopy;
00037     static fd_set errcopy;
00038     int rc;
00039     double worktime;
00040     double remaining;
00041 
00042     /* If we get interrupted, will need to restore select bits */
00043     if (reads) bcopy(reads,&readcopy,sizeof(fd_set));
00044     if (writes) bcopy(writes,&writecopy,sizeof(fd_set));
00045     if (errors) bcopy(errors,&errcopy,sizeof(fd_set));
00046 
00047     /* two cases: if timeout specifies a time structure, we
00048      need to worry about timeouts.  Otherwise, we can
00049      ignore it */
00050 
00051     if (timeout == NULL) {
00052        while (TRUE) {
00053           rc = select(maxfds,reads,writes,errors,NULL);
00054           if ((rc == -1) && (errno == EINTR)) { /* interrupted */
00055              if (reads) bcopy(&readcopy,reads,sizeof(fd_set));
00056              if (writes) bcopy(&writecopy,writes,sizeof(fd_set));
00057              if (errors) bcopy(&errcopy,errors,sizeof(fd_set));
00058              continue;
00059           }
00060           else return(rc);
00061        }
00062     }
00063     else { /* timeout is not null */
00064        timetogo.tv_sec = timeout->tv_sec;
00065        timetogo.tv_usec = timeout->tv_usec;
00066        remaining = timetogo.tv_sec + timetogo.tv_usec/1000000.;
00067        /*
00068           fprintf(stderr,"remaining time = %f\n",remaining);
00069           fflush(stderr);
00070         */
00071        gettimeofday(&Timer2, &tz);
00072        while (TRUE) {
00073           Timer1.tv_sec = Timer2.tv_sec;
00074           Timer1.tv_usec = Timer2.tv_usec;
00075           rc = select(maxfds,reads,writes,errors,&timetogo);
00076           if ((rc == -1) && (errno == EINTR)) { /* interrupted */
00077              gettimeofday(&Timer2, &tz);
00078              /* compute amount remaining */
00079              worktime = (Timer2.tv_sec - Timer1.tv_sec) +
00080                 (Timer2.tv_usec - Timer1.tv_usec)/1000000.;
00081              remaining = remaining - worktime;
00082              timetogo.tv_sec = (int) remaining;
00083              timetogo.tv_usec = (int) ((remaining - timetogo.tv_sec)*
00084                    1000000.);
00085              /* restore the select bits */
00086              if (reads) bcopy(&readcopy,reads,sizeof(fd_set));
00087              if (writes) bcopy(&writecopy,writes,sizeof(fd_set));
00088              if (errors) bcopy(&errcopy,errors,sizeof(fd_set));
00089              continue;
00090           }
00091           else return(rc);
00092        }
00093      }
00094    }
00095 #endif
00096 
00097 FD_MANAGER *FD_MANAGER::_mgr = 0;
00098 
00099 /* -------------------------------------------------------------------------
00100  *
00101  * Utilities for reading/writing and modifying the characteristics of
00102  * tty's.
00103  *
00104  * ------------------------------------------------------------------------- */
00105 
00106    /* This basically says all reads should return
00107     * immediately with however many characters are 
00108     * requested or are available, whichever is smaller.
00109     */
00110 #define  VMIN_CHARACTERS 0
00111 #define  VTIME_LENGTH    0
00112 #define  MILLISEC_TO_TIME(PTR, MSEC, TIME)       \
00113         if ((MSEC) != -1) {                     \
00114            (TIME).tv_sec  =  (MSEC)/1000;       \
00115            (TIME).tv_usec = ((MSEC)%1000)*1000; \
00116            PTR =  &TIME;                        \
00117         } else                                  \
00118            PTR = NULL
00119 
00120 /* ------------------------ Static Routines  ------------------------------- */
00121 
00122 #if !defined(sun) && !defined(hpux) && !defined(sgi)
00123     int TTYfd::_timeout = 0;
00124 #else
00125 #   ifdef hp
00126        int TTYfd::_timeout = 120;
00127 #   else
00128        int TTYfd::_timeout = 30;
00129 #   endif
00130 #endif
00131 
00132 
00133 /* ------------------------ Private Routines ------------------------------- */
00134 
00135 /*
00136  * DESCR  : Returns TRUE if the specified file descriptor is not currently
00137  *          configured to VMIN = MIN and VTIME = TIME.
00138  */
00139 int TTYfd::not_configured( int MIN, int TIME)
00140 {
00141 #ifndef WIN32
00142   return (_ios_current.c_cc[VMIN]  != MIN ||
00143      _ios_current.c_cc[VTIME] != TIME);
00144 #else
00145 // XXX: minimum number of characters?
00146   return (_ct_current.ReadTotalTimeoutConstant != (unsigned)TIME);
00147 #endif
00148 }
00149 
00150 /* -----------------------------------------------------------------------
00151  * DESCR   : Query termios
00152  * RETURNS : 0 - on success
00153  *          -1 - on failure
00154  * ----------------------------------------------------------------------- */
00155 int TTYfd::get_flags()
00156 {
00157 #ifndef WIN32
00158    if (tcgetattr(_fd, &_ios_current) == -1) {
00159       perror("TTYfd::get_flags [ioctl TCGETA]");
00160       return -1;
00161    }
00162 #else
00163    if (!GetCommState((HANDLE)_fd, &_dcb_current) ||
00164        !GetCommTimeouts((HANDLE)_fd, &_ct_current)) {
00165       perror("TTYfd::get_flags [GetCommState]");
00166       return -1;
00167    }
00168 #endif
00169 
00170    return 0;
00171 }
00172 
00173 /* -----------------------------------------------------------------------
00174  * DESCR   : Sets termios "c_cflag".
00175  * RETURNS : 0 - on success
00176  *          -1 - on failure
00177  * ----------------------------------------------------------------------- */
00178 int TTYfd::set_flags()
00179 {
00180 #ifndef WIN32
00181    return tcsetattr(_fd, TCSADRAIN, &_ios_current);
00182 #else
00183    return (SetCommState((HANDLE)_fd, &_dcb_current) &&
00184       SetCommTimeouts((HANDLE)_fd, &_ct_current));
00185 #endif
00186 }
00187 
00188 
00189 /* ------------------------ Public Routines  ------------------------------- */
00190 /*LINTLIBRARY*/
00191 
00192 /* -----------------------------------------------------------------------
00193  * DESCR   : Clear input and output buffers.
00194  * ----------------------------------------------------------------------- */
00195 int TTYfd::clear()
00196 {
00197 #ifndef WIN32
00198    return tcflush(_fd, TCIOFLUSH);
00199 #else
00200    return PurgeComm((HANDLE)_fd, PURGE_TXCLEAR | PURGE_RXCLEAR);
00201 #endif
00202 }
00203 
00204 
00205 /* -----------------------------------------------------------------------
00206  * DESCR   : Send break.  NB: HPUX used to ignore "duration", but doesn't as
00207                               of hpux 10.
00208  * RETURNS : 0 - on success
00209  *          -1 - on failure
00210  * ----------------------------------------------------------------------- */
00211 int TTYfd::send_break(
00212    int  duration
00213    )
00214 {
00215 #ifndef WIN32
00216    if (tcsendbreak(_fd, duration) == -1) {
00217       perror("TTYbreak [ioctl TCSBRK]");
00218       return -1;
00219    }
00220 #else
00221    if (SetCommBreak((HANDLE)_fd) == FALSE) {
00222       perror("TTYbreak [EscapeCommFunction BRK]");
00223       return -1;
00224    }
00225 #endif
00226 
00227    return 0;
00228 }
00229 
00230 static void cspeed(speed_t sp, char *buf)
00231 {
00232    switch(sp) {
00233       case B0:     strcat(buf, "0");
00234     brcase B50:    strcat(buf, "50");
00235     brcase B75:    strcat(buf, "75");
00236     brcase B110:   strcat(buf, "110");
00237     brcase B134:   strcat(buf, "134");
00238     brcase B150:   strcat(buf, "150");
00239     brcase B200:   strcat(buf, "200");
00240     brcase B300:   strcat(buf, "300");
00241     brcase B600:   strcat(buf, "600");
00242     brcase B1200:  strcat(buf, "1200");
00243     brcase B1800:  strcat(buf, "1800");
00244     brcase B2400:  strcat(buf, "2400");
00245     brcase B4800:  strcat(buf, "4800");
00246     brcase B9600:  strcat(buf, "9600");
00247     brcase B19200: strcat(buf, "19200");
00248     brcase B38400: strcat(buf, "38400");
00249     brdefault:     strcat(buf, "unknown");
00250    }
00251 }
00252 
00253 /* -----------------------------------------------------------------------
00254  * DESCR   : Prints the current terminal characteristics.
00255  * ----------------------------------------------------------------------- */
00256 void TTYfd::print_flags()
00257 {
00258    char  buf[1024];
00259    speed_t  speed;
00260 
00261    buf[0] = '\0';
00262    if (get_flags())
00263       return;
00264 
00265 #ifndef WIN32
00266    switch(_ios_current.c_cflag & CSIZE) {
00267       case CS5: strcat(buf, "5");
00268     brcase CS6: strcat(buf, "6");
00269     brcase CS7: strcat(buf, "7");
00270     brcase CS8: strcat(buf, "8");
00271    }
00272    strcat(buf, " char bits\t");
00273 
00274    speed = cfgetispeed(&_ios_current);
00275    cspeed(speed, buf);
00276    strcat(buf, " baud input\t");
00277    speed = cfgetospeed(&_ios_current);
00278    cspeed(speed, buf);
00279    strcat(buf, " baud output\t");
00280 
00281    if (!(_ios_current.c_cflag & PARENB)) 
00282       strcat(buf, "no   parity\t");
00283    else if (_ios_current.c_cflag & PARODD)
00284       strcat(buf, "odd  parity\t");
00285    else 
00286       strcat(buf, "even parity\t");
00287 
00288    if (_ios_current.c_cflag & CSTOPB)
00289       strcat(buf, "2 stop bits.");
00290    else
00291       strcat(buf, "1 stop bit.");
00292 
00293 #else
00294 
00295    switch(_dcb_current.ByteSize) {
00296       case CS5: strcat(buf, "5");
00297     brcase CS6: strcat(buf, "6");
00298     brcase CS7: strcat(buf, "7");
00299     brcase CS8: strcat(buf, "8");
00300    }
00301    strcat(buf, " char bits\t");
00302 
00303    speed = _dcb_current.BaudRate;
00304    cspeed(speed, buf);
00305    strcat(buf, " baud input\t");
00306 // XXX: different input/output speeds?
00307    cspeed(speed, buf);
00308    strcat(buf, " baud output\t");
00309 
00310    switch (_dcb_current.Parity) {
00311        case NOPARITY:    strcat(buf, "no    parity\t");
00312      brcase EVENPARITY:  strcat(buf, "even  parity\t");
00313      brcase ODDPARITY:   strcat(buf, "odd   parity\t");
00314      brcase MARKPARITY:  strcat(buf, "mark  parity\t");
00315      brcase SPACEPARITY: strcat(buf, "space parity\t");
00316    }
00317 
00318    if (_dcb_current.StopBits == TWOSTOPBITS)
00319       strcat(buf, "2 stop bits.");
00320    else
00321       strcat(buf, "1 stop bit.");
00322 #endif
00323 
00324    cerr << buf << endl;
00325 }
00326 
00327 
00328 /* -----------------------------------------------------------------------
00329  * DESCR   : Set input and output speed of the tty.  Speeds are defined in
00330  *           <termios.h> and are of the form B9600 B1200 etc.
00331  * ----------------------------------------------------------------------- */
00332 int TTYfd::set_speed(
00333    long           speed
00334    )
00335 {
00336    if (get_flags() < 0) 
00337       return -1;
00338 
00339 #ifndef WIN32
00340    cfsetospeed(&_ios_current, speed);
00341    cfsetispeed(&_ios_current, speed);
00342 #else
00343    _dcb_current.BaudRate =speed;
00344 #endif
00345 
00346    return set_flags();
00347 }
00348 
00349 
00350 /* -----------------------------------------------------------------------
00351  * DESCR   : Sets No stop bits.
00352  * RETURNS : 0 - on success
00353  *          -1 - on failure
00354  * ----------------------------------------------------------------------- */
00355 int TTYfd::set_stopbits(
00356    int     num
00357    )
00358 {
00359    if (num != 1 && num != 2) {
00360       cerr << "TTYfd::set_stopbits: must be 1 or 2: " << num << endl;
00361       return -1;
00362    }
00363 
00364    if (get_flags() < 0)
00365       return -1;
00366 
00367 #ifndef WIN32
00368    _ios_current.c_cflag &= num == 1 ? ~0 : ~CSTOPB;
00369    _ios_current.c_cflag |= num == 1 ?  0 :  CSTOPB;
00370 #else
00371    _dcb_current.StopBits = (num == 1) ? ONESTOPBIT : TWOSTOPBITS;
00372 #endif
00373 
00374    return set_flags();
00375 }
00376 
00377 
00378 /* -----------------------------------------------------------------------
00379  * DESCR   : Sizes are defined in <termio.h> and are of the form CS7, CS8 etc.
00380  * ----------------------------------------------------------------------- */
00381 int TTYfd::set_charsize(
00382    short   size
00383    )
00384 {
00385    if (get_flags() < 0)
00386       return -1;
00387 
00388 #ifndef WIN32
00389    _ios_current.c_cflag &= ~CSIZE;
00390    _ios_current.c_cflag |= CSIZE & size;
00391 #else
00392    _dcb_current.ByteSize = (unsigned int)size;
00393 #endif
00394 
00395    return set_flags();
00396 }
00397 
00398 
00399 /* -----------------------------------------------------------------------
00400  * DESCR   : Sets parity characteristic of device.
00401  * ----------------------------------------------------------------------- */
00402 int TTYfd::set_parity(
00403    TTYparity parity
00404    )
00405 {
00406    if (get_flags() < 0)
00407       return -1;
00408 
00409 #ifndef WIN32
00410    switch (parity) {
00411     case   TTY_ODD: 
00412       _ios_current.c_cflag |= PARENB;
00413       _ios_current.c_cflag |= PARODD;
00414     brcase TTY_EVEN: 
00415       _ios_current.c_cflag |= PARENB;
00416       _ios_current.c_cflag &= ~PARODD;
00417     brcase  TTY_NONE: 
00418       _ios_current.c_cflag &= ~PARENB;
00419       }
00420 #else
00421    switch (parity) {
00422     case   TTY_ODD: 
00423       _dcb_current.Parity = ODDPARITY;
00424     brcase TTY_EVEN: 
00425       _dcb_current.Parity = EVENPARITY;
00426     brcase  TTY_NONE: 
00427       _dcb_current.Parity = NOPARITY;
00428       }
00429 #endif
00430 
00431    return set_flags();
00432 }
00433 
00434 
00435 /* -----------------------------------------------------------------------
00436  * DESCR   : Set timeout for read.  See termio.h for detailed description
00437  *           of VMIN and VTIME flags.  The basic idea is that VMIN 
00438  *           determines how many characters must be read for a read op to
00439  *           be satisfied, and VTIME is either the amount of time allowed
00440  *           between reading consecutive characters, or it's the entire 
00441  *           length of the read operation in .1 msecs (if VMIN = 0).
00442  * ----------------------------------------------------------------------- */
00443 int TTYfd::set_min_and_time(
00444    int   minimum,  /* min # of characters to read */
00445    int   time      /* min delay between chars, or total read time */
00446    )
00447 {
00448    get_flags();
00449 
00450    if (not_configured(minimum, time)) {
00451 #ifndef WIN32
00452      _ios_current.c_cc[VMIN]  = minimum;
00453      _ios_current.c_cc[VTIME] = time;
00454 #else
00455      _ct_current.ReadTotalTimeoutConstant = time;
00456      if (minimum != 0)
00457    cerr << "TTYfd::set_min_and_time (minimum!=0)" << endl;
00458        // XXX: min # of characters
00459 #endif
00460 
00461      return set_flags();
00462    }
00463 
00464    return 0;
00465 }
00466 
00467 
00468 /* -----------------------------------------------------------------------
00469  * DESCR   : Read commands from tty
00470  *
00471  *           Read immeadiately :
00472  *           cc = TTYread_all (fd, buf, maxnum); 
00473  * ----------------------------------------------------------------------- */
00474 int TTYfd::read_all(
00475    char   *buf,
00476    int     maxbytes
00477    )
00478 {
00479    int     i, num;
00480 
00481    if (not_configured(0, 0) && set_min_and_time(0, 0) == -1) {
00482       cerr << "TTYfd::read_all: TTYfd::set_min_and_time failed" << endl;
00483       return -1;
00484    }
00485 
00486 #ifndef WIN32
00487    if ((num = read(_fd, buf, maxbytes)) < 0) {
00488       if (errno != EWOULDBLOCK) {
00489          perror("TTYread_all [read failed]");
00490          return -1;
00491       } else
00492          return 0;
00493    }
00494 #else
00495    COMSTAT stat;
00496    DWORD eflags;
00497    ClearCommError((HANDLE)_fd, &eflags, &stat);
00498    if (stat.cbInQue >= (unsigned int)maxbytes)
00499      stat.cbInQue = maxbytes;
00500    if (stat.cbInQue > 0) {
00501      unsigned long bytes;
00502      int error = ReadFile((HANDLE)_fd, buf, stat.cbInQue, &bytes, NULL);
00503      num = bytes;
00504      if (error==FALSE)
00505        return -1;
00506    } else
00507      return 0;
00508 #endif
00509 
00510    if (TTYdebug) {       
00511       for (i=0; i < num; i++)
00512          printf("[0x%x]%s", (byte)buf[i], i == num-1 ? ".\n":"");
00513       cerr << "TTYread_all: done.\n";
00514    }
00515 
00516    return num;
00517 }
00518 
00519 
00520 /* -----------------------------------------------------------------------
00521  * DESCR   : Read commands from tty
00522  *           
00523  *           Interrupt driven read :
00524  *           cc = TTYnread (fd, buf, num, timeout, num_read);
00525  * ----------------------------------------------------------------------- */
00526 int TTYfd::nread(
00527    char  *buf,
00528    int    readnum,
00529    int    timeoutval  /* In millisecs, 0 for poll, -1 for indefinite */
00530    )
00531 {
00532    register int    i, num = 0, howmany = 0;
00533    char           *buf_save = buf;
00534 
00535    if (not_configured  (VMIN_CHARACTERS, VTIME_LENGTH) &&
00536        set_min_and_time(VMIN_CHARACTERS, VTIME_LENGTH) == -1) {
00537       cerr << "TTYfd::nread: TTYfd::set_min_and_time failed" << endl;
00538       return -1;
00539    }
00540 
00541 #ifndef WIN32
00542    struct timeval  timeout, *toptr;
00543    fd_set          readfds;
00544    MILLISEC_TO_TIME(toptr, timeoutval, timeout);
00545         
00546    FD_ZERO(&readfds);
00547    FD_SET(_fd, &readfds);
00548    for (buf += num; num < readnum; buf += howmany, num += howmany)
00549       if ((i = SELECT(FD_SETSIZE, &readfds, 0, 0, toptr)) == 0) {
00550          if (TTYdebug)
00551             cerr << "Timeout expired" << endl; 
00552          return num;
00553       } else if (i < 0) {
00554          perror("TTYnread [select failed]");
00555          return -1;
00556       } else if ((howmany = read(_fd, buf, (readnum - num))) < 1) {
00557          char pbuf[256]; sprintf(pbuf, "TTYfd::nread [read failed] %d", _fd);
00558          perror(pbuf);
00559          break;
00560       }
00561 #else
00562    unsigned long bytes;
00563    for (buf +=num; num<readnum; buf+=howmany, num+=howmany) {
00564       int error = ReadFile((HANDLE)_fd, buf, readnum-num, &bytes, NULL);
00565       if (bytes==0) {
00566    if (TTYdebug)
00567           cerr << "Timeout expired" << endl;
00568    return num;
00569       }
00570       howmany = bytes;
00571    }
00572 #endif
00573 
00574    if (TTYdebug) {
00575       for (i = 0, buf = buf_save; i < num; i++, buf++)
00576           printf("[0x%x]%s", (byte)(*buf), (i == num-1) ? ".\n" : "");
00577       cerr << "TTYnread: done" << endl;
00578    }
00579 
00580    return num;
00581 }
00582 
00583 int
00584 TTYfd::read_synchronized(
00585    char  sentinel,
00586    int   record_size,
00587    char *buf
00588    )
00589 { 
00590    return read_synchronized(sentinel, 0, 0, record_size, buf);
00591 }
00592 
00593 int
00594 TTYfd::read_synchronized(
00595    int   sentinel_bit,
00596    int   record_size,
00597    char *buf
00598    )
00599 { 
00600    return read_synchronized('\0', sentinel_bit, 1, record_size, buf);
00601 }
00602 
00603 int
00604 TTYfd::read_synchronized(
00605    char  sentinel,
00606    int   sentinel_bit,
00607    int   which_sentinel,
00608    int   record_size,
00609    char *buf
00610    )
00611 {
00612    if (record_size > MAX_REC_SIZE) {
00613       cerr << "TTYfd::read_synchronized() : record size of "
00614            << record_size << " bigger than max size of " 
00615            <<  MAX_REC_SIZE << endl;
00616       return 0;
00617    }
00618 
00619    if (_synch_pos == 0) {
00620       int  retries = 0;    // read single bytes until a byte is found in 
00621       do {                 // which the sentinel bit is on.
00622          if (nread(_synch_buf, 1, _timeout) != 1 || 
00623              ((which_sentinel == 1 && !BIT(sentinel_bit, _synch_buf[0])) ||
00624               (which_sentinel == 0 && _synch_buf[0] != sentinel))
00625             )
00626             retries++;
00627          else
00628             _synch_pos ++;
00629       } while (retries < record_size && !_synch_pos);
00630 
00631       if (retries == record_size) {
00632          clear();
00633          cerr << "TTYfd::read_synchronized(): no sentinel after trying " 
00634               << retries << " times" << endl;
00635          return 0;
00636       }
00637    }
00638 
00639    // Read the remaining record_size bytes that make up a data record.
00640    int nr, need = record_size - _synch_pos;
00641    if ((nr = nread(&_synch_buf[_synch_pos], need, _timeout)) != -1) {
00642       _synch_pos = (_synch_pos + nr) % record_size;
00643       if (nr == need) {
00644          for (int i = 0; i < record_size; i++)
00645              buf[i] = _synch_buf[i];    // copy bytes out of cache
00646          return 1;
00647       }
00648    }
00649 
00650    return 0;
00651 }
00652 
00653 
00654 /* -----------------------------------------------------------------------
00655  * DESCR   : Insures that all characters currently queued for output will
00656  *           be sent with the current settings of the TTY port.  That is,
00657  *           later changes to the TTY are guaranteed not to affect the 
00658  *           currently queued characters.
00659  * ----------------------------------------------------------------------- */
00660 int TTYfd::drain()
00661 {
00662 #ifndef WIN32
00663    return tcdrain(_fd);
00664 #else
00665    return PurgeComm((HANDLE)_fd, PURGE_TXCLEAR);
00666 #endif
00667 }
00668 
00669 
00670 /* -----------------------------------------------------------------------
00671  * DESCR   : Write buf to tty
00672  * ----------------------------------------------------------------------- */
00673 int TTYfd::write(
00674    const char *buf,
00675    int         writenum,
00676    int         timeoutval   /* millisecs */
00677    )
00678 {
00679    struct   timeval  timeout, *toptr;
00680    int      num = 0, i;
00681 
00682    if (TTYdebug) {
00683       cerr << "TTYfd::write: writing..." << endl;
00684 
00685       for (i=0; i<writenum; i++)
00686          printf("[0x%x]%s", (byte)buf[i], (i==writenum-1) ? ".\n":"");
00687    }
00688 
00689    MILLISEC_TO_TIME(toptr, timeoutval, timeout);
00690 
00691 #ifndef WIN32
00692    int      howmany;
00693    fd_set   writefds;
00694    if ((num = ::write(_fd, buf, writenum)) < 0) {
00695       perror("TTYfd::write [write failed]");
00696       return -1;
00697    }
00698 
00699    FD_ZERO(&writefds);
00700    FD_SET(_fd, &writefds);
00701    for (; num < writenum; num += howmany, buf += howmany) {
00702       if (SELECT(FD_SETSIZE, 0, &writefds, 0, toptr) <= 0) {
00703          perror("TTYfd::write [select failed]");
00704          break;
00705       }
00706       if ((howmany = ::write(_fd, buf, writenum-num)) != 1) {
00707          perror("TTYfd::write [write failed]");
00708          break;
00709       }
00710    }
00711 #else
00712    unsigned long bytes;
00713    if (WriteFile((HANDLE)_fd, buf, writenum, &bytes, NULL) == FALSE)
00714      perror("TTYfd::write [WriteFile failed]");
00715    num = bytes;
00716 #endif
00717 
00718    if (TTYdebug)
00719       cerr << "TTYwrite: done" << endl;
00720 
00721    return num;
00722 }
00723 
00724 
00725 /* -----------------------------------------------------------------------
00726  * DESCR   : Flush the port, set baud rates, etc.
00727  * DETAILS : The tty is initialized to - 9600 baud, 8bits, 1stop bit, no parity
00728  * RETURNS : -1 on failure
00729  *           device's file descriptor if successful.
00730  * ----------------------------------------------------------------------- */
00731 int TTYfd::setup()
00732 {
00733    get_flags();
00734 
00735    /* We support three arches here: hpux, sgi, & solaris. -tsm */
00736 
00737 #ifndef WIN32
00738    _ios_current.c_cc[VMIN]  = VMIN_CHARACTERS;
00739    _ios_current.c_cc[VTIME] = VTIME_LENGTH;
00740 #ifndef macosx
00741    _ios_current.c_iflag &= ~(PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL|IUCLC|
00742               IXON|IXANY|IXOFF
00743 #ifdef IMAXBEL
00744               |IMAXBEL
00745 #endif
00746               );
00747 #endif /* macosx */
00748    _ios_current.c_iflag |= IGNBRK;
00749    _ios_current.c_oflag &= ~(OPOST);
00750    cfsetispeed(&_ios_current, B9600);
00751    cfsetospeed(&_ios_current, B9600);
00752    _ios_current.c_cflag &= ~(CSIZE|CSTOPB|PARENB);
00753    _ios_current.c_cflag |= CS8|CREAD|CLOCAL;
00754    _ios_current.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHONL|TOSTOP|IEXTEN
00755 #ifdef ECHOCTL
00756               |ECHOCTL
00757 #endif
00758 #ifdef ECHOKE
00759               |ECHOKE
00760 #endif
00761 #ifdef PENDIN
00762               |PENDIN
00763 #endif
00764               );
00765 #else
00766    _ct_current.ReadIntervalTimeout = MAXDWORD;
00767    _ct_current.ReadTotalTimeoutMultiplier = MAXDWORD;
00768    _ct_current.ReadTotalTimeoutConstant = VTIME_LENGTH;
00769    _ct_current.WriteTotalTimeoutMultiplier = 0;
00770    _ct_current.WriteTotalTimeoutConstant = 0;
00771    _dcb_current.fParity = FALSE;
00772    _dcb_current.fBinary = TRUE;
00773    _dcb_current.fInX = FALSE;
00774    _dcb_current.BaudRate = CBR_9600;
00775    _dcb_current.ByteSize = 8;
00776    _dcb_current.Parity = NOPARITY;
00777    _dcb_current.StopBits = ONESTOPBIT;
00778 #endif
00779    set_flags();
00780 
00781 // bcz: this insures that the serial port is configured
00782 //      properly for the Suns.  However, tsm thought this 
00783 //      might cause problems in some strange cases...
00784 //      so if things are broken, you might look here...
00785 // XXX - lem: following #ifdef is never true.
00786 //            change to "#ifdef sun" to let it be true,
00787 //            and be sure to fix the broken code when you do.
00788 #ifdef sol
00789    int xxx = TIOCM_DTR|TIOCM_RTS;
00790    ioctl(_fd, TIOCMBIC, &xxx); 
00791    ioctl(_fd, TCIOMBIS, &xxx);  // Error: TCIOMBIS is not defined
00792 #endif
00793 
00794    return _fd;
00795 }
00796 
00797 /* -----------------------------------------------------------------------
00798  * DESCR   : Closes a TTY.
00799  * RETURNS : -1 on failure, 0 on success
00800  * ----------------------------------------------------------------------- */
00801 int TTYfd::close()
00802 {
00803 #ifndef WIN32
00804    _ios_current = _ios_saved;
00805 #else
00806    _ct_current = _ct_saved;
00807    _dcb_current = _dcb_saved;
00808 #endif
00809 
00810    set_flags();         /* reset attributes */
00811 
00812 #ifndef WIN32
00813    if (::close(_fd)) {
00814 #else
00815    if (CloseHandle((HANDLE)_fd) == FALSE) {
00816 #endif
00817      char buf[256]; sprintf(buf, "TTYfd::close - failed on : %d", _fd);
00818      perror(buf);
00819      return -1;
00820    }
00821 
00822    _fd = -1;
00823 
00824    return 0;
00825 }
00826 
00827 /* -----------------------------------------------------------------------
00828  * DESCR   : Open tty, get file discriptor.
00829  * RETURNS : -1 on failure
00830  *           device's file descriptor if successful.
00831  * ----------------------------------------------------------------------- */
00832 int TTYfd::open()
00833 {
00834   if (_fd == -1) {
00835 #ifdef sun
00836     if ((_fd = ::open(_dev, O_RDWR|O_NDELAY  |O_NOCTTY, 0)) < 0) {     /* Open for non-blocking read */
00837 #elif WIN32
00838     if ((HANDLE)(_fd = (int)CreateFile(_dev, GENERIC_READ|GENERIC_WRITE, 0, NULL,
00839                    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) ==
00840    INVALID_HANDLE_VALUE) {
00841 #else
00842     if ((_fd = ::open(_dev, O_RDWR|O_NONBLOCK|O_NOCTTY, 0)) < 0) {     /* Open for non-blocking read */
00843 #endif
00844       char buf[256]; sprintf(buf, "TTYfd::open - failed on : %s", _dev);
00845       perror(buf);
00846       return -1;
00847     }
00848 
00849     get_flags();                  /* save tty attributes  */
00850 
00851 #ifndef WIN32
00852     _ios_saved = _ios_current;
00853 #else
00854     _ct_saved = _ct_current;
00855     _dcb_saved = _dcb_current;
00856 #endif
00857 
00858 #ifdef hp
00859     mflag dtr_set = MDTR | MRTS;
00860     ioctl(_fd, MCSETA, &dtr_set);
00861 #endif
00862   }
00863 
00864   return 1; // Success
00865 }
00866 
00867 int 
00868 TTYfd::activate()
00869 {
00870    if (open() <  0) {
00871       cerr << "Couldn't open the serial port:" << _dev << endl;
00872       return 0;
00873    }
00874    setup();
00875    clear(); 
00876 
00877    if (_manager)
00878       _manager->add(this);
00879 
00880    return 1;
00881 }
00882 
00883 int 
00884 TTYfd::deactivate()
00885 {
00886    if (_fd != -1)
00887       close();
00888    if (_manager)
00889       _manager->rem(this);
00890 
00891    return 1;
00892 }
00893 
00894 TTYfd::TTYfd(
00895    FD_MANAGER  *manager,
00896    const char  *dev,
00897    const char  *name
00898    ):_synch_pos(0), _manager(manager)
00899 { 
00900    if (dev != NULL)
00901    {
00902       strcpy(_dev, dev);
00903    }
00904    else 
00905    {
00906       str_ptr name_var = Config::get_var_str(name,NULL_STR,false);
00907       if (name_var != NULL_STR)
00908       {
00909          strcpy(_dev, **name_var);
00910       }
00911       else 
00912       {
00913          _dev[0] = '\0';
00914       }
00915    }
00916    //Only apply the the timeout if it's >-1, rather than default to 0,
00917    //since the default is platform dependent. Well, its different
00918    //on some obsolete platforms, like sun, sgi, etc...
00919    int timeout = Config::get_var_int("TTY_TIMEOUT",-1,true);
00920    if (timeout>=0) _timeout = timeout;
00921 }
00922 
00923 
00924 

Generated on Mon Sep 18 11:39:34 2006 for jot by  doxygen 1.4.4