blob: e62814a9f6c8bcc09a3473f21ce5fb678fe0c66a [file] [log] [blame]
Scottfe06ed82015-11-05 17:15:01 -08001# 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 time
6
7from autotest_lib.client.common_lib import error
8
9class PDConsoleUtils(object):
10 """ Provides a set of methods common to USB PD FAFT tests
11
12 Each instance of this class is associated with a particular
13 servo UART console. USB PD tests will typically use the console
14 command 'pd' and its subcommands to control/monitor Type C PD
15 connections. The servo object used for UART operations is
16 passed in and stored when this object is created.
17
18 """
19
20 SRC_CONNECT = 'SRC_READY'
21 SNK_CONNECT = 'SNK_READY'
22 SRC_DISC = 'SRC_DISCONNECTED'
23 SNK_DISC = 'SNK_DISCONNECTED'
24
25 # dualrole input/ouput values
26 DUALROLE_QUERY_DELAY = 0.25
27 dual_index = {'on': 0, 'off': 1, 'snk': 2, 'src': 3}
28 dualrole_cmd = ['on', 'off', 'sink', 'source']
29 dualrole_resp = ['on', 'off', 'force sink', 'force source']
30
31 def __init__(self, console):
32 """ Console can be either usbpd, ec, or plankton_ec UART
33 This object with then be used by the class which creates
34 the PDConsoleUtils class to send/receive commands to UART
35 """
36 # save console for UART access functions
37 self.console = console
38
39 def send_pd_command(self, cmd):
40 """Send command to PD console UART
41
42 @param cmd: pd command string
43 """
44 self.console.send_command(cmd)
45
46 def verify_pd_console(self):
47 """Verify that PD commands exist on UART console
48
49 Send 'help' command to UART console
50 @returns: True if 'pd' is found, False if not
51 """
52
53 l = self.console.send_command_get_output('help', ['(pd)\s+([\w]+)'])
54 if l[0][1] == 'pd':
55 return True
56 else:
57 return False
58
59 def execute_pd_state_cmd(self, port):
60 """Get PD state for specified channel
61
62 pd 0/1 state command gives produces 5 fields. An example
63 is shown here:
64 Port C1 CC2, Ena - Role: SRC-DFP-VC State: SRC_READY, Flags: 0x1954
65
66 A dict is created containing port, polarity, role, pd_state, and flags
67
68 @param port: Type C PD port 0 or 1
69
70 @returns: A dict with the 5 fields listed above
71 """
72 cmd = 'pd'
73 subcmd = 'state'
74 pd_cmd = cmd +" " + str(port) + " " + subcmd
75 pd_state_list = self.console.send_command_get_output(pd_cmd,
76 ['Port\s+([\w]+)\s+([\w]+)',
77 'Role:\s+([\w]+-[\w]+)',
78 'State:\s+([\w]+_[\w]+)',
79 'Flags:\s+([\w]+)'])
80
81 # Fill the dict fields from the list
82 state_result = {}
83 state_result['port'] = pd_state_list[0][1]
84 state_result['polarity'] = pd_state_list[0][2]
85 state_result['role'] = pd_state_list[1][1]
86 state_result['pd_state'] = pd_state_list[2][1]
87 state_result['flags'] = pd_state_list[3][1]
88
89 return state_result
90
91 def get_pd_state(self, port):
92 """Get the current PD state
93
94 @param port: Type C PD port 0/1
95 @returns: current pd state
96 """
97
98 pd_dict = self.execute_pd_state_cmd(port)
99 return pd_dict['pd_state']
100
101 def get_pd_port(self, port):
102 """Get the current PD port
103
104 @param port: Type C PD port 0/1
105 @returns: current pd state
106 """
107 pd_dict = self.execute_pd_state_cmd(port)
108 return pd_dict['port']
109
110 def get_pd_role(self, port):
111 """Get the current PD power role (source or sink)
112
113 @param port: Type C PD port 0/1
114 @returns: current pd state
115 """
116 pd_dict = self.execute_pd_state_cmd(port)
117 return pd_dict['role']
118
119 def get_pd_flags(self, port):
120 """Get the current PD flags
121
122 @param port: Type C PD port 0/1
123 @returns: current pd state
124 """
125 pd_dict = self.execute_pd_state_cmd(port)
126 return pd_dict['flags']
127
128 def get_pd_dualrole(self):
129 """Get the current PD dualrole setting
130
131 @returns: current PD dualrole setting
132 """
133 cmd = 'pd dualrole'
134 dual_list = self.console.send_command_get_output(cmd,
135 ['dual-role toggling:\s+([\w ]+)'])
136 return dual_list[0][1]
137
138 def set_pd_dualrole(self, value):
139 """Set pd dualrole
140
141 It can be set to either:
142 1. on
143 2. off
144 3. snk (force sink mode)
145 4. src (force source mode)
146 After setting, the current value is read to confirm that it
147 was set properly.
148
149 @param value: One of the 4 options listed
150 """
151 # Get string required for console command
152 dual_index = self.dual_index[value]
153 # Create console command
154 cmd = 'pd dualrole ' + self.dualrole_cmd[dual_index]
155 self.console.send_command(cmd)
156 time.sleep(self.DUALROLE_QUERY_DELAY)
157 # Get current setting to verify that command was successful
158 dual = self.get_pd_dualrole()
159 # If it doesn't match, then raise error
160 if dual != self.dualrole_resp[dual_index]:
161 raise error.TestFail("dualrole error: " +
162 self.dualrole_resp[dual_index] + " != "+dual)
163
164 def query_pd_connection(self):
165 """Determine if PD connection is present
166
167 Try the 'pd 0/1 state' command and see if it's in either
168 expected state of a conneciton. Record the port number
169 that has an active connection
170
171 @returns: dict with params port, connect, and state
172 """
173 status = {}
174 port = 0;
175 status['connect'] = False
176 status['port'] = port
177 state = self.get_pd_state(port)
178 # Check port 0 first
179 if state == self.SRC_CONNECT or state == self.SNK_CONNECT:
180 status['connect'] = True
181 status['role'] = state
182 else:
183 port = 1
184 status['port'] = port
185 state = self.get_pd_state(port)
186 # Check port 1
187 if state == self.SRC_CONNECT or state == self.SNK_CONNECT:
188 status['connect'] = True
189 status['role'] = state
190
191 return status
192
193