Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/display/util/edid_parser.h" | 5 #include "ui/display/util/edid_parser.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/hash.h" | 9 #include "base/hash.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 // treated as swap. The 'serial number' field in EDID isn't used here because | 22 // treated as swap. The 'serial number' field in EDID isn't used here because |
| 23 // it is not guaranteed to have unique number and it may have the same fixed | 23 // it is not guaranteed to have unique number and it may have the same fixed |
| 24 // value (like 0). | 24 // value (like 0). |
| 25 int64_t GetID(uint16_t manufacturer_id, | 25 int64_t GetID(uint16_t manufacturer_id, |
| 26 uint32_t product_code_hash, | 26 uint32_t product_code_hash, |
| 27 uint8_t output_index) { | 27 uint8_t output_index) { |
| 28 return ((static_cast<int64_t>(manufacturer_id) << 40) | | 28 return ((static_cast<int64_t>(manufacturer_id) << 40) | |
| 29 (static_cast<int64_t>(product_code_hash) << 8) | output_index); | 29 (static_cast<int64_t>(product_code_hash) << 8) | output_index); |
| 30 } | 30 } |
| 31 | 31 |
| 32 // Returns a 64-bit identifier for this model of display, using | 32 // Returns a 32-bit identifier for this model of display, using |
| 33 // |manufacturer_id| and |product_code_hash|. | 33 // |manufacturer_id| and |product_code|. |
| 34 int64_t GetProductID(uint16_t manufacturer_id, uint32_t product_code_hash) { | 34 uint32_t GetProductID(uint16_t manufacturer_id, uint16_t product_code) { |
| 35 return ((static_cast<int64_t>(manufacturer_id) << 32) | | 35 return ((static_cast<uint32_t>(manufacturer_id) << 16) | |
| 36 (static_cast<int64_t>(product_code_hash))); | 36 (static_cast<uint32_t>(product_code))); |
| 37 } | 37 } |
| 38 | 38 |
| 39 } // namespace | 39 } // namespace |
| 40 | 40 |
| 41 bool GetDisplayIdFromEDID(const std::vector<uint8_t>& edid, | 41 bool GetDisplayIdFromEDID(const std::vector<uint8_t>& edid, |
| 42 uint8_t output_index, | 42 uint8_t output_index, |
| 43 int64_t* display_id_out, | 43 int64_t* display_id_out, |
| 44 int64_t* product_id_out) { | 44 int64_t* product_id_out) { |
| 45 uint16_t manufacturer_id = 0; | 45 uint16_t manufacturer_id = 0; |
| 46 uint16_t product_code = 0; | |
| 46 std::string product_name; | 47 std::string product_name; |
| 47 | 48 |
| 48 // ParseOutputDeviceData fails if it doesn't have product_name. | 49 // ParseOutputDeviceData fails if it doesn't have product_name. |
| 49 ParseOutputDeviceData(edid, &manufacturer_id, &product_name, nullptr, | 50 ParseOutputDeviceData(edid, &manufacturer_id, &product_code, &product_name, |
| 50 nullptr); | 51 nullptr, nullptr); |
| 51 | 52 |
| 52 // Generates product specific value from product_name instead of product code. | 53 // Generates product specific value from product_name instead of product code. |
| 53 // See crbug.com/240341 | 54 // See crbug.com/240341 |
| 54 uint32_t product_code_hash = product_name.empty() ? | 55 uint32_t product_code_hash = product_name.empty() ? |
| 55 0 : base::Hash(product_name); | 56 0 : base::Hash(product_name); |
|
oshima
2015/05/20 15:37:33
would you mind moving this code inside following i
robert.bradford
2015/05/20 17:13:58
Done.
| |
| 56 if (manufacturer_id != 0) { | 57 if (manufacturer_id != 0) { |
| 57 // An ID based on display's index will be assigned later if this call | 58 // An ID based on display's index will be assigned later if this call |
| 58 // fails. | 59 // fails. |
| 59 *display_id_out = GetID( | 60 *display_id_out = GetID( |
| 60 manufacturer_id, product_code_hash, output_index); | 61 manufacturer_id, product_code_hash, output_index); |
| 62 // product_id is 64-bit signed so it can store -1 as kInvalidProductID and | |
| 63 // not match a valid product id which will all be in the lowest 32-bits. | |
| 61 if (product_id_out) | 64 if (product_id_out) |
| 62 *product_id_out = GetProductID(manufacturer_id, product_code_hash); | 65 *product_id_out = GetProductID(manufacturer_id, product_code); |
| 63 return true; | 66 return true; |
| 64 } | 67 } |
| 65 return false; | 68 return false; |
| 66 } | 69 } |
| 67 | 70 |
| 68 bool ParseOutputDeviceData(const std::vector<uint8_t>& edid, | 71 bool ParseOutputDeviceData(const std::vector<uint8_t>& edid, |
| 69 uint16_t* manufacturer_id, | 72 uint16_t* manufacturer_id, |
| 73 uint16_t* product_code, | |
| 70 std::string* human_readable_name, | 74 std::string* human_readable_name, |
| 71 gfx::Size* active_pixel_out, | 75 gfx::Size* active_pixel_out, |
| 72 gfx::Size* physical_display_size_out) { | 76 gfx::Size* physical_display_size_out) { |
| 73 // See http://en.wikipedia.org/wiki/Extended_display_identification_data | 77 // See http://en.wikipedia.org/wiki/Extended_display_identification_data |
| 74 // for the details of EDID data format. We use the following data: | 78 // for the details of EDID data format. We use the following data: |
| 75 // bytes 8-9: manufacturer EISA ID, in big-endian | 79 // bytes 8-9: manufacturer EISA ID, in big-endian |
| 80 // bytes 10-11: manufacturer product code, in little-endian | |
| 76 // bytes 54-125: four descriptors (18-bytes each) which may contain | 81 // bytes 54-125: four descriptors (18-bytes each) which may contain |
| 77 // the display name. | 82 // the display name. |
| 78 const unsigned int kManufacturerOffset = 8; | 83 const unsigned int kManufacturerOffset = 8; |
| 79 const unsigned int kManufacturerLength = 2; | 84 const unsigned int kManufacturerLength = 2; |
| 85 const unsigned int kProductCodeOffset = 10; | |
| 86 const unsigned int kProductCodeLength = 2; | |
| 80 const unsigned int kDescriptorOffset = 54; | 87 const unsigned int kDescriptorOffset = 54; |
| 81 const unsigned int kNumDescriptors = 4; | 88 const unsigned int kNumDescriptors = 4; |
| 82 const unsigned int kDescriptorLength = 18; | 89 const unsigned int kDescriptorLength = 18; |
| 83 // The specifier types. | 90 // The specifier types. |
| 84 const unsigned char kMonitorNameDescriptor = 0xfc; | 91 const unsigned char kMonitorNameDescriptor = 0xfc; |
| 85 | 92 |
| 86 if (manufacturer_id) { | 93 if (manufacturer_id) { |
| 87 if (edid.size() < kManufacturerOffset + kManufacturerLength) { | 94 if (edid.size() < kManufacturerOffset + kManufacturerLength) { |
| 88 LOG(ERROR) << "too short EDID data: manifacturer id"; | 95 LOG(ERROR) << "too short EDID data: manufacturer id"; |
| 89 return false; | 96 return false; |
| 90 } | 97 } |
| 91 | 98 |
| 92 *manufacturer_id = | 99 *manufacturer_id = |
| 93 *reinterpret_cast<const uint16_t*>(&edid[kManufacturerOffset]); | 100 *reinterpret_cast<const uint16_t*>(&edid[kManufacturerOffset]); |
| 94 #if defined(ARCH_CPU_LITTLE_ENDIAN) | 101 #if defined(ARCH_CPU_LITTLE_ENDIAN) |
| 95 *manufacturer_id = base::ByteSwap(*manufacturer_id); | 102 *manufacturer_id = base::ByteSwap(*manufacturer_id); |
| 96 #endif | 103 #endif |
| 97 } | 104 } |
| 98 | 105 |
| 106 if (product_code) { | |
| 107 if (edid.size() < kProductCodeOffset + kProductCodeLength) { | |
| 108 LOG(ERROR) << "too short EDID data: manufacturer product code"; | |
| 109 return false; | |
| 110 } | |
| 111 | |
| 112 *product_code = | |
| 113 *reinterpret_cast<const uint16_t*>(&edid[kProductCodeOffset]); | |
| 114 } | |
| 115 | |
| 99 if (human_readable_name) | 116 if (human_readable_name) |
| 100 human_readable_name->clear(); | 117 human_readable_name->clear(); |
| 101 | 118 |
| 102 for (unsigned int i = 0; i < kNumDescriptors; ++i) { | 119 for (unsigned int i = 0; i < kNumDescriptors; ++i) { |
| 103 if (edid.size() < kDescriptorOffset + (i + 1) * kDescriptorLength) | 120 if (edid.size() < kDescriptorOffset + (i + 1) * kDescriptorLength) |
| 104 break; | 121 break; |
| 105 | 122 |
| 106 size_t offset = kDescriptorOffset + i * kDescriptorLength; | 123 size_t offset = kDescriptorOffset + i * kDescriptorLength; |
| 107 | 124 |
| 108 // Detailed Timing Descriptor: | 125 // Detailed Timing Descriptor: |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 248 *flag = false; | 265 *flag = false; |
| 249 } | 266 } |
| 250 return true; | 267 return true; |
| 251 } | 268 } |
| 252 } | 269 } |
| 253 | 270 |
| 254 return false; | 271 return false; |
| 255 } | 272 } |
| 256 | 273 |
| 257 } // namespace ui | 274 } // namespace ui |
| OLD | NEW |