From: Tulio A M Mendes Date: Tue, 17 Feb 2026 07:45:06 +0000 (-0300) Subject: fix: keyboard CTRL key support for CTRL+C/CTRL+Z in shell X-Git-Url: https://projects.tadryanom.me/docs/static/gitweb.js?a=commitdiff_plain;h=94a9f6cb77cfbb28126e4f1e8e33addc7fe4b97a;p=AdrOS.git fix: keyboard CTRL key support for CTRL+C/CTRL+Z in shell Root cause: The PS/2 keyboard driver had no CTRL key tracking. When CTRL was held and a letter pressed, the driver sent the plain letter character (e.g., 'c') instead of the control character (e.g., 0x03 for CTRL+C). Fix: Added ctrl_held state tracking in hal/x86/keyboard.c for Left CTRL (scancode 0x1D press / 0x9D release). When CTRL is held and a letter key is pressed, emit (c & 0x1F) — the standard control character encoding: CTRL+C = 0x03, CTRL+Z = 0x1A, CTRL+D = 0x04, etc. Shell read_line_edit() already handled these bytes correctly: - 0x03 (CTRL+C): prints ^C, newline, cancels current line - 0x1A (CTRL+Z): ignored at prompt (no foreground job) - 0x04 (CTRL+D): EOF on empty line During command execution, tty_restore() re-enables ISIG, so the TTY kernel driver intercepts CTRL+C/CTRL+Z and sends SIGINT/SIGTSTP to the foreground process group via TIOCSPGRP. --- diff --git a/src/hal/x86/keyboard.c b/src/hal/x86/keyboard.c index 11fbe4c..e85a14c 100644 --- a/src/hal/x86/keyboard.c +++ b/src/hal/x86/keyboard.c @@ -10,6 +10,7 @@ static hal_keyboard_scan_cb_t g_scan_cb = 0; /* Modifier state */ static volatile int shift_held = 0; +static volatile int ctrl_held = 0; /* Extended scancode state (0xE0 prefix) */ static volatile int e0_prefix = 0; @@ -103,6 +104,8 @@ static void emit_escape_seq(const char* seq) { #define SC_RSHIFT_PRESS 0x36 #define SC_LSHIFT_REL 0xAA #define SC_RSHIFT_REL 0xB6 +#define SC_LCTRL_PRESS 0x1D +#define SC_LCTRL_REL 0x9D /* Extended (0xE0-prefixed) scancodes */ #define SC_E0_UP 0x48 @@ -169,7 +172,7 @@ static void kbd_irq(struct registers* regs) { return; } - /* Track shift state */ + /* Track modifier state */ if (scancode == SC_LSHIFT_PRESS || scancode == SC_RSHIFT_PRESS) { shift_held = 1; return; @@ -178,6 +181,14 @@ static void kbd_irq(struct registers* regs) { shift_held = 0; return; } + if (scancode == SC_LCTRL_PRESS) { + ctrl_held = 1; + return; + } + if (scancode == SC_LCTRL_REL) { + ctrl_held = 0; + return; + } /* Ignore key releases for normal keys */ if (scancode & 0x80) return; @@ -185,7 +196,13 @@ static void kbd_irq(struct registers* regs) { if (scancode < 128) { char c = shift_held ? scancode_map_shift[scancode] : scancode_map[scancode]; if (c != 0 && g_cb) { - g_cb(c); + if (ctrl_held && c >= 'a' && c <= 'z') { + g_cb(c - 'a' + 1); /* Ctrl+A=0x01 .. Ctrl+Z=0x1A */ + } else if (ctrl_held && c >= 'A' && c <= 'Z') { + g_cb(c - 'A' + 1); + } else { + g_cb(c); + } } } } diff --git a/user/sh.c b/user/sh.c index 14ff5f4..1af3ab3 100644 --- a/user/sh.c +++ b/user/sh.c @@ -313,6 +313,11 @@ static int read_line_edit(void) { return 0; } + /* Ctrl+Z = ignored at prompt (no foreground job to suspend) */ + if (c == 26) { + continue; + } + /* Ctrl+A = beginning of line */ if (c == 1) { while (pos > 0) { term_write("\b", 1); pos--; }