• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5import logging
6import time
7
8from autotest_lib.client.common_lib import error
9from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
10from autotest_lib.server.cros.servo import pd_console
11
12
13class 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