2
* Copyright © 2016 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 3,
6
* as published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by: Nick Dedekind <nick.dedekind@canonical.com>
25
miral::Edid& miral::Edid::parse_data(std::vector<uint8_t> const& data)
27
if (data.size() != 128 && data.size() != 256) {
28
throw std::runtime_error("Incorrect EDID structure size");
32
uint8_t sum = std::accumulate(data.begin(), data.end(), 0);
34
throw std::runtime_error("Invalid EDID checksum");
38
static constexpr uint8_t sig[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
39
if (std::memcmp(data.data(), sig, sizeof sig)) {
40
throw std::runtime_error("Invalid EDID header");
43
vendor = { (char)((data[8] >> 2 & 0x1f) + 'A' - 1),
44
(char)((((data[8] & 0x3) << 3) | ((data[9] & 0xe0) >> 5)) + 'A' - 1),
45
(char)((data[9] & 0x1f) + 'A' - 1) };
47
product_code = *(uint16_t*)&data[10];
48
serial_number = *(uint32_t*)&data[12];
50
size.width = (int)data[21] * 10;
51
size.height = (int)data[22] * 10;
53
for (int descriptor_index = 0, i = 54; descriptor_index < 4; descriptor_index++, i += 18) { //read through descriptor blocks... 54-71, 72-89, 90-107, 108-125
54
if (data[i] == 0x00) { //not a timing descriptor
56
auto& descriptor = descriptors[descriptor_index];
57
auto& value = descriptor.value;
59
descriptor.type = static_cast<Edid::Descriptor::Type>(data[i+3]);
61
switch (descriptor.type) {
62
case Descriptor::Type::monitor_name:
63
for (int j = 5; j < 18; j++) {
64
if (data[i+j] == 0x0a) {
67
value.monitor_name[j-5] = data[i+j];
71
case Descriptor::Type::monitor_limits:
73
case Descriptor::Type::unspecified_text:
74
for (int j = 5; j < 18; j++) {
75
if (data[i+j] == 0x0a) {
78
value.unspecified_text[j-5] = data[i+j];
82
case Descriptor::Type::serial_number:
83
for (int j = 5; j < 18; j++) {
84
if (data[i+j] == 0x0a) {
87
value.serial_number[j-5] = data[i+j];
100
std::string miral::Edid::Descriptor::string_value() const
103
case Type::monitor_name:
104
return std::string(value.monitor_name);
105
case Type::unspecified_text:
106
return std::string(value.unspecified_text);
107
case Type::serial_number:
108
return std::string(value.serial_number);