EDID.cpp 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281
  1. /*
  2. * Copyright (c) 2022, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Function.h>
  7. #include <AK/QuickSort.h>
  8. #include <LibEDID/EDID.h>
  9. #ifndef KERNEL
  10. # include <AK/ScopeGuard.h>
  11. # include <Kernel/API/FB.h>
  12. # include <fcntl.h>
  13. # include <unistd.h>
  14. # ifdef ENABLE_PNP_IDS_DATA
  15. # include <LibEDID/PnpIDs.h>
  16. # endif
  17. #endif
  18. namespace EDID {
  19. // clang doesn't like passing around pointers to members in packed structures,
  20. // even though we're only using them for arithmetic purposes
  21. #ifdef __clang__
  22. # pragma clang diagnostic ignored "-Waddress-of-packed-member"
  23. #endif
  24. namespace Definitions {
  25. struct [[gnu::packed]] StandardTimings {
  26. u8 horizontal_8_pixels;
  27. u8 ratio_and_refresh_rate;
  28. };
  29. struct [[gnu::packed]] DetailedTiming {
  30. u16 pixel_clock;
  31. u8 horizontal_addressable_pixels_low;
  32. u8 horizontal_blanking_pixels_low;
  33. u8 horizontal_addressable_and_blanking_pixels_high;
  34. u8 vertical_addressable_lines_low;
  35. u8 vertical_blanking_lines_low;
  36. u8 vertical_addressable_and_blanking_lines_high;
  37. u8 horizontal_front_porch_pixels_low;
  38. u8 horizontal_sync_pulse_width_pixels_low;
  39. u8 vertical_front_porch_and_sync_pulse_width_lines_low;
  40. u8 horizontal_and_vertical_front_porch_sync_pulse_width_high;
  41. u8 horizontal_addressable_image_size_mm_low;
  42. u8 vertical_addressable_image_size_mm_low;
  43. u8 horizontal_vertical_addressable_image_size_mm_high;
  44. u8 right_or_left_horizontal_border_pixels;
  45. u8 top_or_bottom_vertical_border_lines;
  46. u8 features;
  47. };
  48. enum class DisplayDescriptorTag : u8 {
  49. ManufacturerSpecified_First = 0x0,
  50. ManufacturerSpecified_Last = 0xf,
  51. Dummy = 0x10,
  52. EstablishedTimings3 = 0xf7,
  53. CVTTimingCodes = 0xf8,
  54. DisplayColorManagementData = 0xf9,
  55. StandardTimingIdentifications = 0xfa,
  56. ColorPointData = 0xfb,
  57. DisplayProductName = 0xfc,
  58. DisplayRangeLimits = 0xfd,
  59. AlphanumericDataString = 0xfe,
  60. DisplayProductSerialNumber = 0xff
  61. };
  62. struct [[gnu::packed]] DisplayDescriptor {
  63. u16 zero;
  64. u8 reserved1;
  65. u8 tag;
  66. u8 reserved2;
  67. union {
  68. struct [[gnu::packed]] {
  69. u8 ascii_name[13];
  70. } display_product_name;
  71. struct [[gnu::packed]] {
  72. u8 ascii_str[13];
  73. } display_product_serial_number;
  74. struct [[gnu::packed]] {
  75. u8 revision;
  76. u8 dmt_bits[6];
  77. u8 reserved[6];
  78. } established_timings3;
  79. struct [[gnu::packed]] {
  80. u8 version;
  81. u8 cvt[4][3];
  82. } coordinated_video_timings;
  83. };
  84. };
  85. static_assert(sizeof(DetailedTiming) == sizeof(DisplayDescriptor));
  86. struct [[gnu::packed]] EDID {
  87. u64 header;
  88. struct [[gnu::packed]] {
  89. u16 manufacturer_id;
  90. u16 product_code;
  91. u32 serial_number;
  92. u8 week_of_manufacture;
  93. u8 year_of_manufacture;
  94. } vendor;
  95. struct [[gnu::packed]] {
  96. u8 version;
  97. u8 revision;
  98. } version;
  99. struct [[gnu::packed]] {
  100. u8 video_input_definition;
  101. u8 horizontal_size_or_aspect_ratio;
  102. u8 vertical_size_or_aspect_ratio;
  103. u8 display_transfer_characteristics;
  104. u8 feature_support;
  105. } basic_display_parameters;
  106. struct [[gnu::packed]] {
  107. u8 red_green_low_order_bits;
  108. u8 blue_white_low_order_bits;
  109. u8 red_x_high_order_bits;
  110. u8 red_y_high_order_bits;
  111. u8 green_x_high_order_bits;
  112. u8 green_y_high_order_bits;
  113. u8 blue_x_high_order_bits;
  114. u8 blue_y_high_order_bits;
  115. u8 white_x_high_order_bits;
  116. u8 white_y_high_order_bits;
  117. } color_characteristics;
  118. struct [[gnu::packed]] {
  119. u8 timings_1;
  120. u8 timings_2;
  121. u8 manufacturer_reserved;
  122. } established_timings;
  123. StandardTimings standard_timings[8];
  124. union {
  125. DetailedTiming detailed_timing;
  126. DisplayDescriptor display_descriptor;
  127. } detailed_timing_or_display_descriptors[4];
  128. u8 extension_block_count;
  129. u8 checksum;
  130. };
  131. enum class ExtensionBlockTag : u8 {
  132. CEA_861 = 0x2,
  133. VideoTimingBlock = 0x10,
  134. DisplayInformation = 0x40,
  135. LocalizedString = 0x50,
  136. DigitalPacketVideoLink = 0x60,
  137. ExtensionBlockMap = 0xf0,
  138. ManufacturerDefined = 0xff
  139. };
  140. struct [[gnu::packed]] ExtensionBlock {
  141. u8 tag;
  142. union {
  143. struct [[gnu::packed]] {
  144. u8 block_tags[126];
  145. } map;
  146. struct [[gnu::packed]] {
  147. u8 revision;
  148. u8 bytes[125];
  149. } block;
  150. struct [[gnu::packed]] {
  151. u8 revision;
  152. u8 dtd_start_offset;
  153. u8 flags;
  154. union {
  155. u8 bytes[123];
  156. };
  157. } cea861extension;
  158. };
  159. u8 checksum;
  160. };
  161. }
  162. static_assert(sizeof(Definitions::EDID) == Parser::BufferSize);
  163. static_assert(sizeof(Definitions::ExtensionBlock) == 128);
  164. class CEA861ExtensionBlock final {
  165. friend class Parser;
  166. public:
  167. enum class DataBlockTag : u8 {
  168. Reserved = 0,
  169. Audio,
  170. Video,
  171. VendorSpecific,
  172. SpeakerAllocation,
  173. VesaDTC,
  174. Reserved2,
  175. Extended
  176. };
  177. ErrorOr<IterationDecision> for_each_short_video_descriptor(Function<IterationDecision(bool, VIC::Details const&)> callback) const
  178. {
  179. return for_each_data_block([&](DataBlockTag tag, ReadonlyBytes bytes) -> ErrorOr<IterationDecision> {
  180. if (tag != DataBlockTag::Video)
  181. return IterationDecision::Continue;
  182. // Short video descriptors are one byte values
  183. for (size_t i = 0; i < bytes.size(); i++) {
  184. u8 byte = m_edid.read_host(&bytes[i]);
  185. bool is_native = (byte & 0x80) != 0;
  186. u8 vic_id = byte & 0x7f;
  187. auto* vic_details = VIC::find_details_by_vic_id(vic_id);
  188. if (!vic_details)
  189. return Error::from_string_literal("CEA 861 extension block has invalid short video descriptor"sv);
  190. IterationDecision decision = callback(is_native, *vic_details);
  191. if (decision != IterationDecision::Continue)
  192. return decision;
  193. }
  194. return IterationDecision::Continue;
  195. });
  196. }
  197. ErrorOr<IterationDecision> for_each_dtd(Function<IterationDecision(Parser::DetailedTiming const&)> callback) const
  198. {
  199. u8 dtd_start = m_edid.read_host(&m_block->cea861extension.dtd_start_offset);
  200. if (dtd_start < 4) {
  201. // dtd_start == 4 means there are no data blocks, but there are still DTDs
  202. return IterationDecision::Continue;
  203. }
  204. if (dtd_start > offsetof(Definitions::ExtensionBlock, checksum) - sizeof(Definitions::DetailedTiming))
  205. return Error::from_string_literal("CEA 861 extension block has invalid DTD list"sv);
  206. size_t dtd_index = 0;
  207. for (size_t offset = dtd_start; offset <= offsetof(Definitions::ExtensionBlock, checksum) - sizeof(Definitions::DetailedTiming); offset += sizeof(Definitions::DetailedTiming)) {
  208. auto& dtd = *(Definitions::DetailedTiming const*)((u8 const*)m_block + offset);
  209. if (m_edid.read_host(&dtd.pixel_clock) == 0)
  210. break;
  211. IterationDecision decision = callback(Parser::DetailedTiming(m_edid, &dtd));
  212. if (decision != IterationDecision::Continue)
  213. return decision;
  214. dtd_index++;
  215. }
  216. return IterationDecision::Continue;
  217. }
  218. private:
  219. CEA861ExtensionBlock(Parser const& edid, Definitions::ExtensionBlock const* block)
  220. : m_edid(edid)
  221. , m_block(block)
  222. {
  223. }
  224. ErrorOr<IterationDecision> for_each_data_block(Function<ErrorOr<IterationDecision>(DataBlockTag, ReadonlyBytes)> callback) const
  225. {
  226. u8 dtd_start = m_edid.read_host(&m_block->cea861extension.dtd_start_offset);
  227. if (dtd_start <= 4)
  228. return IterationDecision::Continue;
  229. if (dtd_start > offsetof(Definitions::ExtensionBlock, checksum))
  230. return Error::from_string_literal("CEA 861 extension block has invalid DTD start offset"sv);
  231. auto* data_block_header = &m_block->cea861extension.bytes[0];
  232. auto* data_block_end = (u8 const*)m_block + dtd_start;
  233. while (data_block_header < data_block_end) {
  234. auto header_byte = m_edid.read_host(data_block_header);
  235. size_t payload_size = header_byte & 0x1f;
  236. auto tag = (DataBlockTag)((header_byte >> 5) & 0x7);
  237. if (tag == DataBlockTag::Extended && payload_size == 0)
  238. return Error::from_string_literal("CEA 861 extension block has invalid extended data block size"sv);
  239. auto decision = TRY(callback(tag, m_edid.m_bytes.slice(data_block_header - m_edid.m_bytes.data() + 1, payload_size)));
  240. if (decision != IterationDecision::Continue)
  241. return decision;
  242. data_block_header += 1 + payload_size;
  243. }
  244. return IterationDecision::Continue;
  245. }
  246. ErrorOr<IterationDecision> for_each_display_descriptor(Function<IterationDecision(u8, Definitions::DisplayDescriptor const&)> callback) const
  247. {
  248. u8 dtd_start = m_edid.read_host(&m_block->cea861extension.dtd_start_offset);
  249. if (dtd_start <= 4)
  250. return IterationDecision::Continue;
  251. if (dtd_start > offsetof(Definitions::ExtensionBlock, checksum) - sizeof(Definitions::DetailedTiming))
  252. return Error::from_string_literal("CEA 861 extension block has invalid DTD list"sv);
  253. for (size_t offset = dtd_start; offset <= offsetof(Definitions::ExtensionBlock, checksum) - sizeof(Definitions::DisplayDescriptor); offset += sizeof(Definitions::DisplayDescriptor)) {
  254. auto& dd = *(Definitions::DisplayDescriptor const*)((u8 const*)m_block + offset);
  255. if (m_edid.read_host(&dd.zero) != 0 || m_edid.read_host(&dd.reserved1) != 0)
  256. continue;
  257. u8 tag = m_edid.read_host(&dd.tag);
  258. IterationDecision decision = callback(tag, dd);
  259. if (decision != IterationDecision::Continue)
  260. return decision;
  261. }
  262. return IterationDecision::Continue;
  263. }
  264. Parser const& m_edid;
  265. Definitions::ExtensionBlock const* m_block;
  266. };
  267. template<typename T>
  268. T Parser::read_host(T const* field) const
  269. {
  270. VERIFY((u8 const*)field >= m_bytes.data() && (u8 const*)field + sizeof(T) <= m_bytes.data() + m_bytes.size());
  271. size_t offset = (u8 const*)field - m_bytes.data();
  272. T value;
  273. if constexpr (sizeof(T) > 1)
  274. ByteReader::load(m_bytes.offset(offset), value);
  275. else
  276. value = m_bytes.at(offset);
  277. return value;
  278. }
  279. template<typename T>
  280. requires(IsIntegral<T> && sizeof(T) > 1) T Parser::read_le(T const* field)
  281. const
  282. {
  283. static_assert(sizeof(T) > 1);
  284. return AK::convert_between_host_and_little_endian(read_host(field));
  285. }
  286. template<typename T>
  287. requires(IsIntegral<T> && sizeof(T) > 1) T Parser::read_be(T const* field)
  288. const
  289. {
  290. static_assert(sizeof(T) > 1);
  291. return AK::convert_between_host_and_big_endian(read_host(field));
  292. }
  293. ErrorOr<Parser> Parser::from_bytes(ReadonlyBytes bytes)
  294. {
  295. Parser edid(bytes);
  296. if (auto parse_result = edid.parse(); parse_result.is_error())
  297. return parse_result.error();
  298. return edid;
  299. }
  300. ErrorOr<Parser> Parser::from_bytes(ByteBuffer&& bytes)
  301. {
  302. Parser edid(move(bytes));
  303. if (auto parse_result = edid.parse(); parse_result.is_error())
  304. return parse_result.error();
  305. return edid;
  306. }
  307. #ifndef KERNEL
  308. ErrorOr<Parser> Parser::from_framebuffer_device(int framebuffer_fd, size_t head)
  309. {
  310. RawBytes edid_bytes;
  311. FBHeadEDID edid_info {};
  312. edid_info.head_index = head;
  313. edid_info.bytes = &edid_bytes[0];
  314. edid_info.bytes_size = sizeof(edid_bytes);
  315. if (fb_get_head_edid(framebuffer_fd, &edid_info) < 0) {
  316. int err = errno;
  317. if (err == EOVERFLOW) {
  318. // We need a bigger buffer with at least bytes_size bytes
  319. auto edid_byte_buffer = TRY(ByteBuffer::create_zeroed(edid_info.bytes_size));
  320. edid_info.bytes = edid_byte_buffer.data();
  321. if (fb_get_head_edid(framebuffer_fd, &edid_info) < 0) {
  322. err = errno;
  323. return Error::from_errno(err);
  324. }
  325. return from_bytes(move(edid_byte_buffer));
  326. }
  327. return Error::from_errno(err);
  328. }
  329. auto edid_byte_buffer = TRY(ByteBuffer::copy((void const*)edid_bytes, sizeof(edid_bytes)));
  330. return from_bytes(move(edid_byte_buffer));
  331. }
  332. ErrorOr<Parser> Parser::from_framebuffer_device(String const& framebuffer_device, size_t head)
  333. {
  334. int framebuffer_fd = open(framebuffer_device.characters(), O_RDWR | O_CLOEXEC);
  335. if (framebuffer_fd < 0) {
  336. int err = errno;
  337. return Error::from_errno(err);
  338. }
  339. ScopeGuard fd_guard([&] {
  340. close(framebuffer_fd);
  341. });
  342. return from_framebuffer_device(framebuffer_fd, head);
  343. }
  344. #endif
  345. Parser::Parser(ReadonlyBytes bytes)
  346. : m_bytes(move(bytes))
  347. {
  348. }
  349. Parser::Parser(ByteBuffer&& bytes)
  350. : m_bytes_buffer(move(bytes))
  351. , m_bytes(m_bytes_buffer)
  352. {
  353. }
  354. Parser::Parser(Parser const& other)
  355. : m_bytes_buffer(other.m_bytes_buffer)
  356. , m_revision(other.m_revision)
  357. {
  358. if (m_bytes_buffer.is_empty())
  359. m_bytes = other.m_bytes_buffer; // We don't own the buffer
  360. else
  361. m_bytes = m_bytes_buffer; // We own the buffer
  362. }
  363. Parser& Parser::operator=(Parser&& from)
  364. {
  365. m_bytes_buffer = move(from.m_bytes_buffer);
  366. m_bytes = move(from.m_bytes);
  367. m_revision = from.m_revision;
  368. return *this;
  369. }
  370. Parser& Parser::operator=(Parser const& other)
  371. {
  372. if (this == &other)
  373. return *this;
  374. m_bytes_buffer = other.m_bytes_buffer;
  375. if (m_bytes_buffer.is_empty())
  376. m_bytes = other.m_bytes_buffer; // We don't own the buffer
  377. else
  378. m_bytes = m_bytes_buffer; // We own the buffer
  379. m_revision = other.m_revision;
  380. return *this;
  381. }
  382. bool Parser::operator==(Parser const& other) const
  383. {
  384. if (this == &other)
  385. return true;
  386. return m_bytes == other.m_bytes;
  387. }
  388. Definitions::EDID const& Parser::raw_edid() const
  389. {
  390. return *(Definitions::EDID const*)m_bytes.data();
  391. }
  392. ErrorOr<void> Parser::parse()
  393. {
  394. if (m_bytes.size() < sizeof(Definitions::EDID))
  395. return Error::from_string_literal("Incomplete Parser structure"sv);
  396. auto const& edid = raw_edid();
  397. u64 header = read_le(&edid.header);
  398. if (header != 0x00ffffffffffff00ull)
  399. return Error::from_string_literal("No Parser header"sv);
  400. u8 major_version = read_host(&edid.version.version);
  401. m_revision = read_host(&edid.version.revision);
  402. if (major_version != 1 || m_revision > 4)
  403. return Error::from_string_literal("Unsupported Parser version"sv);
  404. #ifdef KERNEL
  405. m_version = TRY(Kernel::KString::formatted("1.{}", (int)m_revision));
  406. #else
  407. m_version = String::formatted("1.{}", (int)m_revision);
  408. #endif
  409. u8 checksum = 0x0;
  410. for (size_t i = 0; i < sizeof(Definitions::EDID); i++)
  411. checksum += m_bytes[i];
  412. if (checksum != 0) {
  413. if (m_revision >= 4) {
  414. return Error::from_string_literal("Parser checksum mismatch"sv);
  415. } else {
  416. dbgln("EDID checksum mismatch, data may be corrupted!");
  417. }
  418. }
  419. u16 packed_id = read_be(&raw_edid().vendor.manufacturer_id);
  420. m_legacy_manufacturer_id[0] = (char)((u16)'A' + ((packed_id >> 10) & 0x1f) - 1);
  421. m_legacy_manufacturer_id[1] = (char)((u16)'A' + ((packed_id >> 5) & 0x1f) - 1);
  422. m_legacy_manufacturer_id[2] = (char)((u16)'A' + (packed_id & 0x1f) - 1);
  423. m_legacy_manufacturer_id[3] = '\0';
  424. return {};
  425. }
  426. ErrorOr<IterationDecision> Parser::for_each_extension_block(Function<IterationDecision(unsigned, u8, u8, ReadonlyBytes)> callback) const
  427. {
  428. auto& edid = raw_edid();
  429. u8 raw_extension_block_count = read_host(&edid.extension_block_count);
  430. if (raw_extension_block_count == 0)
  431. return IterationDecision::Continue;
  432. if (sizeof(Definitions::EDID) + (size_t)raw_extension_block_count * sizeof(Definitions::ExtensionBlock) > m_bytes.size())
  433. return Error::from_string_literal("Truncated EDID");
  434. auto validate_block_checksum = [&](Definitions::ExtensionBlock const& block) {
  435. u8 checksum = 0x0;
  436. auto* bytes = (u8 const*)&block;
  437. for (size_t i = 0; i < sizeof(block); i++)
  438. checksum += bytes[i];
  439. return checksum == 0;
  440. };
  441. auto* raw_extension_blocks = (Definitions::ExtensionBlock const*)(m_bytes.data() + sizeof(Definitions::EDID));
  442. Definitions::ExtensionBlock const* current_extension_map = nullptr;
  443. unsigned raw_index = 0;
  444. if (m_revision <= 3) {
  445. if (raw_extension_block_count > 1) {
  446. current_extension_map = &raw_extension_blocks[0];
  447. raw_index++;
  448. if (read_host(&current_extension_map->tag) != (u8)Definitions::ExtensionBlockTag::ExtensionBlockMap)
  449. return Error::from_string_literal("Did not find extension map at block 1"sv);
  450. if (!validate_block_checksum(*current_extension_map))
  451. return Error::from_string_literal("Extension block map checksum mismatch"sv);
  452. }
  453. } else if (read_host(&raw_extension_blocks[0].tag) == (u8)Definitions::ExtensionBlockTag::ExtensionBlockMap) {
  454. current_extension_map = &raw_extension_blocks[0];
  455. raw_index++;
  456. }
  457. for (; raw_index < raw_extension_block_count; raw_index++) {
  458. auto& raw_block = raw_extension_blocks[raw_index];
  459. u8 tag = read_host(&raw_block.tag);
  460. if (current_extension_map && raw_index == 127) {
  461. if (tag != (u8)Definitions::ExtensionBlockTag::ExtensionBlockMap)
  462. return Error::from_string_literal("Did not find extension map at block 128"sv);
  463. current_extension_map = &raw_extension_blocks[127];
  464. if (!validate_block_checksum(*current_extension_map))
  465. return Error::from_string_literal("Extension block map checksum mismatch"sv);
  466. continue;
  467. }
  468. if (tag == (u8)Definitions::ExtensionBlockTag::ExtensionBlockMap)
  469. return Error::from_string_literal("Unexpected extension map encountered"sv);
  470. if (!validate_block_checksum(raw_block))
  471. return Error::from_string_literal("Extension block checksum mismatch"sv);
  472. size_t offset = (u8 const*)&raw_block - m_bytes.data();
  473. IterationDecision decision = callback(raw_index + 1, tag, raw_block.block.revision, m_bytes.slice(offset, sizeof(Definitions::ExtensionBlock)));
  474. if (decision != IterationDecision::Continue)
  475. return decision;
  476. }
  477. return IterationDecision::Continue;
  478. }
  479. StringView Parser::version() const
  480. {
  481. #ifdef KERNEL
  482. return m_version->view();
  483. #else
  484. return m_version;
  485. #endif
  486. }
  487. StringView Parser::legacy_manufacturer_id() const
  488. {
  489. return m_legacy_manufacturer_id;
  490. }
  491. #ifndef KERNEL
  492. String Parser::manufacturer_name() const
  493. {
  494. auto manufacturer_id = legacy_manufacturer_id();
  495. # ifdef ENABLE_PNP_IDS_DATA
  496. if (auto pnp_id_data = PnpIDs::find_by_manufacturer_id(manufacturer_id); pnp_id_data.has_value())
  497. return pnp_id_data.value().manufacturer_name;
  498. # endif
  499. return manufacturer_id;
  500. }
  501. #endif
  502. u16 Parser::product_code() const
  503. {
  504. return read_le(&raw_edid().vendor.product_code);
  505. }
  506. u32 Parser::serial_number() const
  507. {
  508. return read_le(&raw_edid().vendor.serial_number);
  509. }
  510. auto Parser::digital_display() const -> Optional<DigitalDisplay>
  511. {
  512. auto& edid = raw_edid();
  513. u8 video_input_definition = read_host(&edid.basic_display_parameters.video_input_definition);
  514. if (!(video_input_definition & 0x80))
  515. return {}; // This is an analog display
  516. u8 feature_support = read_host(&edid.basic_display_parameters.feature_support);
  517. return DigitalDisplay(video_input_definition, feature_support, m_revision);
  518. }
  519. auto Parser::analog_display() const -> Optional<AnalogDisplay>
  520. {
  521. auto& edid = raw_edid();
  522. u8 video_input_definition = read_host(&edid.basic_display_parameters.video_input_definition);
  523. if ((video_input_definition & 0x80) != 0)
  524. return {}; // This is a digital display
  525. u8 feature_support = read_host(&edid.basic_display_parameters.feature_support);
  526. return AnalogDisplay(video_input_definition, feature_support, m_revision);
  527. }
  528. auto Parser::screen_size() const -> Optional<ScreenSize>
  529. {
  530. auto& edid = raw_edid();
  531. u8 horizontal_size_or_aspect_ratio = read_host(&edid.basic_display_parameters.horizontal_size_or_aspect_ratio);
  532. u8 vertical_size_or_aspect_ratio = read_host(&edid.basic_display_parameters.vertical_size_or_aspect_ratio);
  533. if (horizontal_size_or_aspect_ratio == 0 || vertical_size_or_aspect_ratio == 0) {
  534. // EDID < 1.4: Unknown or undefined
  535. // EDID >= 1.4: If both are 0 it is unknown or undefined
  536. // If one of them is 0 then we're dealing with aspect ratios
  537. return {};
  538. }
  539. return ScreenSize(horizontal_size_or_aspect_ratio, vertical_size_or_aspect_ratio);
  540. }
  541. auto Parser::aspect_ratio() const -> Optional<ScreenAspectRatio>
  542. {
  543. if (m_revision < 4)
  544. return {};
  545. auto& edid = raw_edid();
  546. u8 value_1 = read_host(&edid.basic_display_parameters.horizontal_size_or_aspect_ratio);
  547. u8 value_2 = read_host(&edid.basic_display_parameters.vertical_size_or_aspect_ratio);
  548. if (value_1 == 0 && value_2 == 0)
  549. return {}; // Unknown or undefined
  550. if (value_1 != 0 && value_2 != 0)
  551. return {}; // Dimensions are in cm
  552. if (value_1 == 0)
  553. return ScreenAspectRatio(ScreenAspectRatio::Orientation::Portrait, FixedPoint<16>(100) / FixedPoint<16>((i32)value_2 + 99));
  554. VERIFY(value_2 == 0);
  555. return ScreenAspectRatio(ScreenAspectRatio::Orientation::Landscape, FixedPoint<16>((i32)value_1 + 99) / 100);
  556. }
  557. Optional<FixedPoint<16>> Parser::gamma() const
  558. {
  559. u8 display_transfer_characteristics = read_host(&raw_edid().basic_display_parameters.display_transfer_characteristics);
  560. if (display_transfer_characteristics == 0xff) {
  561. if (m_revision < 4)
  562. return {};
  563. // TODO: EDID >= 1.4 stores more gamma details in an extension block (e.g. DI-EXT)
  564. return {};
  565. }
  566. FixedPoint<16> gamma { (i32)display_transfer_characteristics + 100 };
  567. gamma /= 100;
  568. return gamma;
  569. }
  570. u32 Parser::DetailedTiming::pixel_clock_khz() const
  571. {
  572. // Note: The stored value is in units of 10 kHz, which means that to get the
  573. // value in kHz, we need to multiply it by 10.
  574. return (u32)m_edid.read_le(&m_detailed_timings.pixel_clock) * 10;
  575. }
  576. u16 Parser::DetailedTiming::horizontal_addressable_pixels() const
  577. {
  578. u8 low = m_edid.read_host(&m_detailed_timings.horizontal_addressable_pixels_low);
  579. u8 high = m_edid.read_host(&m_detailed_timings.horizontal_addressable_and_blanking_pixels_high) >> 4;
  580. return ((u16)high << 8) | (u16)low;
  581. }
  582. u16 Parser::DetailedTiming::horizontal_blanking_pixels() const
  583. {
  584. u8 low = m_edid.read_host(&m_detailed_timings.horizontal_blanking_pixels_low);
  585. u8 high = m_edid.read_host(&m_detailed_timings.horizontal_addressable_and_blanking_pixels_high) & 0xf;
  586. return ((u16)high << 8) | (u16)low;
  587. }
  588. u16 Parser::DetailedTiming::vertical_addressable_lines_raw() const
  589. {
  590. u8 low = m_edid.read_host(&m_detailed_timings.vertical_addressable_lines_low);
  591. u8 high = m_edid.read_host(&m_detailed_timings.vertical_addressable_and_blanking_lines_high) >> 4;
  592. return ((u16)high << 8) | (u16)low;
  593. }
  594. u16 Parser::DetailedTiming::vertical_addressable_lines() const
  595. {
  596. auto lines = vertical_addressable_lines_raw();
  597. return is_interlaced() ? lines * 2 : lines;
  598. }
  599. u16 Parser::DetailedTiming::vertical_blanking_lines() const
  600. {
  601. u8 low = m_edid.read_host(&m_detailed_timings.vertical_blanking_lines_low);
  602. u8 high = m_edid.read_host(&m_detailed_timings.vertical_addressable_and_blanking_lines_high) & 0xf;
  603. return ((u16)high << 8) | (u16)low;
  604. }
  605. u16 Parser::DetailedTiming::horizontal_front_porch_pixels() const
  606. {
  607. u8 low = m_edid.read_host(&m_detailed_timings.horizontal_front_porch_pixels_low);
  608. u8 high = m_edid.read_host(&m_detailed_timings.horizontal_and_vertical_front_porch_sync_pulse_width_high) >> 6;
  609. return ((u16)high << 8) | (u16)low;
  610. }
  611. u16 Parser::DetailedTiming::horizontal_sync_pulse_width_pixels() const
  612. {
  613. u8 low = m_edid.read_host(&m_detailed_timings.horizontal_sync_pulse_width_pixels_low);
  614. u8 high = (m_edid.read_host(&m_detailed_timings.horizontal_and_vertical_front_porch_sync_pulse_width_high) >> 4) & 3;
  615. return ((u16)high << 8) | (u16)low;
  616. }
  617. u16 Parser::DetailedTiming::vertical_front_porch_lines() const
  618. {
  619. u8 low = m_edid.read_host(&m_detailed_timings.vertical_front_porch_and_sync_pulse_width_lines_low) >> 4;
  620. u8 high = (m_edid.read_host(&m_detailed_timings.horizontal_and_vertical_front_porch_sync_pulse_width_high) >> 2) & 3;
  621. return ((u16)high << 4) | (u16)low;
  622. }
  623. u16 Parser::DetailedTiming::vertical_sync_pulse_width_lines() const
  624. {
  625. u8 low = m_edid.read_host(&m_detailed_timings.vertical_front_porch_and_sync_pulse_width_lines_low) & 0xf;
  626. u8 high = m_edid.read_host(&m_detailed_timings.horizontal_and_vertical_front_porch_sync_pulse_width_high) & 3;
  627. return ((u16)high << 4) | (u16)low;
  628. }
  629. u16 Parser::DetailedTiming::horizontal_image_size_mm() const
  630. {
  631. u8 low = m_edid.read_host(&m_detailed_timings.horizontal_addressable_image_size_mm_low);
  632. u8 high = m_edid.read_host(&m_detailed_timings.horizontal_vertical_addressable_image_size_mm_high) >> 4;
  633. return ((u16)high << 8) | (u16)low;
  634. }
  635. u16 Parser::DetailedTiming::vertical_image_size_mm() const
  636. {
  637. u8 low = m_edid.read_host(&m_detailed_timings.vertical_addressable_image_size_mm_low);
  638. u8 high = m_edid.read_host(&m_detailed_timings.horizontal_vertical_addressable_image_size_mm_high) & 0xf;
  639. return ((u16)high << 8) | (u16)low;
  640. }
  641. u8 Parser::DetailedTiming::horizontal_right_or_left_border_pixels() const
  642. {
  643. return m_edid.read_host(&m_detailed_timings.right_or_left_horizontal_border_pixels);
  644. }
  645. u8 Parser::DetailedTiming::vertical_top_or_bottom_border_lines() const
  646. {
  647. return m_edid.read_host(&m_detailed_timings.top_or_bottom_vertical_border_lines);
  648. }
  649. bool Parser::DetailedTiming::is_interlaced() const
  650. {
  651. return (m_edid.read_host(&m_detailed_timings.features) & (1 << 7)) != 0;
  652. }
  653. FixedPoint<16, u32> Parser::DetailedTiming::refresh_rate() const
  654. {
  655. // Blanking = front porch + sync pulse width + back porch
  656. u32 total_horizontal_pixels = (u32)horizontal_addressable_pixels() + (u32)horizontal_blanking_pixels();
  657. u32 total_vertical_lines = (u32)vertical_addressable_lines_raw() + (u32)vertical_blanking_lines();
  658. u32 total_pixels = total_horizontal_pixels * total_vertical_lines;
  659. if (total_pixels == 0)
  660. return {};
  661. // Use a bigger fixed point representation due to the large numbers involved and then downcast
  662. // Note: We need to convert the pixel clock from kHz to Hertz to actually calculate this correctly.
  663. return FixedPoint<32, u64>(pixel_clock_khz() * 1000) / total_pixels;
  664. }
  665. ErrorOr<IterationDecision> Parser::for_each_established_timing(Function<IterationDecision(EstablishedTiming const&)> callback) const
  666. {
  667. static constexpr EstablishedTiming established_timing_byte1[8] = {
  668. { EstablishedTiming::Source::VESA, 800, 600, 60, 0x9 },
  669. { EstablishedTiming::Source::VESA, 800, 600, 56, 0x8 },
  670. { EstablishedTiming::Source::VESA, 640, 480, 75, 0x6 },
  671. { EstablishedTiming::Source::VESA, 640, 480, 73, 0x5 },
  672. { EstablishedTiming::Source::Apple, 640, 480, 67 },
  673. { EstablishedTiming::Source::IBM, 640, 480, 60, 0x4 },
  674. { EstablishedTiming::Source::IBM, 720, 400, 88 },
  675. { EstablishedTiming::Source::IBM, 720, 400, 70 }
  676. };
  677. static constexpr EstablishedTiming established_timing_byte2[8] = {
  678. { EstablishedTiming::Source::VESA, 1280, 1024, 75, 0x24 },
  679. { EstablishedTiming::Source::VESA, 1024, 768, 75, 0x12 },
  680. { EstablishedTiming::Source::VESA, 1024, 768, 70, 0x11 },
  681. { EstablishedTiming::Source::VESA, 1024, 768, 60, 0x10 },
  682. { EstablishedTiming::Source::IBM, 1024, 768, 87, 0xf },
  683. { EstablishedTiming::Source::Apple, 832, 624, 75 },
  684. { EstablishedTiming::Source::VESA, 800, 600, 75, 0xb },
  685. { EstablishedTiming::Source::VESA, 800, 600, 72, 0xa }
  686. };
  687. static constexpr EstablishedTiming established_timing_byte3[1] = {
  688. { EstablishedTiming::Source::Apple, 1152, 870, 75 }
  689. };
  690. auto& established_timings = raw_edid().established_timings;
  691. for (int i = 7; i >= 0; i--) {
  692. if (!(established_timings.timings_1 & (1 << i)))
  693. continue;
  694. IterationDecision decision = callback(established_timing_byte1[i]);
  695. if (decision != IterationDecision::Continue)
  696. return decision;
  697. }
  698. for (int i = 7; i >= 0; i--) {
  699. if (!(established_timings.timings_2 & (1 << i)))
  700. continue;
  701. IterationDecision decision = callback(established_timing_byte2[i]);
  702. if (decision != IterationDecision::Continue)
  703. return decision;
  704. }
  705. if ((established_timings.manufacturer_reserved & (1 << 7)) != 0) {
  706. IterationDecision decision = callback(established_timing_byte3[0]);
  707. if (decision != IterationDecision::Continue)
  708. return decision;
  709. }
  710. u8 manufacturer_specific = established_timings.manufacturer_reserved & 0x7f;
  711. if (manufacturer_specific != 0) {
  712. IterationDecision decision = callback(EstablishedTiming(EstablishedTiming::Source::Manufacturer, 0, 0, manufacturer_specific));
  713. if (decision != IterationDecision::Continue)
  714. return decision;
  715. }
  716. auto callback_decision = IterationDecision::Continue;
  717. auto result = for_each_display_descriptor([&](u8 descriptor_tag, auto& display_descriptor) {
  718. if (descriptor_tag != (u8)Definitions::DisplayDescriptorTag::EstablishedTimings3)
  719. return IterationDecision::Continue;
  720. static constexpr EstablishedTiming established_timings3_bytes[] = {
  721. // Byte 1
  722. { EstablishedTiming::Source::VESA, 640, 350, 85, 0x1 },
  723. { EstablishedTiming::Source::VESA, 640, 400, 85, 0x2 },
  724. { EstablishedTiming::Source::VESA, 720, 400, 85, 0x3 },
  725. { EstablishedTiming::Source::VESA, 640, 480, 85, 0x7 },
  726. { EstablishedTiming::Source::VESA, 848, 480, 60, 0xe },
  727. { EstablishedTiming::Source::VESA, 800, 600, 85, 0xc },
  728. { EstablishedTiming::Source::VESA, 1024, 768, 85, 0x13 },
  729. { EstablishedTiming::Source::VESA, 1152, 864, 75, 0x15 },
  730. // Byte 2
  731. { EstablishedTiming::Source::VESA, 1280, 768, 60, 0x16 },
  732. { EstablishedTiming::Source::VESA, 1280, 768, 60, 0x17 },
  733. { EstablishedTiming::Source::VESA, 1280, 768, 75, 0x18 },
  734. { EstablishedTiming::Source::VESA, 1280, 768, 85, 0x19 },
  735. { EstablishedTiming::Source::VESA, 1280, 960, 60, 0x20 },
  736. { EstablishedTiming::Source::VESA, 1280, 960, 85, 0x21 },
  737. { EstablishedTiming::Source::VESA, 1280, 1024, 60, 0x23 },
  738. { EstablishedTiming::Source::VESA, 1280, 1024, 85, 0x25 },
  739. // Byte 3
  740. { EstablishedTiming::Source::VESA, 1360, 768, 60, 0x27 },
  741. { EstablishedTiming::Source::VESA, 1440, 900, 60, 0x2e },
  742. { EstablishedTiming::Source::VESA, 1440, 900, 60, 0x2f },
  743. { EstablishedTiming::Source::VESA, 1440, 900, 75, 0x30 },
  744. { EstablishedTiming::Source::VESA, 1440, 900, 85, 0x31 },
  745. { EstablishedTiming::Source::VESA, 1400, 1050, 60, 0x29 },
  746. { EstablishedTiming::Source::VESA, 1400, 1050, 60, 0x2a },
  747. { EstablishedTiming::Source::VESA, 1400, 1050, 75, 0x2b },
  748. // Byte 4
  749. { EstablishedTiming::Source::VESA, 1400, 1050, 85, 0x2c },
  750. { EstablishedTiming::Source::VESA, 1680, 1050, 60, 0x39 },
  751. { EstablishedTiming::Source::VESA, 1680, 1050, 60, 0x3a },
  752. { EstablishedTiming::Source::VESA, 1680, 1050, 75, 0x3b },
  753. { EstablishedTiming::Source::VESA, 1680, 1050, 85, 0x3c },
  754. { EstablishedTiming::Source::VESA, 1600, 1200, 60, 0x33 },
  755. { EstablishedTiming::Source::VESA, 1600, 1200, 65, 0x34 },
  756. { EstablishedTiming::Source::VESA, 1600, 1200, 70, 0x35 },
  757. // Byte 5
  758. { EstablishedTiming::Source::VESA, 1600, 1200, 75, 0x36 },
  759. { EstablishedTiming::Source::VESA, 1600, 1200, 85, 0x37 },
  760. { EstablishedTiming::Source::VESA, 1792, 1344, 60, 0x3e },
  761. { EstablishedTiming::Source::VESA, 1792, 1344, 75, 0x3f },
  762. { EstablishedTiming::Source::VESA, 1856, 1392, 60, 0x41 },
  763. { EstablishedTiming::Source::VESA, 1856, 1392, 75, 0x42 },
  764. { EstablishedTiming::Source::VESA, 1920, 1200, 60, 0x44 },
  765. { EstablishedTiming::Source::VESA, 1920, 1200, 60, 0x45 },
  766. // Byte 6
  767. { EstablishedTiming::Source::VESA, 1920, 1200, 75, 0x46 },
  768. { EstablishedTiming::Source::VESA, 1920, 1200, 85, 0x47 },
  769. { EstablishedTiming::Source::VESA, 1920, 1440, 60, 0x49 },
  770. { EstablishedTiming::Source::VESA, 1920, 1440, 75, 0x4a }
  771. // Reserved
  772. };
  773. size_t byte_index = 0;
  774. for (u8 dmt_bits : display_descriptor.established_timings3.dmt_bits) {
  775. for (int i = 7; i >= 0; i--) {
  776. if ((dmt_bits & (1 << i)) == 0)
  777. continue;
  778. size_t table_index = byte_index * 8 + (size_t)(7 - i);
  779. if (table_index >= (sizeof(established_timings3_bytes) + 7) / sizeof(established_timings3_bytes[0]))
  780. break; // Sometimes reserved bits are set
  781. callback_decision = callback(established_timings3_bytes[table_index]);
  782. if (callback_decision != IterationDecision::Continue)
  783. return IterationDecision::Break;
  784. }
  785. byte_index++;
  786. }
  787. return IterationDecision::Break; // Only process one descriptor
  788. });
  789. if (result.is_error())
  790. return result.error();
  791. return callback_decision;
  792. }
  793. ErrorOr<IterationDecision> Parser::for_each_standard_timing(Function<IterationDecision(StandardTiming const&)> callback) const
  794. {
  795. for (size_t index = 0; index < 8; index++) {
  796. auto& standard_timings = raw_edid().standard_timings[index];
  797. if (standard_timings.horizontal_8_pixels == 0x1 && standard_timings.ratio_and_refresh_rate == 0x1)
  798. continue; // Skip unused records
  799. u16 width = 8 * ((u16)read_host(&standard_timings.horizontal_8_pixels) + 31);
  800. u8 aspect_ratio_and_refresh_rate = read_host(&standard_timings.ratio_and_refresh_rate);
  801. u8 refresh_rate = (aspect_ratio_and_refresh_rate & 0x3f) + 60;
  802. u16 height;
  803. StandardTiming::AspectRatio aspect_ratio;
  804. switch ((aspect_ratio_and_refresh_rate >> 6) & 3) {
  805. case 0:
  806. height = (width * 10) / 16;
  807. aspect_ratio = StandardTiming::AspectRatio::AR_16_10;
  808. break;
  809. case 1:
  810. height = (width * 3) / 4;
  811. aspect_ratio = StandardTiming::AspectRatio::AR_4_3;
  812. break;
  813. case 2:
  814. height = (width * 4) / 5;
  815. aspect_ratio = StandardTiming::AspectRatio::AR_5_4;
  816. break;
  817. case 3:
  818. height = (width * 9) / 16;
  819. aspect_ratio = StandardTiming::AspectRatio::AR_16_9;
  820. break;
  821. default:
  822. VERIFY_NOT_REACHED();
  823. }
  824. auto* dmt = DMT::find_timing_by_std_id(standard_timings.horizontal_8_pixels, standard_timings.ratio_and_refresh_rate);
  825. IterationDecision decision = callback(StandardTiming(width, height, refresh_rate, aspect_ratio, dmt ? dmt->dmt_id : 0));
  826. if (decision != IterationDecision::Continue)
  827. return decision;
  828. }
  829. return IterationDecision::Continue;
  830. }
  831. u16 Parser::CoordinatedVideoTiming::horizontal_addressable_pixels() const
  832. {
  833. u32 aspect_h, aspect_v;
  834. switch (aspect_ratio()) {
  835. case AspectRatio::AR_4_3:
  836. aspect_h = 4;
  837. aspect_v = 3;
  838. break;
  839. case AspectRatio::AR_16_9:
  840. aspect_h = 16;
  841. aspect_v = 9;
  842. break;
  843. case AspectRatio::AR_16_10:
  844. aspect_h = 16;
  845. aspect_v = 10;
  846. break;
  847. case AspectRatio::AR_15_9:
  848. aspect_h = 15;
  849. aspect_v = 9;
  850. break;
  851. }
  852. // Round down to nearest cell as per 3.10.3.8
  853. return (u16)(8 * ((((u32)vertical_addressable_lines() * aspect_h) / aspect_v) / 8));
  854. }
  855. u16 Parser::CoordinatedVideoTiming::vertical_addressable_lines() const
  856. {
  857. return ((u16)(m_cvt.bytes[1] >> 4) << 8) | (u16)m_cvt.bytes[0];
  858. }
  859. auto Parser::CoordinatedVideoTiming::aspect_ratio() const -> AspectRatio
  860. {
  861. return (AspectRatio)((m_cvt.bytes[2] >> 2) & 0x3);
  862. }
  863. u16 Parser::CoordinatedVideoTiming::preferred_refresh_rate()
  864. {
  865. switch ((m_cvt.bytes[2] >> 5) & 3) {
  866. case 0:
  867. return 50;
  868. case 1:
  869. return 60;
  870. case 2:
  871. return 75;
  872. case 3:
  873. return 85;
  874. default:
  875. VERIFY_NOT_REACHED();
  876. }
  877. }
  878. ErrorOr<IterationDecision> Parser::for_each_coordinated_video_timing(Function<IterationDecision(CoordinatedVideoTiming const&)> callback) const
  879. {
  880. return for_each_display_descriptor([&](u8 descriptor_tag, Definitions::DisplayDescriptor const& display_descriptor) {
  881. if (descriptor_tag != (u8)Definitions::DisplayDescriptorTag::CVTTimingCodes)
  882. return IterationDecision::Continue;
  883. u8 version = read_host(&display_descriptor.coordinated_video_timings.version);
  884. if (version != 1) {
  885. dbgln("Unsupported CVT display descriptor version: {}", version);
  886. return IterationDecision::Continue;
  887. }
  888. for (size_t i = 0; i < 4; i++) {
  889. const DMT::CVT cvt {
  890. {
  891. read_host(&display_descriptor.coordinated_video_timings.cvt[i][0]),
  892. read_host(&display_descriptor.coordinated_video_timings.cvt[i][1]),
  893. read_host(&display_descriptor.coordinated_video_timings.cvt[i][2]),
  894. }
  895. };
  896. if (cvt.bytes[0] == 0 && cvt.bytes[1] == 0 && cvt.bytes[2] == 0)
  897. continue;
  898. IterationDecision decision = callback(CoordinatedVideoTiming(cvt));
  899. if (decision != IterationDecision::Continue)
  900. return decision;
  901. }
  902. return IterationDecision::Continue;
  903. });
  904. }
  905. ErrorOr<IterationDecision> Parser::for_each_detailed_timing(Function<IterationDecision(DetailedTiming const&, unsigned)> callback) const
  906. {
  907. auto& edid = raw_edid();
  908. for (size_t raw_index = 0; raw_index < 4; raw_index++) {
  909. if (raw_index == 0 || read_le(&edid.detailed_timing_or_display_descriptors[raw_index].detailed_timing.pixel_clock) != 0) {
  910. IterationDecision decision = callback(DetailedTiming(*this, &edid.detailed_timing_or_display_descriptors[raw_index].detailed_timing), 0);
  911. if (decision != IterationDecision::Continue)
  912. return decision;
  913. }
  914. }
  915. Optional<Error> extension_error;
  916. auto result = for_each_extension_block([&](u8 block_id, u8 tag, u8, ReadonlyBytes bytes) {
  917. if (tag != (u8)Definitions::ExtensionBlockTag::CEA_861)
  918. return IterationDecision::Continue;
  919. CEA861ExtensionBlock cea861(*this, (Definitions::ExtensionBlock const*)bytes.data());
  920. auto result = cea861.for_each_dtd([&](auto& dtd) {
  921. return callback(dtd, block_id);
  922. });
  923. if (result.is_error()) {
  924. dbgln("Failed to iterate DTDs in CEA861 extension block: {}", result.error());
  925. extension_error = result.error();
  926. return IterationDecision::Break;
  927. }
  928. return result.value();
  929. });
  930. if (!result.is_error()) {
  931. if (extension_error.has_value())
  932. return extension_error.value();
  933. }
  934. return result;
  935. }
  936. auto Parser::detailed_timing(size_t index) const -> Optional<DetailedTiming>
  937. {
  938. Optional<DetailedTiming> found_dtd;
  939. auto result = for_each_detailed_timing([&](DetailedTiming const& dtd, unsigned) {
  940. if (index == 0) {
  941. found_dtd = dtd;
  942. return IterationDecision::Break;
  943. }
  944. index--;
  945. return IterationDecision::Continue;
  946. });
  947. if (result.is_error()) {
  948. dbgln("Error getting Parser detailed timing #{}: {}", index, result.error());
  949. return {};
  950. }
  951. return found_dtd;
  952. }
  953. ErrorOr<IterationDecision> Parser::for_each_short_video_descriptor(Function<IterationDecision(unsigned, bool, VIC::Details const&)> callback) const
  954. {
  955. Optional<Error> extension_error;
  956. auto result = for_each_extension_block([&](u8 block_id, u8 tag, u8, ReadonlyBytes bytes) {
  957. if (tag != (u8)Definitions::ExtensionBlockTag::CEA_861)
  958. return IterationDecision::Continue;
  959. CEA861ExtensionBlock cea861(*this, (Definitions::ExtensionBlock const*)bytes.data());
  960. auto result = cea861.for_each_short_video_descriptor([&](bool is_native, VIC::Details const& vic) {
  961. return callback(block_id, is_native, vic);
  962. });
  963. if (result.is_error()) {
  964. extension_error = result.error();
  965. return IterationDecision::Break;
  966. }
  967. return result.value();
  968. });
  969. if (result.is_error()) {
  970. dbgln("Failed to iterate Parser extension blocks: {}", result.error());
  971. return IterationDecision::Break;
  972. }
  973. return result.value();
  974. }
  975. ErrorOr<IterationDecision> Parser::for_each_display_descriptor(Function<IterationDecision(u8, Definitions::DisplayDescriptor const&)> callback) const
  976. {
  977. auto& edid = raw_edid();
  978. for (size_t raw_index = 1; raw_index < 4; raw_index++) {
  979. auto& display_descriptor = edid.detailed_timing_or_display_descriptors[raw_index].display_descriptor;
  980. if (read_le(&display_descriptor.zero) != 0 || read_host(&display_descriptor.reserved1) != 0)
  981. continue;
  982. u8 tag = read_host(&display_descriptor.tag);
  983. IterationDecision decision = callback(tag, display_descriptor);
  984. if (decision != IterationDecision::Continue)
  985. return decision;
  986. }
  987. Optional<Error> extension_error;
  988. auto result = for_each_extension_block([&](u8, u8 tag, u8, ReadonlyBytes bytes) {
  989. if (tag != (u8)Definitions::ExtensionBlockTag::CEA_861)
  990. return IterationDecision::Continue;
  991. CEA861ExtensionBlock cea861(*this, (Definitions::ExtensionBlock const*)bytes.data());
  992. auto result = cea861.for_each_display_descriptor([&](u8 tag, auto& display_descriptor) {
  993. return callback(tag, display_descriptor);
  994. });
  995. if (result.is_error()) {
  996. dbgln("Failed to iterate display descriptors in CEA861 extension block: {}", result.error());
  997. extension_error = result.error();
  998. return IterationDecision::Break;
  999. }
  1000. return result.value();
  1001. });
  1002. if (!result.is_error()) {
  1003. if (extension_error.has_value())
  1004. return extension_error.value();
  1005. }
  1006. return result;
  1007. }
  1008. #ifndef KERNEL
  1009. String Parser::display_product_name() const
  1010. {
  1011. String product_name;
  1012. auto result = for_each_display_descriptor([&](u8 descriptor_tag, Definitions::DisplayDescriptor const& display_descriptor) {
  1013. if (descriptor_tag != (u8)Definitions::DisplayDescriptorTag::DisplayProductName)
  1014. return IterationDecision::Continue;
  1015. StringBuilder str;
  1016. for (u8 byte : display_descriptor.display_product_name.ascii_name) {
  1017. if (byte == 0xa)
  1018. break;
  1019. str.append((char)byte);
  1020. }
  1021. product_name = str.build();
  1022. return IterationDecision::Break;
  1023. });
  1024. if (result.is_error()) {
  1025. dbgln("Failed to locate product name display descriptor: {}", result.error());
  1026. return {};
  1027. }
  1028. return product_name;
  1029. }
  1030. String Parser::display_product_serial_number() const
  1031. {
  1032. String product_name;
  1033. auto result = for_each_display_descriptor([&](u8 descriptor_tag, Definitions::DisplayDescriptor const& display_descriptor) {
  1034. if (descriptor_tag != (u8)Definitions::DisplayDescriptorTag::DisplayProductSerialNumber)
  1035. return IterationDecision::Continue;
  1036. StringBuilder str;
  1037. for (u8 byte : display_descriptor.display_product_serial_number.ascii_str) {
  1038. if (byte == 0xa)
  1039. break;
  1040. str.append((char)byte);
  1041. }
  1042. product_name = str.build();
  1043. return IterationDecision::Break;
  1044. });
  1045. if (result.is_error()) {
  1046. dbgln("Failed to locate product name display descriptor: {}", result.error());
  1047. return {};
  1048. }
  1049. return product_name;
  1050. }
  1051. #endif
  1052. auto Parser::supported_resolutions() const -> ErrorOr<Vector<SupportedResolution>>
  1053. {
  1054. Vector<SupportedResolution> resolutions;
  1055. auto add_resolution = [&](unsigned width, unsigned height, FixedPoint<16, u32> refresh_rate, bool preferred = false) {
  1056. auto it = resolutions.find_if([&](auto& info) {
  1057. return info.width == width && info.height == height;
  1058. });
  1059. if (it == resolutions.end()) {
  1060. resolutions.append({ width, height, { { refresh_rate, preferred } } });
  1061. } else {
  1062. auto& info = *it;
  1063. SupportedResolution::RefreshRate* found_refresh_rate = nullptr;
  1064. for (auto& supported_refresh_rate : info.refresh_rates) {
  1065. if (supported_refresh_rate.rate == refresh_rate) {
  1066. found_refresh_rate = &supported_refresh_rate;
  1067. break;
  1068. }
  1069. }
  1070. if (found_refresh_rate)
  1071. found_refresh_rate->preferred |= preferred;
  1072. else
  1073. info.refresh_rates.append({ refresh_rate, preferred });
  1074. }
  1075. };
  1076. auto result = for_each_established_timing([&](auto& established_timing) {
  1077. if (established_timing.source() != EstablishedTiming::Source::Manufacturer)
  1078. add_resolution(established_timing.width(), established_timing.height(), established_timing.refresh_rate());
  1079. return IterationDecision::Continue;
  1080. });
  1081. if (result.is_error())
  1082. return result.error();
  1083. result = for_each_standard_timing([&](auto& standard_timing) {
  1084. add_resolution(standard_timing.width(), standard_timing.height(), standard_timing.refresh_rate());
  1085. return IterationDecision::Continue;
  1086. });
  1087. if (result.is_error())
  1088. return result.error();
  1089. size_t detailed_timing_index = 0;
  1090. result = for_each_detailed_timing([&](auto& detailed_timing, auto) {
  1091. bool is_preferred = detailed_timing_index++ == 0;
  1092. add_resolution(detailed_timing.horizontal_addressable_pixels(), detailed_timing.vertical_addressable_lines(), detailed_timing.refresh_rate(), is_preferred);
  1093. return IterationDecision::Continue;
  1094. });
  1095. if (result.is_error())
  1096. return result.error();
  1097. result = for_each_short_video_descriptor([&](unsigned, bool, VIC::Details const& vic_details) {
  1098. add_resolution(vic_details.horizontal_pixels, vic_details.vertical_lines, vic_details.refresh_rate_hz());
  1099. return IterationDecision::Continue;
  1100. });
  1101. if (result.is_error())
  1102. return result.error();
  1103. result = for_each_coordinated_video_timing([&](auto& coordinated_video_timing) {
  1104. if (auto* dmt = DMT::find_timing_by_cvt(coordinated_video_timing.cvt_code())) {
  1105. add_resolution(dmt->horizontal_pixels, dmt->vertical_lines, dmt->vertical_frequency_hz());
  1106. } else {
  1107. // TODO: We couldn't find this cvt code, try to decode it
  1108. auto cvt = coordinated_video_timing.cvt_code();
  1109. dbgln("TODO: Decode CVT code: {:02x},{:02x},{:02x}", cvt.bytes[0], cvt.bytes[1], cvt.bytes[2]);
  1110. }
  1111. return IterationDecision::Continue;
  1112. });
  1113. quick_sort(resolutions, [&](auto& info1, auto& info2) {
  1114. if (info1.width < info2.width)
  1115. return true;
  1116. if (info1.width == info2.width && info1.height < info2.height)
  1117. return true;
  1118. return false;
  1119. });
  1120. for (auto& res : resolutions) {
  1121. if (res.refresh_rates.size() > 1)
  1122. quick_sort(res.refresh_rates);
  1123. }
  1124. return resolutions;
  1125. }
  1126. }