tty: small improvements
authorAlan Cox <alan@linux.intel.com>
Sat, 3 Jan 2015 22:03:03 +0000 (22:03 +0000)
committerAlan Cox <alan@linux.intel.com>
Sat, 3 Jan 2015 22:03:03 +0000 (22:03 +0000)
Shave 90 bytes off tty_inproc (still too big!)
Fix VKILL bug
Timeout/VMIN handling

Kernel/include/tty.h
Kernel/tty.c

index 8ea8e3d..c1265ae 100644 (file)
@@ -148,7 +148,7 @@ struct termios {
 /* Group the tty into a single object. That lets 8bit processors keep all
    the data indexed off a single register */
 struct tty {
-    uint16_t pgrp;
+    /* Put flag first: makes it cheaper when short of registers */
     uint8_t flag;              /* Use uint8 pad - makes the whole struct
                                    24 byte - a nice number for CPUs with no 
                                    multiplier */
@@ -156,6 +156,7 @@ struct tty {
 #define TTYF_STOP      1
 #define TTYF_DISCARD   2
 #define TTYF_DEAD      4
+    uint16_t pgrp;
     struct termios termios;
 };
 
index 6385b22..00b9cf6 100644 (file)
@@ -57,8 +57,16 @@ int tty_read(uint8_t minor, uint8_t rawflag, uint8_t flag)
                                        uputc(c, udata.u_base);
                                break;
                        }
+                       if (!(t->termios.c_lflag & ICANON)) {
+                               uint8_t n = t->termios.c_cc[VTIME];
+                               if (n)
+                                       udata.u_ptab->p_timeout = n + 1;
+                        }
                        if (psleep_flags(q, flag))
-                               return -1;
+                               return -1;
+                        /* timer expired */
+                        if (udata.u_ptab->p_timeout == 1)
+                                goto out;
                }
 
                ++nread;
@@ -79,6 +87,7 @@ int tty_read(uint8_t minor, uint8_t rawflag, uint8_t flag)
 
                ++udata.u_base;
        }
+out:
        wakeup(&q->q_count);
        return nread;
 }
@@ -124,7 +133,7 @@ int tty_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
                        if (t->termios.c_oflag & OPOST) {
                                if (c == '\n' && (t->termios.c_oflag & ONLCR))
                                        tty_putc_wait(minor, '\r');
-                               if (c == '\r' && (t->termios.c_oflag & OCRNL))
+                               else if (c == '\r' && (t->termios.c_oflag & OCRNL))
                                        c = '\n';
                        }
                        tty_putc_wait(minor, c);
@@ -244,7 +253,6 @@ int tty_ioctl(uint8_t minor, uint16_t request, char *data)
  * UZI180 - This routine is called from the raw Hardware read routine,
  * either interrupt or polled, to process the input character.  HFB
  */
-
 int tty_inproc(uint8_t minor, unsigned char c)
 {
        unsigned char oc;
@@ -277,12 +285,12 @@ int tty_inproc(uint8_t minor, unsigned char c)
 
        if (t->termios.c_lflag & ISIG) {
                if (c == t->termios.c_cc[VINTR]) {      /* ^C */
-                       sgrpsig(t->pgrp, SIGINT);
-                       clrq(q);
-                       t->flag &= ~(TTYF_STOP | TTYF_DISCARD);
-                       return 1;
+                       wr = SIGINT;
+                       goto sigout;
                } else if (c == t->termios.c_cc[VQUIT]) {       /* ^\ */
-                       sgrpsig(t->pgrp, SIGQUIT);
+                       wr = SIGQUIT;
+sigout:
+                       sgrpsig(t->pgrp, wr);
                        clrq(q);
                        t->flag &= ~(TTYF_STOP | TTYF_DISCARD);
                        return 1;
@@ -305,24 +313,11 @@ int tty_inproc(uint8_t minor, unsigned char c)
        }
        if (canon) {
                if (c == t->termios.c_cc[VERASE]) {
-                       if (uninsq(q, &oc)) {
-                               if (oc == '\n' || oc == t->termios.c_cc[VEOL])
-                                       insq(q, oc);    /* Don't erase past nl */
-                               else if (t->termios.c_lflag & ECHOE)
-                                       tty_erase(minor);
-                               return 1;
-                       } else if (c == t->termios.c_cc[VKILL]) {
-                               while (uninsq(q, &oc)) {
-                                       if (oc == '\n'
-                                           || oc == t->termios.c_cc[VEOL]) {
-                                               insq(q, oc);    /* Don't erase past nl */
-                                               break;
-                                       }
-                                       if (t->termios.c_lflag & ECHOK)
-                                               tty_erase(minor);
-                               }
-                               return 1;
-                       }
+                       wr = ECHOE;
+                       goto eraseout;
+               } else if (c == t->termios.c_cc[VKILL]) {
+                       wr = ECHOK;
+                       goto eraseout;
                }
        }
 
@@ -342,6 +337,19 @@ int tty_inproc(uint8_t minor, unsigned char c)
            || c == t->termios.c_cc[VEOF])
                wakeup(q);
        return wr;
+
+eraseout:
+       while (uninsq(q, &oc)) {
+               if (oc == '\n' || oc == t->termios.c_cc[VEOL]) {
+                       insq(q, oc);    /* Don't erase past nl */
+                       break;
+               }
+               if (t->termios.c_lflag & wr)
+                       tty_erase(minor);
+                if (wr == ECHOE)
+                        break;
+       }
+       return 1;
 }
 
 /* called when a UART transmitter is ready for the next character */