home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume25 / tcsh-6.01 / part05 / mi.termios.c < prev    next >
C/C++ Source or Header  |  1991-12-19  |  11KB  |  393 lines

  1. /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.01/RCS/mi.termios.c,v 1.1 1991/11/26 04:28:26 christos Exp $ */
  2. /* termios.c - fake termios interface using sgtty interface 
  3.  *            by Magnus Doell and Bruce Evans.
  4.  *
  5.  */
  6. #include "sh.h"
  7. #ifdef _MINIX
  8.  
  9. RCSID($Id: mi.termios.c,v 1.1 1991/11/26 04:28:26 christos Exp $)
  10.  
  11. /* Undefine everything that clashes with sgtty.h. */
  12. #undef B0
  13. #undef B50
  14. #undef B75
  15. #undef B110
  16. #undef B134
  17. #undef B150
  18. #undef B200
  19. #undef B300
  20. #undef B600
  21. #undef B1200
  22. #undef B1800
  23. #undef B2400
  24. #undef B4800
  25. #undef B9600
  26. #undef B19200
  27. #undef B28800
  28. #undef B38400
  29. #undef B57600
  30. #undef B115200
  31. /* Do not #undef CRMOD. We want a warning when they differ! */
  32. #undef ECHO
  33. /* Do not #undef XTABS. We want a warning when they differ! */
  34.  
  35. /* Redefine some of the termios.h names just undefined with 'T_' prefixed
  36.  * to the name.  Don't bother with the low speeds - Minix does not support
  37.  * them.  Add support for higher speeds (speeds are now easy and don't need
  38.  * defines because they are not encoded).
  39.  */
  40. #define T_ECHO        000001
  41.  
  42. #include <errno.h>
  43. #include <sgtty.h>
  44.  
  45. static _PROTOTYPE( int tc_to_sg_speed, (speed_t speed) );
  46. static _PROTOTYPE( speed_t sg_to_tc_speed, (int speed) );
  47. #define B19200   192
  48.  
  49. /* The speed get/set functions could be macros in the Minix implementation
  50.  * because there are speed fields in the structure with no fancy packing
  51.  * and it is not practical to check the values outside the driver.
  52.  * Where tests are necessary because the driver acts different from what
  53.  * POSIX requires, they are done in tcsetattr.
  54.  */
  55.  
  56. speed_t cfgetispeed(termios_p)
  57. struct termios *termios_p;
  58. {
  59.     return termios_p->c_ispeed;
  60. }
  61.  
  62. speed_t cfgetospeed(termios_p)
  63. struct termios *termios_p;
  64. {
  65.     return termios_p->c_ospeed;
  66. }
  67.  
  68. speed_t cfsetispeed(termios_p, speed)
  69. struct termios *termios_p;
  70. speed_t speed;
  71. {
  72.     termios_p->c_ispeed = speed;
  73.     return 0;
  74. }
  75.  
  76. speed_t cfsetospeed(termios_p, speed)
  77. struct termios *termios_p;
  78. speed_t speed;
  79. {
  80.     termios_p->c_ospeed = speed;
  81.     return 0;
  82. }
  83.  
  84. static speed_t sg_to_tc_speed(speed)
  85. int speed;
  86. {
  87.     /* The speed encodings in sgtty.h and termios.h are different.  Both are
  88.      * inflexible.  Minix doesn't really support B0 but we map it through
  89.      * anyway.  It doesn't support B50, B75 or B134.
  90.      */
  91.     switch (speed) {
  92.     case B0: return 0;
  93.     case B110: return 110;
  94.     case B200: return 200;
  95.     case B300: return 300;
  96.     case B600: return 600;
  97.     case B1200: return 1200;
  98.     case B1800: return 1800;
  99.     case B2400: return 2400;
  100.     case B4800: return 4800;
  101.     case B9600: return 9600;
  102.     case B19200: return 19200;
  103. #ifdef B28800
  104.     case B28800: return 28800;
  105. #endif
  106. #ifdef B38400
  107.     case B38400: return 38400;
  108. #endif
  109. #ifdef B57600
  110.     case B57600: return 57600;
  111. #endif
  112. #ifdef B115200
  113.     case B115200: return 115200;
  114. #endif
  115.     default: return (speed_t)-1;
  116.     }
  117. }
  118.  
  119. static int tc_to_sg_speed(speed)
  120. speed_t speed;
  121. {
  122.     /* Don't use a switch here in case the compiler is 16-bit and doesn't
  123.      * properly support longs (speed_t's) in switches.  It turns out the
  124.      * switch is larger and slower for most compilers anyway!
  125.      */
  126.     if (speed == 0) return 0;
  127.     if (speed == 110) return B110;
  128.     if (speed == 200) return B200;
  129.     if (speed == 300) return B300;
  130.     if (speed == 600) return B600;
  131.     if (speed == 1200) return B1200;
  132.     if (speed == 1800) return B1800;
  133.     if (speed == 2400) return B2400;
  134.     if (speed == 4800) return B4800;
  135.     if (speed == 9600) return B9600;
  136.     if (speed == 19200) return B19200;
  137. #ifdef B28800
  138.     if (speed == 28800) return B28800;
  139. #endif
  140. #ifdef B38400
  141.     if (speed == 38400) return B38400;
  142. #endif
  143. #ifdef B57600
  144.     if (speed == 57600) return B57600;
  145. #endif
  146. #ifdef B115200
  147.     if (speed == 115200) return B115200;
  148. #endif
  149.     return -1;
  150. }
  151.  
  152. int tcgetattr(filedes, termios_p)
  153. int filedes;
  154. struct termios *termios_p;
  155. {
  156.     struct sgttyb sgbuf;
  157.     struct tchars tcbuf;
  158.  
  159.     if (ioctl(filedes, TIOCGETP, &sgbuf) < 0
  160.     || ioctl(filedes, TIOCGETC, (struct sgttyb *) &tcbuf) < 0)
  161.     {
  162.     return -1;
  163.     }
  164.  
  165.     /* Minix input flags:
  166.      *   BRKINT:  forced off (break is not recognized)
  167.      *   IGNBRK:  forced on (break is not recognized)
  168.      *   ICRNL:   set if CRMOD is set and not RAW (CRMOD also controls output)
  169.      *   IGNCR:   forced off (ignoring cr's is not supported)
  170.      *   INLCR:   forced off (mapping nl's to cr's is not supported)
  171.      *   ISTRIP:  forced off (should be off for consoles, on for rs232 no RAW)
  172.      *   IXOFF:   forced off (rs232 uses CTS instead of XON/XOFF)
  173.      *   IXON:    forced on if not RAW
  174.      *   PARMRK:  forced off (no '\377', '\0', X sequence on errors)
  175.      * ? IGNPAR:  forced off (input with parity/framing errors is kept)
  176.      * ? INPCK:   forced off (input parity checking is not supported)
  177.      */
  178.     termios_p->c_iflag = IGNBRK;
  179.     if (!(sgbuf.sg_flags & RAW))
  180.     {
  181.     termios_p->c_iflag |= IXON;
  182.     if (sgbuf.sg_flags & CRMOD)
  183.     {
  184.         termios_p->c_iflag |= ICRNL;
  185.     }
  186.     }
  187.  
  188.     /* Minix output flags:
  189.      *   OPOST:   set if CRMOD or XTABS is set
  190.      *   XTABS:   copied from sg_flags
  191.      *   CRMOD:      copied from sg_flags
  192.      */
  193.     termios_p->c_oflag = sgbuf.sg_flags & (CRMOD | XTABS);
  194.     if (termios_p->c_oflag)
  195.     {
  196.     termios_p->c_oflag |= OPOST;
  197.     }
  198.  
  199.     /* Minix local flags:
  200.      *   ECHO:    set if ECHO is set
  201.      *   ECHOE:   set if ECHO is set (ERASE echoed as error-corecting backspace)
  202.      *   ECHOK:   set if ECHO is set ('\n' echoed after KILL char)
  203.      *   ECHONL:  forced off ('\n' not echoed when ECHO isn't set)
  204.      *   ICANON:  set if neither CBREAK nor RAW
  205.      *   IEXTEN:  forced off
  206.      *   ISIG:    set if not RAW
  207.      *   NOFLSH:  forced off (input/output queues are always flushed)
  208.      *   TOSTOP:  forced off (no job control)
  209.      */
  210.     termios_p->c_lflag = 0;
  211.     if (sgbuf.sg_flags & ECHO)
  212.     {
  213.     termios_p->c_lflag |= T_ECHO | ECHOE | ECHOK;
  214.     }
  215.     if (!(sgbuf.sg_flags & RAW))
  216.     {
  217.     termios_p->c_lflag |= ISIG;
  218.     if (!(sgbuf.sg_flags & CBREAK))
  219.     {
  220.         termios_p->c_lflag |= ICANON;
  221.     }
  222.     }
  223.  
  224.     /* Minix control flags:
  225.      *   CLOCAL:  forced on (ignore modem status lines - not quite right)
  226.      *   CREAD:   forced on (receiver is always enabled)
  227.      *   CSIZE:   CS5-CS8 correspond directly to BITS5-BITS8
  228.      *   CSTOPB:  set for B110 (driver will generate 2 stop-bits than)
  229.      *   HUPCL:   forced off
  230.      *   PARENB:  set if EVENP or ODDP is set
  231.      *   PARODD:  set if ODDP is set
  232.      */
  233.     termios_p->c_cflag = CLOCAL | CREAD;
  234.     switch (sgbuf.sg_flags & BITS8)
  235.     {
  236.     case BITS5: termios_p->c_cflag |= CS5; break;
  237.     case BITS6: termios_p->c_cflag |= CS6; break;
  238.     case BITS7: termios_p->c_cflag |= CS7; break;
  239.     case BITS8: termios_p->c_cflag |= CS8; break;
  240.     }
  241.     if (sgbuf.sg_flags & ODDP)
  242.     {
  243.     termios_p->c_cflag |= PARENB | PARODD;
  244.     }
  245.     if (sgbuf.sg_flags & EVENP)
  246.     {
  247.     termios_p->c_cflag |= PARENB;
  248.     }
  249.     if (sgbuf.sg_ispeed == B110)
  250.     {
  251.     termios_p->c_cflag |= CSTOPB;
  252.     }
  253.  
  254.     /* Minix may give back different input and output baudrates,
  255.      * but only the input baudrate is valid for both.
  256.      * As our termios emulation will fail, if input baudrate differs
  257.      * from output baudrate, force them to be equal.
  258.      * Otherwise it would be very suprisingly not to be able to set
  259.      * the terminal back to the state returned by tcgetattr :).
  260.      */
  261.     termios_p->c_ospeed =
  262.     termios_p->c_ispeed =
  263.         sg_to_tc_speed((unsigned char) sgbuf.sg_ispeed);
  264.  
  265.     /* Minix control characters correspond directly except VSUSP and the
  266.      * important VMIN and VTIME are not really supported.
  267.      */
  268.     termios_p->c_cc[VEOF] = tcbuf.t_eofc;
  269.     termios_p->c_cc[VEOL] = tcbuf.t_brkc;
  270.     termios_p->c_cc[VERASE] = sgbuf.sg_erase;
  271.     termios_p->c_cc[VINTR] = tcbuf.t_intrc;
  272.     termios_p->c_cc[VKILL] = sgbuf.sg_kill;
  273.     termios_p->c_cc[VQUIT] = tcbuf.t_quitc;
  274.     termios_p->c_cc[VSTART] = tcbuf.t_startc;
  275.     termios_p->c_cc[VSTOP] = tcbuf.t_stopc;
  276.     termios_p->c_cc[VMIN] = 1;
  277.     termios_p->c_cc[VTIME] = 0;
  278.     termios_p->c_cc[VSUSP] = 0;
  279.  
  280.     return 0;
  281. }
  282.  
  283. int tcsetattr(filedes, opt_actions, termios_p)
  284. int filedes;
  285. int opt_actions;
  286. struct termios *termios_p;
  287. {
  288.     struct sgttyb sgbuf;
  289.     struct tchars tcbuf;
  290.     int sgspeed;
  291.  
  292.     /* Posix 1003.1-1988 page 135 says:
  293.      * Attempts to set unsupported baud rates shall be ignored, and it is
  294.      * implementation-defined whether an error is returned by any or all of
  295.      * cfsetispeed(), cfsetospeed(), or tcsetattr(). This refers both to
  296.      * changes to baud rates not supported by the hardware, and to changes
  297.      * setting the input and output baud rates to different values if the
  298.      * hardware does not support it.
  299.      * Ignoring means not to change the existing settings, doesn't it?
  300.      */
  301.     if ((termios_p->c_ispeed != 0 && termios_p->c_ispeed != termios_p->c_ospeed)
  302.     || (sgspeed = tc_to_sg_speed(termios_p->c_ospeed)) < 0)
  303.     {
  304.     errno = EINVAL;
  305.     return -1;
  306.     }
  307.  
  308.     sgbuf.sg_ispeed = sgbuf.sg_ospeed = sgspeed;
  309.     sgbuf.sg_flags = 0;
  310.  
  311.     /* I don't know what should happen with requests that are not supported by
  312.      * old Minix drivers and therefore cannot be emulated.
  313.      * Returning an error may confuse the application (the values aren't really
  314.      * invalid or unsupported by the hardware, they just couldn't be satisfied
  315.      * by the driver). Not returning an error might be even worse because the
  316.      * driver will act different to what the application requires it to act
  317.      * after sucessfully setting the attributes as specified.
  318.      * Settings that cannot be emulated fully include:
  319.      *   c_ospeed != 110 && c_cflag & CSTOPB
  320.      *   c_ospeed == 110 && ! c_cflag & CSTOPB
  321.      *   (c_cc[VMIN] != 1 || c_cc[VTIME] != 0) && ! c_lflag & ICANON
  322.      *   c_lflag & ICANON && ! c_lflag & ISIG
  323.      * For the moment I just ignore these conflicts.
  324.      */
  325.  
  326.     if (termios_p->c_oflag & OPOST)
  327.     {
  328.     /* CRMOD isn't Posix and may conflict with ICRNL, which is Posix,
  329.      * so we just ignore it.
  330.      */
  331.     if (termios_p->c_oflag & XTABS)
  332.     {
  333.         sgbuf.sg_flags |= XTABS;
  334.     }
  335.     }
  336.  
  337.     if (termios_p->c_iflag & ICRNL)
  338.     {
  339.     /* We couldn't do it better :-(. */
  340.     sgbuf.sg_flags |= CRMOD;
  341.     }
  342.  
  343.     if (termios_p->c_lflag & T_ECHO)
  344.     {
  345.     sgbuf.sg_flags |= ECHO;
  346.     }
  347.     if (!(termios_p->c_lflag & ICANON))
  348.     {
  349.     if (termios_p->c_lflag & ISIG)
  350.     {
  351.          sgbuf.sg_flags |= CBREAK;
  352.     }
  353.     else
  354.     {
  355.          sgbuf.sg_flags |= RAW;
  356.     }
  357.     }
  358.  
  359.     switch (termios_p->c_cflag & CSIZE)
  360.     {
  361.     case CS5: sgbuf.sg_flags |= BITS5; break;
  362.     case CS6: sgbuf.sg_flags |= BITS6; break;
  363.     case CS7: sgbuf.sg_flags |= BITS7; break;
  364.     case CS8: sgbuf.sg_flags |= BITS8; break;
  365.     }
  366.     if (termios_p->c_cflag & PARENB)
  367.     {
  368.     if (termios_p->c_cflag & PARODD)
  369.     {
  370.         sgbuf.sg_flags |= ODDP;
  371.     }
  372.     else
  373.     {
  374.         sgbuf.sg_flags |= EVENP;
  375.     }
  376.     }
  377.  
  378.     sgbuf.sg_erase = termios_p->c_cc[VERASE];
  379.     sgbuf.sg_kill = termios_p->c_cc[VKILL];
  380.  
  381.     tcbuf.t_intrc = termios_p->c_cc[VINTR];
  382.     tcbuf.t_quitc = termios_p->c_cc[VQUIT];
  383.     tcbuf.t_startc = termios_p->c_cc[VSTART];
  384.     tcbuf.t_stopc = termios_p->c_cc[VSTOP];
  385.     tcbuf.t_eofc = termios_p->c_cc[VEOF];
  386.     tcbuf.t_brkc = termios_p->c_cc[VEOL];
  387.  
  388.     return ioctl(filedes, TIOCSETP, &sgbuf) < 0 &&
  389.        ioctl(filedes, TIOCSETC, (struct sgttyb *) &tcbuf) < 0 ?
  390.         -1 : 0;
  391. }
  392. #endif /* _MINIX */
  393.