mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 10:48:38 +00:00
158 lines
4.6 KiB
C
158 lines
4.6 KiB
C
// Copyright (c) 2023-2026 Chris (boreddevnl)
|
|
// This software is released under the GNU General Public License v3.0. See LICENSE file for details.
|
|
// This header needs to maintain in any file it is present in, as per the GPL license terms.
|
|
#include "tty.h"
|
|
#include "spinlock.h"
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#define TTY_MAX 8
|
|
#define TTY_OUT_SIZE 16384
|
|
#define TTY_IN_SIZE 4096
|
|
|
|
typedef struct {
|
|
bool used;
|
|
int id;
|
|
char out_buf[TTY_OUT_SIZE];
|
|
uint32_t out_head;
|
|
uint32_t out_tail;
|
|
char in_buf[TTY_IN_SIZE];
|
|
uint32_t in_head;
|
|
uint32_t in_tail;
|
|
int fg_pid;
|
|
spinlock_t lock;
|
|
} tty_t;
|
|
|
|
static tty_t ttys[TTY_MAX] = {0};
|
|
|
|
extern void mem_memset(void *dest, int val, size_t len);
|
|
|
|
static tty_t *tty_get(int tty_id) {
|
|
if (tty_id < 0 || tty_id >= TTY_MAX) return NULL;
|
|
if (!ttys[tty_id].used) return NULL;
|
|
return &ttys[tty_id];
|
|
}
|
|
|
|
int tty_create(void) {
|
|
for (int i = 0; i < TTY_MAX; i++) {
|
|
if (!ttys[i].used) {
|
|
ttys[i].used = true;
|
|
ttys[i].id = i;
|
|
ttys[i].out_head = 0;
|
|
ttys[i].out_tail = 0;
|
|
ttys[i].in_head = 0;
|
|
ttys[i].in_tail = 0;
|
|
ttys[i].fg_pid = -1;
|
|
ttys[i].lock = SPINLOCK_INIT;
|
|
mem_memset(ttys[i].out_buf, 0, sizeof(ttys[i].out_buf));
|
|
mem_memset(ttys[i].in_buf, 0, sizeof(ttys[i].in_buf));
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int tty_destroy(int tty_id) {
|
|
if (tty_id < 0 || tty_id >= TTY_MAX) return -1;
|
|
tty_t *tty = &ttys[tty_id];
|
|
|
|
uint64_t rflags = spinlock_acquire_irqsave(&tty->lock);
|
|
if (!tty->used) {
|
|
spinlock_release_irqrestore(&tty->lock, rflags);
|
|
return -1;
|
|
}
|
|
|
|
tty->used = false;
|
|
tty->id = -1;
|
|
tty->out_head = 0;
|
|
tty->out_tail = 0;
|
|
tty->in_head = 0;
|
|
tty->in_tail = 0;
|
|
tty->fg_pid = -1;
|
|
mem_memset(tty->out_buf, 0, sizeof(tty->out_buf));
|
|
mem_memset(tty->in_buf, 0, sizeof(tty->in_buf));
|
|
|
|
spinlock_release_irqrestore(&tty->lock, rflags);
|
|
return 0;
|
|
}
|
|
|
|
static int tty_write_ring(char *buf, uint32_t size, uint32_t *head, uint32_t *tail, const char *data, size_t len) {
|
|
int written = 0;
|
|
for (size_t i = 0; i < len; i++) {
|
|
uint32_t next = (*head + 1) % size;
|
|
if (next == *tail) break;
|
|
buf[*head] = data[i];
|
|
*head = next;
|
|
written++;
|
|
}
|
|
return written;
|
|
}
|
|
|
|
static int tty_read_ring(char *buf, uint32_t size, uint32_t *head, uint32_t *tail, char *out, size_t max_len) {
|
|
int read = 0;
|
|
while (*tail != *head && (size_t)read < max_len) {
|
|
out[read++] = buf[*tail];
|
|
*tail = (*tail + 1) % size;
|
|
}
|
|
return read;
|
|
}
|
|
|
|
int tty_write_output(int tty_id, const char *data, size_t len) {
|
|
tty_t *tty = tty_get(tty_id);
|
|
if (!tty || !data || len == 0) return 0;
|
|
|
|
uint64_t rflags = spinlock_acquire_irqsave(&tty->lock);
|
|
int written = tty_write_ring(tty->out_buf, TTY_OUT_SIZE, &tty->out_head, &tty->out_tail, data, len);
|
|
spinlock_release_irqrestore(&tty->lock, rflags);
|
|
return written;
|
|
}
|
|
|
|
int tty_read_output(int tty_id, char *buf, size_t max_len) {
|
|
tty_t *tty = tty_get(tty_id);
|
|
if (!tty || !buf || max_len == 0) return 0;
|
|
|
|
uint64_t rflags = spinlock_acquire_irqsave(&tty->lock);
|
|
int read = tty_read_ring(tty->out_buf, TTY_OUT_SIZE, &tty->out_head, &tty->out_tail, buf, max_len);
|
|
spinlock_release_irqrestore(&tty->lock, rflags);
|
|
return read;
|
|
}
|
|
|
|
int tty_write_input(int tty_id, const char *data, size_t len) {
|
|
tty_t *tty = tty_get(tty_id);
|
|
if (!tty || !data || len == 0) return 0;
|
|
|
|
uint64_t rflags = spinlock_acquire_irqsave(&tty->lock);
|
|
int written = tty_write_ring(tty->in_buf, TTY_IN_SIZE, &tty->in_head, &tty->in_tail, data, len);
|
|
spinlock_release_irqrestore(&tty->lock, rflags);
|
|
return written;
|
|
}
|
|
|
|
int tty_read_input(int tty_id, char *buf, size_t max_len) {
|
|
tty_t *tty = tty_get(tty_id);
|
|
if (!tty || !buf || max_len == 0) return 0;
|
|
|
|
uint64_t rflags = spinlock_acquire_irqsave(&tty->lock);
|
|
int read = tty_read_ring(tty->in_buf, TTY_IN_SIZE, &tty->in_head, &tty->in_tail, buf, max_len);
|
|
spinlock_release_irqrestore(&tty->lock, rflags);
|
|
return read;
|
|
}
|
|
|
|
int tty_set_foreground(int tty_id, int pid) {
|
|
tty_t *tty = tty_get(tty_id);
|
|
if (!tty) return -1;
|
|
|
|
uint64_t rflags = spinlock_acquire_irqsave(&tty->lock);
|
|
tty->fg_pid = pid;
|
|
spinlock_release_irqrestore(&tty->lock, rflags);
|
|
return 0;
|
|
}
|
|
|
|
int tty_get_foreground(int tty_id) {
|
|
tty_t *tty = tty_get(tty_id);
|
|
if (!tty) return -1;
|
|
|
|
uint64_t rflags = spinlock_acquire_irqsave(&tty->lock);
|
|
int pid = tty->fg_pid;
|
|
spinlock_release_irqrestore(&tty->lock, rflags);
|
|
return pid;
|
|
}
|