diff --git a/include/socks/termios.h b/include/socks/termios.h new file mode 100644 index 0000000..1394659 --- /dev/null +++ b/include/socks/termios.h @@ -0,0 +1,113 @@ +#ifndef SOCKS_TERMIOS_H_ +#define SOCKS_TERMIOS_H_ + +#include + +#define NCCS 32 + +#define BRKINT 00000001 +#define ICRNL 00000002 +#define IGNBRK 00000004 +#define IGNCR 00000010 +#define IGNPAR 00000020 +#define INLCR 00000040 +#define INPCK 00000100 +#define ISTRIP 00000200 +#define IUCLC 00000400 +#define IXANY 00001000 +#define IXOFF 00002000 +#define IXON 00004000 +#define PARMRK 00010000 + +#define OPOST 00000001 +#define OLCUC 00000002 +#define ONLCR 00000004 +#define OCRNL 00000010 +#define ONOCR 00000020 +#define ONLRET 00000040 +#define NLDLY 00000100 +#define NL0 00000000 +#define NL1 00000100 +#define OFILL 00000200 +#define CRDLY 00003400 +#define CR0 00000000 +#define CR1 00000400 +#define CR2 00001000 +#define CR3 00002000 +#define TABDLY 00034000 +#define TAB0 00000000 +#define TAB1 00004000 +#define TAB2 00010000 +#define TAB3 00020000 +#define BSDLY 00040000 +#define BS0 00000000 +#define BS1 00040000 +#define VTDLY 00100000 +#define VT0 00000000 +#define VT1 00100000 +#define FFDLY 00200000 +#define FF0 00000000 +#define FF1 00200000 + +#define B0 0 +#define B50 50 +#define B75 75 +#define B110 110 +#define B134 134 +#define B150 150 +#define B200 200 +#define B300 300 +#define B600 600 +#define B1200 1200 +#define B1800 1800 +#define B2400 2400 +#define B4800 4800 +#define B9600 9600 +#define B19200 19200 +#define B38400 38400 + +#define CSIZE 00000007 +#define CS5 00000000 +#define CS6 00000001 +#define CS7 00000002 +#define CS8 00000004 +#define CSTOPB 00000010 +#define CREAD 00000020 +#define PARENB 00000040 +#define PARODD 00000100 +#define HUPCL 00000200 +#define CLOCAL 00000400 + +#define ECHO 00000001 +#define ECHOE 00000002 +#define ECHOK 00000004 +#define ECHONL 00000010 +#define ICANON 00000020 +#define IEXTEN 00000040 +#define ISIG 00000100 +#define NOFLSH 00000200 +#define TOSTOP 00000400 +#define XCASE 00001000 + +#define TCSANOW 1 +#define TCSADRAIN 2 +#define TCSAFLUSH 3 + +#define TCIFLUSH 1 +#define TCOFLUSH 2 +#define TCIOFLUSH (TCIFLUSH | TCOFLUSH) + +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; +typedef unsigned char cc_t; + +struct termios { + tcflag_t c_iflag; + tcflag_t c_oflag; + tcflag_t c_cflag; + tcflag_t c_lflag; + cc_t c_line; + cc_t c_cc[NCCS]; +}; + +#endif diff --git a/include/socks/tty.h b/include/socks/tty.h index aa70e9e..6bb2d11 100644 --- a/include/socks/tty.h +++ b/include/socks/tty.h @@ -5,12 +5,14 @@ #include #include #include +#include #include #define TTY_DEVICE(dev) ((dev)->dev_type == DEV_TYPE_CHAR ? (dev)->chr.c_tty : NULL) #define TTY_DRIVER(drv) ((struct tty_driver *)((char *)drv - offsetof(struct tty_driver, tty_base))) #define TTY_INPUT_QUEUE_SIZE 256 +#define TTY_LINE_MAX 4096 struct kext; @@ -92,13 +94,14 @@ struct tty_driver { struct tty_ldisc { char name[OBJECT_NAME_MAX]; + kern_status_t(*read)(struct device *, void *, size_t, size_t *, socks_flags_t); void(*write)(struct device *, const struct input_event *); }; struct tty_device { unsigned int tty_xcells, tty_ycells; unsigned int tty_xcur, tty_ycur; - unsigned int tty_iflag, tty_oflag, tty_lflag; + struct termios tty_config; tty_attrib_t tty_curattrib; enum tty_modifier_key tty_modstate; @@ -107,6 +110,7 @@ struct tty_device { /* input characters processed from tty_events, returned by tty_read() */ struct ringbuffer tty_input; + char *tty_linebuf; }; extern kern_status_t tty_bootstrap(void); diff --git a/kernel/tty/ldisc.c b/kernel/tty/ldisc.c index 337b633..a8211cf 100644 --- a/kernel/tty/ldisc.c +++ b/kernel/tty/ldisc.c @@ -3,6 +3,7 @@ #include static void default_ldisc_write(struct device *, const struct input_event *); +static kern_status_t default_ldisc_read(struct device *tty, void *buf, size_t max, size_t *nr_read, socks_flags_t flags); static char keycode_chars[] = { [KEY_UNKNOWN] = ' ', @@ -234,6 +235,7 @@ static char keycode_chars_shift[] = { static struct tty_ldisc default_ldisc = { .name = "n_tty", + .read = default_ldisc_read, .write = default_ldisc_write, }; @@ -254,6 +256,34 @@ static enum tty_modifier_key get_modifier_key(const struct input_event *ev) } } +static bool is_arrow_key(const struct input_event *ev, char *ch) +{ + bool ret = false; + switch (ev->ev_key.key) { + case KEY_UP: + ret = true; + *ch = 'A'; + break; + case KEY_DOWN: + ret = true; + *ch = 'B'; + break; + case KEY_RIGHT: + ret = true; + *ch = 'C'; + break; + case KEY_LEFT: + ret = true; + *ch = 'D'; + break; + default: + ret = false; + break; + } + + return ret; +} + static void handle_modifier_keys(struct device *tty, enum tty_modifier_key modkey, const struct input_event *ev) { struct tty_device *ttydev = TTY_DEVICE(tty); @@ -273,13 +303,13 @@ static void convert_ev_to_chars(struct device *tty, const struct input_event *ev struct tty_device *ttydev = TTY_DEVICE(tty); - char echo[2]; + char echo[4]; int echo_len = 0; + char data[4]; + int data_len = 0; + char c = keycode_chars[ev->ev_key.key]; - if (c == 0) { - return; - } if (ttydev->tty_modstate & TTY_KEY_CTRL) { if (!isalpha(c)) { @@ -293,24 +323,67 @@ static void convert_ev_to_chars(struct device *tty, const struct input_event *ev c = tolower(c); c -= 97; c++; + data[0] = c; + data_len = 1; } else if (ttydev->tty_modstate & TTY_KEY_SHIFT) { c = keycode_chars_shift[ev->ev_key.key]; echo[0] = c; echo_len = 1; - } else { + data[0] = c; + data_len = 1; + } else if (is_arrow_key(ev, &c)) { + echo[0] = '^'; + echo[1] = '['; + echo[2] = '['; + echo[3] = c; + echo_len = 4; + + data[0] = 0x1b; + data[1] = '['; + data[2] = c; + data_len = 3; + } else if (c != 0) { echo[0] = c; echo_len = 1; + data[0] = c; + data_len = 1; } - if (c == 0) { + if (data_len == 0) { return; } - ringbuffer_write(&ttydev->tty_input, sizeof c, &c, S_NOBLOCK); + ringbuffer_write(&ttydev->tty_input, data_len, data, S_NOBLOCK); size_t nr_written; tty_write(tty, echo, echo_len, &nr_written, S_NOBLOCK); } +static kern_status_t canonical_read(struct device *tty, void *buf, size_t max, size_t *nr_read, socks_flags_t flags) +{ + //struct tty_device *ttydev = TTY_DEVICE(tty); + //struct termios backup = ttydev + //char *linebuf = ttydev->tty_linebuf; + //unsigned int pos = 0, len = 0; + return KERN_OK; +} + +static kern_status_t non_canonical_read(struct device *tty, void *buf, size_t max, size_t *nr_read, socks_flags_t flags) +{ + return KERN_OK; +} + +static kern_status_t default_ldisc_read(struct device *tty, void *buf, size_t max, size_t *nr_read, socks_flags_t flags) +{ + struct tty_device *ttydev = TTY_DEVICE(tty); + if (ttydev->tty_config.c_lflag & ICANON) { + return canonical_read(tty, buf, max, nr_read, flags); + } else { + return non_canonical_read(tty, buf, max, nr_read, flags); + } + + return KERN_OK; +} + static void default_ldisc_write(struct device *tty, const struct input_event *ev) { enum tty_modifier_key modkeys = get_modifier_key(ev); diff --git a/kernel/tty/tty.c b/kernel/tty/tty.c index f9ae3b8..f2fa8ef 100644 --- a/kernel/tty/tty.c +++ b/kernel/tty/tty.c @@ -75,8 +75,14 @@ static void putchar(struct device *tty, int c) kern_status_t tty_read(struct device *tty, void *buf, size_t max, size_t *nr_read, socks_flags_t flags) { - printk("tty_read"); - return KERN_OK; + kern_status_t status = KERN_UNSUPPORTED; + struct tty_device *ttydev = TTY_DEVICE(tty); + + if (ttydev->tty_ldisc || ttydev->tty_ldisc->read) { + status = ttydev->tty_ldisc->read(tty, buf, max, nr_read, flags); + } + + return status; } kern_status_t tty_write(struct device *tty, const void *buf, size_t len, size_t *nr_written, socks_flags_t flags)