1fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott# Copyright 2015 The Chromium OS Authors. All rights reserved.
2fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott# Use of this source code is governed by a BSD-style license that can be
3fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott# found in the LICENSE file.
4fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
5fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scottimport logging
6fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scottimport time
7fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
8fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scottfrom autotest_lib.client.common_lib import error
9fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scottfrom autotest_lib.server.cros.faft.firmware_test import FirmwareTest
10fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scottfrom autotest_lib.server.cros.servo import pd_console
11fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
12fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
13fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scottclass firmware_PDConnect(FirmwareTest):
14fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott    """
15fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott    Servo based USB PD connect/disconnect test. This test is written
16fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott    for the DUT and requires that the DUT support dualrole (SRC or SNK)
17fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott    operation in order to force a disconnect and connect event. The test
18fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott    does not depend on the DUT acting as source or sink, either mode
19fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott    should pass.
20fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
21fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott    Pass critera is 100%  of connections resulting in successful connections
22fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
23fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott    """
24fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott    version = 1
25fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
26fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
27fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott    def initialize(self, host, cmdline_args):
28fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        super(firmware_PDConnect, self).initialize(host, cmdline_args)
29fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        # Only run in normal mode
30fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        self.switcher.setup_mode('normal')
31fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        self.usbpd.send_command("chan 0")
32fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
33fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
34fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott    def cleanup(self):
35fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        self.usbpd.send_command("chan 0xffffffff")
36fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        super(firmware_PDConnect, self).cleanup()
37fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
38fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
39fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott    def _test_pd_connection(self, connect_state, port):
40fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        """Verify current pd state matches the expected value.
41fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
42fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        The current state will be read up to 2 times. This
43fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        may not be required, but during development testing
44fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        instances were observed where state reads on glados
45fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        did not give the full state string which would then
46fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        applear to be a failure even though the type C connection
47fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        had been made.
48fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
49fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        @params connect_state: Expected state string
50fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        @params port: port number <0/1> to query
51fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        @returns: True if state matches, false otherwise
52fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        """
53fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        for attempts in range(1,3):
54fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            pd_state = self.pd.get_pd_state(self.port)
55fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            if pd_state == connect_state:
56fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott                return True
57fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        return False
58fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
59fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
60fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott    def run_once(self):
61fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        """Exectue disconnect/connect sequence test
62fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
63fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        """
64fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        # delay between test iterations
65fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        DUALROLE_SET_DELAY = 2
66fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
67fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        # create objects for pd utilities
68fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        self.pd = pd_console.PDConsoleUtils(self.usbpd)
69fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
70fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        # Make sure PD support exists in the UART console
71fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        if self.pd.verify_pd_console() == False:
72fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            raise error.TestFail("pd command not present on console!")
73fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
74fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        # Enable dualrole mode
75fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        self.pd.set_pd_dualrole('on')
76fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        time.sleep(DUALROLE_SET_DELAY)
77fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
78fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        # Type C connection (PD contract) should exist at this point
79fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        connect_status = self.pd.query_pd_connection()
80fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        if connect_status['connect'] == False:
81fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            raise error.TestFail("pd connection not found")
82fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        # Record port where type C connection was detected
83fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        self.port = connect_status['port']
84fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        # Save the SRC vs SNK state
85fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        connect_state = connect_status['role']
86fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
87fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        logging.info('Type C connection detected on Port %d: %r',
88fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott                     self.port, connect_state)
89fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
90fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        # determine the dualrole command to connect/disconnect
91fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        if  connect_state == 'SRC_READY':
92fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            disc_cmd = 'snk'
93fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            connect_cmd = 'src'
94fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        else:
95fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            disc_cmd = 'src'
96fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            connect_cmd = 'snk'
97fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
98fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        # counter used for successful iterations
99fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        success = 0
100fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        total_attempts = 100
101fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
102fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        # Attempt connect/disconnect iterations
103fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        for test_count in range(1, total_attempts + 1):
104fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            logging.info ('\n************ Iteration %r ***************',
105fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott                          test_count)
106fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            # Force Type C disconnect
107fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            self.pd.set_pd_dualrole(disc_cmd)
108fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            time.sleep(DUALROLE_SET_DELAY)
109fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            # Attempt to reconnect
110fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            self.pd.set_pd_dualrole(connect_cmd)
111fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            time.sleep(DUALROLE_SET_DELAY)
112fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            # Verify connection was successful
113fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            if self._test_pd_connection(connect_state, self.port) == True:
114fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott                success += 1
115fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
116fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        self.pd.set_pd_dualrole('on')
117fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        logging.info ('************ Connection Stats ***************')
118fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        logging.info ('Attempts = %d: Connections = %d', test_count, success)
119fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        logging.info ('*********************************************')
120fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott        if success != total_attempts:
121fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott            raise error.TestFail("Attempts = " + str(total_attempts) +
122fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott                                 ': Success = ' + str(success))
123fe06ed8afdd7323a1f3ee60c746b5c0335c659c0Scott
124