mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
kernel: console
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include <kernel/pseudodevices.h>
|
||||
#include <arch/ps2.h>
|
||||
#include <kernel/keyboard.h>
|
||||
#include <kernel/console.h>
|
||||
|
||||
static cpu_t bsp_cpu;
|
||||
|
||||
@@ -62,5 +63,8 @@ void kernel_entry() {
|
||||
keyboard_init();
|
||||
arch_ps2_init();
|
||||
|
||||
console_init();
|
||||
logging_sethook(console_putc);
|
||||
|
||||
__assert(!"kernel entry end");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef _CONSOLE_H
|
||||
#define _CONSOLE_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
void console_init();
|
||||
void console_putc(char c);
|
||||
void console_write(char *str, size_t size);
|
||||
|
||||
#endif
|
||||
@@ -6,6 +6,7 @@
|
||||
#define DEV_MAJOR_NULL 1
|
||||
#define DEV_MAJOR_FULL 2
|
||||
#define DEV_MAJOR_ZERO 3
|
||||
#define DEV_MAJOR_CONSOLE 4
|
||||
|
||||
typedef struct {
|
||||
int (*open)(int minor, int flags);
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef _TERMIOS_H
|
||||
#define _TERMIOS_H
|
||||
|
||||
typedef unsigned char cc_t;
|
||||
typedef unsigned int speed_t;
|
||||
typedef unsigned int tcflag_t;
|
||||
|
||||
#define VINTR 0
|
||||
#define ISIG 0000001
|
||||
#define NCCS 32
|
||||
#define ECHO 0000010
|
||||
#define ICANON 0000002
|
||||
#define VMIN 6
|
||||
#define INLCR 0000100
|
||||
#define IGNCR 0000200
|
||||
#define ICRNL 0000400
|
||||
#define OCRNL 0000010
|
||||
|
||||
typedef struct {
|
||||
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];
|
||||
speed_t ibaud;
|
||||
speed_t obaud;
|
||||
} termios_t;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,177 @@
|
||||
#include <kernel/console.h>
|
||||
#include <mutex.h>
|
||||
#include <ringbuffer.h>
|
||||
#include <logging.h>
|
||||
#include <kernel/term.h>
|
||||
#include <kernel/devfs.h>
|
||||
#include <errno.h>
|
||||
#include <kernel/keyboard.h>
|
||||
#include <termios.h>
|
||||
|
||||
#define BUFFER_SIZE 4096
|
||||
static mutex_t writemutex;
|
||||
static mutex_t readmutex;
|
||||
static semaphore_t readsemaphore;
|
||||
static ringbuffer_t readbuffer;
|
||||
static thread_t *thread;
|
||||
static termios_t termios;
|
||||
|
||||
void console_write(char *str, size_t count) {
|
||||
MUTEX_ACQUIRE(&writemutex, false);
|
||||
|
||||
term_write(str, count);
|
||||
|
||||
MUTEX_RELEASE(&writemutex);
|
||||
}
|
||||
|
||||
void console_putc(char c) {
|
||||
console_write(&c, 1);
|
||||
}
|
||||
|
||||
#define THREAD_BUFFER_SIZE 128
|
||||
|
||||
static void consolethread() {
|
||||
char buffer[THREAD_BUFFER_SIZE + 1];
|
||||
uintmax_t buffpos = 0;
|
||||
|
||||
for (;;) {
|
||||
kbpacket_t packet;
|
||||
keyboard_wait(keyboard_console, &packet);
|
||||
if (packet.flags & KBPACKET_FLAGS_RELEASED)
|
||||
continue;
|
||||
|
||||
char asciibuffer[2] = {0, 0};
|
||||
char *target = asciibuffer;
|
||||
|
||||
if (packet.ascii) {
|
||||
if (packet.ascii == '\r' && (termios.c_iflag & IGNCR))
|
||||
continue;
|
||||
|
||||
if (packet.ascii == '\r' && (termios.c_iflag & ICRNL))
|
||||
packet.ascii = '\n';
|
||||
|
||||
if (packet.ascii == '\n' && (termios.c_iflag & INLCR))
|
||||
packet.ascii = '\r';
|
||||
|
||||
// TODO TRANSLATE TO CTRL CODE IF APPLICABLE
|
||||
} else {
|
||||
// TODO SWITCH OF SPECIAL KEYS
|
||||
}
|
||||
|
||||
asciibuffer[0] = packet.ascii;
|
||||
size_t targetlen = strlen(target);
|
||||
if (targetlen == 0)
|
||||
continue;
|
||||
|
||||
if (termios.c_lflag & ICANON) {
|
||||
bool flush = false;
|
||||
if (packet.ascii == '\b') {
|
||||
if (buffpos == 0)
|
||||
continue;
|
||||
--buffpos;
|
||||
buffer[buffpos] = '\0';
|
||||
if (termios.c_lflag & ECHO)
|
||||
console_write("\b \b", 3);
|
||||
continue;
|
||||
} else if (packet.ascii == '\n') {
|
||||
flush = true;
|
||||
}
|
||||
|
||||
if (termios.c_lflag & ECHO)
|
||||
console_write(target, targetlen);
|
||||
|
||||
for (size_t i = 0; i < targetlen; ++i) {
|
||||
buffer[buffpos++] = target[i];
|
||||
if (buffpos == THREAD_BUFFER_SIZE) {
|
||||
flush = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flush) {
|
||||
MUTEX_ACQUIRE(&readmutex, false);
|
||||
bool hasdata = readbuffer.write - readbuffer.read > 0;
|
||||
ringbuffer_write(&readbuffer, buffer, buffpos);
|
||||
buffpos = 0;
|
||||
if (hasdata == false)
|
||||
semaphore_signal(&readsemaphore);
|
||||
MUTEX_RELEASE(&readmutex);
|
||||
}
|
||||
} else {
|
||||
if (termios.c_lflag & ECHO)
|
||||
console_write(target, targetlen);
|
||||
|
||||
MUTEX_ACQUIRE(&readmutex, false);
|
||||
bool hasdata = readbuffer.write - readbuffer.read > 0;
|
||||
ringbuffer_write(&readbuffer, target, targetlen);
|
||||
if (hasdata == false)
|
||||
semaphore_signal(&readsemaphore);
|
||||
MUTEX_RELEASE(&readmutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int read(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *readc) {
|
||||
size_t total = 0;
|
||||
for (;;) {
|
||||
if (semaphore_test(&readsemaphore) == false) {
|
||||
*readc = 0;
|
||||
if (termios.c_cc[VMIN] == 0)
|
||||
return 0;
|
||||
|
||||
if (flags & V_FFLAGS_NONBLOCKING)
|
||||
return EAGAIN;
|
||||
|
||||
int i = semaphore_wait(&readsemaphore, true);
|
||||
if (i)
|
||||
return i;
|
||||
}
|
||||
|
||||
MUTEX_ACQUIRE(&readmutex, false);
|
||||
|
||||
size_t read = ringbuffer_read(&readbuffer, buffer, size);
|
||||
size_t left = readbuffer.write - readbuffer.read;
|
||||
|
||||
MUTEX_RELEASE(&readmutex);
|
||||
|
||||
size -= read;
|
||||
buffer = (void *)((uintptr_t)buffer + read);
|
||||
total += read;
|
||||
|
||||
if (size == 0 || total >= termios.c_cc[VMIN]) {
|
||||
if (left > 0)
|
||||
semaphore_signal(&readsemaphore);
|
||||
*readc = total;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int write(int minor, void *buffer, size_t size, uintmax_t offset, int flags, size_t *writec) {
|
||||
*writec = size;
|
||||
console_write(buffer, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static devops_t devops = {
|
||||
.write = write,
|
||||
.read = read
|
||||
};
|
||||
|
||||
void console_init() {
|
||||
SEMAPHORE_INIT(&readsemaphore, 0);
|
||||
MUTEX_INIT(&writemutex);
|
||||
MUTEX_INIT(&readmutex);
|
||||
__assert(ringbuffer_init(&readbuffer, BUFFER_SIZE) == 0);
|
||||
__assert(devfs_register(&devops, "console", V_TYPE_CHDEV, DEV_MAJOR_CONSOLE, 0, 0644) == 0);
|
||||
thread = sched_newthread(consolethread, PAGE_SIZE * 16, 0, NULL, NULL);
|
||||
__assert(thread);
|
||||
sched_queue(thread);
|
||||
|
||||
termios.c_iflag = ICRNL;
|
||||
termios.c_lflag = ECHO | ICANON | ISIG;
|
||||
termios.c_cc[VINTR] = 0x03;
|
||||
termios.ibaud = 38400;
|
||||
termios.obaud = 38400;
|
||||
termios.c_cc[VMIN] = 1;
|
||||
}
|
||||
Reference in New Issue
Block a user