diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index ecbeb7db77..f5e99b4701 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -156,6 +156,10 @@ set(KERNEL_SOURCES FileSystem/SysFS/Subsystems/Devices/Storage/DeviceAttribute.cpp FileSystem/SysFS/Subsystems/Devices/Storage/DeviceDirectory.cpp FileSystem/SysFS/Subsystems/Devices/Storage/Directory.cpp + FileSystem/SysFS/Subsystems/Devices/Graphics/Directory.cpp + FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/Directory.cpp + FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceDirectory.cpp + FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceAttribute.cpp FileSystem/SysFS/Subsystems/Devices/Directory.cpp FileSystem/SysFS/Subsystems/Firmware/BIOS/Component.cpp FileSystem/SysFS/Subsystems/Firmware/BIOS/Directory.cpp diff --git a/Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/CharacterDevicesDirectory.h b/Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/CharacterDevicesDirectory.h index e6714124a3..7fe13f7a52 100644 --- a/Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/CharacterDevicesDirectory.h +++ b/Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/CharacterDevicesDirectory.h @@ -13,7 +13,10 @@ namespace Kernel { class Device; +class DisplayConnector; class SysFSCharacterDevicesDirectory final : public SysFSDirectory { + friend class DisplayConnector; + public: virtual StringView name() const override { return "char"sv; } static NonnullRefPtr must_create(SysFSDeviceIdentifiersDirectory const&); diff --git a/Kernel/FileSystem/SysFS/Subsystems/Devices/Directory.cpp b/Kernel/FileSystem/SysFS/Subsystems/Devices/Directory.cpp index af8217f01e..0d4178159f 100644 --- a/Kernel/FileSystem/SysFS/Subsystems/Devices/Directory.cpp +++ b/Kernel/FileSystem/SysFS/Subsystems/Devices/Directory.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -16,6 +17,7 @@ UNMAP_AFTER_INIT NonnullRefPtr SysFSDevicesDirectory::mus auto devices_directory = adopt_ref_if_nonnull(new (nothrow) SysFSDevicesDirectory(root_directory)).release_nonnull(); MUST(devices_directory->m_child_components.with([&](auto& list) -> ErrorOr { list.append(SysFSStorageDirectory::must_create(*devices_directory)); + list.append(SysFSGraphicsDirectory::must_create(*devices_directory)); return {}; })); return devices_directory; diff --git a/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/Directory.cpp b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/Directory.cpp new file mode 100644 index 0000000000..febfbf3b00 --- /dev/null +++ b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/Directory.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Kernel { + +UNMAP_AFTER_INIT NonnullRefPtr SysFSGraphicsDirectory::must_create(SysFSDevicesDirectory const& parent_directory) +{ + auto directory = adopt_ref(*new (nothrow) SysFSGraphicsDirectory(parent_directory)); + MUST(directory->m_child_components.with([&](auto& list) -> ErrorOr { + list.append(SysFSDisplayConnectorsDirectory::must_create(*directory)); + return {}; + })); + return directory; +} + +UNMAP_AFTER_INIT SysFSGraphicsDirectory::SysFSGraphicsDirectory(SysFSDevicesDirectory const& parent_directory) + : SysFSDirectory(parent_directory) +{ +} + +} diff --git a/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/Directory.h b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/Directory.h new file mode 100644 index 0000000000..7378d0ebfc --- /dev/null +++ b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/Directory.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Kernel { + +class SysFSGraphicsDirectory : public SysFSDirectory { + friend class SysFSComponentRegistry; + +public: + virtual StringView name() const override { return "graphics"sv; } + static NonnullRefPtr must_create(SysFSDevicesDirectory const&); + +private: + explicit SysFSGraphicsDirectory(SysFSDevicesDirectory const&); +}; + +} diff --git a/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceAttribute.cpp b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceAttribute.cpp new file mode 100644 index 0000000000..5b7c44b773 --- /dev/null +++ b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceAttribute.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include + +namespace Kernel { + +StringView DisplayConnectorAttributeSysFSComponent::name() const +{ + switch (m_type) { + case Type::MutableModeSettingCapable: + return "mutable_mode_setting_capable"sv; + case Type::DoubleFrameBufferingCapable: + return "double_framebuffering_capable"sv; + case Type::FlushSupport: + return "flush_support"sv; + case Type::PartialFlushSupport: + return "partial_flush_support"sv; + case Type::RefreshRateSupport: + return "refresh_rate_support"sv; + case Type::EDID: + return "edid"sv; + default: + VERIFY_NOT_REACHED(); + } +} + +NonnullRefPtr DisplayConnectorAttributeSysFSComponent::must_create(DisplayConnectorSysFSDirectory const& device_directory, Type type) +{ + return adopt_ref(*new (nothrow) DisplayConnectorAttributeSysFSComponent(device_directory, type)); +} + +DisplayConnectorAttributeSysFSComponent::DisplayConnectorAttributeSysFSComponent(DisplayConnectorSysFSDirectory const& device_directory, Type type) + : SysFSComponent() + , m_device(device_directory.device({})) + , m_type(type) +{ +} + +ErrorOr DisplayConnectorAttributeSysFSComponent::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription*) const +{ + auto blob = TRY(try_to_generate_buffer()); + + if ((size_t)offset >= blob->size()) + return 0; + + ssize_t nread = min(static_cast(blob->size() - offset), static_cast(count)); + TRY(buffer.write(blob->data() + offset, nread)); + return nread; +} + +ErrorOr> DisplayConnectorAttributeSysFSComponent::try_to_generate_buffer() const +{ + OwnPtr value; + switch (m_type) { + case Type::MutableModeSettingCapable: + value = TRY(KString::formatted("{:d}", m_device->mutable_mode_setting_capable())); + break; + case Type::DoubleFrameBufferingCapable: + value = TRY(KString::formatted("{:d}", m_device->double_framebuffering_capable())); + break; + case Type::FlushSupport: + value = TRY(KString::formatted("{:d}", m_device->flush_support())); + break; + case Type::PartialFlushSupport: + value = TRY(KString::formatted("{:d}", m_device->partial_flush_support())); + break; + case Type::RefreshRateSupport: + value = TRY(KString::formatted("{:d}", m_device->refresh_rate_support())); + break; + case Type::EDID: { + auto edid_buffer = TRY(m_device->get_edid()); + return KBuffer::try_create_with_bytes("SysFS DisplayConnectorAttributeSysFSComponent EDID buffer"sv, edid_buffer.bytes()); + } + default: + VERIFY_NOT_REACHED(); + } + return KBuffer::try_create_with_bytes("SysFS DisplayConnectorAttributeSysFSComponent buffer"sv, value->view().bytes()); +} +} diff --git a/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceAttribute.h b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceAttribute.h new file mode 100644 index 0000000000..f1db9cb30a --- /dev/null +++ b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceAttribute.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +namespace Kernel { + +class DisplayConnectorAttributeSysFSComponent : public SysFSComponent { +public: + enum class Type { + MutableModeSettingCapable, + DoubleFrameBufferingCapable, + FlushSupport, + PartialFlushSupport, + RefreshRateSupport, + EDID, + }; + +public: + static NonnullRefPtr must_create(DisplayConnectorSysFSDirectory const& device_directory, Type); + + virtual ErrorOr read_bytes(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const override; + virtual ~DisplayConnectorAttributeSysFSComponent() {}; + + virtual StringView name() const override; + +protected: + ErrorOr> try_to_generate_buffer() const; + DisplayConnectorAttributeSysFSComponent(DisplayConnectorSysFSDirectory const& device, Type); + NonnullRefPtr m_device; + Type const m_type { Type::MutableModeSettingCapable }; +}; + +} diff --git a/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceDirectory.cpp b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceDirectory.cpp new file mode 100644 index 0000000000..0256417821 --- /dev/null +++ b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceDirectory.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace Kernel { + +DisplayConnector const& DisplayConnectorSysFSDirectory::device(Badge) const +{ + return *m_device; +} + +UNMAP_AFTER_INIT NonnullRefPtr DisplayConnectorSysFSDirectory::create(SysFSDirectory const& parent_directory, DisplayConnector const& device) +{ + // FIXME: Handle allocation failure gracefully + auto device_name = MUST(KString::formatted("{}", device.minor())); + auto directory = adopt_ref(*new (nothrow) DisplayConnectorSysFSDirectory(move(device_name), parent_directory, device)); + MUST(directory->m_child_components.with([&](auto& list) -> ErrorOr { + list.append(DisplayConnectorAttributeSysFSComponent::must_create(*directory, DisplayConnectorAttributeSysFSComponent::Type::MutableModeSettingCapable)); + list.append(DisplayConnectorAttributeSysFSComponent::must_create(*directory, DisplayConnectorAttributeSysFSComponent::Type::DoubleFrameBufferingCapable)); + list.append(DisplayConnectorAttributeSysFSComponent::must_create(*directory, DisplayConnectorAttributeSysFSComponent::Type::FlushSupport)); + list.append(DisplayConnectorAttributeSysFSComponent::must_create(*directory, DisplayConnectorAttributeSysFSComponent::Type::PartialFlushSupport)); + list.append(DisplayConnectorAttributeSysFSComponent::must_create(*directory, DisplayConnectorAttributeSysFSComponent::Type::RefreshRateSupport)); + list.append(DisplayConnectorAttributeSysFSComponent::must_create(*directory, DisplayConnectorAttributeSysFSComponent::Type::EDID)); + return {}; + })); + return directory; +} + +UNMAP_AFTER_INIT DisplayConnectorSysFSDirectory::DisplayConnectorSysFSDirectory(NonnullOwnPtr device_directory_name, SysFSDirectory const& parent_directory, DisplayConnector const& device) + : SysFSDirectory(parent_directory) + , m_device(device) + , m_device_directory_name(move(device_directory_name)) +{ +} + +} diff --git a/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceDirectory.h b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceDirectory.h new file mode 100644 index 0000000000..5ff79a007a --- /dev/null +++ b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceDirectory.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Kernel { + +class DisplayConnectorAttributeSysFSComponent; +class DisplayConnectorSysFSDirectory final : public SysFSDirectory { +public: + static NonnullRefPtr create(SysFSDirectory const&, DisplayConnector const&); + + virtual StringView name() const override { return m_device_directory_name->view(); } + + DisplayConnector const& device(Badge) const; + +private: + DisplayConnectorSysFSDirectory(NonnullOwnPtr device_directory_name, SysFSDirectory const&, DisplayConnector const&); + RefPtr m_device; + NonnullOwnPtr m_device_directory_name; +}; + +} diff --git a/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/Directory.cpp b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/Directory.cpp new file mode 100644 index 0000000000..1d897e153b --- /dev/null +++ b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/Directory.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +namespace Kernel { + +static SysFSDisplayConnectorsDirectory* s_the { nullptr }; + +UNMAP_AFTER_INIT NonnullRefPtr SysFSDisplayConnectorsDirectory::must_create(SysFSGraphicsDirectory const& parent_directory) +{ + auto directory = adopt_ref(*new (nothrow) SysFSDisplayConnectorsDirectory(parent_directory)); + s_the = directory; + return directory; +} + +SysFSDisplayConnectorsDirectory& SysFSDisplayConnectorsDirectory::the() +{ + VERIFY(s_the); + return *s_the; +} + +void SysFSDisplayConnectorsDirectory::plug(Badge, DisplayConnectorSysFSDirectory& new_device_directory) +{ + MUST(m_child_components.with([&](auto& list) -> ErrorOr { + list.append(new_device_directory); + auto pointed_component_base_name = MUST(KString::try_create(new_device_directory.name())); + auto pointed_component_relative_path = MUST(new_device_directory.relative_path(move(pointed_component_base_name), 0)); + return {}; + })); +} +void SysFSDisplayConnectorsDirectory::unplug(Badge, SysFSDirectory& removed_device_directory) +{ + MUST(m_child_components.with([&](auto& list) -> ErrorOr { + list.remove(removed_device_directory); + return {}; + })); +} + +UNMAP_AFTER_INIT SysFSDisplayConnectorsDirectory::SysFSDisplayConnectorsDirectory(SysFSGraphicsDirectory const& parent_directory) + : SysFSDirectory(parent_directory) +{ +} + +} diff --git a/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/Directory.h b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/Directory.h new file mode 100644 index 0000000000..04038277d1 --- /dev/null +++ b/Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/Directory.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022, Liav A. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Kernel { + +class DisplayConnectorSysFSDirectory; +class DisplayConnector; +class SysFSGraphicsDirectory; +class SysFSDisplayConnectorsDirectory : public SysFSDirectory { + friend class SysFSComponentRegistry; + +public: + virtual StringView name() const override { return "connectors"sv; } + static SysFSDisplayConnectorsDirectory& the(); + static NonnullRefPtr must_create(SysFSGraphicsDirectory const&); + + void plug(Badge, DisplayConnectorSysFSDirectory&); + void unplug(Badge, SysFSDirectory&); + +private: + explicit SysFSDisplayConnectorsDirectory(SysFSGraphicsDirectory const&); +}; + +} diff --git a/Kernel/Graphics/DisplayConnector.cpp b/Kernel/Graphics/DisplayConnector.cpp index e6462e33d1..9cf8f327b8 100644 --- a/Kernel/Graphics/DisplayConnector.cpp +++ b/Kernel/Graphics/DisplayConnector.cpp @@ -4,6 +4,9 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include +#include +#include #include #include #include @@ -57,12 +60,31 @@ ErrorOr DisplayConnector::write(OpenFileDescription&, u64, UserOrKernelB void DisplayConnector::will_be_destroyed() { GraphicsManagement::the().detach_display_connector({}, *this); - Device::will_be_destroyed(); + + VERIFY(m_symlink_sysfs_component); + VERIFY(!is_block_device()); + SysFSCharacterDevicesDirectory::the().m_child_components.with([&](auto& list) -> void { + list.remove(*m_symlink_sysfs_component); + }); + m_symlink_sysfs_component.clear(); + SysFSDisplayConnectorsDirectory::the().unplug({}, *m_sysfs_device_directory); + before_will_be_destroyed_remove_from_device_management(); } void DisplayConnector::after_inserting() { - Device::after_inserting(); + after_inserting_add_to_device_management(); + auto sysfs_display_connector_device_directory = DisplayConnectorSysFSDirectory::create(SysFSDisplayConnectorsDirectory::the(), *this); + m_sysfs_device_directory = sysfs_display_connector_device_directory; + SysFSDisplayConnectorsDirectory::the().plug({}, *sysfs_display_connector_device_directory); + VERIFY(!m_symlink_sysfs_component); + auto sys_fs_component = MUST(SysFSSymbolicLinkDeviceComponent::try_create(SysFSDeviceIdentifiersDirectory::the(), *this, *m_sysfs_device_directory)); + m_symlink_sysfs_component = sys_fs_component; + VERIFY(!is_block_device()); + SysFSCharacterDevicesDirectory::the().m_child_components.with([&](auto& list) -> void { + list.append(*m_symlink_sysfs_component); + }); + auto rounded_size = MUST(Memory::page_round_up(m_framebuffer_resource_size)); if (!m_framebuffer_at_arbitrary_physical_range) {