/* * Copyright (c) 2021, Liav A. * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Kernel { class DeviceManagement { public: DeviceManagement(); static void initialize(); static DeviceManagement& the(); void attach_null_device(NullDevice const&); void attach_device_control_device(DeviceControlDevice const&); bool is_console_device_attached() const { return !m_console_device.is_null(); } void attach_console_device(ConsoleDevice const&); Optional dequeue_top_device_event(Badge); void after_inserting_device(Badge, Device&); void before_device_removal(Badge, Device&); void for_each(Function); ErrorOr try_for_each(Function(Device&)>); Device* get_device(MajorNumber major, MinorNumber minor); NullDevice const& null_device() const; NullDevice& null_device(); ConsoleDevice const& console_device() const; ConsoleDevice& console_device(); template static inline ErrorOr> try_create_device(Args&&... args) requires(requires(Args... args) { DeviceType::try_create(args...); }) { auto device = TRY(DeviceType::try_create(forward(args)...)); TRY(device->after_inserting()); return device; } template static inline ErrorOr> try_create_device(Args&&... args) { auto device = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) DeviceType(forward(args)...))); TRY(device->after_inserting()); return device; } private: LockRefPtr m_null_device; LockRefPtr m_console_device; LockRefPtr m_device_control_device; SpinlockProtected, LockRank::None> m_devices {}; mutable Spinlock m_event_queue_lock {}; CircularQueue m_event_queue; }; }