blob: b82cc0cfae9b48251733d3ccf4d4cd3f06055138 [file] [log] [blame]
# 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))