18 Commits
Author SHA1 Message Date
TermiNexus eb953bb1d3 feat(keyboard): 接入 USB 键盘输入到 /dev/input/keyboard
现场证据:keyboard.init 的 0xF4 被 ACK,但按键时 [kbd] first IRQ1 从不出现;同时 [usb] device addr=1 class=03 proto=01 ep=1 说明真实按键来自 USB 键盘。usb_kbd 已通过 UHCI 中断回调收到报告并生成 kbd_buf 事件,但全仓无人消费(usb_kbd_thread 从未启动),所以 /dev/input/keyboard 永远读不到 USB 按键。① keyboard.vp 新增 inject_byte/inject_csi/inject_csi_tilde 三个公开注入函数,复用 _out_push/_emit_csi,不改 read_scancode/has_data/irq_handler 语义。② usb_kbd.vp 在 _on_int_complete 的按下沿(与上一帧 6 键码比较后新出现的键)按 boot protocol(枚举时已 SET_PROTOCOL(0):modifier+reserved+keycode[6])解码成 ASCII/ANSI,注入同一 out_buf:字母数字含 Shift/CapsLock、Enter\\n、Backspace\\b、方向键 ESC[A/B/C/D、Home/End ESC[H/F、Delete/PgUp/PgDn/Insert ESC[3~/5~/6~/2~,与 PS/2 路径一致;按住不重复、松开不产字节。③ 不新建线程、不启动 kbd_thread,USB 与 PS/2 共用同一队列,中断上下文内写入(IF=0)。④ 加一次性诊断 [usb_kbd] first key。
2026-10-17 15:43:48 +08:00
TermiNexus 4195b05f75 diag(keyboard): IRQ1 首达与 0xF4 ACK 打点
键盘仍无字符。加两条一次性诊断:① irq_handler 首次触发打 [kbd] first IRQ1(判断中断是否送达);② init() 的 0xF4 扫描使能命令按 ACK 结果打 ok/not ACKed(判断命令是否送到键盘)。两者组合可区分'命令没送达'、'中断没到'、'解码丢字节'三种情况。
2026-10-17 15:33:55 +08:00
TermiNexus 850c4b8adc fix(keyboard,explorer): 键盘解码单队列化消除读循环自旋;关窗清理悬垂状态
① 卡死/键盘无效:has_data() 把'原始待解码'与'已解码可读'混成一个计数,而 read_scancode() 只看已解码队列;一旦出现 has_data()>0 但本次取不到字节(断码/修饰键/E0 前缀),devfs 的读循环里 count 不前进而 has_data() 恒真 ⇒ asm.sti() 后无 yield 自旋,协作式调度下整机停死。改为解码下沉到 IRQ、只保留一个输出队列(has_data()==out_count,read_scancode() 返回 0 ⟺ 队列空),ANSI 序列整条原子入队;devfs 读循环以 read_scancode() 返回 0 为唯一终止条件。② 关窗:DESTROY 与关闭键路径清 drag_win,focus/_activate_from_taskbar 校验槽位存活;poll_requests 单轮最多处理一圈(head 已推进,剩余留到下轮,不丢消息也不自旋)。③ vpui:孤立 ESC 后紧跟的普通键不再被吞。
2026-10-17 13:20:22 +08:00
TermiNexus 266e6fbcfb feat(keyboard): 恢复 Shift/CapsLock 与方向键等特殊键
旧内核桌面 desktop.vp 里有完整的键盘解码(修饰键状态、特殊键映射、重复),S3e 下沉后丢了,只剩一个简化 scancode_to_ascii(shift/caps 字段从未赋值、方向键返回 0 被丢)。① 内核 keyboard.vp:新增解码层 _decode_scancode + 输出队列,跟踪 Shift(0x2A/0x36)/CapsLock(0x3A)/Ctrl/Alt,Shift 输出大写与上档符号、Caps 只翻转字母区;E0 前缀的独立方向键/Home/End/Delete/PageUp/PageDown/Insert 输出 ANSI 序列(ESC[A/B/C/D、ESC[H/F、ESC[3~/5~/6~/2~);释放码只清状态不产字符。devfs 的 ASCII 字节流契约不变。② vpui:Tk 新增 _ansi_state/_ansi_param 与 _fold_ansi_key(),在 KEY 分发前折叠 ANSI 序列,映射到既有 VK_* 语义(Text/Entry 里那些分支不再是死代码)。Trim:Insert 无 VK_INSERT 定义、被吞掉;typematic 重复未恢复;USB 键盘未涉及。
2026-10-17 13:01:56 +08:00
TermiNexus 66dc11364a fix(keyboard): 断码不再产出字符,修正每个键输出两个字符
scancode_to_ascii 先剥掉 bit7(KEY_RELEASED)再查表,导致按键释放也被翻译成同一个 ASCII —— 打 ls 得到 llss。断码直接返回 '\\0'。
2026-10-17 12:00:26 +08:00
TermiNexus 3a497e38ec fix(usb): 控制传输短读判失败+描述符链完整性校验;CCB 读改写屏蔽 IRQ1;清理已验证探针
uhci.control_transfer:除错误位外再比对 DATA TD 的 Actual Length(bit10:0)。短读时错误位可能全 0(QEMU/硬件不把短包当错误),只查错误位会漏 —— 现场是 USB 鼠标的 25 字节配置描述符只落下前 9 字节 ⇒ 接口解析为 0 ⇒ [usb_mse] no USB mouse found。

usb._parse_config 改为返回实际走完的偏移,enumerate_port 要求恰好走完 total_len,否则重读、仍不完整即报错返回(fail-fast,不带着半截描述符继续);同时删除两条探针。

keyboard.init/mouse.init 读-改-写 CCB 全程 pic.setMask(1):读 CCB 的 0x20 会把 CCB 值放进 0x60 输出缓冲并拉高 IRQ1,IRQ1 handler 会把它当扫描码抢走(现场 sc=0x47),使回读拿到残留值。改为只在校验失败时打印错误,去掉全部 [kbd] 探针。

清理已验证调试输出:idt 的 IRQ1 handler 探针及其计数器、desktop 的 [dbg] back_fb/row_buf/bg_row_buf、main 的 [DBG] LAPIC/idt32/swint/pic_isr 与 [DB] BootInfo 转储、timer 的 [PIT] 与自旋打印及随之无用的 import。
2026-10-16 15:26:35 +08:00
TermiNexus 89907682ec fix(keyboard): init() 对齐 mouse 写法 - 去掉 0xAD/0xAE 键盘接口禁用序列(CCB 回写失败会停在禁用态),并补 pic.clearMask(1) 2026-10-16 14:14:51 +08:00
TermiNexus d37eac32fe fix(keyboard): init() 改为幂等(避免重复初始化禁用键盘接口);按键时打印扫描码/字符到串口便于验证 2026-10-16 14:12:50 +08:00
TermiNexus 0d0dba476f fix(vkernel): 键盘无法输入 - 键盘/鼠标共享 0x60 统一为单一消费者(IRQ1 ISR→buffer→desktop 轮询),IRQ1 只收键盘字节 2026-10-15 17:24:17 +08:00
TermiNexus cc061b2ad3 fix(vkernel): 修复 PS/2 鼠标位移符号误判(|位移|≥128 时方向翻转、光标向左飞没)
根因(静态定位,非速度问题):PS/2 协议里第 2/3 字节是位移“幅值”,符号在第 1 字节的
bit4(X)/bit5(Y)。而驱动把位移按 int8 存储/解释,于是 |位移| ≥ 128 时字节最高位被当成
符号位:
- 向右快移(幅值 0x80~0xFF)被读成负数 → _cursor_x 一路减小 → 撞上 if _cursor_x<0
  被夹成 0 → 表现为“光标往左飞没了”;
- int8 装不下 9 位有符号位移(符号位在 flags 里),结构上必然丢符号。

修改:
- drivers/input/mouse/mouse.vp:mouse_packet.dx/dy 与 byte2/byte3 改为 uint8,保存原始
  幅值字节,消除 int8 截断;flags(含符号位)照旧保留。
- services/desktop.vp::_update_mouse:按协议用“幅值 + 符号位”重建带符号位移
  (命中 flags.bit4/bit5 时幅值 -256),再做屏幕 Y 轴反向。
- USB HID 分支不动:USB 报告的 X/Y 本身即 int8 有符号,原解释正确。
2026-10-14 15:12:19 +08:00
TermiNexus a44f55574c fix(vkernel): 鼠标“飞”与刷屏性能 —— 帧缓冲改回写映射 + 鼠标驱动丢弃溢出包/细化分辨率
方案 A(帧缓冲映射):
- 去掉帧缓冲的 PTE_PCD,改为回写映射。原先非缓存映射下每次写屏直通设备,大块刷新极慢;
  QEMU 下回写显示正确(TCG 不模拟缓存不一致),真机严格正确应改 write-combining(PAT),
  已在代码注释里写明。
- 说明:“只刷脏行”本已是现状(_mark_rows_dirty 按区域标脏,全屏刷仅启动那一次)。

方案 C(鼠标驱动加固,drivers/input/mouse/mouse.vp):
- irq_handler 丢弃带 X/Y overflow 位(bit6/bit7)的包:此时设备给的是饱和值,直接采用
  会产生 ±127 级跳变,表现为光标“飞”。
- init 中在 0xF6(Set Defaults) 之后用 0xE8/0x03 把分辨率设为 8 counts/mm,避免默认最粗的
  4 counts/mm 造成每计数位移偏大。
2026-10-14 15:05:02 +08:00
TermiNexus 0919a058a8 fix(vkernel): 预留内核 .bss 与栈区,修堆 arena 覆盖未预留内核内存
根因:bootloader 只按 kernel 文件大小 AllocatePages(.bss 不占文件),于是 .bss
尾部(ticks/_perf_* 等全局量)与主线程栈区(0x60000~0x80000)在 memmap 里仍是
EfiConventionalMemory,被内核 mm 的堆 arena 当作空闲内存占用 → 内核全局量被写坏、
堆元数据被反向破坏,最终桌面线程栈上的 va_list 被改坏,vsnprintf 读 %d 变参时
#GP(rip=0x130d45, err=0x0)。

- linker.ld: .bss 末尾加 LONG(0) 强制 PROGBITS,使 kernel.bin 的 FileSize 涵盖
  .bss,bootloader 的 PagesNeeded 得以预留整块内核镜像(含 .bss)
- mm.init: 新增 KernelAddr/KernelEnd,挑 arena 时把与内核镜像 [kernel_PhysAddr,
  __bss_end) 重叠的 region 起点抬到镜像末端(不整段丢弃)
- main.vp: 取 __bss_end 并传入 mm.init
- boot.c: ExitBootServices 前用 AllocatePages(AllocateAddress, EfiLoaderData)
  占位内核栈区 0x60000~0x80000,使其在 memmap 中标记已用

另含在途整理:多处补显式收窄转换(uint8()/uint16() 等)、kbd_svc 构造改为
kbd_svc.__init__() 等。
2026-10-14 12:54:43 +08:00
TermiNexus 5b4bab59cc chore(ViperOS): 合并落库内核侧在途改动并移除 vpsdk wiki 拷贝
VKernel / vpsdk / Apps / Libs 共 30 个源文件:内核与 SDK 侧的新语法适配及编译修正(含 bootinfo.vp / main.vp 位宽改 uint64、gfx.vp 前向引用改指针、devfs.vp 指针解引用赋值、elf.vp 跨模块函数取值等)。删除 vpsdk/wiki/*.md(14 文件,约 -8100 行):与仓库根 wiki 重复的拷贝,统一以根 wiki 为唯一来源。
2026-10-07 19:04:33 +08:00
TermiNexus 5f5a119f06 fix(vkernel): schedule_int_transfer 的 toggle 形参改为值传递
schedule_int_transfer 第 6 形参原为 toggle_ptr: uint8*,却直接转发给 _td_set_token 的值形参 toggle: uint8,命中指针隐式转整数禁令(uhci.vp:160 CastError)。改为 toggle: uint8 值传递,四个调用点去掉取地址,buf 仍以 & 传。同时纳入工作区既有的指针语法迁移:t.CPtr 改 X*、c.Addr 改 &、c.Set(c.Deref(...)) 改 *p = v。
2026-09-27 15:05:37 +08:00
TermiNexus a518f75b24 chore(vkernel): 重置基线 — 纳入 TPV codegen 修复配合的内核侧调整与既有工作区内容
- devfs.vp: string.split 传 PATH_BUFFER_SIZE(配合 split 新增容量参数)

- fat32_types.vp: lfn_extract 越界钳制(base+i > MAX_LFN 返回 -1)

- sheet.vp: gfx.Renderer 实参修正为 (fb, zb, w, h)(原单参导致 w/h=0 渲染空操作)

- 同批包含 VKernel 其余既有移植改动与 vpsdk/Apps/Libs 工作区内容
2026-09-11 14:27:01 +08:00
TermiNexus cd1cc915c5 修正了build.py,重置基线 2026-09-11 10:34:34 +08:00
TermiNexus 20e7289c61 将 .py 和 .pyi 后缀名改为了 .vp 和 .vpi 后缀名 2026-07-30 16:34:26 +08:00
Viper 6813947181 Initial import of ViperOS 2026-07-19 12:38:20 +08:00