Change of vterm handling logic on backend chardev input event (#40)
authorLunaixsky <lunaixsky@qq.com>
Sun, 28 Jul 2024 21:50:17 +0000 (22:50 +0100)
committerGitHub <noreply@github.com>
Sun, 28 Jul 2024 21:50:17 +0000 (22:50 +0100)
* fix: term should not ignore underlying input event

* term should always respond the input event from underlying
  termport awared character device, by process the raw input
  buffer according one's lflags.ICANNO setting when the data
  is avaliable

* fix: race when parent get destroyed before children

* fix: orphan a process's children when it is about to destroy
* fix: devzero: mis-used offset cause segfault

* add support of setting serial io speed

* fix: truncate the overflowed input instead of running over.

* rewrite the line control

* rewrite the line control implementation to make it
  clean and less hacky.
* correct some POSIX compliance issue related to some
  control characters.
* fix issue where ANSI line control failed to echo the
  transformed special character
* add a sanity filter to sh to filter out any unprintable
  character.

* fix: make lxconsole work with vterm refactor

* fix: tdev_do_read do not check the linebuffer::sflag

* add a config term for lxconsole (vgacon)

* rename tty/tty.c to vga_rawtty.c for clarity

28 files changed:
lunaix-os/hal/char/LBuild
lunaix-os/hal/char/LConfig
lunaix-os/hal/char/devzero.c
lunaix-os/hal/char/lxconsole.c
lunaix-os/hal/char/serial.c
lunaix-os/hal/char/uart/16x50.h
lunaix-os/hal/char/uart/16x50_base.c
lunaix-os/hal/gfxa/vga/LBuild
lunaix-os/hal/gfxa/vga/vga_rawtty.c [moved from lunaix-os/kernel/tty/tty.c with 87% similarity]
lunaix-os/hal/term/LBuild
lunaix-os/hal/term/default_ops.c [new file with mode: 0644]
lunaix-os/hal/term/lcntls/ansi_cntl.c
lunaix-os/hal/term/lcntls/lcntl.c
lunaix-os/hal/term/lcntls/lcntl.h [new file with mode: 0644]
lunaix-os/hal/term/term.c
lunaix-os/hal/term/term_io.c
lunaix-os/includes/hal/serial.h
lunaix-os/includes/hal/term.h
lunaix-os/includes/lunaix/ds/rbuffer.h
lunaix-os/includes/usr/lunaix/serial.h
lunaix-os/kernel/LBuild
lunaix-os/kernel/ds/rbuffer.c
lunaix-os/kernel/kinit.c
lunaix-os/kernel/process/sched.c
lunaix-os/kernel/process/signal.c
lunaix-os/usr/init/init.c
lunaix-os/usr/libc/includes/termios.h
lunaix-os/usr/sh/sh.c

index 88b33102a513d175fe3cc31f6a4cbabc34a36e08..c00a394db99cc03e38437c9779176e51a795cb13 100644 (file)
@@ -4,5 +4,7 @@ sources([
     "devnull.c",
     "serial.c",
     "devzero.c",
     "devnull.c",
     "serial.c",
     "devzero.c",
-    "lxconsole.c",
-])
\ No newline at end of file
+])
+
+if config("vga_console"):
+    sources("lxconsole.c")
\ No newline at end of file
index 1b5ead4d72c1cd330781b3ab57e7b43b5db825ef..157e2d7ba1036cbada8f227ba29d33d2bd7b5f67 100644 (file)
@@ -5,3 +5,10 @@ def char_device():
     """ Controlling support of character devices """
 
     add_to_collection(hal)
     """ Controlling support of character devices """
 
     add_to_collection(hal)
+
+    @Term
+    def vga_console():
+        """ Enable VGA console device (text mode only) """
+
+        type(bool)
+        default(True)
index 9013a471f09c22234ff6984e105e700980f04eb1..c637a34d0e3e4c49e654a06a6b2bf548631383cd 100644 (file)
@@ -6,14 +6,14 @@
 static int
 __zero_rd_pg(struct device* dev, void* buf, size_t offset)
 {
 static int
 __zero_rd_pg(struct device* dev, void* buf, size_t offset)
 {
-    memset(&((u8_t*)buf)[offset], 0, PAGE_SIZE);
+    memset(buf, 0, PAGE_SIZE);
     return PAGE_SIZE;
 }
 
 static int
 __zero_rd(struct device* dev, void* buf, size_t offset, size_t len)
 {
     return PAGE_SIZE;
 }
 
 static int
 __zero_rd(struct device* dev, void* buf, size_t offset, size_t len)
 {
-    memset(&((u8_t*)buf)[offset], 0, len);
+    memset(buf, 0, len);
     return len;
 }
 
     return len;
 }
 
index 63876707cfe4ff87dc9523dbc133b71b082ce493..4922297aaeead97009b739b29131155b3973cf4e 100644 (file)
@@ -27,6 +27,7 @@
 
 struct console
 {
 
 struct console
 {
+    struct capability_meta* tp_cap;
     struct lx_timer* flush_timer;
     struct fifo_buf output;
     struct fifo_buf input;
     struct lx_timer* flush_timer;
     struct fifo_buf output;
     struct fifo_buf input;
@@ -90,8 +91,12 @@ __lxconsole_listener(struct input_device* dev)
     }
 
     fifo_putone(&lx_console.input, ttychr);
     }
 
     fifo_putone(&lx_console.input, ttychr);
-    pwake_all(&lx_reader);
 
 
+    struct termport_capability* tpcap;
+    tpcap = get_capability(lx_console.tp_cap, typeof(*tpcap));
+    term_notify_data_avaliable(tpcap);
+    
+    pwake_all(&lx_reader);
 done:
     return INPUT_EVT_NEXT;
 }
 done:
     return INPUT_EVT_NEXT;
 }
@@ -132,6 +137,14 @@ __tty_read(struct device* dev, void* buf, size_t offset, size_t len)
     return count + fifo_read(&console->input, buf + count, len - count);
 }
 
     return count + fifo_read(&console->input, buf + count, len - count);
 }
 
+int
+__tty_read_async(struct device* dev, void* buf, size_t offset, size_t len)
+{
+    struct console* console = (struct console*)dev->underlay;
+
+    return fifo_read(&console->input, buf, len);
+}
+
 size_t
 __find_next_line(size_t start)
 {
 size_t
 __find_next_line(size_t start)
 {
@@ -279,13 +292,23 @@ lxconsole_spawn_ttydev(struct device_def* devdef)
     tty_dev->ops.write_page = __tty_write_pg;
     tty_dev->ops.read = __tty_read;
     tty_dev->ops.read_page = __tty_read_pg;
     tty_dev->ops.write_page = __tty_write_pg;
     tty_dev->ops.read = __tty_read;
     tty_dev->ops.read_page = __tty_read_pg;
+    tty_dev->ops.write_async = __tty_write;
+    tty_dev->ops.read_async = __tty_read_async;
 
     waitq_init(&lx_reader);
     input_add_listener(__lxconsole_listener);
 
 
     waitq_init(&lx_reader);
     input_add_listener(__lxconsole_listener);
 
+    struct termport_capability* tp_cap;
+
+    tp_cap = new_capability(TERMPORT_CAP, struct termport_capability);
+    term_cap_set_operations(tp_cap, termport_default_ops);
+    
+    lx_console.tp_cap = cap_meta(tp_cap);
+    device_grant_capability(tty_dev, lx_console.tp_cap);
+
     register_device(tty_dev, &devdef->class, "vcon");
 
     register_device(tty_dev, &devdef->class, "vcon");
 
-    term_create(tty_dev, "FB");
+    term_create(tty_dev, "VCON");
 
     return 0;
 }
 
     return 0;
 }
@@ -295,5 +318,4 @@ static struct device_def lxconsole_def = {
     .class = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_BUILTIN),
     .init = lxconsole_spawn_ttydev
 };
     .class = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_BUILTIN),
     .init = lxconsole_spawn_ttydev
 };
-// FIXME
 EXPORT_DEVICE(lxconsole, &lxconsole_def, load_onboot);
\ No newline at end of file
 EXPORT_DEVICE(lxconsole, &lxconsole_def, load_onboot);
\ No newline at end of file
index 15a9c9ed098113e963c7af5c52af1284d9a45dd2..803fdb59287330a340760eb59c54b5c4287abcb5 100644 (file)
@@ -46,6 +46,10 @@ serial_end_recv(struct serial_dev* sdev)
     mark_device_done_read(sdev->dev);
 
     pwake_one(&sdev->wq_rxdone);
     mark_device_done_read(sdev->dev);
 
     pwake_one(&sdev->wq_rxdone);
