edid_parser.cc 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/display/util/edid_parser.h"
  5. #include <stddef.h>
  6. #include <algorithm>
  7. #include <bitset>
  8. #include "base/check.h"
  9. #include "base/hash/hash.h"
  10. #include "base/hash/md5.h"
  11. #include "base/metrics/histogram_functions.h"
  12. #include "base/strings/string_number_conversions.h"
  13. #include "base/strings/string_util.h"
  14. #include "base/strings/stringprintf.h"
  15. #include "base/sys_byteorder.h"
  16. #include "third_party/skia/include/core/SkColorSpace.h"
  17. #include "ui/display/util/display_util.h"
  18. #include "ui/gfx/geometry/size.h"
  19. namespace display {
  20. namespace {
  21. constexpr char kParseEdidFailureMetric[] = "Display.ParseEdidFailure";
  22. constexpr char kParseExternalDisplayEdidOptionalsMetric[] =
  23. "Display.External.ParseEdidOptionals";
  24. constexpr char kBlockZeroSerialNumberTypeMetric[] =
  25. "Display.External.BlockZeroSerialNumberType";
  26. constexpr char kNumOfSerialNumbersProvidedByExternalDisplay[] =
  27. "Display.External.NumOfSerialNumbersProvided";
  28. constexpr uint8_t kMaxSerialNumberCount = 2;
  29. // These values are persisted to logs. Entries should not be renumbered and
  30. // numeric values should never be reused.
  31. enum class ParseEdidFailure {
  32. kNoError = 0,
  33. kManufacturerId = 1,
  34. kProductId = 2,
  35. kYearOfManufacture = 3,
  36. kBitsPerChannel = 4,
  37. kGamma = 5,
  38. kChromaticityCoordinates = 6,
  39. kDisplayName = 7,
  40. kExtensions = 8,
  41. kSerialNumber = 9,
  42. kWeekOfManufacture = 10,
  43. kPhysicalSize = 11,
  44. kMaxValue = kPhysicalSize,
  45. };
  46. // These values are persisted to logs. Entries should not be renumbered and
  47. // numeric values should never be reused. This enum is used to track the
  48. // availability (or lack thereof) of optional fields during EDID parsing.
  49. enum class ParseEdidOptionals {
  50. kAllAvailable = 0,
  51. kBlockZeroSerialNumber = 1,
  52. kDescriptorBlockSerialNumber = 2,
  53. kWeekOfManufacture = 3,
  54. kPhysicalSize = 4,
  55. kMaxValue = kPhysicalSize,
  56. };
  57. // These values are persisted to logs. Entries should not be renumbered and
  58. // numeric values should never be reused. This enum is used to track the
  59. // serial number types that can be retrieved from an EDID's block zero.
  60. enum class BlockZeroSerialNumberType {
  61. kNormal = 0,
  62. kRepeatingPattern = 1,
  63. kNoSerialNumber = 2,
  64. kMaxValue = kNoSerialNumber,
  65. };
  66. BlockZeroSerialNumberType GetSerialNumberType(const uint8_t serial_number[],
  67. size_t size) {
  68. int sum = serial_number[0];
  69. bool all_equal = true;
  70. for (size_t i = 1; i < size; ++i) {
  71. sum += serial_number[i];
  72. if (serial_number[i - 1] != serial_number[i])
  73. all_equal = false;
  74. }
  75. if (sum == 0)
  76. return BlockZeroSerialNumberType::kNoSerialNumber;
  77. if (all_equal)
  78. return BlockZeroSerialNumberType::kRepeatingPattern;
  79. return BlockZeroSerialNumberType::kNormal;
  80. }
  81. } // namespace
  82. EdidParser::EdidParser(const std::vector<uint8_t>& edid_blob, bool is_external)
  83. : is_external_display_(is_external),
  84. manufacturer_id_(0),
  85. product_id_(0),
  86. year_of_manufacture_(display::kInvalidYearOfManufacture),
  87. gamma_(0.0),
  88. bits_per_channel_(-1),
  89. primaries_({0}) {
  90. ParseEdid(edid_blob);
  91. }
  92. EdidParser::~EdidParser() = default;
  93. uint32_t EdidParser::GetProductCode() const {
  94. return ((static_cast<uint32_t>(manufacturer_id_) << 16) |
  95. (static_cast<uint32_t>(product_id_)));
  96. }
  97. int64_t EdidParser::GetIndexBasedDisplayId(uint8_t output_index) const {
  98. // Generates product specific value from product_name instead of product code.
  99. // See https://crbug.com/240341
  100. const uint32_t product_code_hash =
  101. display_name_.empty() ? 0 : base::Hash(display_name_);
  102. // An ID based on display's index will be assigned later if this call fails.
  103. return GenerateDisplayID(manufacturer_id_, product_code_hash, output_index);
  104. }
  105. int64_t EdidParser::GetEdidBasedDisplayId() const {
  106. const std::string string_to_hash =
  107. base::NumberToString(manufacturer_id_) +
  108. base::NumberToString(product_id_) + display_name_ +
  109. base::NumberToString(week_of_manufacture()) +
  110. base::NumberToString(year_of_manufacture_) + max_image_size().ToString() +
  111. block_zero_serial_number_hash() + descriptor_block_serial_number_hash();
  112. return static_cast<int64_t>(base::PersistentHash(string_to_hash));
  113. }
  114. // static
  115. void EdidParser::SplitProductCodeInManufacturerIdAndProductId(
  116. int64_t product_code,
  117. uint16_t* manufacturer_id,
  118. uint16_t* product_id) {
  119. DCHECK(manufacturer_id);
  120. DCHECK(product_id);
  121. // Undo GetProductCode() packing.
  122. *product_id = product_code & 0xFFFF;
  123. *manufacturer_id = (product_code >> 16) & 0xFFFF;
  124. }
  125. // static
  126. std::string EdidParser::ManufacturerIdToString(uint16_t manufacturer_id) {
  127. // Constants are taken from "VESA Enhanced EDID Standard" Release A, Revision
  128. // 2, Sep 2006, Sec 3.4.1 "ID Manufacturer Name: 2 Bytes". Essentially these
  129. // are 3 5-bit ASCII characters packed in 2 bytes, where 1 means 'A', etc.
  130. constexpr uint8_t kFiveBitAsciiMask = 0x1F;
  131. constexpr char kFiveBitToAsciiOffset = 'A' - 1;
  132. constexpr size_t kSecondLetterOffset = 5;
  133. constexpr size_t kFirstLetterOffset = 10;
  134. char out[4] = {};
  135. out[2] = (manufacturer_id & kFiveBitAsciiMask) + kFiveBitToAsciiOffset;
  136. out[1] = ((manufacturer_id >> kSecondLetterOffset) & kFiveBitAsciiMask) +
  137. kFiveBitToAsciiOffset;
  138. out[0] = ((manufacturer_id >> kFirstLetterOffset) & kFiveBitAsciiMask) +
  139. kFiveBitToAsciiOffset;
  140. return out;
  141. }
  142. // static
  143. std::string EdidParser::ProductIdToString(uint16_t product_id) {
  144. // From "VESA Enhanced EDID Standard" Release A, Revision 2, Sep 2006, Sec
  145. // 3.4.2 "ID Product Code: 2 Bytes": "The ID product code field, [...]
  146. // contains a 2-byte manufacturer assigned product code. [...] The 2 byte
  147. // number is stored in hex with the least significant byte listed first."
  148. uint8_t lower_char = (product_id >> 8) & 0xFF;
  149. uint8_t upper_char = product_id & 0xFF;
  150. return base::StringPrintf("%02X%02X", upper_char, lower_char);
  151. }
  152. void EdidParser::ParseEdid(const std::vector<uint8_t>& edid) {
  153. // See http://en.wikipedia.org/wiki/Extended_display_identification_data
  154. // for the details of EDID data format. We use the following data:
  155. // bytes 8-9: manufacturer EISA ID, in big-endian
  156. // bytes 10-11: manufacturer product code, in little-endian
  157. constexpr size_t kManufacturerOffset = 8;
  158. constexpr size_t kManufacturerLength = 2;
  159. constexpr size_t kProductIdOffset = 10;
  160. constexpr size_t kProductIdLength = 2;
  161. if (edid.size() < kManufacturerOffset + kManufacturerLength) {
  162. base::UmaHistogramEnumeration(kParseEdidFailureMetric,
  163. ParseEdidFailure::kManufacturerId);
  164. return; // Any other fields below are beyond this edid offset.
  165. }
  166. // ICC filename is generated based on these ids. We always read this as big
  167. // endian so that the file name matches bytes 8-11 as they appear in EDID.
  168. manufacturer_id_ =
  169. (edid[kManufacturerOffset] << 8) + edid[kManufacturerOffset + 1];
  170. if (edid.size() < kProductIdOffset + kProductIdLength) {
  171. base::UmaHistogramEnumeration(kParseEdidFailureMetric,
  172. ParseEdidFailure::kProductId);
  173. return; // Any other fields below are beyond this edid offset.
  174. }
  175. product_id_ = (edid[kProductIdOffset] << 8) + edid[kProductIdOffset + 1];
  176. // Bytes 12-15: dislay serial number, in little-endian (LSB). This field is
  177. // optional and its absence is marked by having all bytes set to 0x00.
  178. // Values do not represent ASCII characters.
  179. constexpr size_t kSerialNumberOffset = 12;
  180. constexpr size_t kSerialNumberLength = 4;
  181. if (edid.size() < kSerialNumberOffset + kSerialNumberLength) {
  182. base::UmaHistogramEnumeration(kParseEdidFailureMetric,
  183. ParseEdidFailure::kSerialNumber);
  184. return; // Any other fields below are beyond this edid offset.
  185. }
  186. const uint8_t serial_number_bytes[kSerialNumberLength] = {
  187. edid[kSerialNumberOffset], edid[kSerialNumberOffset + 1],
  188. edid[kSerialNumberOffset + 2], edid[kSerialNumberOffset + 3]};
  189. // Report the type of serial number encountered in block zero of external
  190. // displays: empty (==0), repeating pattern (e.g. 01010101 or 0F0F0F0F),
  191. // or normal.
  192. if (is_external_display_) {
  193. base::UmaHistogramEnumeration(
  194. kBlockZeroSerialNumberTypeMetric,
  195. GetSerialNumberType(serial_number_bytes,
  196. std::size(serial_number_bytes)));
  197. }
  198. const uint32_t serial_number =
  199. serial_number_bytes[0] + (serial_number_bytes[1] << 8) +
  200. (serial_number_bytes[2] << 16) + (serial_number_bytes[3] << 24);
  201. if (serial_number) {
  202. block_zero_serial_number_hash_ =
  203. base::MD5String(base::NumberToString(serial_number));
  204. }
  205. // Constants are taken from "VESA Enhanced EDID Standard" Release A, Revision
  206. // 2, Sep 2006, Sec 3.4.4 "Week and Year of Manufacture or Model Year: 2
  207. // Bytes".
  208. constexpr size_t kWeekOfManufactureOffset = 16;
  209. constexpr uint32_t kValidWeekValueUpperBound = 0x36;
  210. constexpr uint32_t kModelYearMarker = 0xFF;
  211. if (edid.size() < kWeekOfManufactureOffset + 1) {
  212. base::UmaHistogramEnumeration(kParseEdidFailureMetric,
  213. ParseEdidFailure::kWeekOfManufacture);
  214. return; // Any other fields below are beyond this edid offset.
  215. }
  216. {
  217. const uint8_t byte_data = edid[kWeekOfManufactureOffset];
  218. // Store the value if it's within the range of 1-54 or equals to 0xFF.
  219. if ((byte_data > 0x00 && byte_data <= kValidWeekValueUpperBound) ||
  220. byte_data == kModelYearMarker) {
  221. week_of_manufacture_ = byte_data;
  222. }
  223. }
  224. constexpr size_t kYearOfManufactureOffset = 17;
  225. constexpr uint32_t kValidYearValueLowerBound = 0x10;
  226. constexpr int32_t kYearOffset = 1990;
  227. if (edid.size() < kYearOfManufactureOffset + 1) {
  228. base::UmaHistogramEnumeration(kParseEdidFailureMetric,
  229. ParseEdidFailure::kYearOfManufacture);
  230. return; // Any other fields below are beyond this edid offset.
  231. }
  232. {
  233. const uint8_t byte_data = edid[kYearOfManufactureOffset];
  234. if (byte_data >= kValidYearValueLowerBound)
  235. year_of_manufacture_ = byte_data + kYearOffset;
  236. }
  237. // Constants are taken from "VESA Enhanced EDID Standard" Release A, Revision
  238. // 1, Feb 2000, Sec 3.6 "Basic Display Parameters and Features: 5 bytes"
  239. static constexpr int kBitsPerChannelTable[] = {0, 6, 8, 10, 12, 14, 16, 0};
  240. constexpr size_t kEDIDRevisionNumberOffset = 19;
  241. constexpr uint8_t kEDIDRevision4Value = 4;
  242. constexpr size_t kVideoInputDefinitionOffset = 20;
  243. constexpr uint8_t kDigitalInfoMask = 0x80;
  244. constexpr uint8_t kColorBitDepthMask = 0x70;
  245. constexpr uint8_t kColorBitDepthOffset = 4;
  246. if (edid.size() < kVideoInputDefinitionOffset + 1) {
  247. base::UmaHistogramEnumeration(kParseEdidFailureMetric,
  248. ParseEdidFailure::kBitsPerChannel);
  249. return; // Any other fields below are beyond this edid offset.
  250. }
  251. if (edid[kEDIDRevisionNumberOffset] >= kEDIDRevision4Value &&
  252. (edid[kVideoInputDefinitionOffset] & kDigitalInfoMask)) {
  253. // EDID needs to be revision 4 at least, and kDigitalInfoMask be set for
  254. // the Video Input Definition entry to describe a digital interface.
  255. bits_per_channel_ = kBitsPerChannelTable[(
  256. (edid[kVideoInputDefinitionOffset] & kColorBitDepthMask) >>
  257. kColorBitDepthOffset)];
  258. }
  259. constexpr size_t kEDIDMaxHorizontalImageSizeOffset = 21;
  260. constexpr size_t kEDIDMaxVerticalImageSizeOffset = 22;
  261. if (edid.size() < kEDIDMaxVerticalImageSizeOffset + 1) {
  262. base::UmaHistogramEnumeration(kParseEdidFailureMetric,
  263. ParseEdidFailure::kPhysicalSize);
  264. return; // Any other fields below are beyond this edid offset.
  265. }
  266. const gfx::Size max_image_size(edid[kEDIDMaxHorizontalImageSizeOffset],
  267. edid[kEDIDMaxVerticalImageSizeOffset]);
  268. if (!max_image_size.IsEmpty())
  269. max_image_size_ = max_image_size;
  270. // Constants are taken from "VESA Enhanced EDID Standard" Release A, Revision
  271. // 2, Sep 2006, Sec. 3.6.3 "Display Transfer Characteristics (GAMMA ): 1 Byte"
  272. constexpr size_t kGammaOffset = 23;
  273. constexpr double kGammaMultiplier = 100.0;
  274. constexpr double kGammaBias = 100.0;
  275. if (edid.size() < kGammaOffset + 1) {
  276. base::UmaHistogramEnumeration(kParseEdidFailureMetric,
  277. ParseEdidFailure::kGamma);
  278. return; // Any other fields below are beyond this edid offset.
  279. }
  280. if (edid[kGammaOffset] != 0xFF) {
  281. // Otherwise the byte at kGammaOffset is 0xFF, gamma is stored elsewhere.
  282. gamma_ = (edid[kGammaOffset] + kGammaBias) / kGammaMultiplier;
  283. }
  284. // Offsets, lengths, positions and masks are taken from [1] (or [2]).
  285. // [1] http://en.wikipedia.org/wiki/Extended_display_identification_data
  286. // [2] "VESA Enhanced EDID Standard " Release A, Revision 1, Feb 2000, Sec 3.7
  287. // "Phosphor or Filter Chromaticity: 10 bytes"
  288. constexpr size_t kChromaticityOffset = 25;
  289. constexpr unsigned int kChromaticityLength = 10;
  290. constexpr size_t kRedGreenLsbOffset = 25;
  291. constexpr uint8_t kRedxLsbPosition = 6;
  292. constexpr uint8_t kRedyLsbPosition = 4;
  293. constexpr uint8_t kGreenxLsbPosition = 2;
  294. constexpr uint8_t kGreenyLsbPosition = 0;
  295. constexpr size_t kBlueWhiteLsbOffset = 26;
  296. constexpr uint8_t kBluexLsbPosition = 6;
  297. constexpr uint8_t kBlueyLsbPosition = 4;
  298. constexpr uint8_t kWhitexLsbPosition = 2;
  299. constexpr uint8_t kWhiteyLsbPosition = 0;
  300. // All LSBits parts are 2 bits wide.
  301. constexpr uint8_t kLsbMask = 0x3;
  302. constexpr size_t kRedxMsbOffset = 27;
  303. constexpr size_t kRedyMsbOffset = 28;
  304. constexpr size_t kGreenxMsbOffset = 29;
  305. constexpr size_t kGreenyMsbOffset = 30;
  306. constexpr size_t kBluexMsbOffset = 31;
  307. constexpr size_t kBlueyMsbOffset = 32;
  308. constexpr size_t kWhitexMsbOffset = 33;
  309. constexpr size_t kWhiteyMsbOffset = 34;
  310. static_assert(
  311. kChromaticityOffset + kChromaticityLength == kWhiteyMsbOffset + 1,
  312. "EDID Parameter section length error");
  313. if (edid.size() < kChromaticityOffset + kChromaticityLength) {
  314. base::UmaHistogramEnumeration(kParseEdidFailureMetric,
  315. ParseEdidFailure::kChromaticityCoordinates);
  316. return; // Any other fields below are beyond this edid offset.
  317. }
  318. const uint8_t red_green_lsbs = edid[kRedGreenLsbOffset];
  319. const uint8_t blue_white_lsbs = edid[kBlueWhiteLsbOffset];
  320. // Recompose the 10b values by appropriately mixing the 8 MSBs and the 2 LSBs,
  321. // then rescale to 1024;
  322. primaries_.fRX = ((edid[kRedxMsbOffset] << 2) +
  323. ((red_green_lsbs >> kRedxLsbPosition) & kLsbMask)) /
  324. 1024.0f;
  325. primaries_.fRY = ((edid[kRedyMsbOffset] << 2) +
  326. ((red_green_lsbs >> kRedyLsbPosition) & kLsbMask)) /
  327. 1024.0f;
  328. primaries_.fGX = ((edid[kGreenxMsbOffset] << 2) +
  329. ((red_green_lsbs >> kGreenxLsbPosition) & kLsbMask)) /
  330. 1024.0f;
  331. primaries_.fGY = ((edid[kGreenyMsbOffset] << 2) +
  332. ((red_green_lsbs >> kGreenyLsbPosition) & kLsbMask)) /
  333. 1024.0f;
  334. primaries_.fBX = ((edid[kBluexMsbOffset] << 2) +
  335. ((blue_white_lsbs >> kBluexLsbPosition) & kLsbMask)) /
  336. 1024.0f;
  337. primaries_.fBY = ((edid[kBlueyMsbOffset] << 2) +
  338. ((blue_white_lsbs >> kBlueyLsbPosition) & kLsbMask)) /
  339. 1024.0f;
  340. primaries_.fWX = ((edid[kWhitexMsbOffset] << 2) +
  341. ((blue_white_lsbs >> kWhitexLsbPosition) & kLsbMask)) /
  342. 1024.0f;
  343. primaries_.fWY = ((edid[kWhiteyMsbOffset] << 2) +
  344. ((blue_white_lsbs >> kWhiteyLsbPosition) & kLsbMask)) /
  345. 1024.0f;
  346. // TODO(mcasas): Up to two additional White Point coordinates can be provided
  347. // in a Display Descriptor. Read them if we are not satisfied with |fWX| or
  348. // |fWy|. https://crbug.com/771345.
  349. // See http://en.wikipedia.org/wiki/Extended_display_identification_data
  350. // for the details of EDID data format. We use the following data:
  351. // bytes 54-125: four descriptors (18-bytes each) which may contain
  352. // the display name.
  353. constexpr size_t kDescriptorOffset = 54;
  354. constexpr size_t kNumDescriptors = 4;
  355. constexpr size_t kDescriptorLength = 18;
  356. // The specifier types.
  357. constexpr uint8_t kMonitorNameDescriptor = 0xfc;
  358. constexpr uint8_t kDisplayRangeLimitsDescriptor = 0xfd;
  359. constexpr uint8_t kMonitorSerialNumberDescriptor = 0xff;
  360. display_name_.clear();
  361. for (size_t i = 0; i < kNumDescriptors; ++i) {
  362. if (edid.size() < kDescriptorOffset + (i + 1) * kDescriptorLength)
  363. break;
  364. size_t offset = kDescriptorOffset + i * kDescriptorLength;
  365. // Detailed Timing Descriptor:
  366. if (edid[offset] != 0 && edid[offset + 1] != 0) {
  367. constexpr int kMaxResolution = 10080; // 8k display.
  368. // EDID may contain multiple DTD. Use the first one, that contains the
  369. // highest resolution.
  370. if (active_pixel_size_.IsEmpty()) {
  371. constexpr size_t kHorizontalPixelLsbOffset = 2;
  372. constexpr size_t kHorizontalPixelMsbOffset = 4;
  373. constexpr size_t kVerticalPixelLsbOffset = 5;
  374. constexpr size_t kVerticalPixelMsbOffset = 7;
  375. const uint8_t h_lsb = edid[offset + kHorizontalPixelLsbOffset];
  376. const uint8_t h_msb = edid[offset + kHorizontalPixelMsbOffset];
  377. int h_pixel = std::min(h_lsb + ((h_msb & 0xF0) << 4), kMaxResolution);
  378. const uint8_t v_lsb = edid[offset + kVerticalPixelLsbOffset];
  379. const uint8_t v_msb = edid[offset + kVerticalPixelMsbOffset];
  380. int v_pixel = std::min(v_lsb + ((v_msb & 0xF0) << 4), kMaxResolution);
  381. active_pixel_size_.SetSize(h_pixel, v_pixel);
  382. }
  383. continue;
  384. }
  385. // EDID Other Monitor Descriptors:
  386. // If the descriptor contains the display name, it has the following
  387. // structure:
  388. // bytes 0-2, 4: \0
  389. // byte 3: 0xfc
  390. // bytes 5-17: text data, ending with \r, padding with spaces
  391. // we should check bytes 0-2 and 4, since it may have other values in
  392. // case that the descriptor contains other type of data.
  393. if (edid[offset] == 0 && edid[offset + 1] == 0 && edid[offset + 2] == 0 &&
  394. edid[offset + 3] == kMonitorNameDescriptor && edid[offset + 4] == 0) {
  395. std::string name(reinterpret_cast<const char*>(&edid[offset + 5]),
  396. kDescriptorLength - 5);
  397. base::TrimWhitespaceASCII(name, base::TRIM_TRAILING, &display_name_);
  398. continue;
  399. }
  400. // If the descriptor contains the display's range limits, it has the
  401. // following structure:
  402. // bytes 0-2: \0
  403. // byte 3: 0xfd
  404. // byte 4: Offsets for display range limits
  405. // bytes 5-17: Display range limits and timing information
  406. if (edid[offset] == 0 && edid[offset + 1] == 0 && edid[offset + 2] == 0 &&
  407. edid[offset + 3] == kDisplayRangeLimitsDescriptor) {
  408. // byte 4: Offsets for display range limits
  409. const uint8_t kRateOffset = edid[offset + 4];
  410. // bits 7-4: Reserved \0
  411. if (kRateOffset & 0x10)
  412. continue;
  413. // bit 3: Horizontal max rate offset (not used)
  414. // bit 2: Horizontal min rate offset (not used)
  415. // bit 1: Vertical max rate offset
  416. const uint8_t verticalMaxRateOffset = kRateOffset & (1 << 1) ? 255 : 0;
  417. // bit 0: Vertical min rate offset
  418. const uint8_t verticalMinRateOffset = kRateOffset & (1 << 0) ? 255 : 0;
  419. // bytes 5-8: Rate limits
  420. // Each byte must be within [1, 255].
  421. if (edid[offset + 5] == 0 || edid[offset + 6] == 0 ||
  422. edid[offset + 7] == 0 || edid[offset + 8] == 0)
  423. continue;
  424. // byte 5: Min vertical rate in Hz
  425. min_vfreq_ = edid[offset + 5] + verticalMinRateOffset;
  426. // byte 6: Max vertical rate in Hz
  427. max_vfreq_ = edid[offset + 6] + verticalMaxRateOffset;
  428. // byte 7: Min horizontal rate in kHz (not used)
  429. // byte 8: Max horizontal rate in kHz (not used)
  430. // byte 9: Maximum pixel clock rate (not used)
  431. // byte 10: Extended timing information type (not used)
  432. // bytes 11-17: Video timing parameters (not used)
  433. continue;
  434. }
  435. // If the descriptor contains the display's product serial number, it has
  436. // the following structure:
  437. // bytes 0-2, 4: \0
  438. // byte 3: 0xff
  439. // bytes 5-17: text data, ending with \r, padding with spaces
  440. // we should check bytes 0-2 and 4, since it may have other values in
  441. // case that the descriptor contains other type of data.
  442. if (edid[offset] == 0 && edid[offset + 1] == 0 && edid[offset + 2] == 0 &&
  443. edid[offset + 3] == kMonitorSerialNumberDescriptor &&
  444. edid[offset + 4] == 0) {
  445. std::string serial_number_str(
  446. reinterpret_cast<const char*>(&edid[offset + 5]),
  447. kDescriptorLength - 5);
  448. base::TrimWhitespaceASCII(serial_number_str, base::TRIM_TRAILING,
  449. &serial_number_str);
  450. if (!serial_number_str.empty()) {
  451. descriptor_block_serial_number_hash_ =
  452. base::MD5String(serial_number_str);
  453. }
  454. continue;
  455. }
  456. }
  457. // Verify if the |display_name_| consists of printable characters only.
  458. // Replace unprintable chars with white space.
  459. std::replace_if(
  460. display_name_.begin(), display_name_.end(),
  461. [](char c) { return !isascii(c) || !isprint(c); }, ' ');
  462. // See http://en.wikipedia.org/wiki/Extended_display_identification_data
  463. // for the extension format of EDID. Also see EIA/CEA-861 spec for
  464. // the format of the extensions and how video capability is encoded.
  465. // - byte 0: tag. should be 02h.
  466. // - byte 1: revision. only cares revision 3 (03h).
  467. // - byte 4-: data block.
  468. constexpr size_t kExtensionBaseOffset = 128;
  469. constexpr size_t kExtensionSize = 128;
  470. constexpr size_t kNumExtensionsOffset = 126;
  471. constexpr size_t kDataBlockOffset = 4;
  472. constexpr uint8_t kCEAExtensionTag = '\x02';
  473. constexpr uint8_t kExpectedExtensionRevision = '\x03';
  474. constexpr uint8_t kExtendedTag = 7;
  475. constexpr uint8_t kExtendedVideoCapabilityTag = 0;
  476. constexpr uint8_t kPTOverscanFlagPosition = 4;
  477. constexpr uint8_t kITOverscanFlagPosition = 2;
  478. constexpr uint8_t kCEOverscanFlagPosition = 0;
  479. // See CTA-861-F, particularly Table 56 "Colorimetry Data Block".
  480. constexpr uint8_t kColorimetryDataBlockCapabilityTag = 0x05;
  481. constexpr gfx::ColorSpace::PrimaryID kPrimaryIDMap[] = {
  482. // xvYCC601. Standard Definition Colorimetry based on IEC 61966-2-4.
  483. gfx::ColorSpace::PrimaryID::SMPTE170M,
  484. // xvYCC709. High Definition Colorimetry based on IEC 61966-2-4.
  485. gfx::ColorSpace::PrimaryID::BT709,
  486. // sYCC601. Colorimetry based on IEC 61966-2-1/Amendment 1.
  487. gfx::ColorSpace::PrimaryID::SMPTE170M,
  488. // opYCC601. Colorimetry based on IEC 61966-2-5, Annex A.
  489. gfx::ColorSpace::PrimaryID::SMPTE170M,
  490. // opRGB, Colorimetry based on IEC 61966-2-5.
  491. gfx::ColorSpace::PrimaryID::SMPTE170M,
  492. // BT2020RGB. Colorimetry based on ITU-R BT.2020 R’G’B’.
  493. gfx::ColorSpace::PrimaryID::BT2020,
  494. // BT2020YCC. Colorimetry based on ITU-R BT.2020 Y’C’BC’R.
  495. gfx::ColorSpace::PrimaryID::BT2020,
  496. // BT2020cYCC. Colorimetry based on ITU-R BT.2020 Y’cC’BCC’RC.
  497. gfx::ColorSpace::PrimaryID::BT2020,
  498. };
  499. // See CEA 861.G-2018, Sec.7.5.13, "HDR Static Metadata Data Block" for these.
  500. constexpr uint8_t kHDRStaticMetadataCapabilityTag = 0x6;
  501. constexpr gfx::ColorSpace::TransferID kTransferIDMap[] = {
  502. gfx::ColorSpace::TransferID::BT709,
  503. gfx::ColorSpace::TransferID::GAMMA24,
  504. gfx::ColorSpace::TransferID::PQ,
  505. // STD B67 is also known as Hybrid-log Gamma (HLG).
  506. gfx::ColorSpace::TransferID::HLG,
  507. };
  508. constexpr uint8_t kHDRStaticMetadataDataBlockLengthMask = 0x1F;
  509. if (edid.size() < kNumExtensionsOffset + 1) {
  510. base::UmaHistogramEnumeration(kParseEdidFailureMetric,
  511. ParseEdidFailure::kExtensions);
  512. return; // Any other fields below are beyond this edid offset.
  513. }
  514. const uint8_t num_extensions = edid[kNumExtensionsOffset];
  515. for (size_t i = 0; i < num_extensions; ++i) {
  516. // Skip parsing the whole extension if size is not enough.
  517. if (edid.size() < kExtensionBaseOffset + (i + 1) * kExtensionSize)
  518. break;
  519. const size_t extension_offset = kExtensionBaseOffset + i * kExtensionSize;
  520. const uint8_t cea_tag = edid[extension_offset];
  521. const uint8_t revision = edid[extension_offset + 1];
  522. if (cea_tag != kCEAExtensionTag || revision != kExpectedExtensionRevision)
  523. continue;
  524. const uint8_t timing_descriptors_start = std::min(
  525. edid[extension_offset + 2], static_cast<unsigned char>(kExtensionSize));
  526. for (size_t data_offset = extension_offset + kDataBlockOffset;
  527. data_offset < extension_offset + timing_descriptors_start;) {
  528. // A data block is encoded as:
  529. // - byte 1 high 3 bits: tag. '07' for extended tags.
  530. // - byte 1 remaining bits: the length of data block.
  531. // - byte 2: the extended tag. E.g. '0' for video capability. Values are
  532. // defined by the k...CapabilityTag constants.
  533. // - byte 3: the capability.
  534. const uint8_t tag = edid[data_offset] >> 5;
  535. const uint8_t payload_length = edid[data_offset] & 0x1f;
  536. if (data_offset + payload_length + 1 > edid.size())
  537. break;
  538. if (tag != kExtendedTag || payload_length < 2) {
  539. data_offset += payload_length + 1;
  540. continue;
  541. }
  542. switch (edid[data_offset + 1]) {
  543. case kExtendedVideoCapabilityTag:
  544. // The difference between preferred, IT, and CE video formats doesn't
  545. // matter. Set the flag to true if any of these flags are true.
  546. overscan_flag_ =
  547. (edid[data_offset + 2] & (1 << kPTOverscanFlagPosition)) ||
  548. (edid[data_offset + 2] & (1 << kITOverscanFlagPosition)) ||
  549. (edid[data_offset + 2] & (1 << kCEOverscanFlagPosition));
  550. break;
  551. case kColorimetryDataBlockCapabilityTag: {
  552. constexpr size_t kMaxNumColorimetryEntries = 8;
  553. const std::bitset<kMaxNumColorimetryEntries>
  554. supported_primaries_bitfield(edid[data_offset + 2]);
  555. static_assert(
  556. kMaxNumColorimetryEntries == std::size(kPrimaryIDMap),
  557. "kPrimaryIDMap should describe all possible colorimetry entries");
  558. for (size_t entry = 0; entry < kMaxNumColorimetryEntries; ++entry) {
  559. if (supported_primaries_bitfield[entry])
  560. supported_color_primary_ids_.insert(kPrimaryIDMap[entry]);
  561. }
  562. break;
  563. }
  564. case kHDRStaticMetadataCapabilityTag: {
  565. constexpr size_t kMaxNumHDRStaticMedatataEntries = 4;
  566. const std::bitset<kMaxNumHDRStaticMedatataEntries>
  567. supported_eotfs_bitfield(edid[data_offset + 2]);
  568. static_assert(
  569. kMaxNumHDRStaticMedatataEntries == std::size(kTransferIDMap),
  570. "kTransferIDMap should describe all possible transfer entries");
  571. for (size_t entry = 0; entry < kMaxNumHDRStaticMedatataEntries;
  572. ++entry) {
  573. if (supported_eotfs_bitfield[entry])
  574. supported_color_transfer_ids_.insert(kTransferIDMap[entry]);
  575. }
  576. // See CEA 861.3-2015, Sec.7.5.13, "HDR Static Metadata Data Block"
  577. // for details on the following calculations.
  578. const uint8_t length_of_data_block =
  579. edid[data_offset] & kHDRStaticMetadataDataBlockLengthMask;
  580. if (length_of_data_block <= 3)
  581. break;
  582. const uint8_t desired_content_max_luminance = edid[data_offset + 4];
  583. hdr_static_metadata_ =
  584. absl::make_optional<gfx::HDRStaticMetadata>({});
  585. hdr_static_metadata_->max =
  586. 50.0 * pow(2, desired_content_max_luminance / 32.0);
  587. if (length_of_data_block <= 4)
  588. break;
  589. const uint8_t desired_content_max_frame_average_luminance =
  590. edid[data_offset + 5];
  591. hdr_static_metadata_->max_avg =
  592. 50.0 * pow(2, desired_content_max_frame_average_luminance / 32.0);
  593. if (length_of_data_block <= 5)
  594. break;
  595. const uint8_t desired_content_min_luminance = edid[data_offset + 6];
  596. hdr_static_metadata_->min =
  597. hdr_static_metadata_->max *
  598. pow(desired_content_min_luminance / 255.0, 2) / 100.0;
  599. break;
  600. }
  601. default:
  602. break;
  603. }
  604. data_offset += payload_length + 1;
  605. }
  606. }
  607. base::UmaHistogramEnumeration(kParseEdidFailureMetric,
  608. ParseEdidFailure::kNoError);
  609. ReportEdidOptionalsForExternalDisplay();
  610. }
  611. void EdidParser::ReportEdidOptionalsForExternalDisplay() const {
  612. if (!is_external_display_)
  613. return;
  614. bool all_optionals_available = true;
  615. if (!week_of_manufacture_.has_value()) {
  616. all_optionals_available = false;
  617. base::UmaHistogramEnumeration(kParseExternalDisplayEdidOptionalsMetric,
  618. ParseEdidOptionals::kWeekOfManufacture);
  619. }
  620. if (!max_image_size_.has_value()) {
  621. all_optionals_available = false;
  622. base::UmaHistogramEnumeration(kParseExternalDisplayEdidOptionalsMetric,
  623. ParseEdidOptionals::kPhysicalSize);
  624. }
  625. uint8_t serial_number_count = kMaxSerialNumberCount;
  626. if (!block_zero_serial_number_hash_.has_value()) {
  627. all_optionals_available = false;
  628. serial_number_count--;
  629. base::UmaHistogramEnumeration(kParseExternalDisplayEdidOptionalsMetric,
  630. ParseEdidOptionals::kBlockZeroSerialNumber);
  631. }
  632. if (!descriptor_block_serial_number_hash_.has_value()) {
  633. all_optionals_available = false;
  634. serial_number_count--;
  635. base::UmaHistogramEnumeration(
  636. kParseExternalDisplayEdidOptionalsMetric,
  637. ParseEdidOptionals::kDescriptorBlockSerialNumber);
  638. }
  639. base::UmaHistogramExactLinear(kNumOfSerialNumbersProvidedByExternalDisplay,
  640. serial_number_count, kMaxSerialNumberCount);
  641. if (all_optionals_available) {
  642. base::UmaHistogramEnumeration(kParseExternalDisplayEdidOptionalsMetric,
  643. ParseEdidOptionals::kAllAvailable);
  644. }
  645. }
  646. } // namespace display