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/edid_parser.h" | 5 #include "ui/display/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" |
11 #include "base/sys_byteorder.h" | 11 #include "base/sys_byteorder.h" |
12 | 12 |
13 namespace ui { | 13 namespace ui { |
14 | 14 |
15 namespace { | 15 namespace { |
16 | 16 |
17 // Returns 64-bit persistent ID for the specified manufacturer's ID and | 17 // Returns 64-bit persistent ID for the specified manufacturer's ID and |
18 // product_code_hash, and the index of the output it is connected to. | 18 // product_code_hash, and the index of the output it is connected to. |
19 // |output_index| is used to distinguish the displays of the same type. For | 19 // |output_index| is used to distinguish the displays of the same type. For |
20 // example, swapping two identical display between two outputs will not be | 20 // example, swapping two identical display between two outputs will not be |
21 // treated as swap. The 'serial number' field in EDID isn't used here because | 21 // treated as swap. The 'serial number' field in EDID isn't used here because |
22 // it is not guaranteed to have unique number and it may have the same fixed | 22 // it is not guaranteed to have unique number and it may have the same fixed |
23 // value (like 0). | 23 // value (like 0). |
24 int64 GetID(uint16 manufacturer_id, | 24 int64_t GetID(uint16_t manufacturer_id, |
25 uint32 product_code_hash, | 25 uint32_t product_code_hash, |
26 uint8 output_index) { | 26 uint8_t output_index) { |
27 return ((static_cast<int64>(manufacturer_id) << 40) | | 27 return ((static_cast<int64_t>(manufacturer_id) << 40) | |
28 (static_cast<int64>(product_code_hash) << 8) | output_index); | 28 (static_cast<int64_t>(product_code_hash) << 8) | output_index); |
29 } | 29 } |
30 | 30 |
31 } // namespace | 31 } // namespace |
32 | 32 |
33 bool GetDisplayIdFromEDID(const std::vector<uint8>& edid, | 33 bool GetDisplayIdFromEDID(const std::vector<uint8_t>& edid, |
34 uint8 output_index, | 34 uint8_t output_index, |
35 int64* display_id_out) { | 35 int64_t* display_id_out) { |
36 uint16 manufacturer_id = 0; | 36 uint16_t manufacturer_id = 0; |
37 std::string product_name; | 37 std::string product_name; |
38 | 38 |
39 // ParseOutputDeviceData fails if it doesn't have product_name. | 39 // ParseOutputDeviceData fails if it doesn't have product_name. |
40 ParseOutputDeviceData(edid, &manufacturer_id, &product_name); | 40 ParseOutputDeviceData(edid, &manufacturer_id, &product_name); |
41 | 41 |
42 // Generates product specific value from product_name instead of product code. | 42 // Generates product specific value from product_name instead of product code. |
43 // See crbug.com/240341 | 43 // See crbug.com/240341 |
44 uint32 product_code_hash = product_name.empty() ? | 44 uint32_t product_code_hash = product_name.empty() ? |
45 0 : base::Hash(product_name); | 45 0 : base::Hash(product_name); |
46 if (manufacturer_id != 0) { | 46 if (manufacturer_id != 0) { |
47 // An ID based on display's index will be assigned later if this call | 47 // An ID based on display's index will be assigned later if this call |
48 // fails. | 48 // fails. |
49 *display_id_out = GetID( | 49 *display_id_out = GetID( |
50 manufacturer_id, product_code_hash, output_index); | 50 manufacturer_id, product_code_hash, output_index); |
51 return true; | 51 return true; |
52 } | 52 } |
53 return false; | 53 return false; |
54 } | 54 } |
55 | 55 |
56 bool ParseOutputDeviceData(const std::vector<uint8>& edid, | 56 bool ParseOutputDeviceData(const std::vector<uint8_t>& edid, |
57 uint16* manufacturer_id, | 57 uint16_t* manufacturer_id, |
58 std::string* human_readable_name) { | 58 std::string* human_readable_name) { |
59 // See http://en.wikipedia.org/wiki/Extended_display_identification_data | 59 // See http://en.wikipedia.org/wiki/Extended_display_identification_data |
60 // for the details of EDID data format. We use the following data: | 60 // for the details of EDID data format. We use the following data: |
61 // bytes 8-9: manufacturer EISA ID, in big-endian | 61 // bytes 8-9: manufacturer EISA ID, in big-endian |
62 // bytes 54-125: four descriptors (18-bytes each) which may contain | 62 // bytes 54-125: four descriptors (18-bytes each) which may contain |
63 // the display name. | 63 // the display name. |
64 const unsigned int kManufacturerOffset = 8; | 64 const unsigned int kManufacturerOffset = 8; |
65 const unsigned int kManufacturerLength = 2; | 65 const unsigned int kManufacturerLength = 2; |
66 const unsigned int kDescriptorOffset = 54; | 66 const unsigned int kDescriptorOffset = 54; |
67 const unsigned int kNumDescriptors = 4; | 67 const unsigned int kNumDescriptors = 4; |
68 const unsigned int kDescriptorLength = 18; | 68 const unsigned int kDescriptorLength = 18; |
69 // The specifier types. | 69 // The specifier types. |
70 const unsigned char kMonitorNameDescriptor = 0xfc; | 70 const unsigned char kMonitorNameDescriptor = 0xfc; |
71 | 71 |
72 if (manufacturer_id) { | 72 if (manufacturer_id) { |
73 if (edid.size() < kManufacturerOffset + kManufacturerLength) { | 73 if (edid.size() < kManufacturerOffset + kManufacturerLength) { |
74 LOG(ERROR) << "too short EDID data: manifacturer id"; | 74 LOG(ERROR) << "too short EDID data: manifacturer id"; |
75 return false; | 75 return false; |
76 } | 76 } |
77 | 77 |
78 *manufacturer_id = | 78 *manufacturer_id = |
79 *reinterpret_cast<const uint16*>(&edid[kManufacturerOffset]); | 79 *reinterpret_cast<const uint16_t*>(&edid[kManufacturerOffset]); |
80 #if defined(ARCH_CPU_LITTLE_ENDIAN) | 80 #if defined(ARCH_CPU_LITTLE_ENDIAN) |
81 *manufacturer_id = base::ByteSwap(*manufacturer_id); | 81 *manufacturer_id = base::ByteSwap(*manufacturer_id); |
82 #endif | 82 #endif |
83 } | 83 } |
84 | 84 |
85 if (!human_readable_name) | 85 if (!human_readable_name) |
86 return true; | 86 return true; |
87 | 87 |
88 human_readable_name->clear(); | 88 human_readable_name->clear(); |
89 for (unsigned int i = 0; i < kNumDescriptors; ++i) { | 89 for (unsigned int i = 0; i < kNumDescriptors; ++i) { |
(...skipping 24 matching lines...) Expand all Loading... |
114 if (!isascii(c) || !isprint(c)) { | 114 if (!isascii(c) || !isprint(c)) { |
115 human_readable_name->clear(); | 115 human_readable_name->clear(); |
116 LOG(ERROR) << "invalid EDID: human unreadable char in name"; | 116 LOG(ERROR) << "invalid EDID: human unreadable char in name"; |
117 return false; | 117 return false; |
118 } | 118 } |
119 } | 119 } |
120 | 120 |
121 return true; | 121 return true; |
122 } | 122 } |
123 | 123 |
124 bool ParseOutputOverscanFlag(const std::vector<uint8>& edid, | 124 bool ParseOutputOverscanFlag(const std::vector<uint8_t>& edid, |
125 bool* flag) { | 125 bool* flag) { |
126 // See http://en.wikipedia.org/wiki/Extended_display_identification_data | 126 // See http://en.wikipedia.org/wiki/Extended_display_identification_data |
127 // for the extension format of EDID. Also see EIA/CEA-861 spec for | 127 // for the extension format of EDID. Also see EIA/CEA-861 spec for |
128 // the format of the extensions and how video capability is encoded. | 128 // the format of the extensions and how video capability is encoded. |
129 // - byte 0: tag. should be 02h. | 129 // - byte 0: tag. should be 02h. |
130 // - byte 1: revision. only cares revision 3 (03h). | 130 // - byte 1: revision. only cares revision 3 (03h). |
131 // - byte 4-: data block. | 131 // - byte 4-: data block. |
132 const unsigned int kExtensionBase = 128; | 132 const unsigned int kExtensionBase = 128; |
133 const unsigned int kExtensionSize = 128; | 133 const unsigned int kExtensionSize = 128; |
134 const unsigned int kNumExtensionsOffset = 126; | 134 const unsigned int kNumExtensionsOffset = 126; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 *flag = false; | 188 *flag = false; |
189 } | 189 } |
190 return true; | 190 return true; |
191 } | 191 } |
192 } | 192 } |
193 | 193 |
194 return false; | 194 return false; |
195 } | 195 } |
196 | 196 |
197 } // namespace ui | 197 } // namespace ui |
OLD | NEW |