+
+    struct termport_capability* tpcap;
+    tpcap = get_capability(sdev->tp_cap, typeof(*tpcap));
+    term_notify_data_avaliable(tpcap);
 }
 
 void
 }
 
 void
@@ -223,7 +227,18 @@ __serial_set_speed(struct device* dev, speed_t speed)
     struct serial_dev* sdev = serial_device(dev);
     lock_sdev(sdev);
 
     struct serial_dev* sdev = serial_device(dev);
     lock_sdev(sdev);
 
-    sdev_execmd(sdev, SERIO_SETBRDIV, speed);
+    sdev_execmd(sdev, SERIO_SETBRDRATE, speed);
+
+    unlock_sdev(sdev);
+}
+
+static void
+__serial_set_baseclk(struct device* dev, unsigned int base)
+{
+    struct serial_dev* sdev = serial_device(dev);
+    lock_sdev(sdev);
+
+    sdev_execmd(sdev, SERIO_SETBRDBASE, base);
 
     unlock_sdev(sdev);
 }
 
     unlock_sdev(sdev);
 }
@@ -241,10 +256,16 @@ __serial_set_cntrl_mode(struct device* dev, tcflag_t cflag)
 
 #define RXBUF_SIZE 512
 
 
 #define RXBUF_SIZE 512
 
+static struct termport_cap_ops tpcap_ops = {
+    .set_cntrl_mode = __serial_set_cntrl_mode,
+    .set_clkbase = __serial_set_baseclk,
+    .set_speed = __serial_set_speed
+};
+
 struct serial_dev*
 serial_create(struct devclass* class, char* if_ident)
 {
 struct serial_dev*
 serial_create(struct devclass* class, char* if_ident)
 {
-    struct serial_dev* sdev = valloc(sizeof(struct serial_dev));
+    struct serial_dev* sdev = vzalloc(sizeof(struct serial_dev));
     struct device* dev = device_allocseq(dev_meta(serial_cat), sdev);
     dev->ops.read = __serial_read;
     dev->ops.read_page = __serial_read_page;
     struct device* dev = device_allocseq(dev_meta(serial_cat), sdev);
     dev->ops.read = __serial_read;
     dev->ops.read_page = __serial_read_page;
@@ -260,8 +281,9 @@ serial_create(struct devclass* class, char* if_ident)
 
     struct termport_capability* tp_cap = 
         new_capability(TERMPORT_CAP, struct termport_capability);
 
     struct termport_capability* tp_cap = 
         new_capability(TERMPORT_CAP, struct termport_capability);
-    tp_cap->set_speed = __serial_set_speed;
-    tp_cap->set_cntrl_mode = __serial_set_cntrl_mode;
+    
+    term_cap_set_operations(tp_cap, &tpcap_ops);
+    sdev->tp_cap = cap_meta(tp_cap);
 
     waitq_init(&sdev->wq_rxdone);
     waitq_init(&sdev->wq_txdone);
 
     waitq_init(&sdev->wq_rxdone);
     waitq_init(&sdev->wq_txdone);
index addedfaa828de493b192aa2e507e742a89ea722c..40ebe94a421a7cda1fa47cb1d87ba9af175f6abb 100644 (file)
@@ -69,6 +69,7 @@ struct uart16550
     struct llist_header local_ports;
     struct serial_dev* sdev;
     ptr_t base_addr;
     struct llist_header local_ports;
     struct serial_dev* sdev;
     ptr_t base_addr;
+    unsigned int base_clk;
     int iv;
 
     struct
     int iv;
 
     struct
@@ -118,12 +119,12 @@ void
 uart_free(struct uart16550*);
 
 static inline int
 uart_free(struct uart16550*);
 
 static inline int
-uart_baud_divisor(struct uart16550* uart, int div)
+uart_baud_divisor(struct uart16550* uart, unsigned int div)
 {
     u32_t rlc = uart->read_reg(uart, UART_rLC);
 
     uart->write_reg(uart, UART_rLC, UART_rLC_DLAB | rlc);
 {
     u32_t rlc = uart->read_reg(uart, UART_rLC);
 
     uart->write_reg(uart, UART_rLC, UART_rLC_DLAB | rlc);
-    u8_t ls = (div & 0xff), ms = (div & 0xff00) >> 8;
+    u8_t ls = (div & 0x00ff), ms = (div & 0xff00) >> 8;
 
     uart->write_reg(uart, UART_rLS, ls);
     uart->write_reg(uart, UART_rMS, ms);
 
     uart->write_reg(uart, UART_rLS, ls);
     uart->write_reg(uart, UART_rMS, ms);
index 6e94b847fd4acfd82a75234d0022cb0b4a0bf044..8b3930f29779973071d45facf65f4a56ece92f76 100644 (file)
@@ -16,6 +16,7 @@ uart_alloc(ptr_t base_addr)
     uart->cntl_save.rie = 0;
 
     uart->base_addr = base_addr;
     uart->cntl_save.rie = 0;
 
     uart->base_addr = base_addr;
+    uart->base_clk  = 115200U;
     return uart;
 }
 
     return uart;
 }
 
@@ -69,9 +70,29 @@ uart_general_exec_cmd(struct serial_dev* sdev, u32_t req, va_list args)
         case SERIO_RXDA:
             uart_clrie(uart);
             break;
         case SERIO_RXDA:
             uart_clrie(uart);
             break;
-        case SERIO_SETBRDIV:
-            // TODO
-            break;
+        case SERIO_SETBRDRATE:
+            {
+                unsigned int div, rate;
+
+                rate = va_arg(args, speed_t);
+                if (!rate) {
+                    return EINVAL;
+                }
+
+                div  = uart->base_clk / va_arg(args, speed_t);
+                uart_baud_divisor(uart, div);
+                break;
+            }
+        case SERIO_SETBRDBASE:
+            {
+                int clk = va_arg(args, unsigned int);
+                if (!clk) {
+                    return EINVAL;
+                }
+                
+                uart->base_clk = clk;
+                break;
+            }
         case SERIO_SETCNTRLMODE:
             uart_set_control_mode(uart, va_arg(args, tcflag_t));
             break;
         case SERIO_SETCNTRLMODE:
             uart_set_control_mode(uart, va_arg(args, tcflag_t));
             break;
index b05da8cdcef89d9832d43dfba5832b69e9a5008d..dc8991a04f73ed935e3405d8d191d7df1159f555 100644 (file)
@@ -3,5 +3,6 @@ sources([
     "vga_gfxm_ops.c",
     "vga.c",
     "vga_mmio_ops.c",
     "vga_gfxm_ops.c",
     "vga.c",
     "vga_mmio_ops.c",
-    "vga_pci.c"
+    "vga_pci.c",
+    "vga_rawtty.c",
 ])
\ No newline at end of file
 ])
\ No newline at end of file
similarity index 87%
rename from lunaix-os/kernel/tty/tty.c
rename to lunaix-os/hal/gfxa/vga/vga_rawtty.c
index e5a913f2c97256f76203c1ae29fa808c76596413..21fcd82aa2f9a55568740dd7e4eb65c998fa19d1 100644 (file)
@@ -2,6 +2,9 @@
 #include <lunaix/spike.h>
 #include <lunaix/tty/tty.h>
 #include <stdint.h>
 #include <lunaix/spike.h>
 #include <lunaix/tty/tty.h>
 #include <stdint.h>
+#include <lunaix/owloysius.h>
+#include <lunaix/mm/pagetable.h>
+#include <lunaix/mm/mmio.h>
 
 #include <sys/port_io.h>
 
 
 #include <sys/port_io.h>
 
@@ -113,4 +116,13 @@ tty_put_str_at(char* str, int x, int y)
         }
         str++;
     }
         }
         str++;
     }
-}
\ No newline at end of file
+}
+
+static void
+vga_rawtty_init()
+{
+    // FIXME we should get rid of it at some point
+    tty_init((void*)ioremap(0xB8000, PAGE_SIZE));
+    tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_BLACK);
+}
+owloysius_fetch_init(vga_rawtty_init, on_earlyboot);
\ No newline at end of file
index 9325917bb9a6b006fc5f5e5d3cb5d5be95a94037..ea5b2c396ea6c616f5ee240319fa0d5a72968e53 100644 (file)
@@ -2,6 +2,7 @@ sources([
     "term.c",
     "console.c",
     "term_io.c",
     "term.c",
     "console.c",
     "term_io.c",
+    "default_ops.c",
     "lcntls/ansi_cntl.c",
     "lcntls/lcntl.c",
 ])
