X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/0765e7c133eb393d8cd0292af444543c2edf8ccc..b1644f824d7f4989a94b8a752aadee26cae25069:/lunaix-os/hal/term/term.c diff --git a/lunaix-os/hal/term/term.c b/lunaix-os/hal/term/term.c index 3cc9741..59b7ebe 100644 --- a/lunaix-os/hal/term/term.c +++ b/lunaix-os/hal/term/term.c @@ -5,21 +5,22 @@ #include #include #include +#include -#include +#include + +LOG_MODULE("term"); -#define ANSI_LCNTL 0 #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*)) -static struct devclass termdev = DEVCLASS(DEVIF_NON, DEVFN_TTY, DEV_VTERM); +static struct devclass termdev_class = DEVCLASS(LUNAIX, TTY, VTERM); struct device* sysconsole = NULL; +extern struct termport_pot_ops default_termport_pot_ops; + static int term_exec_cmd(struct device* dev, u32_t req, va_list args) { @@ -85,7 +86,9 @@ term_exec_cmd(struct device* dev, u32_t req, va_list args) tios->c_baud = term->iospeed; } break; case TDEV_TCSETATTR: { + struct termport_pot_ops* pot_ops; struct termios* tios = va_arg(args, struct termios*); + term->iflags = tios->c_iflag; term->oflags = tios->c_oflag; term->lflags = tios->c_lflag; @@ -98,14 +101,16 @@ term_exec_cmd(struct device* dev, u32_t req, va_list args) goto done; } + pot_ops = term->tp_cap->ops; + if (tios->c_baud != term->iospeed) { term->iospeed = tios->c_baud; - term->tp_cap->set_speed(term->chdev, tios->c_baud); + pot_ops->set_speed(term->chdev, tios->c_baud); } if (old_cf != tios->c_cflag) { - term->tp_cap->set_cntrl_mode(term->chdev, tios->c_cflag); + pot_ops->set_cntrl_mode(term->chdev, tios->c_cflag); } } break; default: @@ -136,7 +141,7 @@ tdev_do_write(struct device* dev, void* buf, off_t fpos, size_t len) if (!rbuffer_empty(deref(current))) { term_flush(tdev); } - return 0; + return wrsz; } static int @@ -146,16 +151,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; - 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); } - + + tdev->line_in.sflags = 0; return rdsz; } @@ -167,49 +170,63 @@ load_default_setting(struct term* tdev) 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)); } -struct term* -term_create(struct device* chardev, char* suffix) +static void +alloc_term_buffer(struct term* terminal, size_t sz_hlf) +{ + line_alloc(&terminal->line_in, sz_hlf); + line_alloc(&terminal->line_out, sz_hlf); + terminal->scratch_pad = valloc(sz_hlf); +} + +struct termport_potens* +term_attach_potens(struct device* chardev, + struct termport_pot_ops* ops, char* suffix) { - struct term* terminal = vzalloc(sizeof(struct term)); + struct term* terminal; + struct device* tdev; + struct termport_potens* tp_cap; + terminal = vzalloc(sizeof(struct term)); if (!terminal) { return NULL; } - terminal->dev = device_allocseq(NULL, terminal); + tdev = device_allocseq(NULL, terminal); + terminal->dev = tdev; 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); - line_alloc(&terminal->line_in, 1024); - line_alloc(&terminal->line_out, 1024); + 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 { - register_device(terminal->dev, &termdev, "tty%d", termdev.variant++); + register_device_var(tdev, &termdev_class, "tty"); } - struct capability_meta* termport_cap = device_get_capability(chardev, TERMPORT_CAP); - if (termport_cap) { - terminal->tp_cap = get_capability(termport_cap, struct termport_capability); - } + INFO("spawned: %s", tdev->name_val); + + tp_cap = new_potens(potens(TERMPORT), struct termport_potens); + tp_cap->ops = ops ?: &default_termport_pot_ops; + + terminal->tp_cap = tp_cap; + tp_cap->term = terminal; - struct capability_meta* term_cap = new_capability_marker(TERMIOS_CAP); - device_grant_capability(terminal->dev, term_cap); + device_grant_potens(tdev, potens_meta(tp_cap)); load_default_setting(terminal); - return terminal; + return tp_cap; } int @@ -246,6 +263,7 @@ void term_sendsig(struct term* tdev, int signal) { if ((tdev->lflags & _ISIG)) { - proc_setsignal(get_process(tdev->fggrp), signal); + signal_send(-tdev->fggrp, signal); + pwake_all(&tdev->line_in_event); } } \ No newline at end of file