Home | History | Annotate | Download | only in firmware_PDConnect
      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