\ No newline at end of file
     "lcntls/ansi_cntl.c",
     "lcntls/lcntl.c",
 ])
\ No newline at end of file
diff --git a/lunaix-os/hal/term/default_ops.c b/lunaix-os/hal/term/default_ops.c
new file mode 100644 (file)
index 0000000..fea8355
--- /dev/null
@@ -0,0 +1,25 @@
+#include <hal/term.h>
+
+static void
+__tpcap_default_set_speed(struct device* dev, speed_t speed)
+{
+    
+}
+
+static void
+__tpcap_default_set_baseclk(struct device* dev, unsigned int base)
+{
+    
+}
+
+static void
+__tpcap_default_set_cntrl_mode(struct device* dev, tcflag_t cflag)
+{
+    
+}
+
+struct termport_cap_ops default_termport_cap_ops = {
+    .set_cntrl_mode = __tpcap_default_set_cntrl_mode,
+    .set_clkbase = __tpcap_default_set_baseclk,
+    .set_speed = __tpcap_default_set_speed
+};
\ No newline at end of file
index 778eb4b5d24d931a79f3ae51beb47bca097b6a64..bc66139cb98abd4c67b9e99f9e0d83909142d56b 100644 (file)
@@ -9,25 +9,18 @@
  * @copyright Copyright (c) 2023
  *
  */
  * @copyright Copyright (c) 2023
  *
  */
-#include <hal/term.h>
+#include "lcntl.h"
 #include <usr/lunaix/term.h>
 
 #define CTRL_MNEMO(chr) (chr - 'A' + 1)
 
 #include <usr/lunaix/term.h>
 
 #define CTRL_MNEMO(chr) (chr - 'A' + 1)
 
-static inline int
-__ansi_actcontrol(struct term* termdev, struct linebuffer* lbuf, char chr)
+int
+__ansi_actcontrol(struct lcntl_state* state, char chr)
 {
 {
-    struct rbuffer* cooked = lbuf->next;
-    switch (chr) {
-        default:
-            if ((int)chr < 32) {
-                rbuffer_put(cooked, '^');
-                return rbuffer_put(cooked, chr += 64);
-            }
-            break;
+    if (chr < 32 && chr != '\n') {
+        lcntl_put_char(state, '^');
+        return lcntl_put_char(state, chr += 64);
     }
 
     }
 
-    return rbuffer_put_nof(cooked, chr);
+    return lcntl_put_char(state, chr);
 }
 }
-
-struct term_lcntl ansi_line_controller = {.process_and_put = __ansi_actcontrol};
\ No newline at end of file
index db146e1d84de8f915469dd184a658e47d2276ccf..fb855cc6d32079a0235d9eddd13b971fe5abb9f5 100644 (file)
 #include <hal/term.h>
 #include <usr/lunaix/term.h>
 
 #include <hal/term.h>
 #include <usr/lunaix/term.h>
 
+#include "lcntl.h"
+
 #include <lunaix/process.h>
 #include <lunaix/spike.h>
 
 static inline void
 #include <lunaix/process.h>
 #include <lunaix/spike.h>
 
 static inline void
-raise_sig(struct term* at_term, struct linebuffer* lbuf, int sig)
+init_lcntl_state(struct lcntl_state* state, 
+                 struct term* tdev, enum lcntl_dir direction)
 {
 {
-    term_sendsig(at_term, sig);
-    lbuf->sflags |= LSTATE_SIGRAISE;
+    *state = (struct lcntl_state) {
+        .tdev = tdev,
+        ._lf  = tdev->lflags,
+        ._cf  = tdev->cflags,
+        .direction = direction,
+        .echobuf = tdev->line_out.current,
+    };
+
+    struct linebuffer* lb;
+    if (direction == INBOUND) {
+        state->_if = tdev->iflags;
+        lb = &tdev->line_in;
+    }
+    else {
+        state->_of = tdev->oflags;
+        lb = &tdev->line_out;
+    }
+
+    state->inbuf = lb->current;
+    state->outbuf = lb->next;
+    state->active_line = lb;
 }
 
 }
 
