mirror of
https://github.com/rcore-os/rCore.git
synced 2025-01-19 01:07:05 +04:00
Move keyboard to drivers
This commit is contained in:
parent
9732f2148d
commit
88544bdd3c
@ -1,34 +0,0 @@
|
||||
use crate::sync::SpinLock as Mutex;
|
||||
use lazy_static::lazy_static;
|
||||
use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1};
|
||||
use x86_64::instructions::port::Port;
|
||||
|
||||
pub fn init() {
|
||||
use crate::arch::interrupt::consts;
|
||||
use crate::arch::interrupt::enable_irq;
|
||||
enable_irq(consts::Keyboard);
|
||||
info!("keyboard: init end");
|
||||
}
|
||||
|
||||
/// Receive character from keyboard
|
||||
/// Should be called on every interrupt
|
||||
pub fn receive() -> Option<DecodedKey> {
|
||||
lazy_static! {
|
||||
static ref KEYBOARD: Mutex<Keyboard<layouts::Us104Key, ScancodeSet1>> = Mutex::new(
|
||||
Keyboard::new(layouts::Us104Key, ScancodeSet1, HandleControl::Ignore)
|
||||
);
|
||||
}
|
||||
|
||||
let mut keyboard = KEYBOARD.lock();
|
||||
let mut data_port = Port::<u8>::new(0x60);
|
||||
let mut status_port = Port::<u8>::new(0x64);
|
||||
|
||||
// Output buffer status = 1
|
||||
if unsafe { status_port.read() } & (1 << 0) != 0 {
|
||||
let scancode = unsafe { data_port.read() };
|
||||
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
|
||||
return keyboard.process_keyevent(key_event);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
pub mod keyboard;
|
||||
|
||||
use super::BootInfo;
|
||||
|
||||
pub fn init(_boot_info: &BootInfo) {
|
||||
keyboard::init();
|
||||
}
|
||||
|
||||
pub fn init_graphic(boot_info: &BootInfo) {
|
||||
super::board::init_driver(boot_info);
|
||||
crate::drivers::console::init();
|
||||
}
|
@ -28,9 +28,6 @@ pub const Syscall32: usize = 0x80;
|
||||
|
||||
// IRQ
|
||||
pub const Timer: usize = 0;
|
||||
pub const Keyboard: usize = 1;
|
||||
pub const COM2: usize = 3;
|
||||
pub const COM1: usize = 4;
|
||||
pub const Error: usize = 19;
|
||||
pub const Spurious: usize = 31;
|
||||
|
||||
|
@ -97,10 +97,9 @@ pub extern "C" fn trap_handler(tf: &mut TrapFrame) {
|
||||
}
|
||||
*/
|
||||
}
|
||||
Keyboard => keyboard(),
|
||||
_ => {
|
||||
if IRQ_MANAGER.read().try_handle_interrupt(Some(irq)) {
|
||||
debug!("driver processed interrupt");
|
||||
trace!("driver processed interrupt");
|
||||
return;
|
||||
}
|
||||
warn!("unhandled external IRQ number: {}", irq);
|
||||
@ -152,33 +151,3 @@ fn page_fault(tf: &mut TrapFrame) {
|
||||
error!("\nEXCEPTION: Page Fault @ {:#x}, code: {:?}", addr, code);
|
||||
loop {}
|
||||
}
|
||||
|
||||
fn keyboard() {
|
||||
use crate::arch::driver::keyboard;
|
||||
use pc_keyboard::{DecodedKey, KeyCode};
|
||||
trace!("\nInterupt: Keyboard");
|
||||
if let Some(key) = keyboard::receive() {
|
||||
match key {
|
||||
DecodedKey::Unicode(c) => {
|
||||
// at most 4 is needed
|
||||
let mut buffer = [0u8; 4];
|
||||
let res = c.encode_utf8(&mut buffer);
|
||||
for c in res.bytes() {
|
||||
crate::trap::serial(c)
|
||||
}
|
||||
}
|
||||
DecodedKey::RawKey(code) => {
|
||||
let s = match code {
|
||||
KeyCode::ArrowUp => "\u{1b}[A",
|
||||
KeyCode::ArrowDown => "\u{1b}[B",
|
||||
KeyCode::ArrowRight => "\u{1b}[C",
|
||||
KeyCode::ArrowLeft => "\u{1b}[D",
|
||||
_ => "",
|
||||
};
|
||||
for c in s.bytes() {
|
||||
crate::trap::serial(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ pub mod acpi;
|
||||
pub mod board;
|
||||
pub mod consts;
|
||||
pub mod cpu;
|
||||
pub mod driver;
|
||||
pub mod gdt;
|
||||
pub mod interrupt;
|
||||
pub mod io;
|
||||
@ -38,8 +37,6 @@ pub extern "C" fn _start(boot_info: &'static BootInfo) -> ! {
|
||||
|
||||
// serial
|
||||
crate::drivers::early_init();
|
||||
// init graphic output
|
||||
driver::init_graphic(boot_info);
|
||||
|
||||
println!("Hello world! from CPU {}!", cpu_id);
|
||||
|
||||
@ -64,8 +61,8 @@ pub extern "C" fn _start(boot_info: &'static BootInfo) -> ! {
|
||||
cpu::init();
|
||||
// now we can start LKM.
|
||||
crate::lkm::manager::ModuleManager::init();
|
||||
// use IOAPIC instead of PIC, use APIC Timer instead of PIT, init serial&keyboard in x86_64
|
||||
driver::init(boot_info);
|
||||
// init board
|
||||
board::init_driver(boot_info);
|
||||
// init pci/bus-based devices ,e.g. Intel 10Gb NIC, ...
|
||||
crate::drivers::init();
|
||||
// init cpu scheduler and process manager, and add user shell app in process manager
|
||||
|
@ -119,6 +119,8 @@ pub fn init(dtb: usize) {
|
||||
pub fn init() {
|
||||
bus::pci::init();
|
||||
rtc::rtc_cmos::init();
|
||||
serial::keyboard::init();
|
||||
console::init();
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
|
95
kernel/src/drivers/serial/keyboard.rs
Normal file
95
kernel/src/drivers/serial/keyboard.rs
Normal file
@ -0,0 +1,95 @@
|
||||
//! Keyboard in x86
|
||||
use super::super::DRIVERS;
|
||||
use super::super::IRQ_MANAGER;
|
||||
use super::{super::SERIAL_DRIVERS, SerialDriver};
|
||||
use crate::{
|
||||
drivers::{DeviceType, Driver},
|
||||
sync::SpinNoIrqLock as Mutex,
|
||||
};
|
||||
use alloc::string::String;
|
||||
use alloc::sync::Arc;
|
||||
use pc_keyboard::{layouts, DecodedKey, HandleControl, KeyCode, ScancodeSet1};
|
||||
use uart_16550::SerialPort;
|
||||
use x86_64::instructions::port::Port;
|
||||
|
||||
pub const Keyboard: usize = 1;
|
||||
|
||||
struct Keyboard {
|
||||
keyboard: Mutex<pc_keyboard::Keyboard<layouts::Us104Key, ScancodeSet1>>,
|
||||
}
|
||||
|
||||
impl Keyboard {
|
||||
fn new() -> Keyboard {
|
||||
Keyboard {
|
||||
keyboard: Mutex::new(pc_keyboard::Keyboard::new(
|
||||
layouts::Us104Key,
|
||||
ScancodeSet1,
|
||||
HandleControl::Ignore,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Driver for Keyboard {
|
||||
fn try_handle_interrupt(&self, irq: Option<usize>) -> bool {
|
||||
let mut keyboard = self.keyboard.lock();
|
||||
let mut data_port = Port::<u8>::new(0x60);
|
||||
let mut status_port = Port::<u8>::new(0x64);
|
||||
// Output buffer status = 1
|
||||
if unsafe { status_port.read() } & (1 << 0) != 0 {
|
||||
let scancode = unsafe { data_port.read() };
|
||||
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
|
||||
if let Some(key) = keyboard.process_keyevent(key_event) {
|
||||
match key {
|
||||
DecodedKey::Unicode(c) => {
|
||||
// at most 4 is needed
|
||||
let mut buffer = [0u8; 4];
|
||||
let res = c.encode_utf8(&mut buffer);
|
||||
for c in res.bytes() {
|
||||
crate::trap::serial(c)
|
||||
}
|
||||
}
|
||||
DecodedKey::RawKey(code) => {
|
||||
let s = match code {
|
||||
KeyCode::ArrowUp => "\u{1b}[A",
|
||||
KeyCode::ArrowDown => "\u{1b}[B",
|
||||
KeyCode::ArrowRight => "\u{1b}[C",
|
||||
KeyCode::ArrowLeft => "\u{1b}[D",
|
||||
_ => "",
|
||||
};
|
||||
for c in s.bytes() {
|
||||
crate::trap::serial(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn device_type(&self) -> DeviceType {
|
||||
DeviceType::Serial
|
||||
}
|
||||
|
||||
fn get_id(&self) -> String {
|
||||
format!("keyboard")
|
||||
}
|
||||
}
|
||||
|
||||
impl SerialDriver for Keyboard {
|
||||
fn read(&self) -> u8 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn write(&self, data: &[u8]) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
let keyboard = Arc::new(Keyboard::new());
|
||||
DRIVERS.write().push(keyboard.clone());
|
||||
SERIAL_DRIVERS.write().push(keyboard.clone());
|
||||
IRQ_MANAGER.write().register_irq(Keyboard, keyboard);
|
||||
}
|
@ -5,6 +5,8 @@ use core::fmt::{Result, Write};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub mod com;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub mod keyboard;
|
||||
|
||||
pub trait SerialDriver: Driver {
|
||||
// read one byte from tty
|
||||
|
Loading…
Reference in New Issue
Block a user