mirror of
https://github.com/ZeroOSProject/ZeroOS.git
synced 2026-09-13 02:24:42 +08:00
vi and busybox
This commit is contained in:
@@ -0,0 +1,328 @@
|
||||
use crate::drivers::platform::pic;
|
||||
use crate::io::{disable_interrupts, enable_interrupts, inb};
|
||||
|
||||
const DATA_PORT: u16 = 0x60;
|
||||
const STATUS_PORT: u16 = 0x64;
|
||||
const OUTPUT_FULL: u8 = 1 << 0;
|
||||
const BUFFER_SIZE: usize = 256;
|
||||
|
||||
static mut KEYBOARD: Ps2Keyboard = Ps2Keyboard::new();
|
||||
|
||||
pub struct Ps2Keyboard {
|
||||
buffer: [u8; BUFFER_SIZE],
|
||||
read_index: usize,
|
||||
write_index: usize,
|
||||
shift: bool,
|
||||
extended: bool,
|
||||
}
|
||||
|
||||
impl Ps2Keyboard {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
buffer: [0; BUFFER_SIZE],
|
||||
read_index: 0,
|
||||
write_index: 0,
|
||||
shift: false,
|
||||
extended: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn push(&mut self, byte: u8) {
|
||||
let next = (self.write_index + 1) % BUFFER_SIZE;
|
||||
if next != self.read_index {
|
||||
self.buffer[self.write_index] = byte;
|
||||
self.write_index = next;
|
||||
}
|
||||
}
|
||||
|
||||
fn pop(&mut self) -> Option<u8> {
|
||||
if self.read_index == self.write_index {
|
||||
return None;
|
||||
}
|
||||
|
||||
let byte = self.buffer[self.read_index];
|
||||
self.read_index = (self.read_index + 1) % BUFFER_SIZE;
|
||||
Some(byte)
|
||||
}
|
||||
|
||||
fn handle_scancode(&mut self, scancode: u8) {
|
||||
if scancode == 0xe0 {
|
||||
self.extended = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if self.extended {
|
||||
self.extended = false;
|
||||
if scancode & 0x80 != 0 {
|
||||
return;
|
||||
}
|
||||
match scancode {
|
||||
0x48 => self.push_escape_sequence(b"\x1b[A"),
|
||||
0x50 => self.push_escape_sequence(b"\x1b[B"),
|
||||
0x4b => self.push_escape_sequence(b"\x1b[D"),
|
||||
0x4d => self.push_escape_sequence(b"\x1b[C"),
|
||||
0x47 => self.push_escape_sequence(b"\x1b[H"),
|
||||
0x4f => self.push_escape_sequence(b"\x1b[F"),
|
||||
0x53 => self.push_escape_sequence(b"\x1b[3~"),
|
||||
_ => {}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let released = scancode & 0x80 != 0;
|
||||
let code = scancode & 0x7f;
|
||||
|
||||
match code {
|
||||
0x2a | 0x36 => {
|
||||
self.shift = !released;
|
||||
return;
|
||||
}
|
||||
_ if released => return,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if let Some(ascii) = scancode_set1_to_ascii(code, self.shift) {
|
||||
self.push(ascii);
|
||||
}
|
||||
}
|
||||
|
||||
fn push_escape_sequence(&mut self, bytes: &[u8]) {
|
||||
for byte in bytes {
|
||||
self.push(*byte);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn init() {
|
||||
unsafe {
|
||||
drain_output_buffer();
|
||||
pic::unmask_irq(pic::KEYBOARD_IRQ);
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn zeroos_ps2_keyboard_interrupt() {
|
||||
unsafe {
|
||||
if inb(STATUS_PORT) & OUTPUT_FULL != 0 {
|
||||
let scancode = inb(DATA_PORT);
|
||||
(*(&raw mut KEYBOARD)).handle_scancode(scancode);
|
||||
}
|
||||
|
||||
pic::end_of_interrupt(pic::KEYBOARD_IRQ);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_char() -> Option<u8> {
|
||||
disable_interrupts();
|
||||
let ch = unsafe { (*(&raw mut KEYBOARD)).pop() };
|
||||
enable_interrupts();
|
||||
ch
|
||||
}
|
||||
|
||||
pub fn has_char() -> bool {
|
||||
disable_interrupts();
|
||||
let ready = unsafe {
|
||||
let keyboard = &*(&raw const KEYBOARD);
|
||||
keyboard.read_index != keyboard.write_index
|
||||
};
|
||||
enable_interrupts();
|
||||
ready
|
||||
}
|
||||
|
||||
unsafe fn drain_output_buffer() {
|
||||
unsafe {
|
||||
while inb(STATUS_PORT) & OUTPUT_FULL != 0 {
|
||||
let _ = inb(DATA_PORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn scancode_set1_to_ascii(code: u8, shift: bool) -> Option<u8> {
|
||||
let byte = match code {
|
||||
0x01 => 0x1b,
|
||||
0x02 => {
|
||||
if shift {
|
||||
b'!'
|
||||
} else {
|
||||
b'1'
|
||||
}
|
||||
}
|
||||
0x03 => {
|
||||
if shift {
|
||||
b'@'
|
||||
} else {
|
||||
b'2'
|
||||
}
|
||||
}
|
||||
0x04 => {
|
||||
if shift {
|
||||
b'#'
|
||||
} else {
|
||||
b'3'
|
||||
}
|
||||
}
|
||||
0x05 => {
|
||||
if shift {
|
||||
b'$'
|
||||
} else {
|
||||
b'4'
|
||||
}
|
||||
}
|
||||
0x06 => {
|
||||
if shift {
|
||||
b'%'
|
||||
} else {
|
||||
b'5'
|
||||
}
|
||||
}
|
||||
0x07 => {
|
||||
if shift {
|
||||
b'^'
|
||||
} else {
|
||||
b'6'
|
||||
}
|
||||
}
|
||||
0x08 => {
|
||||
if shift {
|
||||
b'&'
|
||||
} else {
|
||||
b'7'
|
||||
}
|
||||
}
|
||||
0x09 => {
|
||||
if shift {
|
||||
b'*'
|
||||
} else {
|
||||
b'8'
|
||||
}
|
||||
}
|
||||
0x0a => {
|
||||
if shift {
|
||||
b'('
|
||||
} else {
|
||||
b'9'
|
||||
}
|
||||
}
|
||||
0x0b => {
|
||||
if shift {
|
||||
b')'
|
||||
} else {
|
||||
b'0'
|
||||
}
|
||||
}
|
||||
0x0c => {
|
||||
if shift {
|
||||
b'_'
|
||||
} else {
|
||||
b'-'
|
||||
}
|
||||
}
|
||||
0x0d => {
|
||||
if shift {
|
||||
b'+'
|
||||
} else {
|
||||
b'='
|
||||
}
|
||||
}
|
||||
0x0e => 0x08,
|
||||
0x0f => b'\t',
|
||||
0x10 => letter(b'q', shift),
|
||||
0x11 => letter(b'w', shift),
|
||||
0x12 => letter(b'e', shift),
|
||||
0x13 => letter(b'r', shift),
|
||||
0x14 => letter(b't', shift),
|
||||
0x15 => letter(b'y', shift),
|
||||
0x16 => letter(b'u', shift),
|
||||
0x17 => letter(b'i', shift),
|
||||
0x18 => letter(b'o', shift),
|
||||
0x19 => letter(b'p', shift),
|
||||
0x1a => {
|
||||
if shift {
|
||||
b'{'
|
||||
} else {
|
||||
b'['
|
||||
}
|
||||
}
|
||||
0x1b => {
|
||||
if shift {
|
||||
b'}'
|
||||
} else {
|
||||
b']'
|
||||
}
|
||||
}
|
||||
0x1c => b'\r',
|
||||
0x1e => letter(b'a', shift),
|
||||
0x1f => letter(b's', shift),
|
||||
0x20 => letter(b'd', shift),
|
||||
0x21 => letter(b'f', shift),
|
||||
0x22 => letter(b'g', shift),
|
||||
0x23 => letter(b'h', shift),
|
||||
0x24 => letter(b'j', shift),
|
||||
0x25 => letter(b'k', shift),
|
||||
0x26 => letter(b'l', shift),
|
||||
0x27 => {
|
||||
if shift {
|
||||
b':'
|
||||
} else {
|
||||
b';'
|
||||
}
|
||||
}
|
||||
0x28 => {
|
||||
if shift {
|
||||
b'"'
|
||||
} else {
|
||||
b'\''
|
||||
}
|
||||
}
|
||||
0x29 => {
|
||||
if shift {
|
||||
b'~'
|
||||
} else {
|
||||
b'`'
|
||||
}
|
||||
}
|
||||
0x2b => {
|
||||
if shift {
|
||||
b'|'
|
||||
} else {
|
||||
b'\\'
|
||||
}
|
||||
}
|
||||
0x2c => letter(b'z', shift),
|
||||
0x2d => letter(b'x', shift),
|
||||
0x2e => letter(b'c', shift),
|
||||
0x2f => letter(b'v', shift),
|
||||
0x30 => letter(b'b', shift),
|
||||
0x31 => letter(b'n', shift),
|
||||
0x32 => letter(b'm', shift),
|
||||
0x33 => {
|
||||
if shift {
|
||||
b'<'
|
||||
} else {
|
||||
b','
|
||||
}
|
||||
}
|
||||
0x34 => {
|
||||
if shift {
|
||||
b'>'
|
||||
} else {
|
||||
b'.'
|
||||
}
|
||||
}
|
||||
0x35 => {
|
||||
if shift {
|
||||
b'?'
|
||||
} else {
|
||||
b'/'
|
||||
}
|
||||
}
|
||||
0x39 => b' ',
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(byte)
|
||||
}
|
||||
|
||||
const fn letter(lower: u8, shift: bool) -> u8 {
|
||||
if shift { lower - 32 } else { lower }
|
||||
}
|
||||
Reference in New Issue
Block a user