| # Copyright 2015 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import logging |
| import time |
| |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.server.cros.faft.firmware_test import FirmwareTest |
| from autotest_lib.server.cros.servo import pd_console |
| |
| |
| class firmware_PDConnect(FirmwareTest): |
| """ |
| Servo based USB PD connect/disconnect test. This test is written |
| for the DUT and requires that the DUT support dualrole (SRC or SNK) |
| operation in order to force a disconnect and connect event. The test |
| does not depend on the DUT acting as source or sink, either mode |
| should pass. |
| |
| Pass critera is 100% of connections resulting in successful connections |
| |
| """ |
| version = 1 |
| |
| |
| def initialize(self, host, cmdline_args): |
| super(firmware_PDConnect, self).initialize(host, cmdline_args) |
| # Only run in normal mode |
| self.switcher.setup_mode('normal') |
| self.usbpd.send_command("chan 0") |
| |
| |
| def cleanup(self): |
| self.usbpd.send_command("chan 0xffffffff") |
| super(firmware_PDConnect, self).cleanup() |
| |
| |
| def _test_pd_connection(self, connect_state, port): |
| """Verify current pd state matches the expected value. |
| |
| The current state will be read up to 2 times. This |
| may not be required, but during development testing |
| instances were observed where state reads on glados |
| did not give the full state string which would then |
| applear to be a failure even though the type C connection |
| had been made. |
| |
| @params connect_state: Expected state string |
| @params port: port number <0/1> to query |
| @returns: True if state matches, false otherwise |
| """ |
| for attempts in range(1,3): |
| pd_state = self.pd.get_pd_state(self.port) |
| if pd_state == connect_state: |
| return True |
| return False |
| |
| |
| def run_once(self): |
| """Exectue disconnect/connect sequence test |
| |
| """ |
| # delay between test iterations |
| DUALROLE_SET_DELAY = 2 |
| |
| # create objects for pd utilities |
| self.pd = pd_console.PDConsoleUtils(self.usbpd) |
| |
| # Make sure PD support exists in the UART console |
| if self.pd.verify_pd_console() == False: |
| raise error.TestFail("pd command not present on console!") |
| |
| # Enable dualrole mode |
| self.pd.set_pd_dualrole('on') |
| time.sleep(DUALROLE_SET_DELAY) |
| |
| # Type C connection (PD contract) should exist at this point |
| connect_status = self.pd.query_pd_connection() |
| if connect_status['connect'] == False: |
| raise error.TestFail("pd connection not found") |
| # Record port where type C connection was detected |
| self.port = connect_status['port'] |
| # Save the SRC vs SNK state |
| connect_state = connect_status['role'] |
| |
| logging.info('Type C connection detected on Port %d: %r', |
| self.port, connect_state) |
| |
| # determine the dualrole command to connect/disconnect |
| if connect_state == 'SRC_READY': |
| disc_cmd = 'snk' |
| connect_cmd = 'src' |
| else: |
| disc_cmd = 'src' |
| connect_cmd = 'snk' |
| |
| # counter used for successful iterations |
| success = 0 |
| total_attempts = 100 |
| |
| # Attempt connect/disconnect iterations |
| for test_count in range(1, total_attempts + 1): |
| logging.info ('\n************ Iteration %r ***************', |
| test_count) |
| # Force Type C disconnect |
| self.pd.set_pd_dualrole(disc_cmd) |
| time.sleep(DUALROLE_SET_DELAY) |
| # Attempt to reconnect |
| self.pd.set_pd_dualrole(connect_cmd) |
| time.sleep(DUALROLE_SET_DELAY) |
| # Verify connection was successful |
| if self._test_pd_connection(connect_state, self.port) == True: |
| success += 1 |
| |
| self.pd.set_pd_dualrole('on') |
| logging.info ('************ Connection Stats ***************') |
| logging.info ('Attempts = %d: Connections = %d', test_count, success) |
| logging.info ('*********************************************') |
| if success != total_attempts: |
| raise error.TestFail("Attempts = " + str(total_attempts) + |
| ': Success = ' + str(success)) |
| |