asterinas/kernel/aster-nix/src/device/tty/driver.rs

90 lines
2.4 KiB
Rust

// SPDX-License-Identifier: MPL-2.0
pub use aster_frame::arch::console;
use aster_frame::vm::VmReader;
use spin::Once;
use crate::{
device::tty::{get_n_tty, Tty},
prelude::*,
};
pub static TTY_DRIVER: Once<Arc<TtyDriver>> = Once::new();
pub(super) fn init() {
for (_, device) in aster_console::all_devices() {
device.register_callback(&console_input_callback)
}
let tty_driver = Arc::new(TtyDriver::new());
// FIXME: install n_tty into tty_driver?
let n_tty = get_n_tty();
tty_driver.install(n_tty.clone());
TTY_DRIVER.call_once(|| tty_driver);
}
pub struct TtyDriver {
ttys: SpinLock<Vec<Arc<Tty>>>,
}
impl TtyDriver {
pub const fn new() -> Self {
Self {
ttys: SpinLock::new(Vec::new()),
}
}
/// Return the tty device in driver's internal table.
pub fn lookup(&self, index: usize) -> Result<Arc<Tty>> {
let ttys = self.ttys.lock_irq_disabled();
// Return the tty device corresponding to idx
if index >= ttys.len() {
return_errno_with_message!(Errno::ENODEV, "lookup failed. No tty device");
}
let tty = ttys[index].clone();
drop(ttys);
Ok(tty)
}
/// Install a new tty into the driver's internal tables.
pub fn install(self: &Arc<Self>, tty: Arc<Tty>) {
tty.set_driver(Arc::downgrade(self));
self.ttys.lock_irq_disabled().push(tty);
}
/// remove a new tty into the driver's internal tables.
pub fn remove(&self, index: usize) -> Result<()> {
let mut ttys = self.ttys.lock_irq_disabled();
if index >= ttys.len() {
return_errno_with_message!(Errno::ENODEV, "lookup failed. No tty device");
}
let removed_tty = ttys.remove(index);
removed_tty.set_driver(Weak::new());
drop(ttys);
Ok(())
}
pub fn push_char(&self, ch: u8) {
// FIXME: should the char send to all ttys?
for tty in &*self.ttys.lock_irq_disabled() {
tty.push_char(ch);
}
}
}
fn console_input_callback(mut reader: VmReader) {
let tty_driver = get_tty_driver();
while reader.remain() > 0 {
let ch = reader.read_val();
tty_driver.push_char(ch);
}
}
fn serial_input_callback(item: u8) {
let tty_driver = get_tty_driver();
tty_driver.push_char(item);
}
fn get_tty_driver() -> &'static TtyDriver {
TTY_DRIVER.get().unwrap()
}