chameleon.py revision d3fad2c8a0ba1508f5fc3efb90592687ec219d5c
1eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam# Use of this source code is governed by a BSD-style license that can be
3eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam# found in the LICENSE file.
4eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
5c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tamimport httplib
672e354c97eb4890f4ce770ea27caa62cf620b4c1Tom Wai-Hong Tamimport logging
7c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tamimport socket
8e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tamimport time
9eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tamimport xmlrpclib
10e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tamfrom contextlib import contextmanager
11eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
12428b34464f1060129cbcda08d60ec44ed88a518dJ. Richard Barnettefrom PIL import Image
13428b34464f1060129cbcda08d60ec44ed88a518dJ. Richard Barnette
14c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tamfrom autotest_lib.client.bin import utils
15c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tamfrom autotest_lib.client.common_lib import error
165b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tamfrom autotest_lib.client.cros.chameleon import edid as edid_lib
177a4ba1cad16c47849d8dfabcfaf5aa9d64960977Tom Wai-Hong Tam
18eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
19c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong TamCHAMELEON_PORT = 9992
20c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
21c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
22c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tamclass ChameleonConnectionError(error.TestError):
23c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    """Indicates that connecting to Chameleon failed.
24c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
25c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    It is fatal to the test unless caught.
26c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    """
27c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    pass
28c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
29c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
30c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tamclass ChameleonConnection(object):
31c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    """ChameleonConnection abstracts the network connection to the board.
32c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
33c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    ChameleonBoard and ChameleonPort use it for accessing Chameleon RPC.
34c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
35c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    """
36c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
37c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    def __init__(self, hostname, port=CHAMELEON_PORT):
38c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        """Constructs a ChameleonConnection.
39c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
40c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        @param hostname: Hostname the chameleond process is running.
41c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        @param port: Port number the chameleond process is listening on.
42c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
43c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        @raise ChameleonConnectionError if connection failed.
44c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        """
45c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        self.chameleond_proxy = ChameleonConnection._create_server_proxy(
46c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam                hostname, port)
47c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
48c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
49c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    @staticmethod
50c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    def _create_server_proxy(hostname, port):
51c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        """Creates the chameleond server proxy.
52c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
53c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        @param hostname: Hostname the chameleond process is running.
54c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        @param port: Port number the chameleond process is listening on.
55c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
56c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        @return ServerProxy object to chameleond.
57c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
58c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        @raise ChameleonConnectionError if connection failed.
59c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        """
60c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        remote = 'http://%s:%s' % (hostname, port)
61c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        chameleond_proxy = xmlrpclib.ServerProxy(remote, allow_none=True)
62c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        # Call a RPC to test.
63c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        try:
64b4fd848987c6ac62a9e65ff4bb91ef281ab6894eTom Wai-Hong Tam            chameleond_proxy.GetSupportedPorts()
65c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        except (socket.error,
66c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam                xmlrpclib.ProtocolError,
67c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam                httplib.BadStatusLine) as e:
68c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam            raise ChameleonConnectionError(e)
69c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        return chameleond_proxy
70c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
71c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
72eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tamclass ChameleonBoard(object):
73eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    """ChameleonBoard is an abstraction of a Chameleon board.
74eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
75eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    A Chameleond RPC proxy is passed to the construction such that it can
76eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    use this proxy to control the Chameleon board.
77c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
78eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    """
79eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
80c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    def __init__(self, chameleon_connection):
81eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """Construct a ChameleonBoard.
82eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
83c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        @param chameleon_connection: ChameleonConnection object.
84eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
85c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        self._chameleond_proxy = chameleon_connection.chameleond_proxy
86eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
87eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
88eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    def reset(self):
89eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """Resets Chameleon board."""
90eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        self._chameleond_proxy.Reset()
91eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
92eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
93eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    def get_all_ports(self):
94eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """Gets all the ports on Chameleon board which are connected.
95eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
96eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        @return: A list of ChameleonPort objects.
97eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
9819c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam        ports = self._chameleond_proxy.ProbePorts()
9919c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam        return [ChameleonPort(self._chameleond_proxy, port) for port in ports]
10019c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam
10119c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam
10219c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam    def get_all_inputs(self):
10319c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam        """Gets all the input ports on Chameleon board which are connected.
10419c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam
10519c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam        @return: A list of ChameleonPort objects.
10619c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam        """
107eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        ports = self._chameleond_proxy.ProbeInputs()
108eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        return [ChameleonPort(self._chameleond_proxy, port) for port in ports]
109eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
110eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
11119c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam    def get_all_outputs(self):
11219c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam        """Gets all the output ports on Chameleon board which are connected.
11319c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam
11419c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam        @return: A list of ChameleonPort objects.
11519c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam        """
11619c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam        ports = self._chameleond_proxy.ProbeOutputs()
11719c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam        return [ChameleonPort(self._chameleond_proxy, port) for port in ports]
11819c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam
11919c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam
1203d75ebce0a965218db301852e3feb309b3d5b333Tom Wai-Hong Tam    def get_label(self):
1213d75ebce0a965218db301852e3feb309b3d5b333Tom Wai-Hong Tam        """Gets the label which indicates the display connection.
1223d75ebce0a965218db301852e3feb309b3d5b333Tom Wai-Hong Tam
1233d75ebce0a965218db301852e3feb309b3d5b333Tom Wai-Hong Tam        @return: A string of the label, like 'hdmi', 'dp_hdmi', etc.
1243d75ebce0a965218db301852e3feb309b3d5b333Tom Wai-Hong Tam        """
125d7a45223ad35e98496bf3d0f8eeefa7a1eb2d731Tom Wai-Hong Tam        connectors = []
126d7a45223ad35e98496bf3d0f8eeefa7a1eb2d731Tom Wai-Hong Tam        for port in self._chameleond_proxy.ProbeInputs():
127d7a45223ad35e98496bf3d0f8eeefa7a1eb2d731Tom Wai-Hong Tam            if self._chameleond_proxy.HasVideoSupport(port):
128d7a45223ad35e98496bf3d0f8eeefa7a1eb2d731Tom Wai-Hong Tam                connector = self._chameleond_proxy.GetConnectorType(port).lower()
129d7a45223ad35e98496bf3d0f8eeefa7a1eb2d731Tom Wai-Hong Tam                connectors.append(connector)
1303d75ebce0a965218db301852e3feb309b3d5b333Tom Wai-Hong Tam        # Eliminate duplicated ports. It simplifies the labels of dual-port
1313d75ebce0a965218db301852e3feb309b3d5b333Tom Wai-Hong Tam        # devices, i.e. dp_dp categorized into dp.
1323d75ebce0a965218db301852e3feb309b3d5b333Tom Wai-Hong Tam        return '_'.join(sorted(set(connectors)))
1333d75ebce0a965218db301852e3feb309b3d5b333Tom Wai-Hong Tam
1343d75ebce0a965218db301852e3feb309b3d5b333Tom Wai-Hong Tam
135eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tamclass ChameleonPort(object):
1368578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    """ChameleonPort is an abstraction of a general port of a Chameleon board.
1378578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
1388578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    It only contains some common methods shared with audio and video ports.
139eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
14019c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam    A Chameleond RPC proxy and an port_id are passed to the construction.
14119c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam    The port_id is the unique identity to the port.
142eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    """
143eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
14419c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam    def __init__(self, chameleond_proxy, port_id):
145eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """Construct a ChameleonPort.
146eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
147eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        @param chameleond_proxy: Chameleond RPC proxy object.
14819c95d740e9b6194d94e30c4bfce9ce449b34da5Tom Wai-Hong Tam        @param port_id: The ID of the input port.
149eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
1508578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.chameleond_proxy = chameleond_proxy
1518578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.port_id = port_id
152eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
153eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
154eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    def get_connector_id(self):
155eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """Returns the connector ID.
156eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
157eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        @return: A number of connector ID.
158eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
1598578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        return self.port_id
160eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
161eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
162eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    def get_connector_type(self):
163eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """Returns the human readable string for the connector type.
164eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
165eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        @return: A string, like "VGA", "DVI", "HDMI", or "DP".
166eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
1678578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        return self.chameleond_proxy.GetConnectorType(self.port_id)
168eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
169eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
1706bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam    def has_audio_support(self):
1716bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam        """Returns if the input has audio support.
1726bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam
1736bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam        @return: True if the input has audio support; otherwise, False.
1746bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam        """
1758578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        return self.chameleond_proxy.HasAudioSupport(self.port_id)
1766bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam
1776bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam
1786bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam    def has_video_support(self):
1796bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam        """Returns if the input has video support.
1806bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam
1816bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam        @return: True if the input has video support; otherwise, False.
1826bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam        """
1838578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        return self.chameleond_proxy.HasVideoSupport(self.port_id)
1848578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
1858578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
1868578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    def plug(self):
1878578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        """Asserts HPD line to high, emulating plug."""
18872e354c97eb4890f4ce770ea27caa62cf620b4c1Tom Wai-Hong Tam        logging.info('Plug Chameleon port %d', self.port_id)
1898578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.chameleond_proxy.Plug(self.port_id)
1908578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
1918578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
1928578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    def unplug(self):
1938578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        """Deasserts HPD line to low, emulating unplug."""
19472e354c97eb4890f4ce770ea27caa62cf620b4c1Tom Wai-Hong Tam        logging.info('Unplug Chameleon port %d', self.port_id)
1958578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.chameleond_proxy.Unplug(self.port_id)
1968578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
1978578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
19872e354c97eb4890f4ce770ea27caa62cf620b4c1Tom Wai-Hong Tam    def set_plug(self, plug_status):
19972e354c97eb4890f4ce770ea27caa62cf620b4c1Tom Wai-Hong Tam        """Sets plug/unplug by plug_status.
20072e354c97eb4890f4ce770ea27caa62cf620b4c1Tom Wai-Hong Tam
20172e354c97eb4890f4ce770ea27caa62cf620b4c1Tom Wai-Hong Tam        @param plug_status: True to plug; False to unplug.
20272e354c97eb4890f4ce770ea27caa62cf620b4c1Tom Wai-Hong Tam        """
20372e354c97eb4890f4ce770ea27caa62cf620b4c1Tom Wai-Hong Tam        if plug_status:
20472e354c97eb4890f4ce770ea27caa62cf620b4c1Tom Wai-Hong Tam            self.plug()
20572e354c97eb4890f4ce770ea27caa62cf620b4c1Tom Wai-Hong Tam        else:
20672e354c97eb4890f4ce770ea27caa62cf620b4c1Tom Wai-Hong Tam            self.unplug()
20772e354c97eb4890f4ce770ea27caa62cf620b4c1Tom Wai-Hong Tam
20872e354c97eb4890f4ce770ea27caa62cf620b4c1Tom Wai-Hong Tam
2098578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    @property
2108578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    def plugged(self):
2118578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        """
2128578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        @returns True if this port is plugged to Chameleon, False otherwise.
2138578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
2148578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        """
2158578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        return self.chameleond_proxy.IsPlugged(self.port_id)
2168578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
2178578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
2188578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tamclass ChameleonVideoInput(ChameleonPort):
2198578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    """ChameleonVideoInput is an abstraction of a video input port.
2208578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
2218578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    It contains some special methods to control a video input.
2228578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    """
2238578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
224e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam    _DURATION_UNPLUG_FOR_EDID = 5
225e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam    _TIMEOUT_VIDEO_STABLE_PROBE = 10
2265b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam    _EDID_ID_DISABLE = -1
227e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
2288578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    def __init__(self, chameleon_port):
2298578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        """Construct a ChameleonVideoInput.
2308578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
2318578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        @param chameleon_port: A general ChameleonPort object.
2328578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        """
2338578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.chameleond_proxy = chameleon_port.chameleond_proxy
2348578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.port_id = chameleon_port.port_id
2356bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam
2366bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam
237e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam    def wait_video_input_stable(self, timeout=None):
238e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam        """Waits the video input stable or timeout.
239e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam
240e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam        @param timeout: The time period to wait for.
241e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam
242e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam        @return: True if the video input becomes stable within the timeout
243e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam                 period; otherwise, False.
244e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam        """
2458578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        return self.chameleond_proxy.WaitVideoInputStable(self.port_id,
2468578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam                                                          timeout)
247e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam
248e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam
249eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    def read_edid(self):
250eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """Reads the EDID.
251eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
2525b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam        @return: An Edid object or NO_EDID.
253eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
2545b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam        edid_binary = self.chameleond_proxy.ReadEdid(self.port_id)
2555b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam        if edid_binary is None:
2565b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam            return edid_lib.NO_EDID
2573737b1d3e9ce9e12341585d5431d947373dfc424Tom Wai-Hong Tam        # Read EDID without verify. It may be made corrupted as intended
2583737b1d3e9ce9e12341585d5431d947373dfc424Tom Wai-Hong Tam        # for the test purpose.
2595b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam        return edid_lib.Edid(edid_binary.data, skip_verify=True)
260eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
261eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
2627a4ba1cad16c47849d8dfabcfaf5aa9d64960977Tom Wai-Hong Tam    def apply_edid(self, edid):
263eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """Applies the given EDID.
264eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
2655b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam        @param edid: An Edid object or NO_EDID.
266eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
2675b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam        if edid is edid_lib.NO_EDID:
2685b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam          self.chameleond_proxy.ApplyEdid(self.port_id, self._EDID_ID_DISABLE)
2695b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam        else:
2705b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam          edid_binary = xmlrpclib.Binary(edid.data)
2715b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam          edid_id = self.chameleond_proxy.CreateEdid(edid_binary)
2725b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam          self.chameleond_proxy.ApplyEdid(self.port_id, edid_id)
2735b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam          self.chameleond_proxy.DestroyEdid(edid_id)
274c95277635c90ee616898d1f547440eff2dafc9cbMussa
275c95277635c90ee616898d1f547440eff2dafc9cbMussa
276e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam    @contextmanager
277e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam    def use_edid(self, edid):
278e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        """Uses the given EDID in a with statement.
279e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
280e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        It sets the EDID up in the beginning and restores to the original
281e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        EDID in the end. This function is expected to be used in a with
282e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        statement, like the following:
283e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
284e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam            with chameleon_port.use_edid(edid):
285e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam                do_some_test_on(chameleon_port)
286e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
287e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        @param edid: An EDID object.
288e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        """
289e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        # Set the EDID up in the beginning.
290e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        plugged = self.plugged
291e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        if plugged:
292e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam            self.unplug()
293e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
294e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        original_edid = self.read_edid()
295e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        logging.info('Apply EDID on port %d', self.port_id)
296e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        self.apply_edid(edid)
297e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
298e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        if plugged:
299e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam            time.sleep(self._DURATION_UNPLUG_FOR_EDID)
300e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam            self.plug()
301e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam            self.wait_video_input_stable(self._TIMEOUT_VIDEO_STABLE_PROBE)
302e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
3032876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam        try:
3042876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam            # Yeild to execute the with statement.
3052876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam            yield
3062876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam        finally:
3072876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam            # Restore the original EDID in the end.
3082876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam            current_edid = self.read_edid()
3092876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam            if original_edid.data != current_edid.data:
3102876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam                logging.info('Restore the original EDID.')
3112876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam                self.apply_edid(original_edid)
312e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
313e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
314e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam    def use_edid_file(self, filename):
315e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        """Uses the given EDID file in a with statement.
316e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
317e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        It sets the EDID up in the beginning and restores to the original
318e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        EDID in the end. This function is expected to be used in a with
319e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        statement, like the following:
320e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
321e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam            with chameleon_port.use_edid_file(filename):
322e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam                do_some_test_on(chameleon_port)
323e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
324e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        @param filename: A path to the EDID file.
325e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        """
3265b43d6ab4e30473d0935e7ffc3a59767cdfbd34eTom Wai-Hong Tam        return self.use_edid(edid_lib.Edid.from_file(filename))
327e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
328e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
329eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    def fire_hpd_pulse(self, deassert_interval_usec, assert_interval_usec=None,
330e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng                       repeat_count=1, end_level=1):
331eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
332e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng        """Fires one or more HPD pulse (low -> high -> low -> ...).
333e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng
334e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng        @param deassert_interval_usec: The time in microsecond of the
335e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng                deassert pulse.
336e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng        @param assert_interval_usec: The time in microsecond of the
337e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng                assert pulse. If None, then use the same value as
338e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng                deassert_interval_usec.
339e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng        @param repeat_count: The count of HPD pulses to fire.
340e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng        @param end_level: HPD ends with 0 for LOW (unplugged) or 1 for
341e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng                HIGH (plugged).
342eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
3438578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.chameleond_proxy.FireHpdPulse(
3448578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam                self.port_id, deassert_interval_usec,
345e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng                assert_interval_usec, repeat_count, int(bool(end_level)))
346eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
347eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
348dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan    def fire_mixed_hpd_pulses(self, widths):
349dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        """Fires one or more HPD pulses, starting at low, of mixed widths.
350dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan
351dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        One must specify a list of segment widths in the widths argument where
352dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        widths[0] is the width of the first low segment, widths[1] is that of
353dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        the first high segment, widths[2] is that of the second low segment...
354dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        etc. The HPD line stops at low if even number of segment widths are
355dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        specified; otherwise, it stops at high.
356dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan
357dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        @param widths: list of pulse segment widths in usec.
358dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        """
3598578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.chameleond_proxy.FireMixedHpdPulses(self.port_id, widths)
360dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan
361dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan
3624c8022f036732d1e12931a8f6743cfce92ab2fbaTom Wai-Hong Tam    def capture_screen(self):
363eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """Captures Chameleon framebuffer.
364eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
3654c8022f036732d1e12931a8f6743cfce92ab2fbaTom Wai-Hong Tam        @return An Image object.
366eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
367200a00c77422f92a28811c8174a364e1a716e9afTom Wai-Hong Tam        return Image.fromstring(
368200a00c77422f92a28811c8174a364e1a716e9afTom Wai-Hong Tam                'RGB',
3694c8022f036732d1e12931a8f6743cfce92ab2fbaTom Wai-Hong Tam                self.get_resolution(),
3708578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam                self.chameleond_proxy.DumpPixels(self.port_id).data)
371c95277635c90ee616898d1f547440eff2dafc9cbMussa
372eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
373eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    def get_resolution(self):
374eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """Gets the source resolution.
375eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
376eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        @return: A (width, height) tuple.
377eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
37884d759bd4be143e04f69a1def09ad5f36dadb12bTom Wai-Hong Tam        # The return value of RPC is converted to a list. Convert it back to
37984d759bd4be143e04f69a1def09ad5f36dadb12bTom Wai-Hong Tam        # a tuple.
3808578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        return tuple(self.chameleond_proxy.DetectResolution(self.port_id))
3818578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
3828578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
3834e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam    def set_content_protection(self, enable):
3844e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam        """Sets the content protection state on the port.
3854e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam
3864e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam        @param enable: True to enable; False to disable.
3874e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam        """
3884e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam        self.chameleond_proxy.SetContentProtection(self.port_id, enable)
3894e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam
3904e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam
3914e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam    def is_content_protection_enabled(self):
3924e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam        """Returns True if the content protection is enabled on the port.
3934e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam
3944e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam        @return: True if the content protection is enabled; otherwise, False.
3954e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam        """
3964e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam        return self.chameleond_proxy.IsContentProtectionEnabled(self.port_id)
3974e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam
3984e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam
3994e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam    def is_video_input_encrypted(self):
4004e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam        """Returns True if the video input on the port is encrypted.
4014e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam
4024e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam        @return: True if the video input is encrypted; otherwise, False.
4034e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam        """
4044e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam        return self.chameleond_proxy.IsVideoInputEncrypted(self.port_id)
4054e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam
4064e241012e91ba74f1e85d5e6a630290e18a15aa9Tom Wai-Hong Tam
4078578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tamclass ChameleonAudioInput(ChameleonPort):
4088578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    """ChameleonAudioInput is an abstraction of an audio input port.
4098578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
4108578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    It contains some special methods to control an audio input.
4118578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    """
4128578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
4138578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    def __init__(self, chameleon_port):
4148578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        """Construct a ChameleonAudioInput.
4158578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
4168578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        @param chameleon_port: A general ChameleonPort object.
4178578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        """
4188578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.chameleond_proxy = chameleon_port.chameleond_proxy
4198578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.port_id = chameleon_port.port_id
420c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
421c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
422e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang    def start_capturing_audio(self):
423e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang        """Starts capturing audio."""
4248578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        return self.chameleond_proxy.StartCapturingAudio(self.port_id)
425e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang
426e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang
427e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang    def stop_capturing_audio(self):
428e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang        """Stops capturing audio.
429e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang
430e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang        Returns:
431e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang          A tuple (data, format).
432e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang          data: The captured binary data.
433e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang          format: A dict containing:
434e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang            file_type: 'raw' or 'wav'.
435e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang            sample_format: 'S32_LE' for 32-bit signed integer in little-endian.
436e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang              Refer to aplay manpage for other formats.
437e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang            channel: channel number.
438e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang            rate: sampling rate.
439e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang        """
4408578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        rpc_data, data_format = self.chameleond_proxy.StopCapturingAudio(
4418578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam                self.port_id)
442e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang        return rpc_data.data, data_format
443e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang
444e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang
445d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiangclass ChameleonAudioOutput(ChameleonPort):
446d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang    """ChameleonAudioOutput is an abstraction of an audio output port.
447d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang
448d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang    It contains some special methods to control an audio output.
449d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang    """
450d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang
451d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang    def __init__(self, chameleon_port):
452d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang        """Construct a ChameleonAudioOutput.
453d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang
454d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang        @param chameleon_port: A general ChameleonPort object.
455d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang        """
456d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang        self.chameleond_proxy = chameleon_port.chameleond_proxy
457d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang        self.port_id = chameleon_port.port_id
458d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang
459d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang
460d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang    def start_playing_audio(self, data, data_format):
461d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang        """Starts playing audio.
462d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang
463d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang        @param data: The audio data to play.
464d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang        @param data_format: A dict containing data format. Currently Chameleon
465d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang                            only accepts data format:
466d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang                            dict(file_type='raw', sample_format='S32_LE',
467d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang                                 channel=8, rate=48000).
468d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang
469d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang        """
470d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang        return self.chameleond_proxy.StartPlayingAudio(
471d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang                self.port_id, xmlrpclib.Binary(data), data_format)
472d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang
473d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang
474d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang    def stop_playing_audio(self):
475d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang        """Stops capturing audio."""
476d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang        self.chameleond_proxy.StopPlayingAudio(self.port_id)
477d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang
478d3fad2c8a0ba1508f5fc3efb90592687ec219d5cCheng-Yi Chiang
479c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tamdef make_chameleon_hostname(dut_hostname):
480c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    """Given a DUT's hostname, returns the hostname of its Chameleon.
481c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
482c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    @param dut_hostname: Hostname of a DUT.
483c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
484c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    @return Hostname of the DUT's Chameleon.
485c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    """
486c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    host_parts = dut_hostname.split('.')
487c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    host_parts[0] = host_parts[0] + '-chameleon'
488c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    return '.'.join(host_parts)
489c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
490c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
491c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tamdef create_chameleon_board(dut_hostname, args):
492c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    """Given either DUT's hostname or argments, creates a ChameleonBoard object.
493c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
494c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    If the DUT's hostname is in the lab zone, it connects to the Chameleon by
495c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    append the hostname with '-chameleon' suffix. If not, checks if the args
496c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    contains the key-value pair 'chameleon_host=IP'.
497c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
498c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    @param dut_hostname: Hostname of a DUT.
499c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    @param args: A string of arguments passed from the command line.
500c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
501c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    @return A ChameleonBoard object.
502c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
503c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    @raise ChameleonConnectionError if unknown hostname.
504c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    """
505c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    connection = None
506c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    hostname = make_chameleon_hostname(dut_hostname)
507c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    if utils.host_is_in_lab_zone(hostname):
508c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        connection = ChameleonConnection(hostname)
509c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    else:
510c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        args_dict = utils.args_to_dict(args)
511c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        hostname = args_dict.get('chameleon_host', None)
512c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        port = args_dict.get('chameleon_port', CHAMELEON_PORT)
513c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        if hostname:
514c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam            connection = ChameleonConnection(hostname, port)
515c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        else:
516c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam            raise ChameleonConnectionError('No chameleon_host is given in args')
517c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
518c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    return ChameleonBoard(connection)
519