基础vt1000框架
This commit is contained in:
parent
ab6763337a
commit
288db801e1
@ -6,15 +6,47 @@
|
||||
|
||||
typedef void (*key_lis) (uint8_t);
|
||||
|
||||
typedef enum {
|
||||
MODE_A = 'A',
|
||||
MODE_B = 'B',
|
||||
MODE_C = 'C',
|
||||
MODE_D = 'D',
|
||||
MODE_E = 'E',
|
||||
MODE_F = 'F',
|
||||
MODE_G = 'G',
|
||||
MODE_H = 'H',
|
||||
MODE_f = 'f',
|
||||
MODE_J = 'J',
|
||||
MODE_K = 'K',
|
||||
MODE_S = 'S',
|
||||
MODE_T = 'T',
|
||||
MODE_m = 'm'
|
||||
} vt100_mode_t;
|
||||
|
||||
typedef struct tty{
|
||||
uint32_t *frame_buffer; // 图形缓冲区映射
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
bool is_default_frame; // 是否为根缓冲区
|
||||
void (*print)(struct tty *res,const char *string);
|
||||
void (*putchar)(struct tty *res,int c);
|
||||
void (*MoveCursor)(struct tty *res,int x, int y);
|
||||
void (*clear)(struct tty *res);
|
||||
void (*gotoxy)(struct tty *res, int x, int y);
|
||||
void (*screen_ne)(struct tty *res);
|
||||
|
||||
|
||||
bool is_using; // 是否可以接受输入
|
||||
struct FIFO8 *fifo; // 键盘输出缓冲区
|
||||
key_lis keyboard_press; // 键盘按下
|
||||
key_lis keyboard_release; // 键盘松开
|
||||
int xsize, ysize;
|
||||
int x, y;
|
||||
uint8_t color;
|
||||
|
||||
/* vt100 */
|
||||
int vt100; // 是否检测到标志
|
||||
char buffer[81]; // 缓冲区
|
||||
int buf_p; // 缓冲区指针
|
||||
int done; // 这个东西读取完毕没有?
|
||||
vt100_mode_t mode; // 控制模式
|
||||
int color_saved; // 保存的颜色
|
||||
}tty_t;
|
||||
|
||||
#include "task.h"
|
||||
|
@ -73,7 +73,6 @@ int check_task(int *pid){
|
||||
}
|
||||
|
||||
int check_task_usershell(int *pid){
|
||||
while (1) asm("hlt");
|
||||
struct task_struct *shell = found_task_pid(*pid);
|
||||
while (1){
|
||||
if(shell->state == TASK_DEATH){
|
||||
|
@ -403,6 +403,7 @@ void init_sched() {
|
||||
current->mem_size = 0;
|
||||
current->next = current;
|
||||
current->isUser = 0;
|
||||
init_default_tty(current);
|
||||
|
||||
extern header_t *head;
|
||||
extern header_t *tail;
|
||||
|
353
src/kernel/tty.c
353
src/kernel/tty.c
@ -1,27 +1,366 @@
|
||||
#include "../include/tty.h"
|
||||
#include "../include/task.h"
|
||||
#include "../include/graphics.h"
|
||||
#include "../include/printf.h"
|
||||
|
||||
extern uint32_t *screen;
|
||||
extern uint32_t width, height;
|
||||
|
||||
static char eos[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'f', 'J', 'K', 'S', 'T', 'm'};
|
||||
// vt100控制字符中可能的结束符号
|
||||
|
||||
static inline int t_is_eos(char ch) {
|
||||
for (int i = 0; i < sizeof(eos); i++) {
|
||||
if (ch == eos[i]) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline long atol(char* s) {
|
||||
bool neg = *s == '-';
|
||||
if (neg || *s == '+') s++;
|
||||
long n = 0;
|
||||
for (; isdigit(*s); s++)
|
||||
n = n * 10 + (*s - '0');
|
||||
return neg ? -n : n;
|
||||
}
|
||||
|
||||
static void tty_gotoxy(struct tty *res, int x, int y) {
|
||||
if (res->x == x && res->y == y) return;
|
||||
if (x >= 0 && y >= 0) {
|
||||
int x2 = x;
|
||||
int y2 = y;
|
||||
if (x <= res->xsize - 1 && y <= res->ysize - 1) {
|
||||
res->MoveCursor(res, x, y);
|
||||
return;
|
||||
}
|
||||
if (x <= res->xsize - 1) {
|
||||
for (int i = 0; i < y - res->ysize + 1; i++) {
|
||||
res->screen_ne(res);
|
||||
}
|
||||
res->MoveCursor(res, x, res->ysize - 1);
|
||||
return;
|
||||
}
|
||||
if (x > res->xsize - 1) {
|
||||
y2 += x / res->xsize - 1;
|
||||
x2 = x % res->xsize;
|
||||
if (y2 <= res->ysize - 1)
|
||||
tty_gotoxy(res, x2, y2 + 1);
|
||||
else
|
||||
tty_gotoxy(res, x2, y2);
|
||||
}
|
||||
} else {
|
||||
if (x < 0) {
|
||||
x += res->xsize;
|
||||
y--;
|
||||
tty_gotoxy(res, x, y);
|
||||
}
|
||||
if (y < 0) { return; }
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_vt100(struct tty *res, char *string) {
|
||||
switch (res->mode) {
|
||||
case MODE_A: {
|
||||
char dig_string[81] = {0};
|
||||
for (int i = 2, j = 0; string[i]; i++) {
|
||||
if (t_is_eos(string[i])) break;
|
||||
if (!isdigit(string[i])) return 0;
|
||||
dig_string[j++] = string[i];
|
||||
}
|
||||
int delta = atol(dig_string);
|
||||
if (!delta) delta = 1;
|
||||
res->gotoxy(res, res->x, res->y - delta);
|
||||
return 1;
|
||||
}
|
||||
case MODE_B: {
|
||||
char dig_string[81] = {0};
|
||||
for (int i = 2, j = 0; string[i]; i++) {
|
||||
if (t_is_eos(string[i])) break;
|
||||
if (!isdigit(string[i])) return 0;
|
||||
dig_string[j++] = string[i];
|
||||
}
|
||||
int delta = atol(dig_string);
|
||||
if (!delta) delta = 1;
|
||||
res->gotoxy(res, res->x, res->y + delta);
|
||||
return 1;
|
||||
}
|
||||
case MODE_C: {
|
||||
char dig_string[81] = {0};
|
||||
for (int i = 2, j = 0; string[i]; i++) {
|
||||
if (t_is_eos(string[i])) break;
|
||||
if (!isdigit(string[i])) return 0;
|
||||
dig_string[j++] = string[i];
|
||||
}
|
||||
int delta = atol(dig_string);
|
||||
if (!delta) delta = 1;
|
||||
res->gotoxy(res, res->x + delta, res->y);
|
||||
return 1;
|
||||
}
|
||||
case MODE_D: {
|
||||
char dig_string[81] = {0};
|
||||
for (int i = 2, j = 0; string[i]; i++) {
|
||||
if (t_is_eos(string[i])) break;
|
||||
if (!isdigit(string[i])) return 0;
|
||||
dig_string[j++] = string[i];
|
||||
}
|
||||
int delta = atol(dig_string);
|
||||
if (!delta) delta = 1;
|
||||
res->gotoxy(res, res->x - delta, res->y);
|
||||
return 1;
|
||||
}
|
||||
case MODE_E: {
|
||||
char dig_string[81] = {0};
|
||||
for (int i = 2, j = 0; string[i]; i++) {
|
||||
if (t_is_eos(string[i])) break;
|
||||
if (!isdigit(string[i])) return 0;
|
||||
dig_string[j++] = string[i];
|
||||
}
|
||||
int delta = atol(dig_string);
|
||||
if (!delta) delta = 1;
|
||||
res->gotoxy(res, 0, res->y + delta);
|
||||
return 1;
|
||||
}
|
||||
case MODE_F: {
|
||||
char dig_string[81] = {0};
|
||||
for (int i = 2, j = 0; string[i]; i++) {
|
||||
if (t_is_eos(string[i])) break;
|
||||
if (!isdigit(string[i])) return 0;
|
||||
dig_string[j++] = string[i];
|
||||
}
|
||||
int delta = atol(dig_string);
|
||||
if (!delta) delta = 1;
|
||||
res->gotoxy(res, 0, res->y - delta);
|
||||
return 1;
|
||||
}
|
||||
case MODE_G: {
|
||||
char dig_string[81] = {0};
|
||||
for (int i = 2, j = 0; string[i]; i++) {
|
||||
if (t_is_eos(string[i])) break;
|
||||
if (!isdigit(string[i])) return 0;
|
||||
dig_string[j++] = string[i];
|
||||
}
|
||||
int delta = atol(dig_string);
|
||||
if (!delta) delta = 1;
|
||||
res->gotoxy(res, delta - 1, res->y); // 可能是这样的
|
||||
return 1;
|
||||
}
|
||||
case MODE_H: {
|
||||
int k = 0;
|
||||
char dig_string[2][81];
|
||||
memset(dig_string, 0, sizeof(dig_string)); // 全部设置为0
|
||||
for (int i = 2, j = 0; string[i]; i++) {
|
||||
if (t_is_eos(string[i])) break;
|
||||
if (!isdigit(string[i])) {
|
||||
if (string[i] == ';') { // 分号
|
||||
k++;
|
||||
j = 0;
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
dig_string[k][j++] = string[i];
|
||||
}
|
||||
if (k > 1) return 0;
|
||||
|
||||
int delta[2] = {0};
|
||||
for (int i = 0; i <= k; i++) {
|
||||
delta[i] = atol(dig_string[i]);
|
||||
}
|
||||
if (k == 0 && delta[0] != 0) return 0;
|
||||
switch (k) {
|
||||
case 0: res->gotoxy(res, 0, 0); break;
|
||||
case 1: res->gotoxy(res, delta[0], delta[1]); break;
|
||||
default: return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
case MODE_J: {
|
||||
char dig_string[81] = {0};
|
||||
for (int i = 2, j = 0; string[i]; i++) {
|
||||
if (t_is_eos(string[i])) break;
|
||||
if (!isdigit(string[i])) return 0;
|
||||
dig_string[j++] = string[i];
|
||||
}
|
||||
int delta = atol(dig_string);
|
||||
int old_x = res->x, old_y = res->y;
|
||||
switch (delta) {
|
||||
case 0: {
|
||||
int flag = 0;
|
||||
for (int i = old_y * res->xsize + old_x; i < res->xsize * res->ysize; i++) {
|
||||
flag = 1;
|
||||
res->putchar(res, ' ');
|
||||
}
|
||||
if (flag) res->gotoxy(res, old_x, old_y);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
res->gotoxy(res, 0, 0);
|
||||
for (int i = 0; i < old_y * res->xsize + old_x; i++) {
|
||||
res->putchar(res, ' ');
|
||||
}
|
||||
break;
|
||||
case 2: res->clear(res); break;
|
||||
default: return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
case MODE_K: {
|
||||
char dig_string[81] = {0};
|
||||
for (int i = 2, j = 0; string[i]; i++) {
|
||||
if (t_is_eos(string[i])) break;
|
||||
if (!isdigit(string[i])) return 0;
|
||||
dig_string[j++] = string[i];
|
||||
}
|
||||
int delta = atol(dig_string);
|
||||
int old_x = res->x, old_y = res->y;
|
||||
switch (delta) {
|
||||
case 0: {
|
||||
int flag = 0;
|
||||
for (int i = old_y * res->xsize + old_x; i < (old_y + 1) * res->ysize; i++) {
|
||||
flag = 1;
|
||||
res->putchar(res, ' ');
|
||||
}
|
||||
if (flag) res->gotoxy(res, old_x, old_y);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
res->gotoxy(res, 0, res->y);
|
||||
for (int i = old_y * res->xsize; i < old_y * res->xsize + old_x; i++) {
|
||||
res->putchar(res, ' ');
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
res->gotoxy(res, 0, res->y);
|
||||
for (int i = old_y * res->xsize; i < (old_y + 1) * res->xsize; i++) {
|
||||
res->putchar(res, ' ');
|
||||
}
|
||||
res->gotoxy(res, old_x, old_y);
|
||||
break;
|
||||
default: return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
case MODE_S: return 0; // unsupported
|
||||
case MODE_T: {
|
||||
char dig_string[81] = {0};
|
||||
for (int i = 2, j = 0; string[i]; i++) {
|
||||
if (t_is_eos(string[i])) break;
|
||||
if (!isdigit(string[i])) return 0;
|
||||
dig_string[j++] = string[i];
|
||||
}
|
||||
int delta = atol(dig_string);
|
||||
if (delta) return 0;
|
||||
res->screen_ne(res);
|
||||
return 1;
|
||||
}
|
||||
case MODE_m: {
|
||||
// klogd("MODE_m");
|
||||
int k = 0;
|
||||
char dig_string[2][81];
|
||||
memset(dig_string, 0, sizeof(dig_string)); // 全部设置为0
|
||||
for (int i = 2, j = 0; string[i]; i++) {
|
||||
if (t_is_eos(string[i])) break;
|
||||
if (!isdigit(string[i])) {
|
||||
if (string[i] == ';') { // 分号
|
||||
k++;
|
||||
j = 0;
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
dig_string[k][j++] = string[i];
|
||||
}
|
||||
if (k > 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int delta[2] = {0};
|
||||
// klogd("start for %d", k);
|
||||
for (int i = 0; i <= k; i++) {
|
||||
delta[i] = atol(dig_string[i]);
|
||||
}
|
||||
if (delta[0] == 0 && k == 0) {
|
||||
int sel_color = res->color_saved != -1 ? res->color_saved : res->color;
|
||||
res->color = sel_color;
|
||||
res->color_saved = -1;
|
||||
return 1;
|
||||
} else if (delta[0] == 1 && k == 0) { // unsupported
|
||||
return 0;
|
||||
}
|
||||
// klogd("switch k");
|
||||
static const uint8_t color_map[8] = {0, 4, 2, 6, 1, 5, 3, 7};
|
||||
switch (k) {
|
||||
case 0: {
|
||||
if (delta[0] >= 30 && delta[0] <= 37) { // foreground color
|
||||
if (res->color_saved == -1) res->color_saved = res->color;
|
||||
res->color &= 0xf0;
|
||||
res->color |= color_map[delta[0] - 30];
|
||||
return 1;
|
||||
} else if (delta[0] >= 40 && delta[0] <= 47) {
|
||||
if (res->color_saved == -1) res->color_saved = res->color;
|
||||
res->color &= 0x0f;
|
||||
res->color |= color_map[delta[0] - 40] << 4;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
case 1: {
|
||||
if (delta[0] != 1) {
|
||||
return 0;
|
||||
}
|
||||
if (delta[1] >= 30 && delta[1] <= 37) { // foreground color
|
||||
if (res->color_saved == -1) { res->color_saved = res->color; }
|
||||
res->color &= 0xf0;
|
||||
res->color |= color_map[delta[1] - 30] + 8;
|
||||
return 1;
|
||||
} else if (delta[1] >= 40 && delta[1] <= 47) {
|
||||
if (res->color_saved == -1) res->color_saved = res->color;
|
||||
res->color &= 0x0f;
|
||||
res->color |= (color_map[delta[1] - 40] + 8) << 4;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tty_print(struct tty *res,const char *string){
|
||||
vbe_writestring(string);
|
||||
}
|
||||
void tty_putchar(struct tty *res,int c){
|
||||
vbe_putchar(c);
|
||||
}
|
||||
void tty_MoveCursor(struct tty *res,int x, int y){
|
||||
|
||||
}
|
||||
void tty_clear(struct tty *res){
|
||||
vbe_clear();
|
||||
}
|
||||
|
||||
void init_default_tty(struct task_struct *task){
|
||||
task->tty->fifo = kmalloc(sizeof(struct FIFO8));
|
||||
char* buffer = kmalloc(256);
|
||||
|
||||
task->tty->frame_buffer = screen;
|
||||
task->tty->width = width;
|
||||
task->tty->height = height;
|
||||
task->tty->is_default_frame = true;
|
||||
task->tty->is_using = true;
|
||||
task->tty->print = tty_print;
|
||||
task->tty->clear = tty_clear;
|
||||
task->tty->putchar = tty_putchar;
|
||||
task->tty->gotoxy = tty_gotoxy;
|
||||
|
||||
fifo8_init(task->tty->fifo,256,buffer);
|
||||
}
|
||||
|
||||
void free_tty(struct task_struct *task){
|
||||
if(!task->tty->is_default_frame){
|
||||
kfree(task->tty->frame_buffer);
|
||||
}
|
||||
kfree(task->tty->fifo->buf);
|
||||
kfree(task->tty->fifo);
|
||||
kfree(task->tty);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "../include/common.h"
|
||||
#include "../include/graphics.h"
|
||||
#include "../include/serial.h"
|
||||
#include "../include/tty.h"
|
||||
|
||||
static int skip_atoi(const char **s) {
|
||||
int i = 0;
|
||||
@ -305,18 +306,38 @@ void printf(const char *formet, ...) {
|
||||
}
|
||||
|
||||
void screen_clear(){
|
||||
struct task_struct *task = get_current();
|
||||
if(task != NULL){
|
||||
task->tty->clear(task->tty);
|
||||
return;
|
||||
}
|
||||
|
||||
if(vbe_status){
|
||||
vbe_clear();
|
||||
} else vga_clear();
|
||||
}
|
||||
|
||||
void putchar(char c){
|
||||
struct task_struct *task = get_current();
|
||||
if(task != NULL){
|
||||
task->tty->putchar(task->tty,c);
|
||||
return;
|
||||
}
|
||||
|
||||
if(vbe_status){
|
||||
vbe_putchar(c);
|
||||
} else vga_putchar(c);
|
||||
}
|
||||
|
||||
void print(char *message) {
|
||||
struct task_struct *task = get_current();
|
||||
if(task != NULL){
|
||||
task->tty->print(task->tty,message);
|
||||
return;
|
||||
}
|
||||
|
||||
logk(message);
|
||||
|
||||
if(vbe_status){
|
||||
vbe_writestring(message);
|
||||
} else vga_writestring(message);
|
||||
|
Loading…
Reference in New Issue
Block a user