83 lines
2.2 KiB
Rust
83 lines
2.2 KiB
Rust
//! Device virtual file system
|
|
use core::sync::atomic::{AtomicUsize, Ordering};
|
|
|
|
use abi::{
|
|
error::Error,
|
|
io::{FileAttr, FileMode, FileType, OpenOptions},
|
|
};
|
|
use alloc::{boxed::Box, format, string::String};
|
|
use kernel_util::util::OneTimeInit;
|
|
use vfs::{
|
|
CharDevice, CharDeviceWrapper, Vnode, VnodeImpl, VnodeKind, VnodeRef, DIR_POSITION_FROM_CACHE,
|
|
};
|
|
|
|
/// Describes the kind of a character device
|
|
#[derive(Debug)]
|
|
pub enum CharDeviceType {
|
|
/// Regular terminal
|
|
TtyRegular,
|
|
/// Serial terminal
|
|
TtySerial,
|
|
}
|
|
|
|
struct DevfsDirectory;
|
|
|
|
impl VnodeImpl for DevfsDirectory {
|
|
fn open(&self, _node: &VnodeRef, _opts: OpenOptions, _mode: FileMode) -> Result<u64, Error> {
|
|
Ok(DIR_POSITION_FROM_CACHE)
|
|
}
|
|
|
|
fn metadata(&self, _node: &VnodeRef) -> Result<FileAttr, Error> {
|
|
Ok(FileAttr {
|
|
size: 0,
|
|
mode: FileMode::default_dir(),
|
|
ty: FileType::Directory,
|
|
})
|
|
}
|
|
}
|
|
|
|
static DEVFS_ROOT: OneTimeInit<VnodeRef> = OneTimeInit::new();
|
|
|
|
/// Sets up the device filesystem
|
|
pub fn init() {
|
|
let node = Vnode::new("", VnodeKind::Directory);
|
|
node.set_data(Box::new(DevfsDirectory));
|
|
DEVFS_ROOT.init(node);
|
|
}
|
|
|
|
/// Returns the root of the devfs.
|
|
///
|
|
/// # Panics
|
|
///
|
|
/// Will panic if the devfs hasn't yet been initialized.
|
|
pub fn root() -> &'static VnodeRef {
|
|
DEVFS_ROOT.get()
|
|
}
|
|
|
|
fn _add_char_device(dev: &'static dyn CharDevice, name: String) -> Result<(), Error> {
|
|
infoln!("Add char device: {}", name);
|
|
|
|
let node = Vnode::new(name, VnodeKind::Char);
|
|
node.set_data(Box::new(CharDeviceWrapper::new(dev)));
|
|
|
|
DEVFS_ROOT.get().add_child(node);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Adds a character device to the devfs
|
|
pub fn add_char_device(dev: &'static dyn CharDevice, kind: CharDeviceType) -> Result<(), Error> {
|
|
static TTY_COUNT: AtomicUsize = AtomicUsize::new(0);
|
|
static TTYS_COUNT: AtomicUsize = AtomicUsize::new(0);
|
|
|
|
let (count, prefix) = match kind {
|
|
CharDeviceType::TtyRegular => (&TTY_COUNT, "tty"),
|
|
CharDeviceType::TtySerial => (&TTYS_COUNT, "ttyS"),
|
|
};
|
|
|
|
let value = count.fetch_add(1, Ordering::AcqRel);
|
|
let name = format!("{}{}", prefix, value);
|
|
|
|
_add_char_device(dev, name)
|
|
}
|