Przeglądaj źródła

Kernel/SysFS: Add exposing interface for DisplayConnectors

Under normal conditions (when mounting SysFS in /sys), there will be a
new directory in the /sys/devices directory called "graphics".
For now, under that directory there will be only a sub-directory called
"connectors" which will contain all DisplayConnectors' details, each in
its own sub-directory too, distinguished in naming with its minor
number.

Therefore, /sys/devices/graphics/connectors/MINOR_NUMBER/ will contain:
- General device attributes such as mutable_mode_setting_capable,
  double_buffering_capable, flush_support, partial_flush_support and
  refresh_rate_support. These values are exposed in the ioctl interface
  of the DisplayConnector class too, but these can be useful later on
  for command line utilities that want/need to expose these basic
  settings.
- The EDID blob, simply named "edid". This will help userspace to fetch
  the edid without the need of using the ioctl interface later on.
Liav A 3 lat temu
rodzic
commit
da8d18b263

+ 4 - 0
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

+ 3 - 0
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<SysFSCharacterDevicesDirectory> must_create(SysFSDeviceIdentifiersDirectory const&);

+ 2 - 0
Kernel/FileSystem/SysFS/Subsystems/Devices/Directory.cpp

@@ -6,6 +6,7 @@
 
 #include <Kernel/FileSystem/SysFS/RootDirectory.h>
 #include <Kernel/FileSystem/SysFS/Subsystems/Devices/Directory.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/Directory.h>
 #include <Kernel/FileSystem/SysFS/Subsystems/Devices/Storage/Directory.h>
 #include <Kernel/Sections.h>
 
@@ -16,6 +17,7 @@ UNMAP_AFTER_INIT NonnullRefPtr<SysFSDevicesDirectory> 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<void> {
         list.append(SysFSStorageDirectory::must_create(*devices_directory));
+        list.append(SysFSGraphicsDirectory::must_create(*devices_directory));
         return {};
     }));
     return devices_directory;

+ 28 - 0
Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/Directory.cpp

@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/Directory.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/Directory.h>
+#include <Kernel/Sections.h>
+
+namespace Kernel {
+
+UNMAP_AFTER_INIT NonnullRefPtr<SysFSGraphicsDirectory> 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<void> {
+        list.append(SysFSDisplayConnectorsDirectory::must_create(*directory));
+        return {};
+    }));
+    return directory;
+}
+
+UNMAP_AFTER_INIT SysFSGraphicsDirectory::SysFSGraphicsDirectory(SysFSDevicesDirectory const& parent_directory)
+    : SysFSDirectory(parent_directory)
+{
+}
+
+}

+ 26 - 0
Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/Directory.h

@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <Kernel/FileSystem/SysFS/Component.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Directory.h>
+#include <Kernel/Forward.h>
+
+namespace Kernel {
+
+class SysFSGraphicsDirectory : public SysFSDirectory {
+    friend class SysFSComponentRegistry;
+
+public:
+    virtual StringView name() const override { return "graphics"sv; }
+    static NonnullRefPtr<SysFSGraphicsDirectory> must_create(SysFSDevicesDirectory const&);
+
+private:
+    explicit SysFSGraphicsDirectory(SysFSDevicesDirectory const&);
+};
+
+}

+ 87 - 0
Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceAttribute.cpp

@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <Kernel/Bus/PCI/API.h>
+#include <Kernel/Bus/PCI/Access.h>
+#include <Kernel/Debug.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceAttribute.h>
+#include <Kernel/Sections.h>
+
+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> 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<size_t> 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<off_t>(blob->size() - offset), static_cast<off_t>(count));
+    TRY(buffer.write(blob->data() + offset, nread));
+    return nread;
+}
+
+ErrorOr<NonnullOwnPtr<KBuffer>> DisplayConnectorAttributeSysFSComponent::try_to_generate_buffer() const
+{
+    OwnPtr<KString> 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());
+}
+}

+ 42 - 0
Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceAttribute.h

@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <Kernel/FileSystem/SysFS/Component.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceDirectory.h>
+#include <Kernel/Graphics/DisplayConnector.h>
+#include <Kernel/KBuffer.h>
+
+namespace Kernel {
+
+class DisplayConnectorAttributeSysFSComponent : public SysFSComponent {
+public:
+    enum class Type {
+        MutableModeSettingCapable,
+        DoubleFrameBufferingCapable,
+        FlushSupport,
+        PartialFlushSupport,
+        RefreshRateSupport,
+        EDID,
+    };
+
+public:
+    static NonnullRefPtr<DisplayConnectorAttributeSysFSComponent> must_create(DisplayConnectorSysFSDirectory const& device_directory, Type);
+
+    virtual ErrorOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer&, OpenFileDescription*) const override;
+    virtual ~DisplayConnectorAttributeSysFSComponent() {};
+
+    virtual StringView name() const override;
+
+protected:
+    ErrorOr<NonnullOwnPtr<KBuffer>> try_to_generate_buffer() const;
+    DisplayConnectorAttributeSysFSComponent(DisplayConnectorSysFSDirectory const& device, Type);
+    NonnullRefPtr<DisplayConnector> m_device;
+    Type const m_type { Type::MutableModeSettingCapable };
+};
+
+}

