dev: better key handling
This commit is contained in:
parent
ea6684d916
commit
5dd3a252c6
@ -2,5 +2,12 @@ pub static CODE_SET_1_00: &[u8] = &[
|
||||
0x00, b'\x1b', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'0', b'-', b'=', b'\x7f',
|
||||
b'\t', b'q', b'w', b'e', b'r', b't', b'y', b'u', b'i', b'o', b'p', b'[', b']', b'\n', 0x00,
|
||||
b'a', b's', b'd', b'f', b'g', b'h', b'j', b'k', b'l', b';', b'\'', b'`', 0x00, b'\\', b'z',
|
||||
b'x', b'c', b'v', b'b', b'n', b'm', b',', b'.', b'/', 0x00,
|
||||
b'x', b'c', b'v', b'b', b'n', b'm', b',', b'.', b'/', 0x00, b'*', 0x00, b' ',
|
||||
];
|
||||
|
||||
pub static CODE_SET_1_00_SHIFT: &[u8] = &[
|
||||
0x00, b'\x1b', b'!', b'@', b'#', b'$', b'%', b'^', b'&', b'*', b'(', b')', b'_', b'+', b'\x7f',
|
||||
b'\t', b'Q', b'W', b'E', b'R', b'T', b'Y', b'U', b'I', b'O', b'P', b'{', b'}', b'\n', 0x00,
|
||||
b'A', b'S', b'D', b'F', b'G', b'H', b'J', b'K', b'L', b':', b'"', b'~', 0x00, b'|', b'Z', b'X',
|
||||
b'C', b'V', b'B', b'N', b'M', b'<', b'>', b'?', 0x00,
|
||||
];
|
||||
|
@ -13,19 +13,27 @@ use crate::{
|
||||
sync::IrqSafeSpinlock,
|
||||
};
|
||||
|
||||
use self::codeset::CODE_SET_1_00;
|
||||
use self::codeset::{CODE_SET_1_00, CODE_SET_1_00_SHIFT};
|
||||
|
||||
mod codeset;
|
||||
|
||||
/// PS/2 controller driver
|
||||
pub struct PS2Controller {
|
||||
struct Inner {
|
||||
command: IoPort<u8>,
|
||||
data: IoPort<u8>,
|
||||
|
||||
shift: bool,
|
||||
ctrl: bool,
|
||||
|
||||
tty: Option<&'static dyn TtyDevice<16>>,
|
||||
}
|
||||
|
||||
/// PS/2 controller driver
|
||||
pub struct PS2Controller {
|
||||
primary_irq: IrqNumber,
|
||||
#[allow(unused)]
|
||||
auxiliary_irq: IrqNumber,
|
||||
|
||||
tty: IrqSafeSpinlock<Option<&'static dyn TtyDevice<16>>>,
|
||||
inner: IrqSafeSpinlock<Inner>,
|
||||
}
|
||||
|
||||
fn translate(codeset: &[u8], key: u8) -> Option<u8> {
|
||||
@ -40,29 +48,62 @@ fn translate(codeset: &[u8], key: u8) -> Option<u8> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Inner {
|
||||
const STATUS_OUTPUT_FULL: u8 = 1 << 0;
|
||||
const STATUS_INPUT_FULL: u8 = 1 << 1;
|
||||
|
||||
fn send_command(&mut self, cmd: u8) {
|
||||
while self.command.read() & Self::STATUS_INPUT_FULL != 0 {
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
self.command.write(cmd);
|
||||
}
|
||||
|
||||
fn recv_timeout(&mut self, timeout: u64) -> Option<u8> {
|
||||
let mut counter = 0;
|
||||
while self.command.read() & Self::STATUS_OUTPUT_FULL == 0 {
|
||||
counter += 1;
|
||||
if counter > timeout {
|
||||
return None;
|
||||
}
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
Some(self.data.read())
|
||||
}
|
||||
|
||||
fn try_recv(&mut self) -> Option<u8> {
|
||||
if self.command.read() & Inner::STATUS_OUTPUT_FULL != 0 {
|
||||
Some(self.data.read())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl KeyboardDevice for PS2Controller {
|
||||
fn attach(&self, terminal: &'static dyn TtyDevice<16>) {
|
||||
self.tty.lock().replace(terminal);
|
||||
self.inner.lock().tty.replace(terminal);
|
||||
}
|
||||
}
|
||||
|
||||
impl InterruptSource for PS2Controller {
|
||||
unsafe fn init_irq(&'static self) -> Result<(), Error> {
|
||||
let mut inner = self.inner.lock();
|
||||
let intc = PLATFORM.interrupt_controller();
|
||||
|
||||
intc.register_handler(self.primary_irq, self)?;
|
||||
|
||||
// Disable PS/2 devices from sending any further data
|
||||
self.send_command(0xAD);
|
||||
self.send_command(0xA7);
|
||||
inner.send_command(0xAD);
|
||||
inner.send_command(0xA7);
|
||||
|
||||
// Flush the buffer
|
||||
while self.command.read() & Self::STATUS_OUTPUT_FULL != 0 {
|
||||
self.data.read();
|
||||
while inner.command.read() & Inner::STATUS_OUTPUT_FULL != 0 {
|
||||
inner.data.read();
|
||||
}
|
||||
|
||||
// Enable primary port
|
||||
self.send_command(0xAE);
|
||||
inner.send_command(0xAE);
|
||||
|
||||
intc.enable_irq(self.primary_irq)?;
|
||||
|
||||
@ -70,34 +111,103 @@ impl InterruptSource for PS2Controller {
|
||||
}
|
||||
|
||||
fn handle_irq(&self) -> Result<bool, Error> {
|
||||
let status = self.command.read();
|
||||
|
||||
if status & 1 == 0 {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let key = self.data.read();
|
||||
|
||||
if key == 0xE0 {
|
||||
self.data.read();
|
||||
infoln!("TODO: handle 0xE0");
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
self.data.read();
|
||||
|
||||
if key < 128 {
|
||||
let Some(code) = translate(CODE_SET_1_00, key) else {
|
||||
return Ok(true);
|
||||
let mut count = 0;
|
||||
let mut inner = self.inner.lock();
|
||||
loop {
|
||||
let Some(mut scancode) = inner.try_recv() else {
|
||||
break;
|
||||
};
|
||||
let terminal = self.tty.lock();
|
||||
|
||||
if let Some(terminal) = &*terminal {
|
||||
terminal.recv_byte(code);
|
||||
let e0 = scancode == 0xE0;
|
||||
|
||||
if e0 {
|
||||
scancode = inner.recv_timeout(100000000).unwrap();
|
||||
}
|
||||
|
||||
if !e0 {
|
||||
match scancode {
|
||||
// LCtrl pressed
|
||||
0x1D => {
|
||||
inner.ctrl = true;
|
||||
continue;
|
||||
}
|
||||
// LCtrl released
|
||||
0x9D => {
|
||||
inner.ctrl = false;
|
||||
continue;
|
||||
}
|
||||
// LShift pressed
|
||||
0x2A => {
|
||||
inner.shift = true;
|
||||
continue;
|
||||
}
|
||||
// LShift released
|
||||
0xAA => {
|
||||
inner.shift = false;
|
||||
continue;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
if scancode > 128 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let key = match (inner.shift, inner.ctrl, e0) {
|
||||
// No shift, no ctrl
|
||||
(false, false, false) => translate(CODE_SET_1_00, scancode).unwrap_or(0),
|
||||
// Shift, no ctrl
|
||||
(true, false, false) => translate(CODE_SET_1_00_SHIFT, scancode).unwrap_or(0),
|
||||
// No shift, ctrl
|
||||
(false, true, false) => {
|
||||
let key = translate(CODE_SET_1_00, scancode).unwrap_or(0);
|
||||
|
||||
if key == b'c' {
|
||||
0x3
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
// Other keys
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
if key == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(tty) = inner.tty {
|
||||
tty.recv_byte(key);
|
||||
}
|
||||
|
||||
count += 1;
|
||||
}
|
||||
|
||||
Ok(true)
|
||||
|
||||
// let status = self.command.read();
|
||||
|
||||
// if status & 1 == 0 {
|
||||
// return Ok(false);
|
||||
// }
|
||||
|
||||
// let key = self.data.read();
|
||||
|
||||
// if key == 0xE0 {
|
||||
// self.data.read();
|
||||
// infoln!("TODO: handle 0xE0");
|
||||
// return Ok(true);
|
||||
// }
|
||||
|
||||
// self.data.read();
|
||||
|
||||
// if key < 128 {
|
||||
// let terminal = self.tty.lock();
|
||||
|
||||
// }
|
||||
|
||||
// Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,9 +218,6 @@ impl Device for PS2Controller {
|
||||
}
|
||||
|
||||
impl PS2Controller {
|
||||
const STATUS_OUTPUT_FULL: u8 = 1 << 0;
|
||||
const STATUS_INPUT_FULL: u8 = 1 << 1;
|
||||
|
||||
/// Constructs a new instance of the device
|
||||
pub const fn new(
|
||||
primary_irq: IrqNumber,
|
||||
@ -118,19 +225,18 @@ impl PS2Controller {
|
||||
cmd_port: u16,
|
||||
data_port: u16,
|
||||
) -> Self {
|
||||
let inner = Inner {
|
||||
command: IoPort::new(cmd_port),
|
||||
data: IoPort::new(data_port),
|
||||
shift: false,
|
||||
ctrl: false,
|
||||
tty: None,
|
||||
};
|
||||
|
||||
Self {
|
||||
primary_irq,
|
||||
auxiliary_irq,
|
||||
command: IoPort::new(cmd_port),
|
||||
data: IoPort::new(data_port),
|
||||
tty: IrqSafeSpinlock::new(None),
|
||||
inner: IrqSafeSpinlock::new(inner),
|
||||
}
|
||||
}
|
||||
|
||||
fn send_command(&self, cmd: u8) {
|
||||
while self.command.read() & Self::STATUS_INPUT_FULL != 0 {
|
||||
core::hint::spin_loop();
|
||||
}
|
||||
self.command.write(cmd);
|
||||
}
|
||||
}
|
||||
|
@ -266,11 +266,23 @@ impl ConsoleState {
|
||||
let mut flush = false;
|
||||
|
||||
match c {
|
||||
c if c > 127 => {
|
||||
self.buffer.set_char(
|
||||
self.cursor_row,
|
||||
self.cursor_col,
|
||||
ConsoleChar::from_parts(b'?', self.fg_color, ColorAttribute::Red),
|
||||
);
|
||||
|
||||
self.cursor_col += 1;
|
||||
}
|
||||
b'\n' => {
|
||||
self.cursor_row += 1;
|
||||
self.cursor_col = 0;
|
||||
flush = true;
|
||||
}
|
||||
b'\x7f' => {
|
||||
return false;
|
||||
}
|
||||
_ => {
|
||||
self.buffer.set_char(
|
||||
self.cursor_row,
|
||||
|
@ -165,7 +165,7 @@ pub trait TtyDevice<const N: usize>: SerialDevice {
|
||||
}
|
||||
|
||||
// byte == config.chars.interrupt
|
||||
if byte == b'=' && config.line.contains(TerminalLineOptions::SIGNAL) {
|
||||
if byte == config.chars.interrupt && config.line.contains(TerminalLineOptions::SIGNAL) {
|
||||
drop(config);
|
||||
let pgrp = ring.inner.lock().process_group;
|
||||
if let Some(pgrp) = pgrp {
|
||||
|
Loading…
x
Reference in New Issue
Block a user