blob: 917caa5a9a245e5e752b39d8d963db1b9417f56e [file] [log] [blame]
Rong Chang42ea8de2015-03-09 15:19:20 +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
Rong Chang42ea8de2015-03-09 15:19:20 +08005import re
6import time
7import xmlrpclib
8
Johny Lind5c46fa2015-03-26 17:24:40 +08009from autotest_lib.client.bin import utils
Scottfe06ed82015-11-05 17:15:01 -080010from autotest_lib.server.cros.servo import chrome_ec
Johny Lind5c46fa2015-03-26 17:24:40 +080011
Rong Chang42ea8de2015-03-09 15:19:20 +080012
13class PlanktonError(Exception):
14 pass
15
16
17class Plankton(object):
18 """Manages control of a Plankton board via servod XMLRPC.
19
20 Plankton is a testing board developed to aid in USB type C debug and
21 control of various type C host devices. Plankton's features include the
22 simulation of charger, USB 2.0 pass through, USB 3.0 hub, and display port
23 pass through. This class manages setting up and communication with a servo
24 daemon (servod) process. It provides high level functions for setting and
25 reading USB type C role, mux and common controls.
26 """
27
28 DEFAULT_SERVO_HOST = 'localhost'
29 DEFAULT_SERVO_PORT = 9999
30 # USB charging command delays in seconds.
31 USBC_COMMAND_DELAY = 0.5
32 # Plankton USBC commands.
33 USBC_ROLE = 'usbc_role'
Rong Chang4408fec2015-03-10 19:29:08 +080034 USBC_MUX = 'usbc_mux'
Rong Chang42ea8de2015-03-09 15:19:20 +080035 RE_USBC_ROLE_VOLTAGE = re.compile(r'src(\d+)v')
36 USBC_CHARGING_VOLTAGES = {
37 0: 'sink',
38 5: 'src5v',
39 12: 'src12v',
40 20: 'src20v'}
41 VBUS_VOLTAGE_MV = 'vbus_voltage'
42 VBUS_CURRENT_MA = 'vbus_current'
43 VBUS_POWER_MW = 'vbus_power'
Johny Lind5c46fa2015-03-26 17:24:40 +080044 # USBC PD states.
45 USBC_PD_STATES = {
46 'sink': 'SNK_READY',
47 'source': 'SRC_READY'}
48 POLL_STATE_SECS = 2
Rong Chang42ea8de2015-03-09 15:19:20 +080049
50
51 def __init__(self, args_dict=None):
52 """Sets up servo daemon communication.
53
54 @param args_dict: A dictionary contains plankton servod host and port.
55 Example: {'plankton_host': 'localhost',
56 'plankton_port': 9999}
57 """
58 if args_dict is None:
59 args_dict = {}
Scottfe06ed82015-11-05 17:15:01 -080060 plankton_hostname = args_dict.get('plankton_host', self.DEFAULT_SERVO_HOST)
Rong Chang42ea8de2015-03-09 15:19:20 +080061 plankton_port = args_dict.get('plankton_port', self.DEFAULT_SERVO_PORT)
Scottfe06ed82015-11-05 17:15:01 -080062 remote = 'http://%s:%s' % (plankton_hostname, plankton_port)
Rong Chang42ea8de2015-03-09 15:19:20 +080063 self._server = xmlrpclib.ServerProxy(remote)
Johny Lin1f255912015-03-12 12:38:11 +080064 self.init_io_expander()
65
66
67 def init_io_expander(self):
68 """Initializes Plankton IO expander register settings."""
69 if not int(self.get('debug_usb_sel')):
70 raise PlanktonError('debug_usb_sel (SW3) should be ON!! '
71 'Please use CN15 to connect Plankton.')
72 self.set('typec_to_hub_sw', '0')
73 self.set('usb2_mux_sw', '1')
74 self.set('usb_dn_pwren', 'on')
Rong Chang42ea8de2015-03-09 15:19:20 +080075
76
77 def set(self, control_name, value):
Scottfe06ed82015-11-05 17:15:01 -080078 """Sets the value of a control using servod.
79
80 @param control_name: plankton servo control item
81 @param value: value to set plankton servo control item
82 """
Rong Chang42ea8de2015-03-09 15:19:20 +080083 assert control_name
84 self._server.set(control_name, value)
85
86
87 def get(self, control_name):
Scottfe06ed82015-11-05 17:15:01 -080088 """Gets the value of a control from servod.
89
90 @param control_name: plankton servo control item
91 """
Rong Chang42ea8de2015-03-09 15:19:20 +080092 assert control_name
93 return self._server.get(control_name)
94
95
96 @property
97 def vbus_voltage(self):
98 """Gets Plankton VBUS voltage in volts."""
99 return float(self.get(self.VBUS_VOLTAGE_MV)) / 1000.0
100
101
102 @property
103 def vbus_current(self):
104 """Gets Plankton VBUS current in amps."""
105 return float(self.get(self.VBUS_CURRENT_MA)) / 1000.0
106
107
108 @property
109 def vbus_power(self):
110 """Gets Plankton charging power in watts."""
111 return float(self.get(self.VBUS_POWER_MW)) / 1000.0
112
113
114 def get_charging_voltages(self):
115 """Gets the lists of available charging voltages."""
116 return self.USBC_CHARGING_VOLTAGES.keys()
117
118
119 def charge(self, voltage):
120 """Sets Plankton to provide power at specific voltage.
121
122 @param voltage: Specified charging voltage in volts.
123 """
124 if voltage not in self.USBC_CHARGING_VOLTAGES:
125 raise PlanktonError('Invalid charging voltage: %s' % voltage)
126
127 self.set(self.USBC_ROLE, self.USBC_CHARGING_VOLTAGES[voltage])
128 time.sleep(self.USBC_COMMAND_DELAY)
129
130
131 @property
132 def charging_voltage(self):
133 """Gets current charging voltage."""
134 usbc_role = self.get(self.USBC_ROLE)
135 match = self.RE_USBC_ROLE_VOLTAGE(usbc_role)
136 if match:
137 return int(match.group(1))
138
139 if usbc_role == self.USBC_CHARGING_VOLTAGES[0]:
140 return 0
141
142 raise PlanktonError('Invalid USBC role: %s' % usbc_role)
Johny Lind5c46fa2015-03-26 17:24:40 +0800143
144
145 def poll_pd_state(self, state):
146 """Polls until Plankton pd goes to the specific state.
147
148 @param state: Specified pd state name.
149 """
150 if state not in self.USBC_PD_STATES:
151 raise PlanktonError('Invalid state name: %s' % state)
152 utils.poll_for_condition(
153 lambda: self.get('pd_state') == self.USBC_PD_STATES[state],
154 exception=utils.TimeoutError('Plankton not in %s state '
155 'after %s seconds.' %
156 (self.USBC_PD_STATES[state],
157 self.POLL_STATE_SECS)),
158 timeout=self.POLL_STATE_SECS)
Rong Chang4408fec2015-03-10 19:29:08 +0800159
160
161 def set_usbc_mux(self, mux):
162 """Sets Plankton usbc_mux.
163
164 @param mux: Specified mux state name.
165 """
166 if mux not in ['dp', 'usb']:
167 raise PlanktonError('Invalid mux name: %s, '
168 'should be either \'dp\' or \'usb\'.' % mux)
169 self.set(self.USBC_MUX, mux)
170 time.sleep(self.USBC_COMMAND_DELAY)
171
Scottfe06ed82015-11-05 17:15:01 -0800172
173class PlanktonConsole(chrome_ec.ChromeEC):
174 """Manages control of a Plankton PD console.
175
176 We control the PD conolse via the UART of a Servo board. ChromePlankton
177 provides many interfaces to set and get its behavior via console commands.
178 This class is to abstract these interfaces.
179 """
180 pass