x86 console and readline() honor 0x7f
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 10 Apr 2012 21:02:10 +0000 (14:02 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 10 Apr 2012 23:19:54 +0000 (16:19 -0700)
Qemu sends an 0x7f (DEL) via serial when you hit backspace, and readline
was ignoring it.  Not that readline matters much, but it'll now treat
the 0x7f like a backspace (\b, 0x8).

Note that \b and \x7f get sent directly to userspace, and it is up to
them to parse that.  This means that the KB (qemu and real world)
backspace is sending \b, real-world serial (at least my minicom) is
sending \b, but qemu serial sends \x7f.

Keymaps, terminal settings, and what programs expect are all huge pains
in the ass.

kern/arch/i686/console.c
kern/src/readline.c

index c3e114d..7cc09cd 100644 (file)
@@ -72,6 +72,7 @@ static void serial_put_char(struct cons_dev *cdev, uint8_t c)
         * expect (at least for brho) */
        switch (c & 0xff) {
                case '\b':
+               case 0x7f:
                        __serial_put_char(cdev->val, '\b');
                        __serial_put_char(cdev->val, (uint8_t)(' '));
                        __serial_put_char(cdev->val, '\b');
@@ -316,6 +317,7 @@ cga_putc(int c)
 
        switch (c & 0xff) {
        case '\b':
+       case 0x7f:
                if (crt_pos > 0) {
                        crt_pos--;
                        scrolling_crt_pos--;
index 4ced81d..5fd756e 100644 (file)
@@ -27,14 +27,13 @@ int readline(char *buf, size_t buf_l, const char *prompt, ...)
                        printk("read error: %e\n", c);  /* %e! */
                        retval = i;
                        break;
-               } else if (c >= ' ' && i < buf_l - 1) {
-                       if (echoing)
-                               cputchar(c);
-                       buf[i++] = c;
-               } else if (c == '\b' && i > 0) {
-                       if (echoing)
-                               cputchar(c);
-                       i--;
+               } else if (c == '\b' || c == 0x7f) {
+                       if (i > 0) {
+                               if (echoing)
+                                       cputchar(c);
+                               i--;
+                       }
+                       continue;
                } else if (c == '\n' || c == '\r') {
                        /* sending a \n regardless, since the serial port gives us a \r for
                         * carriage returns. */
@@ -44,6 +43,10 @@ int readline(char *buf, size_t buf_l, const char *prompt, ...)
                        buf[i++] = c;
                        retval =  i;
                        break;
+               } else if (c >= ' ' && i < buf_l - 1) {
+                       if (echoing)
+                               cputchar(c);
+                       buf[i++] = c;
                }
        }
        spin_unlock_irqsave(&readline_lock);