Skip to content

Commit

Permalink
Create the line discipline layer
Browse files Browse the repository at this point in the history
Line discipline is a layer in the terminal subsystem of Unix-like systems, governing the processing of input and output streams. It manages tasks such as line editing, buffering, and character echoing, ensuring a smooth user experience. Implementing line discipline will enhance the structure of our system, resulting in a more maintainable and reliable console component.

Close #12
  • Loading branch information
alanjian85 committed Jul 1, 2024
1 parent 830a294 commit 4e35b55
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 125 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ endif()

add_executable(karg
src/dev.c
src/drivers/ldisc.c
src/drivers/plic.c
src/drivers/tty.c
src/drivers/uart.c
Expand Down
2 changes: 1 addition & 1 deletion include/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
#define PROC_FD_CAPACITY 64
#define PROC_TABLE_SIZE 256
#define SCHED_TIMESLICE 10000000
#define TTY_BUF_SIZE 128
#define TTY_SINK_CAPACITY 4
#define UART_RX_BUF_SIZE 128
25 changes: 25 additions & 0 deletions include/drivers/ldisc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <config.h>
#include <dev.h>

typedef struct {
bool crlf;
} ldisc_config_t;

typedef struct {
dev_t dev;
ldisc_config_t config;
} ldisc_dev_t;

typedef struct {
ldisc_dev_t src;
ldisc_dev_t sinks[TTY_SINK_CAPACITY];
u32 nr_sinks;
u32 cursor_pos;
} ldisc_ctrl_blk_t;

i32 ldisc_register_src(u32 num, ldisc_dev_t dev);
i32 ldisc_register_sink(u32 num, ldisc_dev_t dev);
void ldisc_recv_byte(u32 num, u8 byte);
isize ldisc_write(u32 num, const u8 *buf, usize size);
16 changes: 11 additions & 5 deletions include/drivers/tty.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
#pragma once

#include <dev.h>
#include <types.h>
#include <drivers/ldisc.h>
#include <sem.h>

i32 tty_register_src(u32 num, dev_t src);
i32 tty_register_sink(u32 num, dev_t sink);
typedef struct {
ldisc_ctrl_blk_t ldisc_ctrl_blk;
u8 *rx_buf;
usize rx_head, rx_tail;
sem_t rx_sem;
} tty_ctrl_blk_t;

extern
extern tty_ctrl_blk_t *tty_ctrl_blks[DRIVER_DEV_CAPACITY];

i32 tty_init_ctrl_blk(tty_ctrl_blk_t *ctrl_blk);
9 changes: 9 additions & 0 deletions src/dev.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <dev.h>

#include <errno.h>
#include <init.h>
#include <log.h>
#include <module.h>
Expand All @@ -10,14 +11,20 @@ MODULE_NAME("dev");
extern dev_init_t _dev_init_start, _dev_init_end;

isize dev_read(dev_t dev, u8 *buf, usize size) {
if (!dev.driver->read)
return -ENXIO;
return dev.driver->read(dev.num, buf, size);
}

isize dev_write(dev_t dev, const u8 *buf, usize size) {
if (!dev.driver->write)
return -ENXIO;
return dev.driver->write(dev.num, buf, size);
}

i32 dev_ioctl(dev_t dev, u32 req, ...) {
if (!dev.driver->ioctl)
return -ENXIO;
va_list args;
va_start(args);
i32 res = dev.driver->ioctl(dev.num, req, args);
Expand All @@ -26,6 +33,8 @@ i32 dev_ioctl(dev_t dev, u32 req, ...) {
}

i32 dev_vioctl(dev_t dev, u32 req, va_list args) {
if (!dev.driver->ioctl)
return -ENXIO;
return dev.driver->ioctl(dev.num, req, args);
}

Expand Down
88 changes: 88 additions & 0 deletions src/drivers/ldisc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#include <drivers/ldisc.h>

#include <drivers/tty.h>
#include <errno.h>
#include <kalloc.h>

static i32 lazy_init_ctrl_blk(u32 num) {
if (num >= DRIVER_DEV_CAPACITY)
return -EAGAIN;
if (tty_ctrl_blks[num])
return 0;

tty_ctrl_blk_t *tty_ctrl_blk =
(tty_ctrl_blk_t *) kmalloc(sizeof(tty_ctrl_blk_t));
if (!tty_ctrl_blk)
return -ENOMEM;

ldisc_ctrl_blk_t *ctrl_blk = &tty_ctrl_blk->ldisc_ctrl_blk;
ctrl_blk->nr_sinks = 0;
ctrl_blk->cursor_pos = 0;

i32 res = tty_init_ctrl_blk(tty_ctrl_blk);
if (res < 0)
return res;
tty_ctrl_blks[num] = tty_ctrl_blk;
return 0;
}

i32 ldisc_register_src(u32 num, ldisc_dev_t dev) {
i32 res = lazy_init_ctrl_blk(num);
if (res < 0)
return res;
ldisc_ctrl_blk_t *ctrl_blk = &tty_ctrl_blks[num]->ldisc_ctrl_blk;
ctrl_blk->src = dev;
return 0;
}

i32 ldisc_register_sink(u32 num, ldisc_dev_t dev) {
i32 res = lazy_init_ctrl_blk(num);
if (res < 0)
return res;
ldisc_ctrl_blk_t *ctrl_blk = &tty_ctrl_blks[num]->ldisc_ctrl_blk;
if (ctrl_blk->nr_sinks >= TTY_SINK_CAPACITY)
return -EAGAIN;
ctrl_blk->sinks[ctrl_blk->nr_sinks++] = dev;
return 0;
}

void ldisc_recv_byte(u32 num, u8 byte) {
tty_ctrl_blk_t *tty_ctrl_blk = tty_ctrl_blks[num];
ldisc_ctrl_blk_t *ctrl_blk = &tty_ctrl_blk->ldisc_ctrl_blk;
switch (byte) {
case '\r':
tty_ctrl_blk->rx_buf[tty_ctrl_blk->rx_tail++] = '\n';
tty_ctrl_blk->rx_tail %= TTY_BUF_SIZE;
ctrl_blk->cursor_pos++;
sem_signaln(&tty_ctrl_blk->rx_sem, ctrl_blk->cursor_pos);
ctrl_blk->cursor_pos = 0;
ldisc_write(num, (const u8 *) "\n", 1);
break;
case '\x7F':
if (ctrl_blk->cursor_pos > 0) {
if (tty_ctrl_blk->rx_tail == 0) {
tty_ctrl_blk->rx_tail = TTY_BUF_SIZE;
}
tty_ctrl_blk->rx_tail--;
ctrl_blk->cursor_pos--;
ldisc_write(num, (const u8 *) "\b \b", 3);
}
break;
default:
tty_ctrl_blk->rx_buf[tty_ctrl_blk->rx_tail++] = byte;
tty_ctrl_blk->rx_tail %= TTY_BUF_SIZE;
ctrl_blk->cursor_pos++;
ldisc_write(num, &byte, 1);
break;
}
}

isize ldisc_write(u32 num, const u8 *buf, usize size) {
ldisc_ctrl_blk_t *ctrl_blk = &tty_ctrl_blks[num]->ldisc_ctrl_blk;
for (u32 i = 0; i < ctrl_blk->nr_sinks; i++) {
isize res = dev_write(ctrl_blk->sinks[i].dev, buf, size);
if (res < 0)
return res;
}
return size;
}
66 changes: 19 additions & 47 deletions src/drivers/tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,26 @@
#include <errno.h>
#include <kalloc.h>

typedef struct {
dev_t src;
dev_t sinks[TTY_SINK_CAPACITY];
u32 nr_sinks;
} ctrl_blk_t;

static ctrl_blk_t *ctrl_blks[DRIVER_DEV_CAPACITY];
tty_ctrl_blk_t *tty_ctrl_blks[DRIVER_DEV_CAPACITY];

static isize read(u32 num, u8 *buf, usize size) {
if (num >= DRIVER_DEV_CAPACITY || !ctrl_blks[num])
if (num >= DRIVER_DEV_CAPACITY || !tty_ctrl_blks[num])
return -ENXIO;
ctrl_blk_t *ctrl_blk = ctrl_blks[num];
return dev_read(ctrl_blk->src, buf, size);
tty_ctrl_blk_t *ctrl_blk = tty_ctrl_blks[num];
for (usize i = 0; i < size; i++) {
sem_wait(&ctrl_blk->rx_sem);
buf[i] = ctrl_blk->rx_buf[ctrl_blk->rx_head++];
ctrl_blk->rx_head %= TTY_BUF_SIZE;
if (buf[i] == '\n')
return i + 1;
}
return size;
}

static isize write(u32 num, const u8 *buf, usize size) {
if (num >= DRIVER_DEV_CAPACITY || !ctrl_blks[num])
if (num >= DRIVER_DEV_CAPACITY || !tty_ctrl_blks[num])
return -ENXIO;
ctrl_blk_t *ctrl_blk = ctrl_blks[num];
for (u32 i = 0; i < ctrl_blk->nr_sinks; i++) {
isize res = dev_write(ctrl_blk->sinks[i], buf, size);
if (res < 0)
return res;
}
return size;
return ldisc_write(num, buf, size);
}

const driver_t TTY_DRIVER = {
Expand All @@ -37,35 +32,12 @@ const driver_t TTY_DRIVER = {
.ioctl = nullptr,
};

static i32 lazy_init_ctrl_blk(u32 num) {
if (num >= DRIVER_DEV_CAPACITY)
return -EAGAIN;
if (ctrl_blks[num])
return 0;
ctrl_blk_t *ctrl_blk = (ctrl_blk_t *) kmalloc(sizeof(ctrl_blk_t));
if (!ctrl_blk)
i32 tty_init_ctrl_blk(tty_ctrl_blk_t *ctrl_blk) {
ctrl_blk->rx_buf = kmalloc(TTY_BUF_SIZE);
if (!ctrl_blk->rx_buf)
return -ENOMEM;
ctrl_blk->nr_sinks = 0;
ctrl_blks[num] = ctrl_blk;
return 0;
}

i32 tty_register_src(u32 num, dev_t src) {
i32 res = lazy_init_ctrl_blk(num);
if (res < 0)
return res;
ctrl_blk_t *ctrl_blk = ctrl_blks[num];
ctrl_blk->src = src;
return 0;
}

i32 tty_register_sink(u32 num, dev_t sink) {
i32 res = lazy_init_ctrl_blk(num);
if (res < 0)
return res;
ctrl_blk_t *ctrl_blk = ctrl_blks[num];
if (ctrl_blk->nr_sinks >= TTY_SINK_CAPACITY)
return -EAGAIN;
ctrl_blk->sinks[ctrl_blk->nr_sinks++] = sink;
ctrl_blk->rx_head = 0;
ctrl_blk->rx_tail = 0;
sem_init(&ctrl_blk->rx_sem);
return 0;
}
Loading

0 comments on commit 4e35b55

Please sign in to comment.