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