blob: ba1030348bd18549e57f30270c30d3de9e24791d [file] [log] [blame] [edit]
# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Checks EDID for errors, which could indicate invalid or faulty EDID.
If errors are found, returns error.Error objects that store information about
each error's location, message, expected data, and what data is found.
"""
import descriptor
import error
import extensions
import standard_timings
def _LengthError(e):
"""Checks if the length of the EDID is a multiple of 128.
Args:
e: The list form of the EDID to be checked.
Returns:
A list of error.Error objects, or None.
"""
if not len(e) % 128:
return None
else:
return [error.Error('Overall EDID', 'Invalid length', 'Length % 128 = 0',
'Length %% 128 = %d' % (len(e) % 128))]
def _HeaderError(e):
"""Checks if header (bytes 0-7) is set up properly.
Header should be 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00.
Args:
e: The list form of the EDID to be checked.
Returns:
A list of error.Error objects, or None.
"""
magic_header = [
0x00,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0x00
]
header = '%02X%02X ' * 4 % tuple(e[0:8])
if e[0:8] == magic_header:
return None
else:
return [error.Error('Bytes 0-7', 'Incorrect EDID header',
'00FF FFFF FFFF FF00', header)]
return None
def _ChecksumError(e):
"""Checks if checksum is valid.
Checksum for each 128-byte block should be divisible by 256.
Args:
e: The list form of the EDID to be checked.
Returns:
None, if no error, or a list of error.Error objects.
"""
cs_errors = []
for x in xrange(0, len(e), 128):
my_sum = sum(e[x : x + 128])
if my_sum % 256:
block_id = x / 128
my_err = error.Error('Block %d' % block_id, 'Checksum error',
'Sum % 256 = 0', 'Sum %% 256 = %d' % (my_sum % 256))
cs_errors.append(my_err)
return cs_errors
def _DescriptorErrors(edid, version):
"""Checks the descriptor blocks for errors.
Args:
edid: The list form of the EDID to be checked.
version: The string indicating the version of the EDID.
Returns:
A list of error.Error objects.
"""
base = 54 # Descriptor blocks start at byte 54 in base EDID
errors = []
for x in xrange(0, 4):
desc = descriptor.GetDescriptor(edid, base + (x * 18), version)
desc_errors = desc.CheckErrors(x + 1)
if desc_errors:
errors.extend(desc_errors)
return errors
def _BaseStErrors(edid, version):
"""Checks the standard timing section for errors.
Args:
edid: The list form of the EDID to be checked.
version: A string indicating the EDID's version.
Returns:
A list of error.Error objects.
"""
base = 38
errors = []
for x in xrange(0, 8):
st = standard_timings.GetStandardTiming(edid, base + (x * 2), version)
if st:
err = st.CheckErrors(x + 1)
if err:
errors.extend(err)
return errors
def _ExtensionErrors(edid, version):
"""Checks all extensions for errors.
Args:
edid: The EDID being checked.
version: A string indicating the EDID's version.
Returns:
A list of error.Error objects.
"""
num_ext = edid[0x7E]
errors = []
if (num_ext + 1) != (len(edid) / 128):
errors.append(error.Error('Extensions', 'Extension count does not match '
'EDID length', '%d extensions' % num_ext,
'%d extensions' % ((len(edid) / 128) - 1)))
for x in xrange(1, num_ext + 1):
ext = extensions.GetExtension(edid, x, version)
err = ext.CheckErrors(x)
if err:
errors.extend(err)
return errors
def _WeekError(edid):
"""Checks if the manufacturer week is in the proper range of 1-54.
Args:
edid: The list form of the EDID being checked.
Returns:
An error.Error object, if there's an error.
"""
if edid[0x10] > 54 and edid[0x10] != 255:
return [error.Error('Manufacturer/Vendor section- byte 0x10', 'Invalid week'
' value', 'Week in range 1-54', 'Week %d' % edid[0x10])]
def GetErrors(edid, version):
"""Checks EDID for all potential errors.
Args:
edid: The list form of the EDID being checked.
version: The string representing the version of the EDID.
Returns:
A list of error.Error objects.
"""
errors = []
# Check for various errors, and add them to error list
error_check_functions = [
_HeaderError(edid),
_ChecksumError(edid),
_LengthError(edid),
_WeekError(edid),
_DescriptorErrors(edid, version),
_BaseStErrors(edid, version),
_ExtensionErrors(edid, version)
]
for err in error_check_functions:
if err:
errors.extend(err)
return errors