| # 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. |
| |
| """Provides the CoordinatedVideoTiming class with methods for parsing info. |
| |
| CoordinatedVideoTiming info is stored in Video Timing Block extensions. |
| """ |
| |
| import error |
| import tools |
| |
| |
| def GetCoordinatedVideoTiming(edid, start_index): |
| """Returns a CoordinatedVideoTiming object if valid block exists. |
| |
| Args: |
| edid: The list form of the EDID being parsed. |
| start_index: The starting index of the CVT block, relative to base EDID. |
| |
| Returns: |
| A CoordinatedVideoTiming object, if valid; or else None. |
| """ |
| if not(edid[start_index] == edid[start_index + 1] == edid[start_index + 2] |
| == 0x00): |
| return CoordinatedVideoTiming(edid, start_index) |
| else: |
| return None |
| |
| |
| class CoordinatedVideoTiming(object): |
| """Returns a CoordinatedVideoTiming object and its properties.""" |
| |
| _ref_rates = [ |
| [0x10, '50Hz'], |
| [0x08, '60Hz'], |
| [0x04, '75Hz'], |
| [0x02, '85Hz'], |
| [0x01, '60Hz (reduced blanking)'] |
| ] |
| |
| def __init__(self, edid, start_index): |
| """Creates a CoordinatedVideoTiming object. |
| |
| Args: |
| edid: The edid (in list form). |
| start_index: The starting index of the coordinated video timing block, |
| relative to the base EDID. |
| """ |
| self._block = edid[start_index:(start_index + 3)] |
| |
| def GetBlock(self): |
| """Fetches the bytes that constitute the coordinated video timing block. |
| |
| Returns: |
| The list of bytes of the coordinated video timing block. |
| """ |
| return self._block |
| |
| @property |
| def active_vertical_lines(self): |
| """Fetches the number of active vertical lines. |
| |
| Returns: |
| An integer indicating the number of active vertical lines. |
| """ |
| val = ((self._block[1] & 0xF0) << 4) + self._block[0] |
| return (val + 1) * 2 |
| |
| @property |
| def aspect_ratio(self): |
| """Fetches the aspect ratio. |
| |
| Returns: |
| A string indicating the aspect ratio. |
| """ |
| ar = (self._block[1] >> 2) & 0x03 |
| asp_ratio = '' |
| |
| if ar == 0x00: |
| asp_ratio = '4:3 AR' |
| elif ar == 0x01: |
| asp_ratio = '16:9 AR' |
| elif ar == 0x02: |
| asp_ratio = '16:10 AR' |
| elif ar == 0x03: |
| asp_ratio = '15:9 AR' |
| |
| return asp_ratio |
| |
| @property |
| def preferred_vertical_rate(self): |
| """Fetches the preferred refresh rate (byte 3). |
| |
| Returns: |
| A string indicating the preferred refresh rate; the returned value should |
| also be included in supported_vertical_rates. |
| """ |
| pref_code = (self._block[2] >> 5) & 0x03 # Ranges 00-11 (0-3) |
| supp_code = self._block[2] & 0x1F # 5 bits long |
| |
| if pref_code == 0x01 and supp_code & 0x01: |
| pref_code = 4 |
| return self._ref_rates[pref_code][1] |
| |
| @property |
| def supported_vertical_rates(self): |
| """Fetches the list of supported refresh rates. |
| |
| Returns: |
| A dict of strings and booleans, each representing a refresh rate and |
| whether it is supported. |
| """ |
| supp_code = self._block[2] & 0x1F |
| return tools.DictFilter(self._ref_rates, supp_code) |
| |
| def CheckErrors(self, index=None): |
| """Checks for errors in the coordinated video timing block. |
| |
| Args: |
| index: The index of the CoordinatedVideoTiming object within the EDID. |
| |
| Returns: |
| An error.Error object specifying details, if there is one; else, None. |
| """ |
| loc = 'Coordinated video timing block %s' % ('#%d' % index if index else '') |
| errors = [] |
| |
| # Check that preferred refresh rate is supported |
| if self.preferred_vertical_rate not in self.supported_vertical_rates: |
| errors.append(error.Error(loc, 'Preferred refresh rate not supported', |
| '%s supported' % self.preferred_vertical_rate, |
| 'Supported: %s' % |
| self.supported_vertical_rates)) |
| |
| # Check for reserved 0 bits |
| if self._block[1] & 0x03: |
| # Error: Bits 1-0 of byte 2 in CVT should be set to '00' |
| errors.append(error.Error(loc, 'Bits 1-0 of byte 2 incorrectly set', |
| 0x00, self._block[1] & 0x03)) |
| |
| if self._block[2] & 0x80: |
| # Error: Bit 7 of byte 3 in CVT should be set to '0' |
| errors.append(error.Error(loc, 'Bit 7 of byte 3 incorrectly set', 0x00, |
| self._block[2] & 0x80)) |
| |
| return errors |