chameleon.py revision 2876774869edc2ca66476e471c409773ee0ab06d
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
162588ce1c77ed94ffd9cf53540bb5c2cc351558c7Tom Wai-Hong Tamfrom autotest_lib.client.cros.chameleon import edid
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
226e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
2278578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    def __init__(self, chameleon_port):
2288578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        """Construct a ChameleonVideoInput.
2298578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
2308578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        @param chameleon_port: A general ChameleonPort object.
2318578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        """
2328578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.chameleond_proxy = chameleon_port.chameleond_proxy
2338578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.port_id = chameleon_port.port_id
2346bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam
2356bd2f1998baf5e9d53680f52511e2694ccc5d6d6Tom Wai-Hong Tam
236e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam    def wait_video_input_stable(self, timeout=None):
237e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam        """Waits the video input stable or timeout.
238e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam
239e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam        @param timeout: The time period to wait for.
240e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam
241e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam        @return: True if the video input becomes stable within the timeout
242e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam                 period; otherwise, False.
243e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam        """
2448578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        return self.chameleond_proxy.WaitVideoInputStable(self.port_id,
2458578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam                                                          timeout)
246e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam
247e090aa536604063fcaa59955f74eefb07c80ca3aTom Wai-Hong Tam
248eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    def read_edid(self):
249eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """Reads the EDID.
250eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
2517a4ba1cad16c47849d8dfabcfaf5aa9d64960977Tom Wai-Hong Tam        @return: An Edid object.
252eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
2533737b1d3e9ce9e12341585d5431d947373dfc424Tom Wai-Hong Tam        # Read EDID without verify. It may be made corrupted as intended
2543737b1d3e9ce9e12341585d5431d947373dfc424Tom Wai-Hong Tam        # for the test purpose.
2558578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        return edid.Edid(self.chameleond_proxy.ReadEdid(self.port_id).data,
2563737b1d3e9ce9e12341585d5431d947373dfc424Tom Wai-Hong Tam                         skip_verify=True)
257eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
258eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
2597a4ba1cad16c47849d8dfabcfaf5aa9d64960977Tom Wai-Hong Tam    def apply_edid(self, edid):
260eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """Applies the given EDID.
261eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
2627a4ba1cad16c47849d8dfabcfaf5aa9d64960977Tom Wai-Hong Tam        @param edid: An Edid object.
263eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
2648578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        edid_id = self.chameleond_proxy.CreateEdid(xmlrpclib.Binary(edid.data))
2658578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.chameleond_proxy.ApplyEdid(self.port_id, edid_id)
2668578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.chameleond_proxy.DestroyEdid(edid_id)
267c95277635c90ee616898d1f547440eff2dafc9cbMussa
268c95277635c90ee616898d1f547440eff2dafc9cbMussa
269e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam    @contextmanager
270e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam    def use_edid(self, edid):
271e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        """Uses the given EDID in a with statement.
272e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
273e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        It sets the EDID up in the beginning and restores to the original
274e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        EDID in the end. This function is expected to be used in a with
275e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        statement, like the following:
276e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
277e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam            with chameleon_port.use_edid(edid):
278e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam                do_some_test_on(chameleon_port)
279e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
280e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        @param edid: An EDID object.
281e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        """
282e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        # Set the EDID up in the beginning.
283e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        plugged = self.plugged
284e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        if plugged:
285e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam            self.unplug()
286e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
287e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        original_edid = self.read_edid()
288e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        logging.info('Apply EDID on port %d', self.port_id)
289e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        self.apply_edid(edid)
290e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
291e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        if plugged:
292e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam            time.sleep(self._DURATION_UNPLUG_FOR_EDID)
293e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam            self.plug()
294e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam            self.wait_video_input_stable(self._TIMEOUT_VIDEO_STABLE_PROBE)
295e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
2962876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam        try:
2972876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam            # Yeild to execute the with statement.
2982876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam            yield
2992876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam        finally:
3002876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam            # Restore the original EDID in the end.
3012876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam            current_edid = self.read_edid()
3022876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam            if original_edid.data != current_edid.data:
3032876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam                logging.info('Restore the original EDID.')
3042876774869edc2ca66476e471c409773ee0ab06dTom Wai-Hong Tam                self.apply_edid(original_edid)
305e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
306e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
307e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam    def use_edid_file(self, filename):
308e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        """Uses the given EDID file in a with statement.
309e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
310e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        It sets the EDID up in the beginning and restores to the original
311e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        EDID in the end. This function is expected to be used in a with
312e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        statement, like the following:
313e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
314e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam            with chameleon_port.use_edid_file(filename):
315e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam                do_some_test_on(chameleon_port)
316e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
317e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        @param filename: A path to the EDID file.
318e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        """
319e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam        return self.use_edid(edid.Edid.from_file(filename))
320e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
321e6e901f00651bdd4796942b66d492b2de3d803f0Tom Wai-Hong Tam
322eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    def fire_hpd_pulse(self, deassert_interval_usec, assert_interval_usec=None,
323e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng                       repeat_count=1, end_level=1):
324eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
325e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng        """Fires one or more HPD pulse (low -> high -> low -> ...).
326e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng
327e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng        @param deassert_interval_usec: The time in microsecond of the
328e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng                deassert pulse.
329e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng        @param assert_interval_usec: The time in microsecond of the
330e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng                assert pulse. If None, then use the same value as
331e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng                deassert_interval_usec.
332e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng        @param repeat_count: The count of HPD pulses to fire.
333e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng        @param end_level: HPD ends with 0 for LOW (unplugged) or 1 for
334e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng                HIGH (plugged).
335eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
3368578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.chameleond_proxy.FireHpdPulse(
3378578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam                self.port_id, deassert_interval_usec,
338e06f80fae6b4a54721bd0953f3383759791259f9Ting-Yuan Cheng                assert_interval_usec, repeat_count, int(bool(end_level)))
339eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
340eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
341dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan    def fire_mixed_hpd_pulses(self, widths):
342dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        """Fires one or more HPD pulses, starting at low, of mixed widths.
343dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan
344dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        One must specify a list of segment widths in the widths argument where
345dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        widths[0] is the width of the first low segment, widths[1] is that of
346dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        the first high segment, widths[2] is that of the second low segment...
347dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        etc. The HPD line stops at low if even number of segment widths are
348dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        specified; otherwise, it stops at high.
349dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan
350dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        @param widths: list of pulse segment widths in usec.
351dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan        """
3528578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.chameleond_proxy.FireMixedHpdPulses(self.port_id, widths)
353dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan
354dab3815cdcea63b68bb18318442fb759fc8cb6ebHung-ying Tyan
3554c8022f036732d1e12931a8f6743cfce92ab2fbaTom Wai-Hong Tam    def capture_screen(self):
356eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """Captures Chameleon framebuffer.
357eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
3584c8022f036732d1e12931a8f6743cfce92ab2fbaTom Wai-Hong Tam        @return An Image object.
359eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
360200a00c77422f92a28811c8174a364e1a716e9afTom Wai-Hong Tam        return Image.fromstring(
361200a00c77422f92a28811c8174a364e1a716e9afTom Wai-Hong Tam                'RGB',
3624c8022f036732d1e12931a8f6743cfce92ab2fbaTom Wai-Hong Tam                self.get_resolution(),
3638578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam                self.chameleond_proxy.DumpPixels(self.port_id).data)
364c95277635c90ee616898d1f547440eff2dafc9cbMussa
365eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
366eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam    def get_resolution(self):
367eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """Gets the source resolution.
368eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam
369eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        @return: A (width, height) tuple.
370eaee34082a63a957e6881ad779b825a774e3d7edTom Wai-Hong Tam        """
37184d759bd4be143e04f69a1def09ad5f36dadb12bTom Wai-Hong Tam        # The return value of RPC is converted to a list. Convert it back to
37284d759bd4be143e04f69a1def09ad5f36dadb12bTom Wai-Hong Tam        # a tuple.
3738578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        return tuple(self.chameleond_proxy.DetectResolution(self.port_id))
3748578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
3758578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
3768578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tamclass ChameleonAudioInput(ChameleonPort):
3778578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    """ChameleonAudioInput is an abstraction of an audio input port.
3788578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
3798578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    It contains some special methods to control an audio input.
3808578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    """
3818578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
3828578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam    def __init__(self, chameleon_port):
3838578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        """Construct a ChameleonAudioInput.
3848578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam
3858578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        @param chameleon_port: A general ChameleonPort object.
3868578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        """
3878578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.chameleond_proxy = chameleon_port.chameleond_proxy
3888578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        self.port_id = chameleon_port.port_id
389c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
390c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
391e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang    def start_capturing_audio(self):
392e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang        """Starts capturing audio."""
3938578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        return self.chameleond_proxy.StartCapturingAudio(self.port_id)
394e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang
395e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang
396e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang    def stop_capturing_audio(self):
397e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang        """Stops capturing audio.
398e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang
399e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang        Returns:
400e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang          A tuple (data, format).
401e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang          data: The captured binary data.
402e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang          format: A dict containing:
403e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang            file_type: 'raw' or 'wav'.
404e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang            sample_format: 'S32_LE' for 32-bit signed integer in little-endian.
405e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang              Refer to aplay manpage for other formats.
406e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang            channel: channel number.
407e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang            rate: sampling rate.
408e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang        """
4098578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam        rpc_data, data_format = self.chameleond_proxy.StopCapturingAudio(
4108578eeb003a7db21e0a4d85f0192fa45faf8ec80Tom Wai-Hong Tam                self.port_id)
411e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang        return rpc_data.data, data_format
412e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang
413e3bbd6188e6354b55bea1cad39004d587dbe7631Cheng-Yi Chiang
414c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tamdef make_chameleon_hostname(dut_hostname):
415c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    """Given a DUT's hostname, returns the hostname of its Chameleon.
416c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
417c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    @param dut_hostname: Hostname of a DUT.
418c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
419c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    @return Hostname of the DUT's Chameleon.
420c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    """
421c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    host_parts = dut_hostname.split('.')
422c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    host_parts[0] = host_parts[0] + '-chameleon'
423c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    return '.'.join(host_parts)
424c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
425c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
426c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tamdef create_chameleon_board(dut_hostname, args):
427c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    """Given either DUT's hostname or argments, creates a ChameleonBoard object.
428c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
429c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    If the DUT's hostname is in the lab zone, it connects to the Chameleon by
430c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    append the hostname with '-chameleon' suffix. If not, checks if the args
431c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    contains the key-value pair 'chameleon_host=IP'.
432c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
433c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    @param dut_hostname: Hostname of a DUT.
434c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    @param args: A string of arguments passed from the command line.
435c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
436c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    @return A ChameleonBoard object.
437c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
438c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    @raise ChameleonConnectionError if unknown hostname.
439c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    """
440c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    connection = None
441c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    hostname = make_chameleon_hostname(dut_hostname)
442c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    if utils.host_is_in_lab_zone(hostname):
443c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        connection = ChameleonConnection(hostname)
444c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    else:
445c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        args_dict = utils.args_to_dict(args)
446c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        hostname = args_dict.get('chameleon_host', None)
447c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        port = args_dict.get('chameleon_port', CHAMELEON_PORT)
448c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        if hostname:
449c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam            connection = ChameleonConnection(hostname, port)
450c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam        else:
451c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam            raise ChameleonConnectionError('No chameleon_host is given in args')
452c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam
453c3fb2f6ce00d4dad5c5f6478a6fb650dfd89f42cTom Wai-Hong Tam    return ChameleonBoard(connection)
454