Kernel: DeviceManager is now a 'FileSystem' so it can expose devices
Shell reads keyboard through /dev/input :)
This commit is contained in:
parent
f4db246658
commit
a24c2d9be2
|
@ -1,15 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/StringView.h>
|
||||||
#include <BAN/Vector.h>
|
#include <BAN/Vector.h>
|
||||||
|
#include <kernel/FS/FileSystem.h>
|
||||||
|
#include <kernel/FS/Inode.h>
|
||||||
#include <kernel/SpinLock.h>
|
#include <kernel/SpinLock.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
class Device
|
class Device : public Inode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class Type
|
enum class DeviceType
|
||||||
{
|
{
|
||||||
BlockDevice,
|
BlockDevice,
|
||||||
CharacterDevice,
|
CharacterDevice,
|
||||||
|
@ -17,36 +20,59 @@ namespace Kernel
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~Device() {}
|
virtual ~Device() {}
|
||||||
virtual Type type() const = 0;
|
virtual DeviceType device_type() const = 0;
|
||||||
virtual void update() {}
|
virtual void update() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class BlockDevice : public Device
|
class BlockDevice : public Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual Type type() const override { return Type::BlockDevice; }
|
virtual DeviceType device_type() const override { return DeviceType::BlockDevice; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class CharacterDevice : public Device
|
class CharacterDevice : public Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual Type type() const override { return Type::CharacterDevice; }
|
virtual DeviceType device_type() const override { return DeviceType::CharacterDevice; }
|
||||||
|
|
||||||
virtual BAN::ErrorOr<void> read(BAN::Span<uint8_t>);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DeviceManager
|
class DeviceManager final : public FileSystem, public Inode
|
||||||
{
|
{
|
||||||
BAN_NON_COPYABLE(DeviceManager);
|
BAN_NON_COPYABLE(DeviceManager);
|
||||||
BAN_NON_MOVABLE(DeviceManager);
|
BAN_NON_MOVABLE(DeviceManager);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static void initialize();
|
||||||
static DeviceManager& get();
|
static DeviceManager& get();
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
void add_device(Device*);
|
void add_device(Device*);
|
||||||
|
|
||||||
BAN::Vector<Device*> devices() { return m_devices; }
|
virtual ino_t ino() const override { return 0; }
|
||||||
|
virtual mode_t mode() const override { return IFDIR | IRUSR | IWUSR | IXUSR | IRGRP | IXGRP | IROTH | IXOTH; }
|
||||||
|
virtual nlink_t nlink() const override { return 0; }
|
||||||
|
virtual uid_t uid() const override { return 0; }
|
||||||
|
virtual gid_t gid() const override { return 0; }
|
||||||
|
virtual off_t size() const override { return 0; }
|
||||||
|
virtual timespec atime() const override { return { 0, 0 }; }
|
||||||
|
virtual timespec mtime() const override { return { 0, 0 }; }
|
||||||
|
virtual timespec ctime() const override { return { 0, 0 }; }
|
||||||
|
virtual blksize_t blksize() const override { return 0; }
|
||||||
|
virtual blkcnt_t blocks() const override { return 0; }
|
||||||
|
|
||||||
|
virtual BAN::StringView name() const override { return "device-manager"sv; }
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override { return BAN::Error::from_errno(EISDIR); }
|
||||||
|
virtual BAN::ErrorOr<void> create_file(BAN::StringView, mode_t) override { return BAN::Error::from_errno(EINVAL); };
|
||||||
|
|
||||||
|
virtual Type type() const override { return Type::DeviceManager; }
|
||||||
|
virtual bool operator==(const Inode&) const override { return false; }
|
||||||
|
|
||||||
|
virtual BAN::RefPtr<Inode> root_inode() override { return this; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> read_directory_inode_impl(BAN::StringView) override;
|
||||||
|
virtual BAN::ErrorOr<BAN::Vector<BAN::String>> read_directory_entries_impl(size_t) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DeviceManager() = default;
|
DeviceManager() = default;
|
||||||
|
@ -54,6 +80,8 @@ namespace Kernel
|
||||||
private:
|
private:
|
||||||
SpinLock m_lock;
|
SpinLock m_lock;
|
||||||
BAN::Vector<Device*> m_devices;
|
BAN::Vector<Device*> m_devices;
|
||||||
|
|
||||||
|
friend class BAN::RefPtr<DeviceManager>;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -35,6 +35,8 @@ namespace Kernel
|
||||||
|
|
||||||
enum class Type
|
enum class Type
|
||||||
{
|
{
|
||||||
|
DeviceManager,
|
||||||
|
Device,
|
||||||
Ext2,
|
Ext2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace Kernel
|
||||||
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
|
virtual BAN::RefPtr<Inode> root_inode() override { return m_root_inode; }
|
||||||
|
|
||||||
BAN::ErrorOr<void> mount_test();
|
BAN::ErrorOr<void> mount_test();
|
||||||
|
BAN::ErrorOr<void> mount(FileSystem*, BAN::StringView);
|
||||||
|
|
||||||
struct File
|
struct File
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,8 +31,6 @@ namespace Kernel::Input
|
||||||
virtual void on_byte(uint8_t) override;
|
virtual void on_byte(uint8_t) override;
|
||||||
virtual void update() override;
|
virtual void update() override;
|
||||||
|
|
||||||
virtual BAN::ErrorOr<void> read(BAN::Span<uint8_t>) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PS2Keyboard(PS2Controller& controller)
|
PS2Keyboard(PS2Controller& controller)
|
||||||
: m_controller(controller)
|
: m_controller(controller)
|
||||||
|
@ -59,6 +57,31 @@ namespace Kernel::Input
|
||||||
PS2Keymap m_keymap;
|
PS2Keymap m_keymap;
|
||||||
|
|
||||||
State m_state { State::Normal };
|
State m_state { State::Normal };
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual ino_t ino() const override { return 0; }
|
||||||
|
virtual mode_t mode() const override { return IFCHR | IRUSR | IRGRP; }
|
||||||
|
virtual nlink_t nlink() const override { return 0; }
|
||||||
|
virtual uid_t uid() const override { return 0; }
|
||||||
|
virtual gid_t gid() const override { return 0; }
|
||||||
|
virtual off_t size() const override { return 0; }
|
||||||
|
virtual timespec atime() const override { return { 0, 0 }; }
|
||||||
|
virtual timespec mtime() const override { return { 0, 0 }; }
|
||||||
|
virtual timespec ctime() const override { return { 0, 0 }; }
|
||||||
|
virtual blksize_t blksize() const override { return sizeof(KeyEvent); }
|
||||||
|
virtual blkcnt_t blocks() const override { return 0; }
|
||||||
|
|
||||||
|
virtual BAN::StringView name() const override { return "input"sv; }
|
||||||
|
|
||||||
|
virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override;
|
||||||
|
virtual BAN::ErrorOr<void> create_file(BAN::StringView, mode_t) override { return BAN::Error::from_errno(ENOTDIR); }
|
||||||
|
|
||||||
|
virtual Type type() const override { return Type::Device; }
|
||||||
|
virtual bool operator==(const Inode&) const override { return false; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> read_directory_inode_impl(BAN::StringView) override { return BAN::Error::from_errno(ENOTDIR); }
|
||||||
|
virtual BAN::ErrorOr<BAN::Vector<BAN::String>> read_directory_entries_impl(size_t) override { return BAN::Error::from_errno(ENOTDIR); }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,13 +1,35 @@
|
||||||
#include <kernel/Device.h>
|
#include <kernel/Device.h>
|
||||||
#include <kernel/LockGuard.h>
|
#include <kernel/LockGuard.h>
|
||||||
|
#include <kernel/Process.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static DeviceManager* s_instance = nullptr;
|
||||||
|
|
||||||
|
void DeviceManager::initialize()
|
||||||
|
{
|
||||||
|
ASSERT(s_instance == nullptr);
|
||||||
|
|
||||||
|
s_instance = new DeviceManager;
|
||||||
|
ASSERT(s_instance != nullptr);
|
||||||
|
|
||||||
|
MUST(Process::create_kernel(
|
||||||
|
[](void*)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
DeviceManager::get().update();
|
||||||
|
PIT::sleep(1);
|
||||||
|
}
|
||||||
|
}, nullptr)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
DeviceManager& DeviceManager::get()
|
DeviceManager& DeviceManager::get()
|
||||||
{
|
{
|
||||||
static DeviceManager instance;
|
ASSERT(s_instance);
|
||||||
return instance;
|
return *s_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceManager::update()
|
void DeviceManager::update()
|
||||||
|
@ -23,4 +45,26 @@ namespace Kernel
|
||||||
MUST(m_devices.push_back(device));
|
MUST(m_devices.push_back(device));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::RefPtr<Inode>> DeviceManager::read_directory_inode_impl(BAN::StringView name)
|
||||||
|
{
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
for (Device* device : m_devices)
|
||||||
|
if (device->name() == name)
|
||||||
|
return BAN::RefPtr<Inode>(device);
|
||||||
|
return BAN::Error::from_errno(ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<BAN::Vector<BAN::String>> DeviceManager::read_directory_entries_impl(size_t index)
|
||||||
|
{
|
||||||
|
BAN::Vector<BAN::String> result;
|
||||||
|
if (index > 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
LockGuard _(m_lock);
|
||||||
|
TRY(result.reserve(m_devices.size()));
|
||||||
|
for (Device* device : m_devices)
|
||||||
|
TRY(result.emplace_back(device->name()));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
#include <BAN/StringView.h>
|
#include <BAN/StringView.h>
|
||||||
#include <BAN/Vector.h>
|
#include <BAN/Vector.h>
|
||||||
|
#include <kernel/Device.h>
|
||||||
#include <kernel/FS/Ext2.h>
|
#include <kernel/FS/Ext2.h>
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
#include <kernel/PCI.h>
|
#include <kernel/PCI.h>
|
||||||
|
@ -112,15 +113,14 @@ namespace Kernel
|
||||||
|
|
||||||
if (!root_inode())
|
if (!root_inode())
|
||||||
derrorln("Could not locate root partition");
|
derrorln("Could not locate root partition");
|
||||||
|
|
||||||
|
TRY(mount(&DeviceManager::get(), "/dev"));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> VirtualFileSystem::mount_test()
|
BAN::ErrorOr<void> VirtualFileSystem::mount_test()
|
||||||
{
|
{
|
||||||
auto mount = TRY(root_inode()->read_directory_inode("mnt"sv));
|
|
||||||
if (!mount->ifdir())
|
|
||||||
return BAN::Error::from_errno(ENOTDIR);
|
|
||||||
|
|
||||||
for (auto* controller : m_storage_controllers)
|
for (auto* controller : m_storage_controllers)
|
||||||
{
|
{
|
||||||
for (auto* device : controller->devices())
|
for (auto* device : controller->devices())
|
||||||
|
@ -130,12 +130,21 @@ namespace Kernel
|
||||||
if (partition.name() == "mount-test"sv)
|
if (partition.name() == "mount-test"sv)
|
||||||
{
|
{
|
||||||
auto ext2fs = TRY(Ext2FS::create(partition));
|
auto ext2fs = TRY(Ext2FS::create(partition));
|
||||||
TRY(m_mount_points.push_back({ mount, ext2fs }));
|
TRY(mount(ext2fs, "/mnt"sv));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return BAN::Error::from_c_string("Could not find mount-test partition");
|
||||||
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> VirtualFileSystem::mount(FileSystem* file_system, BAN::StringView path)
|
||||||
|
{
|
||||||
|
auto file = TRY(file_from_absolute_path(path));
|
||||||
|
if (!file.inode->ifdir())
|
||||||
|
return BAN::Error::from_errno(ENOTDIR);
|
||||||
|
TRY(m_mount_points.push_back({ file.inode, file_system }));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -226,19 +226,19 @@ namespace Kernel::Input
|
||||||
append_command_queue(Command::SET_LEDS, new_leds);
|
append_command_queue(Command::SET_LEDS, new_leds);
|
||||||
}
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> PS2Keyboard::read(BAN::Span<uint8_t> output)
|
BAN::ErrorOr<size_t> PS2Keyboard::read(size_t, void* buffer, size_t size)
|
||||||
{
|
{
|
||||||
if (output.size() < sizeof(Input::KeyEvent))
|
if (size < sizeof(KeyEvent))
|
||||||
return BAN::Error::from_c_string("Too small buffer for KeyEvent");
|
return BAN::Error::from_errno(ENOBUFS);
|
||||||
|
|
||||||
while (m_event_queue.empty())
|
while (m_event_queue.empty())
|
||||||
PIT::sleep(1);
|
PIT::sleep(1);
|
||||||
|
|
||||||
CriticalScope _;
|
CriticalScope _;
|
||||||
*(Input::KeyEvent*)output.data() = m_event_queue.front();
|
*(KeyEvent*)buffer = m_event_queue.front();
|
||||||
m_event_queue.pop();
|
m_event_queue.pop();
|
||||||
|
|
||||||
return {};
|
return sizeof(KeyEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -79,11 +79,13 @@ namespace Kernel
|
||||||
|
|
||||||
void Shell::run()
|
void Shell::run()
|
||||||
{
|
{
|
||||||
|
int fd = MUST(Process::current()->open("/dev/input"sv, O_RDONLY));
|
||||||
|
|
||||||
TTY_PRINT("{}", m_prompt);
|
TTY_PRINT("{}", m_prompt);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Input::KeyEvent event;
|
Input::KeyEvent event;
|
||||||
MUST(((CharacterDevice*)DeviceManager::get().devices()[0])->read({ (uint8_t*)&event, sizeof(event) }));
|
MUST(Process::current()->read(fd, &event, sizeof(event)));
|
||||||
key_event_callback(event);
|
key_event_callback(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,7 +184,6 @@ extern "C" void kernel_main()
|
||||||
))));
|
))));
|
||||||
#else
|
#else
|
||||||
MUST(scheduler.add_thread(MUST(Thread::create(init2, tty1))));
|
MUST(scheduler.add_thread(MUST(Thread::create(init2, tty1))));
|
||||||
MUST(scheduler.add_thread(MUST(Thread::create(device_updater))));
|
|
||||||
#endif
|
#endif
|
||||||
scheduler.start();
|
scheduler.start();
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
|
@ -206,6 +205,8 @@ void init2(void* tty1_ptr)
|
||||||
|
|
||||||
TTY* tty1 = (TTY*)tty1_ptr;
|
TTY* tty1 = (TTY*)tty1_ptr;
|
||||||
|
|
||||||
|
DeviceManager::initialize();
|
||||||
|
|
||||||
MUST(VirtualFileSystem::initialize());
|
MUST(VirtualFileSystem::initialize());
|
||||||
if (auto res = VirtualFileSystem::get().mount_test(); res.is_error())
|
if (auto res = VirtualFileSystem::get().mount_test(); res.is_error())
|
||||||
dwarnln("{}", res.error());
|
dwarnln("{}", res.error());
|
||||||
|
|
Loading…
Reference in New Issue