This commit is contained in:
2026-04-11 12:48:51 +08:00
parent d459b7a39a
commit ef331b4a6b
6 changed files with 138 additions and 6 deletions

View File

@@ -85,6 +85,7 @@ C_SOURCES := \
clks/kernel/tty.c \
clks/kernel/pmm.c \
clks/kernel/heap.c \
clks/kernel/keyboard.c \
clks/kernel/interrupts.c \
clks/kernel/scheduler.c \
clks/kernel/elf64.c \

View File

@@ -0,0 +1,10 @@
#ifndef CLKS_KEYBOARD_H
#define CLKS_KEYBOARD_H
#include <clks/types.h>
void clks_keyboard_init(void);
void clks_keyboard_handle_scancode(u8 scancode);
u64 clks_keyboard_hotkey_switch_count(void);
#endif

View File

@@ -2,6 +2,7 @@
#include <clks/cpu.h>
#include <clks/interrupts.h>
#include <clks/log.h>
#include <clks/keyboard.h>
#include <clks/scheduler.h>
#include <clks/syscall.h>
#include <clks/types.h>
@@ -18,9 +19,13 @@
#define CLKS_IRQ_BASE 32U
#define CLKS_IRQ_TIMER 32U
#define CLKS_IRQ_KEYBOARD 33U
#define CLKS_IRQ_LAST 47U
#define CLKS_SYSCALL_VECTOR 128U
#define CLKS_PS2_DATA_PORT 0x60U
#define CLKS_PS2_STATUS_PORT 0x64U
struct clks_idt_entry {
u16 offset_low;
u16 selector;
@@ -192,7 +197,7 @@ static void clks_pic_remap_and_mask(void) {
(void)master_mask;
(void)slave_mask;
clks_outb(CLKS_PIC1_DATA, 0xFEU);
clks_outb(CLKS_PIC1_DATA, 0xFCU);
clks_outb(CLKS_PIC2_DATA, 0xFFU);
}
@@ -225,6 +230,10 @@ static void clks_load_idt(void) {
__asm__ volatile("lidt %0" : : "m"(idtr));
}
static clks_bool clks_ps2_has_output(void) {
return (clks_inb(CLKS_PS2_STATUS_PORT) & 0x01U) != 0U ? CLKS_TRUE : CLKS_FALSE;
}
static void clks_enable_interrupts(void) {
__asm__ volatile("sti");
}
@@ -248,6 +257,11 @@ void clks_interrupt_dispatch(struct clks_interrupt_frame *frame) {
if (vector == CLKS_IRQ_TIMER) {
clks_timer_ticks++;
clks_scheduler_on_timer_tick(clks_timer_ticks);
} else if (vector == CLKS_IRQ_KEYBOARD) {
if (clks_ps2_has_output() == CLKS_TRUE) {
u8 scancode = clks_inb(CLKS_PS2_DATA_PORT);
clks_keyboard_handle_scancode(scancode);
}
}
if (vector >= CLKS_IRQ_BASE && vector <= CLKS_IRQ_LAST) {

53
clks/kernel/keyboard.c Normal file
View File

@@ -0,0 +1,53 @@
#include <clks/keyboard.h>
#include <clks/log.h>
#include <clks/tty.h>
#include <clks/types.h>
#define CLKS_SC_ALT 0x38U
#define CLKS_SC_F1 0x3BU
#define CLKS_SC_F2 0x3CU
#define CLKS_SC_F3 0x3DU
#define CLKS_SC_F4 0x3EU
static clks_bool clks_kbd_alt_down = CLKS_FALSE;
static u64 clks_kbd_hotkey_switches = 0ULL;
void clks_keyboard_init(void) {
clks_kbd_alt_down = CLKS_FALSE;
clks_kbd_hotkey_switches = 0ULL;
clks_log(CLKS_LOG_INFO, "KBD", "ALT+F1..F4 TTY HOTKEY ONLINE");
}
void clks_keyboard_handle_scancode(u8 scancode) {
clks_bool released = ((scancode & 0x80U) != 0U) ? CLKS_TRUE : CLKS_FALSE;
u8 code = (u8)(scancode & 0x7FU);
if (code == CLKS_SC_ALT) {
clks_kbd_alt_down = (released == CLKS_FALSE) ? CLKS_TRUE : CLKS_FALSE;
return;
}
if (released == CLKS_TRUE || clks_kbd_alt_down == CLKS_FALSE) {
return;
}
if (code >= CLKS_SC_F1 && code <= CLKS_SC_F4) {
u32 target = (u32)(code - CLKS_SC_F1);
u32 before = clks_tty_active();
u32 after;
clks_tty_switch(target);
after = clks_tty_active();
if (after != before) {
clks_kbd_hotkey_switches++;
clks_log(CLKS_LOG_INFO, "TTY", "HOTKEY SWITCH");
clks_log_hex(CLKS_LOG_INFO, "TTY", "ACTIVE", (u64)after);
clks_log_hex(CLKS_LOG_INFO, "TTY", "HOTKEY_SWITCHES", clks_kbd_hotkey_switches);
}
}
}
u64 clks_keyboard_hotkey_switch_count(void) {
return clks_kbd_hotkey_switches;
}

View File

@@ -7,6 +7,7 @@
#include <clks/fs.h>
#include <clks/heap.h>
#include <clks/interrupts.h>
#include <clks/keyboard.h>
#include <clks/kelf.h>
#include <clks/kernel.h>
#include <clks/log.h>
@@ -63,7 +64,7 @@ static void clks_task_usrd(u64 tick) {
clks_userland_tick(tick);
}
static void clks_stage14_syscall_probe(void) {
static void clks_stage15_syscall_probe(void) {
char child_name[96];
char read_buf[160];
u64 root_children;
@@ -170,7 +171,7 @@ void clks_kernel_main(void) {
clks_tty_init();
}
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE14 START");
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE15 START");
if (boot_fb == CLKS_NULL) {
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
@@ -233,6 +234,7 @@ void clks_kernel_main(void) {
}
clks_exec_init();
clks_keyboard_init();
if (clks_userland_init() == CLKS_FALSE) {
clks_log(CLKS_LOG_ERROR, "USER", "USERLAND INIT FAILED");
@@ -279,11 +281,10 @@ void clks_kernel_main(void) {
syscall_ticks = clks_syscall_invoke_kernel(CLKS_SYSCALL_TIMER_TICKS, 0ULL, 0ULL, 0ULL);
clks_log_hex(CLKS_LOG_INFO, "SYSCALL", "TICKS", syscall_ticks);
clks_stage14_syscall_probe();
clks_stage15_syscall_probe();
clks_log(CLKS_LOG_INFO, "TTY", "VIRTUAL TTY0 READY");
clks_log(CLKS_LOG_DEBUG, "KERNEL", "IDLE LOOP ENTER");
clks_cpu_halt_forever();
}

53
docs/stage15.md Normal file
View File

@@ -0,0 +1,53 @@
# CLeonOS Stage15
## Stage Goal
- Keep ELF path unchanged and continue non-ELF stability work.
- Add PS/2 keyboard IRQ handling in kernel interrupt path.
- Support virtual terminal hotkey switching with `Alt+F1`~`Alt+F4`.
- Keep scheduler, syscall, and existing Stage14 behavior stable.
## What Was Implemented
- New keyboard module:
- `clks/include/clks/keyboard.h`
- `clks/kernel/keyboard.c`
- Interrupt integration:
- Enable IRQ1 (keyboard) alongside IRQ0 in PIC mask.
- Read scancode from PS/2 data port `0x60`.
- Dispatch scancode to keyboard hotkey handler.
- Hotkey behavior:
- Hold `Alt` + press `F1/F2/F3/F4` to switch TTY 0/1/2/3.
- On successful switch, kernel logs active TTY and switch counter.
- Boot stage update:
- `CLEONOS STAGE15 START`.
## Acceptance Criteria
- Kernel boots and prints `CLEONOS STAGE15 START`.
- Boot logs include keyboard module online message:
- `[INFO][KBD] ALT+F1..F4 TTY HOTKEY ONLINE`
- In QEMU runtime:
- Press `Alt+F2` / `Alt+F3` / `Alt+F4` / `Alt+F1`.
- Logs show:
- `[INFO][TTY] HOTKEY SWITCH`
- `[INFO][TTY] ACTIVE: 0X...`
- `[INFO][TTY] HOTKEY_SWITCHES: 0X...`
## Build Targets
- `make setup`
- `make userapps`
- `make iso`
- `make run`
- `make debug`
## QEMU Command
- `qemu-system-x86_64 -M q35 -m 1024M -cdrom build/CLeonOS-x86_64.iso -serial stdio`
## Common Bugs and Debugging
- Hotkey has no effect:
- Verify QEMU window is focused and keyboard input is captured.
- Confirm logs show Stage15 keyboard online message.
- IRQ timer works but keyboard does not:
- Re-check PIC mask includes IRQ1 (master mask should allow IRQ0 and IRQ1).
- Wrong function key mapping:
- Current mapping is Set1 scancode: F1=0x3B, F2=0x3C, F3=0x3D, F4=0x3E.
- Excessive hotkey logs:
- Holding key may repeat make scancode by keyboard auto-repeat; this is expected in current stage.