summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibEDID
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2022-01-17 09:57:08 -0700
committerLinus Groh <mail@linusgroh.de>2022-01-23 22:45:21 +0000
commit49c902d581703bd6db5c7439dd7c1dc0a5b0e726 (patch)
tree65948c3a13f974213743a05f0c3fe1b17f42ace1 /Userland/Libraries/LibEDID
parent03c45b18653b960f1e7c1705ef0cdbb5b2d2f94d (diff)
downloadserenity-49c902d581703bd6db5c7439dd7c1dc0a5b0e726.zip
LibEDID: Add API for conveniently querying EDID from framebuffer device
Diffstat (limited to 'Userland/Libraries/LibEDID')
-rw-r--r--Userland/Libraries/LibEDID/EDID.cpp54
-rw-r--r--Userland/Libraries/LibEDID/EDID.h5
2 files changed, 59 insertions, 0 deletions
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 <AK/QuickSort.h>
#include <LibEDID/EDID.h>
+#ifndef KERNEL
+# include <AK/ScopeGuard.h>
+# include <Kernel/API/FB.h>
+# include <fcntl.h>
+# include <unistd.h>
+#endif
+
namespace EDID {
// clang doesn't like passing around pointers to members in packed structures,
@@ -336,6 +343,53 @@ ErrorOr<Parser> Parser::from_bytes(ByteBuffer&& bytes)
return edid;
}
+#ifndef KERNEL
+ErrorOr<Parser> 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> 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<Parser> from_bytes(ReadonlyBytes);
static ErrorOr<Parser> from_bytes(ByteBuffer&&);
+#ifndef KERNEL
+ static ErrorOr<Parser> from_framebuffer_device(int, size_t);
+ static ErrorOr<Parser> from_framebuffer_device(String const&, size_t);
+#endif
+
String legacy_manufacturer_id() const;
u16 product_code() const;
u32 serial_number() const;