aboutsummaryrefslogtreecommitdiff
path: root/kernel/include/drivers/tty/ldisc.h
diff options
context:
space:
mode:
authornthnluu <nate1299@me.com>2024-01-28 21:20:27 -0500
committernthnluu <nate1299@me.com>2024-01-28 21:20:27 -0500
commitc63f340d90800895f007de64b7d2d14624263331 (patch)
tree2c0849fa597dd6da831c8707b6f2603403778d7b /kernel/include/drivers/tty/ldisc.h
Created student weenix repository
Diffstat (limited to 'kernel/include/drivers/tty/ldisc.h')
-rw-r--r--kernel/include/drivers/tty/ldisc.h68
1 files changed, 68 insertions, 0 deletions
diff --git a/kernel/include/drivers/tty/ldisc.h b/kernel/include/drivers/tty/ldisc.h
new file mode 100644
index 0000000..920c816
--- /dev/null
+++ b/kernel/include/drivers/tty/ldisc.h
@@ -0,0 +1,68 @@
+#pragma once
+
+#include "types.h"
+#include <proc/kmutex.h>
+
+#define LDISC_BUFFER_SIZE 128
+
+/**
+ * The line discipline is implemented as a circular buffer containing two
+ * sections: cooked and raw. These sections are tracked by three indices:
+ * ldisc_cooked, ldisc_tail, and ldisc_head.
+ *
+ * New characters (via ldisc_key_pressed) are put at the head position (and the
+ * head is incremented). If a newline is received, cooked is moved up to the head.
+ * Characters are read from tail up until cooked, and the tail is updated
+ * to equal cooked.
+ *
+ * The cooked portion (ready for reading) runs from ldisc_tail (inclusive) to
+ * ldisc_cooked (exclusive). The raw portion (subject to editing) runs from
+ * ldisc_cooked (inclusive) to ldisc_head (exclusive).
+ *
+ * e.g.
+ * [..........t........c...h.......]
+ * (cooked) ^^^^^^^^^
+ * ^^^^ (raw)
+ *
+ * Bear in mind that the buffer is circular, so another possible configuration
+ * might be
+ *
+ * [....h............t......c......]
+ * (cooked) ^^^^^^^
+ * ^^^^ ^^^^^^^ (raw)
+ *
+ * When incrementing the indices, make sure that you take the circularity of
+ * the buffer into account! (Hint: using LDISC_BUFFER_SIZE macro will be helpful.)
+ *
+ * The field ldisc_full is used to indicate when the circular buffer has been
+ * completely filled. This is necessary because there are two possible states
+ * in which cooked == tail == head:
+ *
+ * 1) The buffer is empty, or
+ *
+ * 2) The buffer is full: head has wrapped around and is equal to tail.
+ *
+ * ldisc_full is used to differentiate between these two states.
+ */
+typedef struct ldisc
+{
+ size_t ldisc_cooked; // Cooked is the index after the most last or most recent '\n' in the buffer.
+ size_t ldisc_tail; // Tail is the index from which characters are read by processes
+ size_t ldisc_head; // Head is the index from which new characters are placed
+ char ldisc_full; // Full identifies if the buffer is full
+ // 1 -> full
+ // 0 -> not full
+
+ ktqueue_t ldisc_read_queue; // Queue for threads waiting for data to be read
+ char ldisc_buffer[LDISC_BUFFER_SIZE];
+} ldisc_t;
+
+void ldisc_init(ldisc_t *ldisc);
+
+long ldisc_wait_read(ldisc_t *ldisc);
+
+size_t ldisc_read(ldisc_t *ldisc, char *buf, size_t count);
+
+void ldisc_key_pressed(ldisc_t *ldisc, char c);
+
+size_t ldisc_get_current_line_raw(ldisc_t *ldisc, char *s); \ No newline at end of file