-static inline int must_inline optimize("-fipa-cp-clone")
-lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out)
+static inline void
+raise_sig(struct lcntl_state* state, int sig)
 {
 {
-    struct rbuffer* raw = lbuf->current;
-    struct rbuffer* cooked = lbuf->next;
-    struct rbuffer* output = tdev->line_out.current;
+    term_sendsig(state->tdev, sig);
+    lcntl_raise_line_event(state, LEVT_SIGRAISE);
+}
 
 
-    int i = 0, _if = tdev->iflags & -!out, _of = tdev->oflags & -!!out,
-        _lf = tdev->lflags;
-    int allow_more = 1, latest_eol = cooked->ptr;
-    char c;
+static inline char
+__remap_character(struct lcntl_state* state, char c)
+{
+    if (c == '\r') {
+        if ((state->_if & _ICRNL) || (state->_of & _OCRNL)) {
+            return '\n';
+        }
+    } 
+    else if (c == '\n') {
+        if ((state->_if & _INLCR) || (state->_of & (_ONLRET))) {
+            return '\r';
+        }
+    }
+    else if ('a' <= c && c <= 'z') {
+        if ((state->_if & _IUCLC)) {
+            return c | 0b100000;
+        } else if ((state->_of & _OLCUC)) {
+            return c & ~0b100000;
+        }
+    }
+
+    return c;
+}
 
 
-    int (*lcntl_slave_put)(struct term*, struct linebuffer*, char) =
-        tdev->lcntl->process_and_put;
+static inline void
+lcntl_echo_char(struct lcntl_state* state, char c)
+{
+    rbuffer_put(state->echobuf, c);
+}
+
+int
+__ansi_actcontrol(struct lcntl_state* state, char chr);
+
+static inline int must_inline
+lcntl_transform_seq(struct lcntl_state* state)
+{
+    struct term* tdev = state->tdev;
+    char c;
+    int i = 0;
+    bool full = false;
 
 #define EOL tdev->cc[_VEOL]
 #define EOF tdev->cc[_VEOF]
 
 #define EOL tdev->cc[_VEOL]
 #define EOF tdev->cc[_VEOF]
@@ -44,121 +99,115 @@ lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out)
 #define QUIT tdev->cc[_VQUIT]
 #define SUSP tdev->cc[_VSUSP]
 
 #define QUIT tdev->cc[_VQUIT]
 #define SUSP tdev->cc[_VSUSP]
 
-#define putc_safe(rb, chr)                  \
-    ({                                      \
-        if (!rbuffer_put_nof(rb, chr)) {    \
-            break;                          \
-        }                                   \
-    })
+    while (!lcntl_test_flag(state, LCNTLF_STOP)) 
+    {
+        lcntl_unset_flag(state, LCNTLF_SPECIAL_CHAR);
 
 
-    if (!out) {
-        // Keep all cc's (except VMIN & VTIME) up to L2 cache.
-        for (size_t i = 0; i < _VMIN; i++) {
-            prefetch_rd(&tdev->cc[i], 2);
+        if (!rbuffer_get(state->inbuf, &c)) {
+            break;
         }
         }
-    }
 
 
-    while (allow_more && rbuffer_get(raw, &c)) {
-
-        if (c == '\r' && ((_if & _ICRNL) || (_of & _OCRNL))) {
-            c = '\n';
-        } else if (c == '\n') {
-            if ((_if & _INLCR) || (_of & (_ONLRET))) {
-                c = '\r';
-            }
-        }
+        c = __remap_character(state, c);
 
         if (c == '\0') {
 
         if (c == '\0') {
-            if ((_if & _IGNBRK)) {
+            if ((state->_if & _IGNBRK)) {
                 continue;
             }
 
                 continue;
             }
 
-            if ((_if & _BRKINT)) {
-                raise_sig(tdev, lbuf, SIGINT);
+            if ((state->_if & _BRKINT)) {
+                raise_sig(state, SIGINT);
                 break;
             }
         }
 
                 break;
             }
         }
 
-        if ('a' <= c && c <= 'z') {
-            if ((_if & _IUCLC)) {
-                c = c | 0b100000;
-            } else if ((_of & _OLCUC)) {
-                c = c & ~0b100000;
-            }
-        }
-
-        if (out) {
+        if (lcntl_outbound(state)) {
             goto do_out;
         }
 
         if (c == '\n') {
             goto do_out;
         }
 
         if (c == '\n') {
-            latest_eol = cooked->ptr + 1;
-            if ((_lf & _ECHONL)) {
-                rbuffer_put(output, c);
+            if (lcntl_check_echo(state, _ECHONL)) {
+                lcntl_echo_char(state, c);
             }
         }
 
         // For input procesing
 
             }
         }
 
         // For input procesing
 
+        lcntl_set_flag(state, LCNTLF_SPECIAL_CHAR);
+
         if (c == '\n' || c == EOL) {
         if (c == '\n' || c == EOL) {
-            lbuf->sflags |= LSTATE_EOL;
-        } else if (c == EOF) {
-            lbuf->sflags |= LSTATE_EOF;
-            rbuffer_clear(raw);
-            break;
-        } else if (c == INTR) {
-            raise_sig(tdev, lbuf, SIGINT);
-        } else if (c == QUIT) {
-            raise_sig(tdev, lbuf, SIGKILL);
-            break;
-        } else if (c == SUSP) {
-            raise_sig(tdev, lbuf, SIGSTOP);
-        } else if (c == ERASE) {
-            if (!rbuffer_erase(cooked))
-                continue;
-        } else if (c == KILL) {
-            // TODO shrink the rbuffer
-        } else {
-            goto keep;
+            lcntl_raise_line_event(state, LEVT_EOL);
         }
         }
-
-        if ((_lf & _ECHOE) && c == ERASE) {
-            rbuffer_put(output, '\x8'); 
-            rbuffer_put(output, ' '); 
-            rbuffer_put(output, '\x8'); 
+        else if (c == EOF) {
+            lcntl_raise_line_event(state, LEVT_EOF);
+            lcntl_set_flag(state, LCNTLF_CLEAR_INBUF);
+            lcntl_set_flag(state, LCNTLF_STOP);
         }
         }
-        if ((_lf & _ECHOK) && c == KILL) {
-            rbuffer_put(output, c);
-            rbuffer_put(output, '\n');
+        else if (c == INTR) {
+            raise_sig(state, SIGINT);
+            lcntl_set_flag(state, LCNTLF_CLEAR_OUTBUF);
         }
         }
-
-        continue;
-
-    keep:
-        if ((_lf & _ECHO)) {
-            rbuffer_put(output, c);
+        else if (c == QUIT) {
+            raise_sig(state, SIGKILL);
+            lcntl_set_flag(state, LCNTLF_CLEAR_OUTBUF);
+            lcntl_set_flag(state, LCNTLF_STOP);
+        }
+        else if (c == SUSP) {
+            raise_sig(state, SIGSTOP);
+        }
+        else if (c == ERASE) {
+            if (rbuffer_erase(state->outbuf) && 
+                lcntl_check_echo(state, _ECHOE)) 
+            {
+                lcntl_echo_char(state, '\x8'); 
+                lcntl_echo_char(state, ' '); 
+                lcntl_echo_char(state, '\x8');
+            }
+            continue;
+        }
+        else if (c == KILL) {
+            lcntl_set_flag(state, LCNTLF_CLEAR_OUTBUF);
+        }
+        else {
+            lcntl_unset_flag(state, LCNTLF_SPECIAL_CHAR);
         }
 
         }
 
-        goto put_char;
+        if (lcntl_check_echo(state, _ECHOK) && c == KILL) {
+            lcntl_echo_char(state, c);
+            lcntl_echo_char(state, '\n');
+        }
 
     do_out:
 
     do_out:
-        if (c == '\n' && (_of & _ONLCR)) {
-            putc_safe(cooked, '\r');
+        if (c == '\n' && (state->_of & _ONLCR)) {
+            full = !rbuffer_put_nof(state->outbuf, '\r');
         }
 
         }
 
-    put_char:
-        if (!out && (_lf & _IEXTEN) && lcntl_slave_put) {
-            allow_more = lcntl_slave_put(tdev, lbuf, c);
-        } else {
-            allow_more = rbuffer_put_nof(cooked, c);
+        if (!full) {
+            if (lcntl_inbound(state) && (state->_lf & _IEXTEN)) {
+                full = !__ansi_actcontrol(state, c);
+            }
+            else {
+                full = !lcntl_put_char(state, c);
+            }
+        }
+
+        if (lcntl_test_flag(state, LCNTLF_CLEAR_INBUF)) {
+            rbuffer_clear(state->inbuf);
+            lcntl_unset_flag(state, LCNTLF_CLEAR_INBUF);
+        }
+        
+        if (lcntl_test_flag(state, LCNTLF_CLEAR_OUTBUF)) {
+            rbuffer_clear(state->outbuf);
+            lcntl_unset_flag(state, LCNTLF_CLEAR_OUTBUF);
         }
         }
+
+        i++;
     }
 
     }
 
-    if (!out && !rbuffer_empty(output) && !(_lf & _NOFLSH)) {
+    if (state->direction != OUTBOUND && !(state->_lf & _NOFLSH)) {
         term_flush(tdev);
     }
 
         term_flush(tdev);
     }
 
-    line_flip(lbuf);
+    line_flip(state->active_line);
 
     return i;
 }
 
     return i;
 }
@@ -166,11 +215,31 @@ lcntl_transform_seq(struct term* tdev, struct linebuffer* lbuf, bool out)
 int
 lcntl_transform_inseq(struct term* tdev)
 {
 int
 lcntl_transform_inseq(struct term* tdev)
 {
-    return lcntl_transform_seq(tdev, &tdev->line_in, false);
+    struct lcntl_state state;
+
+    init_lcntl_state(&state, tdev, INBOUND);
+    return lcntl_transform_seq(&state);
 }
 
 int
 lcntl_transform_outseq(struct term* tdev)
 {
 }
 
 int
 lcntl_transform_outseq(struct term* tdev)
 {
-    return lcntl_transform_seq(tdev, &tdev->line_out, true);
+    struct lcntl_state state;
+
+    init_lcntl_state(&state, tdev, OUTBOUND);
+    return lcntl_transform_seq(&state);
+}
+
+int 
+lcntl_put_char(struct lcntl_state* state, char c)
+{
+    if (lcntl_check_echo(state, _ECHO)) {
+        lcntl_echo_char(state, c);
+    }
+
+    if (!lcntl_test_flag(state, LCNTLF_SPECIAL_CHAR)) {
+        return rbuffer_put_nof(state->outbuf, c);
+    }
+
+    return 1;
 }
\ No newline at end of file
 }
\ No newline at end of file
diff --git a/lunaix-os/hal/term/lcntls/lcntl.h b/lunaix-os/hal/term/lcntls/lcntl.h
new file mode 100644 (file)
index 0000000..f867fa1
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef __LUNAIX_LCNTL_H
+#define __LUNAIX_LCNTL_H
+
+#include <hal/term.h>
+
+#define LCNTLF_SPECIAL_CHAR      0b000001
+#define LCNTLF_CLEAR_INBUF       0b000010
+#define LCNTLF_CLEAR_OUTBUF      0b000100
+#define LCNTLF_STOP              0b001000
+
+enum lcntl_dir {
+    INBOUND,
+    OUTBOUND
+};
+
+struct lcntl_state {
+    struct term* tdev;
+    tcflag_t _if;   // iflags
+    tcflag_t _of;   // oflags
+    tcflag_t _lf;   // local flags
+    tcflag_t _cf;   // control flags
+    tcflag_t _sf;   // state flags
+    enum lcntl_dir direction;
+
+    struct linebuffer* active_line;
+    struct rbuffer* inbuf;
+    struct rbuffer* outbuf;
+    struct rbuffer* echobuf;
+};
+
+int  
+lcntl_put_char(struct lcntl_state* state, char c);
+
+static inline void
+lcntl_set_flag(struct lcntl_state* state, int flags)
+{
+    state->_sf |= flags;
+}
+
+static inline void
+lcntl_raise_line_event(struct lcntl_state* state, int event)
+{
+    state->active_line->sflags |= event;
+}
+
+static inline void
+lcntl_unset_flag(struct lcntl_state* state, int flags)
+{
+    state->_sf &= ~flags;
+}
+
+static inline bool
+lcntl_test_flag(struct lcntl_state* state, int flags)
+{
+    return !!(state->_sf & flags);
+}
+
+static inline bool
+lcntl_outbound(struct lcntl_state* state)
+{
+    return (state->direction == OUTBOUND);
+}
+
+static inline bool
+lcntl_inbound(struct lcntl_state* state)
+{
+    return (state->direction == INBOUND);
+}
+
+static inline bool
+lcntl_check_echo(struct lcntl_state* state, int echo_type)
+{
+    return lcntl_inbound(state) && (state->_lf & echo_type);
+}
+
+
+#endif /* __LUNAIX_LCNTL_H */
index 3db875903761375fd575a265662659279fd9d4df..9f65d386beb1a1b3e1cd4f3b4b7b066111f5a9d0 100644 (file)
@@ -8,15 +8,11 @@
 
 #include <usr/lunaix/ioctl_defs.h>
 
 
 #include <usr/lunaix/ioctl_defs.h>
 