+ 46 - 0
Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceDirectory.cpp

@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <Kernel/Bus/PCI/API.h>
+#include <Kernel/Bus/PCI/Access.h>
+#include <Kernel/Debug.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceAttribute.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceDirectory.h>
+#include <Kernel/Graphics/DisplayConnector.h>
+#include <Kernel/Sections.h>
+
+namespace Kernel {
+
+DisplayConnector const& DisplayConnectorSysFSDirectory::device(Badge<DisplayConnectorAttributeSysFSComponent>) const
+{
+    return *m_device;
+}
+
+UNMAP_AFTER_INIT NonnullRefPtr<DisplayConnectorSysFSDirectory> 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<void> {
+        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<KString> device_directory_name, SysFSDirectory const& parent_directory, DisplayConnector const& device)
+    : SysFSDirectory(parent_directory)
+    , m_device(device)
+    , m_device_directory_name(move(device_directory_name))
+{
+}
+
+}

+ 30 - 0
Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceDirectory.h

@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <Kernel/FileSystem/SysFS/Component.h>
+#include <Kernel/Graphics/DisplayConnector.h>
+#include <Kernel/KString.h>
+
+namespace Kernel {
+
+class DisplayConnectorAttributeSysFSComponent;
+class DisplayConnectorSysFSDirectory final : public SysFSDirectory {
+public:
+    static NonnullRefPtr<DisplayConnectorSysFSDirectory> create(SysFSDirectory const&, DisplayConnector const&);
+
+    virtual StringView name() const override { return m_device_directory_name->view(); }
+
+    DisplayConnector const& device(Badge<DisplayConnectorAttributeSysFSComponent>) const;
+
+private:
+    DisplayConnectorSysFSDirectory(NonnullOwnPtr<KString> device_directory_name, SysFSDirectory const&, DisplayConnector const&);
+    RefPtr<DisplayConnector> m_device;
+    NonnullOwnPtr<KString> m_device_directory_name;
+};
+
+}

+ 54 - 0
Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/Directory.cpp

@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <Kernel/FileSystem/SysFS/RootDirectory.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Directory.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/Directory.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceDirectory.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/Directory.h>
+#include <Kernel/Sections.h>
+#include <Kernel/Storage/StorageDevice.h>
+
+namespace Kernel {
+
+static SysFSDisplayConnectorsDirectory* s_the { nullptr };
+
+UNMAP_AFTER_INIT NonnullRefPtr<SysFSDisplayConnectorsDirectory> 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<DisplayConnector>, DisplayConnectorSysFSDirectory& new_device_directory)
+{
+    MUST(m_child_components.with([&](auto& list) -> ErrorOr<void> {
+        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<DisplayConnector>, SysFSDirectory& removed_device_directory)
+{
+    MUST(m_child_components.with([&](auto& list) -> ErrorOr<void> {
+        list.remove(removed_device_directory);
+        return {};
+    }));
+}
+
+UNMAP_AFTER_INIT SysFSDisplayConnectorsDirectory::SysFSDisplayConnectorsDirectory(SysFSGraphicsDirectory const& parent_directory)
+    : SysFSDirectory(parent_directory)
+{
+}
+
+}

+ 32 - 0
Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/Directory.h

@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2022, Liav A. <liavalb@hotmail.co.il>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <Kernel/FileSystem/SysFS/Component.h>
+#include <Kernel/Forward.h>
+
+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<SysFSDisplayConnectorsDirectory> must_create(SysFSGraphicsDirectory const&);
+
+    void plug(Badge<DisplayConnector>, DisplayConnectorSysFSDirectory&);
+    void unplug(Badge<DisplayConnector>, SysFSDirectory&);
+
+private:
+    explicit SysFSDisplayConnectorsDirectory(SysFSGraphicsDirectory const&);
+};
+
+}

+ 24 - 2
Kernel/Graphics/DisplayConnector.cpp

@@ -4,6 +4,9 @@
  * SPDX-License-Identifier: BSD-2-Clause
  */
 
+#include <Kernel/FileSystem/SysFS/Subsystems/DeviceIdentifiers/CharacterDevicesDirectory.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/DeviceDirectory.h>
+#include <Kernel/FileSystem/SysFS/Subsystems/Devices/Graphics/DisplayConnector/Directory.h>
 #include <Kernel/Graphics/DisplayConnector.h>
 #include <Kernel/Graphics/GraphicsManagement.h>
 #include <Kernel/Memory/MemoryManager.h>
@@ -57,12 +60,31 @@ ErrorOr<size_t> 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) {