Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "chromeos/display/output_util.h" | 5 #include "chromeos/display/output_util.h" |
| 6 | 6 |
| 7 #include <X11/Xlib.h> | 7 #include <X11/Xlib.h> |
| 8 #include <X11/extensions/Xrandr.h> | 8 #include <X11/extensions/Xrandr.h> |
| 9 #include <X11/Xatom.h> | 9 #include <X11/Xatom.h> |
| 10 | 10 |
| 11 #include "base/hash.h" | |
| 11 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 12 #include "base/string_util.h" | 13 #include "base/string_util.h" |
| 13 #include "base/sys_byteorder.h" | 14 #include "base/sys_byteorder.h" |
| 14 | 15 |
| 15 namespace chromeos { | 16 namespace chromeos { |
| 16 namespace { | 17 namespace { |
| 17 | 18 |
| 18 // Prefixes for the built-in displays. | 19 // Prefixes for the built-in displays. |
| 19 const char kInternal_LVDS[] = "LVDS"; | 20 const char kInternal_LVDS[] = "LVDS"; |
| 20 const char kInternal_eDP[] = "eDP"; | 21 const char kInternal_eDP[] = "eDP"; |
| 21 | 22 |
| 22 // Returns 64-bit persistent ID for the specified manufacturer's ID and | 23 // Returns 64-bit persistent ID for the specified manufacturer's ID and |
| 23 // product_code, and the index of the output it is connected to. | 24 // product_name, and the index of the output it is connected to. |
|
oshima
2013/05/21 21:53:31
keep this name consistent in the file, like produc
Jun Mukai
2013/05/22 00:28:05
Done.
| |
| 24 // |output_index| is used to distinguish the displays of the same type. For | 25 // |output_index| is used to distinguish the displays of the same type. For |
| 25 // example, swapping two identical display between two outputs will not be | 26 // example, swapping two identical display between two outputs will not be |
| 26 // treated as swap. The 'serial number' field in EDID isn't used here because | 27 // treated as swap. The 'serial number' field in EDID isn't used here because |
| 27 // it is not guaranteed to have unique number and it may have the same fixed | 28 // it is not guaranteed to have unique number and it may have the same fixed |
| 28 // value (like 0). | 29 // value (like 0). |
| 29 int64 GetID(uint16 manufacturer_id, | 30 int64 GetID(uint16 manufacturer_id, |
| 30 uint16 product_code, | 31 uint32 product_code, |
|
oshima
2013/05/21 21:53:31
ditto
Jun Mukai
2013/05/22 00:28:05
Done.
| |
| 31 uint8 output_index) { | 32 uint8 output_index) { |
| 32 return ((static_cast<int64>(manufacturer_id) << 24) | | 33 return ((static_cast<int64>(manufacturer_id) << 40) | |
| 33 (static_cast<int64>(product_code) << 8) | output_index); | 34 (static_cast<int64>(product_code) << 8) | output_index); |
| 34 } | 35 } |
| 35 | 36 |
| 36 bool IsRandRAvailable() { | 37 bool IsRandRAvailable() { |
| 37 int randr_version_major = 0; | 38 int randr_version_major = 0; |
| 38 int randr_version_minor = 0; | 39 int randr_version_minor = 0; |
| 39 static bool is_randr_available = XRRQueryVersion( | 40 static bool is_randr_available = XRRQueryVersion( |
| 40 base::MessagePumpAuraX11::GetDefaultXDisplay(), | 41 base::MessagePumpAuraX11::GetDefaultXDisplay(), |
| 41 &randr_version_major, &randr_version_minor); | 42 &randr_version_major, &randr_version_minor); |
| 42 return is_randr_available; | 43 return is_randr_available; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 112 | 113 |
| 113 } // namespace | 114 } // namespace |
| 114 | 115 |
| 115 std::string GetDisplayName(XID output_id) { | 116 std::string GetDisplayName(XID output_id) { |
| 116 std::string display_name; | 117 std::string display_name; |
| 117 GetOutputDeviceData(output_id, NULL, NULL, &display_name); | 118 GetOutputDeviceData(output_id, NULL, NULL, &display_name); |
| 118 return display_name; | 119 return display_name; |
| 119 } | 120 } |
| 120 | 121 |
| 121 bool GetDisplayId(XID output_id, size_t output_index, int64* display_id_out) { | 122 bool GetDisplayId(XID output_id, size_t output_index, int64* display_id_out) { |
| 123 unsigned long nitems = 0; | |
| 124 unsigned char* prop = NULL; | |
| 125 if (!GetEDIDProperty(output_id, &nitems, &prop)) | |
| 126 return false; | |
| 127 | |
| 128 bool result = | |
| 129 GetDisplayIdFromEDID(prop, nitems, output_index, display_id_out); | |
| 130 XFree(prop); | |
| 131 return result; | |
| 132 } | |
| 133 | |
| 134 bool GetDisplayIdFromEDID(const unsigned char* prop, | |
| 135 unsigned long nitems, | |
| 136 size_t output_index, | |
| 137 int64* display_id_out) { | |
| 122 uint16 manufacturer_id = 0; | 138 uint16 manufacturer_id = 0; |
| 123 uint16 product_code = 0; | 139 uint16 product_code = 0; |
| 124 if (GetOutputDeviceData( | 140 std::string product_name; |
| 125 output_id, &manufacturer_id, &product_code, NULL) && | 141 |
| 126 manufacturer_id != 0) { | 142 // ParseOutputDeviceData fails if it doesn't have product_name. |
| 143 ParseOutputDeviceData( | |
| 144 prop, nitems, &manufacturer_id, &product_code, &product_name); | |
| 145 | |
| 146 // Generates product specific value from product_name. See crbug.com/240341 | |
| 147 // for why we use product name string instead of product code in EDID. Use | |
| 148 // fallback value to 0 instead of product code just in case that the code | |
| 149 // over-classify a device. | |
| 150 // TODO(mukai): fix the code when we encounter a vendor which doesn't put | |
| 151 // display name but distinguish them by product code. | |
|
oshima
2013/05/21 21:53:31
Actually, we can't use product code because we kno
Jun Mukai
2013/05/22 00:28:05
Done.
| |
| 152 uint32 product_specific_code = product_name.empty() ? | |
| 153 0 : base::Hash(product_name); | |
| 154 if (manufacturer_id != 0) { | |
| 127 // An ID based on display's index will be assigned later if this call | 155 // An ID based on display's index will be assigned later if this call |
| 128 // fails. | 156 // fails. |
| 129 *display_id_out = GetID(manufacturer_id, product_code, output_index); | 157 *display_id_out = GetID( |
| 158 manufacturer_id, product_specific_code, output_index); | |
| 130 return true; | 159 return true; |
| 131 } | 160 } |
| 132 return false; | 161 return false; |
| 133 } | 162 } |
| 134 | 163 |
| 135 bool ParseOutputDeviceData(const unsigned char* prop, | 164 bool ParseOutputDeviceData(const unsigned char* prop, |
| 136 unsigned long nitems, | 165 unsigned long nitems, |
| 137 uint16* manufacturer_id, | 166 uint16* manufacturer_id, |
| 138 uint16* product_code, | 167 uint16* product_code, |
|
oshima
2013/05/21 21:53:31
and if that's the case, we no longer need to parse
Jun Mukai
2013/05/22 00:28:05
Done.
| |
| 139 std::string* human_readable_name) { | 168 std::string* human_readable_name) { |
| 140 // See http://en.wikipedia.org/wiki/Extended_display_identification_data | 169 // See http://en.wikipedia.org/wiki/Extended_display_identification_data |
| 141 // for the details of EDID data format. We use the following data: | 170 // for the details of EDID data format. We use the following data: |
| 142 // bytes 8-9: manufacturer EISA ID, in big-endian | 171 // bytes 8-9: manufacturer EISA ID, in big-endian |
| 143 // bytes 10-11: represents product code, in little-endian | 172 // bytes 10-11: represents product code, in little-endian |
| 144 // bytes 54-125: four descriptors (18-bytes each) which may contain | 173 // bytes 54-125: four descriptors (18-bytes each) which may contain |
| 145 // the display name. | 174 // the display name. |
| 146 const unsigned int kManufacturerOffset = 8; | 175 const unsigned int kManufacturerOffset = 8; |
| 147 const unsigned int kManufacturerLength = 2; | 176 const unsigned int kManufacturerLength = 2; |
| 148 const unsigned int kProductCodeOffset = 10; | 177 const unsigned int kProductCodeOffset = 10; |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 310 } | 339 } |
| 311 | 340 |
| 312 return false; | 341 return false; |
| 313 } | 342 } |
| 314 | 343 |
| 315 bool IsInternalOutputName(const std::string& name) { | 344 bool IsInternalOutputName(const std::string& name) { |
| 316 return name.find(kInternal_LVDS) == 0 || name.find(kInternal_eDP) == 0; | 345 return name.find(kInternal_LVDS) == 0 || name.find(kInternal_eDP) == 0; |
| 317 } | 346 } |
| 318 | 347 |
| 319 } // namespace chromeos | 348 } // namespace chromeos |
| OLD | NEW |