-#define ANSI_LCNTL 0
 #define termdev(dev) ((struct term*)(dev)->underlay)
 
 #define termdev(dev) ((struct term*)(dev)->underlay)
 
-extern struct term_lcntl ansi_line_controller;
-static struct term_lcntl* line_controls[] = {[ANSI_LCNTL] =
-                                                 &ansi_line_controller};
 #define LCNTL_TABLE_LEN (sizeof(line_controls) / sizeof(struct term_lcntl*))
 
 #define LCNTL_TABLE_LEN (sizeof(line_controls) / sizeof(struct term_lcntl*))
 
-static struct devclass termdev = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_VTERM);
+static struct devclass termdev_class = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_VTERM);
 
 struct device* sysconsole = NULL;
 
 
 struct device* sysconsole = NULL;
 
@@ -85,7 +81,9 @@ term_exec_cmd(struct device* dev, u32_t req, va_list args)
             tios->c_baud = term->iospeed;
         } break;
         case TDEV_TCSETATTR: {
             tios->c_baud = term->iospeed;
         } break;
         case TDEV_TCSETATTR: {
+            struct termport_cap_ops* cap_ops;
             struct termios* tios = va_arg(args, struct termios*);
             struct termios* tios = va_arg(args, struct termios*);
+
             term->iflags = tios->c_iflag;
             term->oflags = tios->c_oflag;
             term->lflags = tios->c_lflag;
             term->iflags = tios->c_iflag;
             term->oflags = tios->c_oflag;
             term->lflags = tios->c_lflag;
@@ -98,14 +96,16 @@ term_exec_cmd(struct device* dev, u32_t req, va_list args)
                 goto done;
             }
 
                 goto done;
             }
 
+            cap_ops = term->tp_cap->cap_ops;
+
             if (tios->c_baud != term->iospeed) {
                 term->iospeed = tios->c_baud;
 
             if (tios->c_baud != term->iospeed) {
                 term->iospeed = tios->c_baud;
 
-                term->tp_cap->set_speed(term->chdev, tios->c_baud);
+                cap_ops->set_speed(term->chdev, tios->c_baud);
             }
 
             if (old_cf != tios->c_cflag) {
             }
 
             if (old_cf != tios->c_cflag) {
-                term->tp_cap->set_cntrl_mode(term->chdev, tios->c_cflag);
+                cap_ops->set_cntrl_mode(term->chdev, tios->c_cflag);
             }
         } break;
         default:
             }
         } break;
         default:
@@ -146,16 +146,14 @@ tdev_do_read(struct device* dev, void* buf, off_t fpos, size_t len)
     lbuf_ref_t current = ref_current(&tdev->line_in);
     bool cont = true;
     size_t rdsz = 0;
     lbuf_ref_t current = ref_current(&tdev->line_in);
     bool cont = true;
     size_t rdsz = 0;
-    while (cont && rdsz < len) {
-        if (rbuffer_empty(deref(current))) {
-            tdev->line_in.sflags = 0;
-            cont = term_read(tdev);
-        }
 
 
+    while (cont && rdsz < len) {
+        cont = term_read(tdev);
         rdsz += rbuffer_gets(
             deref(current), &((char*)buf)[rdsz], len - rdsz);
     }
         rdsz += rbuffer_gets(
             deref(current), &((char*)buf)[rdsz], len - rdsz);
     }
-
+    
+    tdev->line_in.sflags = 0;
     return rdsz;
 }
 
     return rdsz;
 }
 
@@ -167,6 +165,7 @@ load_default_setting(struct term* tdev)
     tdev->lflags = _ICANON | _IEXTEN | _ISIG | _ECHO | _ECHOE | _ECHONL;
     tdev->iflags = _ICRNL | _IGNBRK;
     tdev->oflags = _ONLCR | _OPOST;
     tdev->lflags = _ICANON | _IEXTEN | _ISIG | _ECHO | _ECHOE | _ECHONL;
     tdev->iflags = _ICRNL | _IGNBRK;
     tdev->oflags = _ONLCR | _OPOST;
+    tdev->iospeed = _B9600;
     memcpy(tdev->cc, default_cc, _NCCS * sizeof(cc_t));
 }
 
     memcpy(tdev->cc, default_cc, _NCCS * sizeof(cc_t));
 }
 
