From 49c902d581703bd6db5c7439dd7c1dc0a5b0e726 Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 17 Jan 2022 09:57:08 -0700 Subject: [PATCH] LibEDID: Add API for conveniently querying EDID from framebuffer device --- Userland/Libraries/LibEDID/EDID.cpp | 54 +++++++++++++++++++++++++++++ Userland/Libraries/LibEDID/EDID.h | 5 +++ 2 files changed, 59 insertions(+) diff --git a/Userland/Libraries/LibEDID/EDID.cpp b/Userland/Libraries/LibEDID/EDID.cpp index c4a36be73a..ecf333fbed 100644 --- a/Userland/Libraries/LibEDID/EDID.cpp +++ b/Userland/Libraries/LibEDID/EDID.cpp @@ -8,6 +8,13 @@ #include #include +#ifndef KERNEL +# include +# include +# include +# include +#endif + namespace EDID { // clang doesn't like passing around pointers to members in packed structures, @@ -336,6 +343,53 @@ ErrorOr Parser::from_bytes(ByteBuffer&& bytes) return edid; } +#ifndef KERNEL +ErrorOr Parser::from_framebuffer_device(int framebuffer_fd, size_t head) +{ + RawBytes edid_bytes; + FBHeadEDID edid_info {}; + edid_info.head_index = head; + edid_info.bytes = &edid_bytes[0]; + edid_info.bytes_size = sizeof(edid_bytes); + if (fb_get_head_edid(framebuffer_fd, &edid_info) < 0) { + int err = errno; + if (err == EOVERFLOW) { + // We need a bigger buffer with at least bytes_size bytes + auto edid_byte_buffer = ByteBuffer::create_zeroed(edid_info.bytes_size); + if (!edid_byte_buffer.has_value()) + return Error::from_errno(ENOMEM); + edid_info.bytes = edid_byte_buffer.value().data(); + if (fb_get_head_edid(framebuffer_fd, &edid_info) < 0) { + err = errno; + return Error::from_errno(err); + } + + return from_bytes(edid_byte_buffer.release_value()); + } + + return Error::from_errno(err); + } + + auto edid_byte_buffer = ByteBuffer::copy((void const*)edid_bytes, sizeof(edid_bytes)); + if (!edid_byte_buffer.has_value()) + return Error::from_errno(ENOMEM); + return from_bytes(edid_byte_buffer.release_value()); +} + +ErrorOr Parser::from_framebuffer_device(String const& framebuffer_device, size_t head) +{ + int framebuffer_fd = open(framebuffer_device.characters(), O_RDWR | O_CLOEXEC); + if (framebuffer_fd < 0) { + int err = errno; + return Error::from_errno(err); + } + ScopeGuard fd_guard([&] { + close(framebuffer_fd); + }); + return from_framebuffer_device(framebuffer_fd, head); +} +#endif + Parser::Parser(ReadonlyBytes bytes) : m_bytes(move(bytes)) { diff --git a/Userland/Libraries/LibEDID/EDID.h b/Userland/Libraries/LibEDID/EDID.h index 82aced81fe..da966708cd 100644 --- a/Userland/Libraries/LibEDID/EDID.h +++ b/Userland/Libraries/LibEDID/EDID.h @@ -77,6 +77,11 @@ public: static ErrorOr from_bytes(ReadonlyBytes); static ErrorOr from_bytes(ByteBuffer&&); +#ifndef KERNEL + static ErrorOr from_framebuffer_device(int, size_t); + static ErrorOr from_framebuffer_device(String const&, size_t); +#endif + String legacy_manufacturer_id() const; u16 product_code() const; u32 serial_number() const;