@@ -181,38 +180,46 @@ alloc_term_buffer(struct term* terminal, size_t sz_hlf)
 struct term*
 term_create(struct device* chardev, char* suffix)
 {
 struct term*
 term_create(struct device* chardev, char* suffix)
 {
-    struct term* terminal = vzalloc(sizeof(struct term));
+    struct term* terminal;
+    struct device* tdev;
+    struct capability_meta* termport_cap;
+    struct capability_meta* tios_cap;
 
 
+    terminal = vzalloc(sizeof(struct term));
     if (!terminal) {
         return NULL;
     }
 
     if (!terminal) {
         return NULL;
     }
 
-    terminal->dev = device_allocseq(NULL, terminal);
+    tdev = device_allocseq(NULL, terminal);
+    terminal->dev = tdev;
     terminal->chdev = chardev;
 
     terminal->chdev = chardev;
 
-    terminal->dev->ops.read = tdev_do_read;
-    terminal->dev->ops.write = tdev_do_write;
-    terminal->dev->ops.exec_cmd = term_exec_cmd;
+    tdev->ops.read = tdev_do_read;
+    tdev->ops.write = tdev_do_write;
+    tdev->ops.exec_cmd = term_exec_cmd;
 
 
-    // TODO choice of lcntl can be flexible
-    terminal->lcntl = line_controls[ANSI_LCNTL];
+    waitq_init(&terminal->line_in_event);
 
     alloc_term_buffer(terminal, 1024);
 
     if (chardev) {
         int cdev_var = DEV_VAR_FROM(chardev->ident.unique);
 
     alloc_term_buffer(terminal, 1024);
 
     if (chardev) {
         int cdev_var = DEV_VAR_FROM(chardev->ident.unique);
-        register_device(terminal->dev, &termdev, "tty%s%d", suffix, cdev_var);
+        register_device(tdev, &termdev_class, "tty%s%d", suffix, cdev_var);
     } else {
     } else {
-        register_device(terminal->dev, &termdev, "tty%d", termdev.variant++);
+        register_device(tdev, &termdev_class, "tty%d", termdev_class.variant++);
     }
 
     }
 
-    struct capability_meta* termport_cap = device_get_capability(chardev, TERMPORT_CAP);
+    termport_cap = device_get_capability(chardev, TERMPORT_CAP);
     if (termport_cap) {
     if (termport_cap) {
-        terminal->tp_cap = get_capability(termport_cap, struct termport_capability);
+        terminal->tp_cap = 
+            get_capability(termport_cap, struct termport_capability);
+        
+        assert(terminal->tp_cap->cap_ops);
+        terminal->tp_cap->term = terminal;
     }
 
     }
 
-    struct capability_meta* term_cap = new_capability_marker(TERMIOS_CAP);
-    device_grant_capability(terminal->dev, term_cap);
+    tios_cap = new_capability_marker(TERMIOS_CAP);
+    device_grant_capability(tdev, tios_cap);
 
     load_default_setting(terminal);
 
 
     load_default_setting(terminal);
 
@@ -253,6 +260,6 @@ void
 term_sendsig(struct term* tdev, int signal)
 {
     if ((tdev->lflags & _ISIG)) {
 term_sendsig(struct term* tdev, int signal)
 {
     if ((tdev->lflags & _ISIG)) {
-        proc_setsignal(get_process(tdev->fggrp), signal);
+        signal_send(-tdev->fggrp, signal);
     }
 }
\ No newline at end of file
     }
 }
\ No newline at end of file
index b1115c83c9a4cd5e22cfb119ddd0548e926b6806..cb93c4e216bed9af54a91f93a7b6ad0c452db387 100644 (file)
@@ -5,77 +5,45 @@
 
 #include <usr/lunaix/term.h>
 
 
 #include <usr/lunaix/term.h>
 
-#define ONBREAK (LSTATE_EOF | LSTATE_SIGRAISE)
-#define ONSTOP (LSTATE_SIGRAISE | LSTATE_EOL | LSTATE_EOF)
+#define ONBREAK (LEVT_EOF | LEVT_SIGRAISE)
+#define ONSTOP (LEVT_SIGRAISE | LEVT_EOL | LEVT_EOF)
 
 static int
 do_read_raw(struct term* tdev)
 {
 
 static int
 do_read_raw(struct term* tdev)
 {
-    struct device* chdev = tdev->chdev;
-
-    struct linebuffer* line_in = &tdev->line_in;
-    size_t max_lb_sz = line_in->sz_hlf;
-
-    line_flip(line_in);
-
-    char* inbuffer = line_in->current->buffer;
-    size_t min = tdev->cc[_VMIN] - 1;
-    size_t sz = chdev->ops.read_async(chdev, inbuffer, 0, max_lb_sz);
-    time_t t = clock_systime(), dt = 0;
-    time_t expr = (tdev->cc[_VTIME] * 100) - 1;
-
+    struct linebuffer* line_in;
+    lbuf_ref_t current_buf;
+    size_t min, sz = 0;
+    time_t t, expr, dt = 0;
+    
+    line_in = &tdev->line_in;
+    current_buf = ref_current(line_in);
+
+    min = tdev->cc[_VMIN] - 1;
+    t = clock_systime();
+    expr = (tdev->cc[_VTIME] * 100) - 1;
+
+    min = MIN(min, (size_t)line_in->sz_hlf);
     while (sz <= min && dt <= expr) {
         // XXX should we held the device lock while we are waiting?
         sched_pass();
         dt = clock_systime() - t;
         t += dt;
 
     while (sz <= min && dt <= expr) {
         // XXX should we held the device lock while we are waiting?
         sched_pass();
         dt = clock_systime() - t;
         t += dt;
 
-        max_lb_sz -= sz;
-
-        // TODO pass a flags to read to indicate it is non blocking ops
-        sz += chdev->ops.read_async(chdev, &inbuffer[sz], 0, max_lb_sz);
+        sz = deref(current_buf)->len;
     }
 
     }
 
-    rbuffer_puts(line_in->next, inbuffer, sz);
-    line_flip(line_in);
-
     return 0;
 }
 
     return 0;
 }
 
-static int
-do_read_raw_canno(struct term* tdev)
-{
-    struct device* chdev = tdev->chdev;
-    struct linebuffer* line_in = &tdev->line_in;
-    struct rbuffer* current_buf = line_in->current;
-    int sz = chdev->ops.read(chdev, current_buf->buffer, 0, line_in->sz_hlf);
-
-    current_buf->ptr = sz;
-    current_buf->len = sz;
-
-    return sz;
-}
-
-static int
-term_read_noncano(struct term* tdev)
-{
-    struct device* chdev = tdev->chdev;
-    return do_read_raw(tdev);
-}
-
-static int
+static inline int
 term_read_cano(struct term* tdev)
 {
 term_read_cano(struct term* tdev)
 {
-    struct device* chdev = tdev->chdev;
-    struct linebuffer* line_in = &tdev->line_in;
-    int size = 0;
+    struct linebuffer* line_in;
 
 
+    line_in = &tdev->line_in;
     while (!(line_in->sflags & ONSTOP)) {
     while (!(line_in->sflags & ONSTOP)) {
-        // move all hold-out content to 'next' buffer
-        line_flip(line_in);
-
-        size += do_read_raw_canno(tdev);
-        lcntl_transform_inseq(tdev);
+        pwait(&tdev->line_in_event);
     }
 
     return 0;
     }
 
     return 0;
@@ -87,18 +55,22 @@ term_read(struct term* tdev)
     if ((tdev->lflags & _ICANON)) {
         return term_read_cano(tdev);
     }
     if ((tdev->lflags & _ICANON)) {
         return term_read_cano(tdev);
     }
-    return term_read_noncano(tdev);
+
+    return do_read_raw(tdev);
 }
 
 int
 term_flush(struct term* tdev)
 {
 }
 
 int
 term_flush(struct term* tdev)
 {
+    struct device* chardev;
     struct linebuffer* line_out = &tdev->line_out;
     char* xmit_buf = tdev->scratch_pad;
     lbuf_ref_t current_ref = ref_current(line_out);
     struct linebuffer* line_out = &tdev->line_out;
     char* xmit_buf = tdev->scratch_pad;
     lbuf_ref_t current_ref = ref_current(line_out);
-
+    
     int count = 0;
 
     int count = 0;
 
+    chardev = tdev->chdev;
+
     while (!rbuffer_empty(deref(current_ref))) {
         if ((tdev->oflags & _OPOST)) {
             lcntl_transform_outseq(tdev);
     while (!rbuffer_empty(deref(current_ref))) {
         if ((tdev->oflags & _OPOST)) {
             lcntl_transform_outseq(tdev);
@@ -111,7 +83,7 @@ term_flush(struct term* tdev)
         off_t off = 0;
         int ret = 0;
         while (xmit_len && ret >= 0) {
         off_t off = 0;
         int ret = 0;
         while (xmit_len && ret >= 0) {
-            ret = tdev->chdev->ops.write(tdev->chdev, &xmit_buf[off], 0, xmit_len);
+            ret = chardev->ops.write(chardev, &xmit_buf[off], 0, xmit_len);
             xmit_len -= ret;
             off += ret;
             count += ret;
             xmit_len -= ret;
             off += ret;
             count += ret;
@@ -124,4 +96,34 @@ term_flush(struct term* tdev)
     }
 
     return count;
     }
 
     return count;
+}
+
+void
+term_notify_data_avaliable(struct termport_capability* cap)
+{
+    struct term* term;
+    struct device* term_chrdev;
+    struct linebuffer* line_in;
+    lbuf_ref_t current_ref;
+    char* buf;
+    int sz;
+
+    term = cap->term;
+    term_chrdev = term->chdev;
+    line_in = &term->line_in;
+    current_ref = ref_current(line_in);
+    
+    // make room for current buf
+    line_flip(line_in);
+    buf = deref(current_ref)->buffer;
+
+    sz = term_chrdev->ops.read_async(term_chrdev, buf, 0, line_in->sz_hlf);
+    rbuffer_setcontent(deref(current_ref), sz);
+
+    if ((term->lflags & _ICANON)) {
+        lcntl_transform_inseq(term);
+        // write all processed to next, and flip back to current
+    }
+
+    pwake_all(&term->line_in_event);
 }
\ No newline at end of file
 }
\ No newline at end of file
index f65fd08aa74483dcb8422990da737f6d3a20b53a..af345dad6d50ffa358d0449d696db48e91afdaed 100644 (file)
@@ -33,6 +33,8 @@ struct serial_dev
     struct rbuffer rxbuf;
     int wr_len;
 
     struct rbuffer rxbuf;
     int wr_len;
 
+    struct capability_meta* tp_cap;
+
     /**
      * @brief Write buffer to TX. The return code indicate
      * the transaction is either done in synced mode (TX_DONE) or will be
     /**
      * @brief Write buffer to TX. The return code indicate
      * the transaction is either done in synced mode (TX_DONE) or will be
index 4ddf74d38066b18dd4ea6d55cdf9e201f9a5a107..407707e397c6fff6fa446f7fe7eee80b20167abc 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <lunaix/device.h>
 #include <lunaix/ds/rbuffer.h>
 
 #include <lunaix/device.h>
 #include <lunaix/ds/rbuffer.h>
+#include <lunaix/ds/waitq.h>
 #include <lunaix/signal_defs.h>
 
 #include <usr/lunaix/term.h>
 #include <lunaix/signal_defs.h>
 
 #include <usr/lunaix/term.h>
@@ -16,21 +17,15 @@ struct linebuffer
     short sflags;
     short sz_hlf;
 };
     short sflags;
     short sz_hlf;
 };
-#define LSTATE_EOL (1)
-#define LSTATE_EOF (1 << 1)
-#define LSTATE_SIGRAISE (1 << 2)
+#define LEVT_EOL (1)
+#define LEVT_EOF (1 << 1)
+#define LEVT_SIGRAISE (1 << 2)
 
 typedef struct rbuffer** lbuf_ref_t;
 #define ref_current(lbuf) (&(lbuf)->current)
 #define ref_next(lbuf) (&(lbuf)->next)
 #define deref(bref) (*(bref))
 
 
 typedef struct rbuffer** lbuf_ref_t;
 #define ref_current(lbuf) (&(lbuf)->current)
 #define ref_next(lbuf) (&(lbuf)->next)
 #define deref(bref) (*(bref))
 
-struct term_lcntl
-{
-    struct term* term;
-    int (*process_and_put)(struct term*, struct linebuffer*, char);
-};
-
 /**
  * @brief Communication port capability that a device is supported natively, 
  *          or able to emulate low level serial transmission behaviour specify 
 /**
  * @brief Communication port capability that a device is supported natively, 
  *          or able to emulate low level serial transmission behaviour specify 
@@ -46,25 +41,33 @@ struct term_lcntl
  */
 #define TERMIOS_CAP 0x534f4954U
 
  */
 #define TERMIOS_CAP 0x534f4954U
 
-struct termport_capability
-{
-    CAPABILITY_META;
+struct term;
 
 
+struct termport_cap_ops
+{
     void (*set_speed)(struct device*, speed_t);
     void (*set_speed)(struct device*, speed_t);
+    void (*set_clkbase)(struct device*, unsigned int);
     void (*set_cntrl_mode)(struct device*, tcflag_t);
 };
 
     void (*set_cntrl_mode)(struct device*, tcflag_t);
 };
 
+struct termport_capability
+{
+    CAPABILITY_META;
+    struct termport_cap_ops* cap_ops;
+    struct term* term;
+};
+
 struct term
 {
     struct device* dev;
     struct device* chdev;
 struct term
 {
     struct device* dev;
     struct device* chdev;
-    struct term_lcntl* lcntl;
     struct linebuffer line_out;
     struct linebuffer line_in;
     char* scratch_pad;
     pid_t fggrp;
 
     struct termport_capability* tp_cap;
     struct linebuffer line_out;
     struct linebuffer line_in;
     char* scratch_pad;
     pid_t fggrp;
 
     struct termport_capability* tp_cap;
+    waitq_t line_in_event;
 
     /* -- POSIX.1-2008 compliant fields -- */
     tcflag_t iflags;
 
     /* -- POSIX.1-2008 compliant fields -- */
     tcflag_t iflags;
@@ -72,7 +75,11 @@ struct term
     tcflag_t lflags;
     tcflag_t cflags;
     cc_t cc[_NCCS];
     tcflag_t lflags;
     tcflag_t cflags;
     cc_t cc[_NCCS];
+
+    /* -- END POSIX.1-2008 compliant fields -- */
     speed_t iospeed;
     speed_t iospeed;
+    speed_t clkbase;
+    tcflag_t tflags;    // temp flags
 };
 
 extern struct device* sysconsole;
 };
 
 extern struct device* sysconsole;
@@ -83,15 +90,6 @@ term_create(struct device* chardev, char* suffix);
 int
 term_bind(struct term* tdev, struct device* chdev);
 
 int
 term_bind(struct term* tdev, struct device* chdev);
 
-int
-term_push_lcntl(struct term* tdev, struct term_lcntl* lcntl);
-
-int
-term_pop_lcntl(struct term* tdev);
-
-struct term_lcntl*
-term_get_lcntl(u32_t lcntl_index);
-
 static inline void
 line_flip(struct linebuffer* lbf)
 {
 static inline void
 line_flip(struct linebuffer* lbf)
 {
@@ -121,4 +119,20 @@ lcntl_transform_inseq(struct term* tdev);
 int
 lcntl_transform_outseq(struct term* tdev);
 
 int
 lcntl_transform_outseq(struct term* tdev);
 
+static inline void
+term_cap_set_operations(struct termport_capability* cap, 
+                        struct termport_cap_ops* ops)
+{
+    cap->cap_ops = ops;
+}
+
+void
+term_notify_data_avaliable(struct termport_capability* cap);
+
+#define termport_default_ops                                    \
+    ({                                                          \
+        extern struct termport_cap_ops default_termport_cap_ops;\
+        &default_termport_cap_ops;                              \
+    })
+
 #endif /* __LUNAIX_TERM_H */
 #endif /* __LUNAIX_TERM_H */
index d45c9fdf0e405f6aea9889c987fea36e1165e5a0..ffbb99b0b7d873a029b94f0ec7ccc678229f0cdd 100644 (file)
@@ -30,11 +30,22 @@ int
 rbuffer_puts(struct rbuffer* rb, char* c, size_t len);
 
 int
 rbuffer_puts(struct rbuffer* rb, char* c, size_t len);
 
 int
-rbuffer_gets(struct rbuffer* rb, char* buf, size_t len);
+rbuffer_gets_opt(struct rbuffer* rb, char* buf, size_t len, bool consumed);
 
 int
 rbuffer_get(struct rbuffer* rb, char* c);
 
 
 int
 rbuffer_get(struct rbuffer* rb, char* c);
 
+static inline int
+rbuffer_gets(struct rbuffer* rb, char* buf, size_t len)
+{
+    return rbuffer_gets_opt(rb, buf, len, true);
+}
+
+static inline int
+rbuffer_gets_no_consume(struct rbuffer* rb, char* buf, size_t len)
+{
+    return rbuffer_gets_opt(rb, buf, len, false);
+}
 
 static inline void
 rbuffer_clear(struct rbuffer* rb)
 
 static inline void
 rbuffer_clear(struct rbuffer* rb)
@@ -48,6 +59,19 @@ rbuffer_empty(struct rbuffer* rb)
     return rb->len == 0;
 }
 
     return rb->len == 0;
 }
 
+static inline unsigned int
+rbuffer_len(struct rbuffer* rb)
+{
+    return rb->len;
+}
+
+static inline void
+rbuffer_setcontent(struct rbuffer* rb, size_t content_len)
+{
+    rb->ptr = content_len;
+    rb->len = content_len;
+}
+
 static inline bool
 rbuffer_full(struct rbuffer* rb)
 {
 static inline bool
 rbuffer_full(struct rbuffer* rb)
 {
index c01bb15106fe88b2e673204e8f99fd691c3d3e1d..6f731554547d6f8ffa03d896bbaf8f767de66191 100644 (file)
@@ -3,13 +3,14 @@
 
 #include "ioctl_defs.h"
 
 
 #include "ioctl_defs.h"
 
-#define SERIO_RXEN IOREQ(1, 0)
-#define SERIO_RXDA IOREQ(2, 0)
+#define SERIO_RXEN          IOREQ(1, 0)
+#define SERIO_RXDA          IOREQ(2, 0)
 
 
-#define SERIO_TXEN IOREQ(3, 0)
-#define SERIO_TXDA IOREQ(4, 0)
+#define SERIO_TXEN          IOREQ(3, 0)
+#define SERIO_TXDA          IOREQ(4, 0)
 
 
-#define SERIO_SETBRDIV IOREQ(5, 0)
-#define SERIO_SETCNTRLMODE IOREQ(6, 0)
+#define SERIO_SETBRDRATE    IOREQ(5, 0)
+#define SERIO_SETCNTRLMODE  IOREQ(6, 0)
+#define SERIO_SETBRDBASE    IOREQ(7, 0)
 
 #endif /* __LUNAIX_USERIAL_H */
 
 #endif /* __LUNAIX_USERIAL_H */
index b52bc29e12160501727c89ef431670036a7b1925..600b5128d8cb47d13a0619e20723617d558972f4 100644 (file)
@@ -13,7 +13,6 @@ sources([
     "kinit.c",
     "lunad.c",
     "spike.c",
     "kinit.c",
     "lunad.c",
     "spike.c",
-    "tty/tty.c",
     "kprint/kp_records.c",
     "kprint/kprintf.c",
     "time/clock.c",
     "kprint/kp_records.c",
     "kprint/kprintf.c",
     "time/clock.c",
index eea75d6e5b1d1f38df4098075a93200171b47301..82d1402b8d7d788fa2e48c82bbab010715b8b94a 100644 (file)
@@ -61,7 +61,7 @@ rbuffer_puts(struct rbuffer* rb, char* buf, size_t len)
 }
 
 int
 }
 
 int
-rbuffer_gets(struct rbuffer* rb, char* buf, size_t len)
+rbuffer_gets_opt(struct rbuffer* rb, char* buf, size_t len, bool consumed)
 {
     if (!len || !rb->len)
         return 0;
 {
     if (!len || !rb->len)
         return 0;
@@ -79,7 +79,9 @@ rbuffer_gets(struct rbuffer* rb, char* buf, size_t len)
         memcpy(&buf[-nlen], &rb->buffer[ptr_start], nlen);
     }
 
         memcpy(&buf[-nlen], &rb->buffer[ptr_start], nlen);
     }
 
-    rb->len -= nlen;
+    if (consumed) {
+        rb->len -= nlen;
+    }
 
     return nlen;
 }
 
     return nlen;
 }
index ca28001f8bc66b255604297d727267455743ea3d..24550cf5192829fc2c7eb91adb0224dfe9038340 100644 (file)
@@ -43,14 +43,9 @@ kernel_bootstrap(struct boot_handoff* bhctx)
     /* Begin kernel bootstrapping sequence */
     boot_begin(bhctx);
 
     /* Begin kernel bootstrapping sequence */
     boot_begin(bhctx);
 
-    tty_init((void*)ioremap(0xB8000, PAGE_SIZE));
-    
     /* Setup kernel memory layout and services */
     kmem_init(bhctx);
 
     /* Setup kernel memory layout and services */
     kmem_init(bhctx);
 
-    // FIXME this goes to hal/gfxa
-    tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_BLACK);
-
     boot_parse_cmdline(bhctx);
 
     /* Prepare stack trace environment */
     boot_parse_cmdline(bhctx);
 
     /* Prepare stack trace environment */
index 91cf61becdc53c0d2a8411f1f7426990531f4eea..82a2aa9abc15b9c4a13a15e950218c1f4f2b9412 100644 (file)
@@ -33,6 +33,8 @@ struct scheduler sched_ctx;
 
 struct cake_pile *proc_pile ,*thread_pile;
 
 
 struct cake_pile *proc_pile ,*thread_pile;
 
+#define root_process   (sched_ctx.procs[1])
+
 LOG_MODULE("SCHED")
 
 void
 LOG_MODULE("SCHED")
 
 void
@@ -256,7 +258,6 @@ __DEFINE_LXSYSCALL1(unsigned int, alarm, unsigned int, seconds)
 
     bed->alarm_time = seconds ? now + seconds : 0;
 
 
     bed->alarm_time = seconds ? now + seconds : 0;
 
-    struct proc_info* root_proc = sched_ctx.procs[0];
     if (llist_empty(&bed->sleepers)) {
         llist_append(&sched_ctx.sleepers, &bed->sleepers);
     }
     if (llist_empty(&bed->sleepers)) {
         llist_append(&sched_ctx.sleepers, &bed->sleepers);
     }
@@ -435,7 +436,7 @@ commit_process(struct proc_info* process)
     // every process is the child of first process (pid=1)
     if (!process->parent) {
         if (likely(!kernel_process(process))) {
     // every process is the child of first process (pid=1)
     if (!process->parent) {
         if (likely(!kernel_process(process))) {
-            process->parent = sched_ctx.procs[1];
+            process->parent = root_process;
         } else {
             process->parent = process;
         }
         } else {
             process->parent = process;
         }
@@ -474,6 +475,20 @@ destory_thread(struct thread* thread)
     cake_release(thread_pile, thread);
 }
 
     cake_release(thread_pile, thread);
 }
 
+static void
+orphan_children(struct proc_info* proc)
+{
+    struct proc_info *root;
+    struct proc_info *pos, *n;
+
+    root = root_process;
+
+    llist_for_each(pos, n, &proc->children, siblings) {
+        pos->parent = root;
+        llist_append(&root->children, &pos->siblings);
+    }
+}
+
 void 
 delete_process(struct proc_info* proc)
 {
 void 
 delete_process(struct proc_info* proc)
 {
@@ -520,6 +535,8 @@ delete_process(struct proc_info* proc)
         destory_thread(pos);
     }
 
         destory_thread(pos);
     }
 
+    orphan_children(proc);
+
     procvm_unmount_release(mm);
 
     cake_release(proc_pile, proc);
     procvm_unmount_release(mm);
 
     cake_release(proc_pile, proc);
index e40526ee9bb6fd2583a286e2645ffadfefcc71a3..eef5c7ba4f72b3a57d08d5059f1067fa01622872 100644 (file)
@@ -147,8 +147,7 @@ int
 signal_send(pid_t pid, signum_t signum)
 {
     if (signum >= _SIG_NUM) {
 signal_send(pid_t pid, signum_t signum)
 {
     if (signum >= _SIG_NUM) {
-        syscall_result(EINVAL);
-        return -1;
+        return EINVAL;
     }
 
     pid_t sender_pid = __current->pid;
     }
 
     pid_t sender_pid = __current->pid;
@@ -166,8 +165,7 @@ signal_send(pid_t pid, signum_t signum)
     } else {
         // TODO: send to all process.
         //  But I don't want to support it yet.
     } else {
         // TODO: send to all process.
         //  But I don't want to support it yet.
-        syscall_result(EINVAL);
-        return -1;
+        return EINVAL;
     }
 
 send_grp: ;
     }
 
 send_grp: ;
@@ -179,8 +177,7 @@ send_grp: ;
 
 send_single:
     if (proc_terminated(proc)) {
 
 send_single:
     if (proc_terminated(proc)) {
-        syscall_result(EINVAL);
-        return -1;
+        return EINVAL;
     }
 
     proc_setsignal(proc, signum);
     }
 
     proc_setsignal(proc, signum);
@@ -358,7 +355,7 @@ __DEFINE_LXSYSCALL(int, pause)
 
 __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
 {
 
 __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
 {
-    return signal_send(pid, signum);
+    return syscall_result(signal_send(pid, signum));
 }
 
 __DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
 }
 
 __DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
index 2416e07836a6e243131b08096a73710c1acf3c7c..47fcf68e0ae7739e4cc73ea97dfaeb2b6773f700 100644 (file)
@@ -36,6 +36,9 @@ init_termios(int fd) {
     term.c_oflag = ONLCR | OPOST;
     term.c_cflag = CREAD | CLOCAL | CS8 | CPARENB;
     term.c_cc[VERASE] = 0x7f;
     term.c_oflag = ONLCR | OPOST;
     term.c_cflag = CREAD | CLOCAL | CS8 | CPARENB;
     term.c_cc[VERASE] = 0x7f;
+    
+    cfsetispeed(&term, B9600);
+    cfsetospeed(&term, B9600);
 
     check(tcsetattr(fd, 0, &term));
 
 
     check(tcsetattr(fd, 0, &term));
 
index 42ad0ac86ed0b2cc85c97ba7015c00b91a70596b..abdcf8562b1321b523a29315215b0bfea7f308b1 100644 (file)
@@ -89,12 +89,20 @@ static inline speed_t cfgetospeed(const struct termios* termios) { return termio
 
 static inline int cfsetispeed(struct termios* termios, speed_t baud)
 {
 
 static inline int cfsetispeed(struct termios* termios, speed_t baud)
 {
+    if (baud > B38400) {
+        return -1;
+    }
+
     termios->c_baud = baud;
     return 0;
 }
 
 static inline int cfsetospeed(struct termios* termios, speed_t baud)
 {
     termios->c_baud = baud;
     return 0;
 }
 
 static inline int cfsetospeed(struct termios* termios, speed_t baud)
 {
+    if (baud > B38400) {
+        return -1;
+    }
+
     termios->c_baud = baud;
     return 0;
 }
     termios->c_baud = baud;
     return 0;
 }
@@ -110,5 +118,4 @@ int     tcgetattr(int, struct termios *);
 int     tcsendbreak(int, int);
 int     tcsetattr(int, int, const struct termios *);
 
 int     tcsendbreak(int, int);
 int     tcsetattr(int, int, const struct termios *);
 
-
 #endif /* __LUNAIX_TERMIOS_H */
 #endif /* __LUNAIX_TERMIOS_H */
index 2ac473a5a6b45839e596e0928a3970cf30eb0d6e..c2c8347f3f7d6969fd03f838b7b5607dadbe0e7e 100644 (file)
@@ -132,6 +132,27 @@ sh_exec(const char** argv)
     waitpid(p, NULL, 0);
 }
 
     waitpid(p, NULL, 0);
 }
 
+static char*
+sanity_filter(char* buf)
+{
+    int off = 0, i = 0;
+    char c;
+    do {
+        c = buf[i];
+        
+        if ((32 <= c && c <= 126) || !c) {
+            buf[i - off] = c;
+        }
+        else {
+            off++;
+        }
+
+        i++;
+    } while(c);
+
+    return buf;
+}
+
 void
 sh_loop()
 {
 void
 sh_loop()
 {
@@ -157,6 +178,7 @@ sh_loop()
         }
 
         buf[sz] = '\0';
         }
 
         buf[sz] = '\0';
+        sanity_filter(buf);
 
         // currently, this shell only support single argument
         if (!parse_cmdline(buf, argv)) {
 
         // currently, this shell only support single argument
         if (!parse_cmdline(buf, argv)) {