blob: bf73bb996aaa283f53296e6c952ff363045d8de8 [file] [log] [blame]
J. Richard Barnette384056b2012-04-16 11:04:46 -07001# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Craig Harrison2b6c6fc2011-06-23 10:34:02 -07002# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4#
5# Expects to be run in an environment with sudo and no interactive password
6# prompt, such as within the Chromium OS development chroot.
7
Todd Brochefe72cb2012-07-11 19:58:53 -07008import logging, os, re, select, subprocess, sys, time, xmlrpclib
Jon Salzc88e5b62011-11-30 14:38:54 +08009from autotest_lib.client.bin import utils as client_utils
Simran Basi741b5d42012-05-18 11:27:15 -070010from autotest_lib.client.common_lib import error
Jon Salzc88e5b62011-11-30 14:38:54 +080011from autotest_lib.server import utils
Craig Harrison2b6c6fc2011-06-23 10:34:02 -070012
J. Richard Barnette384056b2012-04-16 11:04:46 -070013class Servo(object):
Craig Harrison2b6c6fc2011-06-23 10:34:02 -070014 """Manages control of a Servo board.
15
16 Servo is a board developed by hardware group to aide in the debug and
17 control of various partner devices. Servo's features include the simulation
18 of pressing the power button, closing the lid, and pressing Ctrl-d. This
19 class manages setting up and communicating with a servo demon (servod)
20 process. It provides both high-level functions for common servo tasks and
21 low-level functions for directly setting and reading gpios.
22 """
23
Chrome Bot9a1137d2011-07-19 14:35:00 -070024 # Power button press delays in seconds.
J. Richard Barnetted2e4cbd2012-06-29 12:18:40 -070025 #
26 # TODO(jrbarnette): The EC specification says that 8.0 seconds
27 # should be enough for the long power press. However, on
28 # existing platforms (e.g. Alex), we need a bit more time.
29 # Being generous is the right thing to do for existing platforms,
30 # but if this code is to be used for qualification of new hardware,
31 # we should be less generous.
32 LONG_DELAY = 8.2
Chrome Bot9a1137d2011-07-19 14:35:00 -070033 SHORT_DELAY = 0.1
34 NORMAL_TRANSITION_DELAY = 1.2
Todd Broch31c82502011-08-29 08:14:39 -070035 # Maximum number of times to re-read power button on release.
36 RELEASE_RETRY_MAX = 5
Todd Brochcf7c6652012-02-24 13:03:59 -080037 GET_RETRY_MAX = 10
Chrome Bot9a1137d2011-07-19 14:35:00 -070038
39 # Delays to deal with computer transitions.
40 SLEEP_DELAY = 6
41 BOOT_DELAY = 10
Jon Salzc88e5b62011-11-30 14:38:54 +080042 RECOVERY_BOOT_DELAY = 30
J. Richard Barnettec5a77ad2012-04-25 08:19:00 -070043 RECOVERY_INSTALL_DELAY = 540
Chrome Bot9a1137d2011-07-19 14:35:00 -070044
45 # Servo-specific delays.
46 MAX_SERVO_STARTUP_DELAY = 10
47 SERVO_SEND_SIGNAL_DELAY = 0.5
Craig Harrison2b6c6fc2011-06-23 10:34:02 -070048
Jon Salzc88e5b62011-11-30 14:38:54 +080049 # Time between an usb disk plugged-in and detected in the system.
50 USB_DETECTION_DELAY = 10
51
Todd Broch9753bd42012-03-21 10:15:08 -070052 KEY_MATRIX = {
53 'm1': {'ctrl_r': ['0', '0'], 'd': ['0', '1'],
54 'enter': ['1', '0'], 'none': ['1', '1']},
55 'm2': {'ctrl': ['0', '0'], 'refresh': ['0', '1'],
56 'unused': ['1', '0'], 'none': ['1', '1']}
57 }
Chris Masone6a0680f2012-03-02 08:40:00 -080058
J. Richard Barnette67ccb872012-04-19 16:34:56 -070059
Chris Masone6a0680f2012-03-02 08:40:00 -080060 @staticmethod
J. Richard Barnette67ccb872012-04-19 16:34:56 -070061 def _make_servo_hostname(hostname):
62 host_parts = hostname.split('.')
63 host_parts[0] = host_parts[0] + '-servo'
64 return '.'.join(host_parts)
Chris Masone6a0680f2012-03-02 08:40:00 -080065
J. Richard Barnette67ccb872012-04-19 16:34:56 -070066 @staticmethod
67 def get_lab_servo(target_hostname):
68 """Instantiate a Servo for |target_hostname| in the lab.
Chris Masone6a0680f2012-03-02 08:40:00 -080069
J. Richard Barnette67ccb872012-04-19 16:34:56 -070070 Assuming that |target_hostname| is a device in the CrOS test
71 lab, create and return a Servo object pointed at the servo
72 attached to that DUT. The servo in the test lab is assumed
73 to already have servod up and running on it.
74
75 @param target_hostname: device whose servo we want to target.
Chris Masone6a0680f2012-03-02 08:40:00 -080076 @return an appropriately configured Servo
77 """
J. Richard Barnette67ccb872012-04-19 16:34:56 -070078 servo_host = Servo._make_servo_hostname(target_hostname)
79 if utils.host_is_in_lab_zone(servo_host):
80 try:
81 return Servo(servo_host=servo_host)
82 except:
83 # TODO(jrbarnette): Long-term, if we can't get to
84 # a servo in the lab, we want to fail, so we should
85 # pass any exceptions along. Short-term, we're not
86 # ready to rely on servo, so we ignore failures.
87 pass
88 return None
Chris Masone6a0680f2012-03-02 08:40:00 -080089
90
J. Richard Barnette55fb8062012-05-23 10:29:31 -070091 def __init__(self, servo_host='localhost', servo_port=9999,
92 cold_reset=False):
Craig Harrison2b6c6fc2011-06-23 10:34:02 -070093 """Sets up the servo communication infrastructure.
94
J. Richard Barnette55fb8062012-05-23 10:29:31 -070095 @param servo_host Name of the host where the servod process
96 is running.
97 @param servo_port Port the servod process is listening on.
98 @param cold_reset If True, cold reset device and boot during init,
99 otherwise perform init with device running.
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700100 """
J. Richard Barnette384056b2012-04-16 11:04:46 -0700101 self._server = None
Todd Broch5fd6bc02011-07-20 15:53:37 -0700102
Chrome Bot9a1137d2011-07-19 14:35:00 -0700103 self._do_cold_reset = cold_reset
Todd Brochf24d2782011-08-19 10:55:41 -0700104 self._connect_servod(servo_host, servo_port)
Chrome Bot9a1137d2011-07-19 14:35:00 -0700105
106
107 def initialize_dut(self):
108 """Initializes a dut for testing purposes."""
109 if self._do_cold_reset:
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700110 self._init_seq_cold_reset_devmode()
111 else:
112 self._init_seq()
113
114
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700115 def power_long_press(self):
Chrome Bot9a1137d2011-07-19 14:35:00 -0700116 """Simulate a long power button press."""
J. Richard Barnettef12bff22012-07-18 14:41:06 -0700117 # After a long power press, the EC may ignore the next power
118 # button press (at least on Alex). To guarantee that this
119 # won't happen, we need to allow the EC one second to
120 # collect itself.
Chrome Bot9a1137d2011-07-19 14:35:00 -0700121 self.power_key(Servo.LONG_DELAY)
J. Richard Barnettef12bff22012-07-18 14:41:06 -0700122 time.sleep(1.0)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700123
124
125 def power_normal_press(self):
Chrome Bot9a1137d2011-07-19 14:35:00 -0700126 """Simulate a normal power button press."""
127 self.power_key()
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700128
129
130 def power_short_press(self):
Chrome Bot9a1137d2011-07-19 14:35:00 -0700131 """Simulate a short power button press."""
132 self.power_key(Servo.SHORT_DELAY)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700133
134
Chrome Bot9a1137d2011-07-19 14:35:00 -0700135 def power_key(self, secs=NORMAL_TRANSITION_DELAY):
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700136 """Simulate a power button press.
137
138 Args:
139 secs: Time in seconds to simulate the keypress.
140 """
Craig Harrison6b36b122011-06-28 17:58:43 -0700141 self.set_nocheck('pwr_button', 'press')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700142 time.sleep(secs)
Todd Broch31c82502011-08-29 08:14:39 -0700143 self.set_nocheck('pwr_button', 'release')
144 # TODO(tbroch) Different systems have different release times on the
145 # power button that this loop addresses. Longer term we may want to
146 # make this delay platform specific.
147 retry = 1
148 while True:
149 value = self.get('pwr_button')
150 if value == 'release' or retry > Servo.RELEASE_RETRY_MAX:
151 break
Todd Broch9753bd42012-03-21 10:15:08 -0700152 logging.info('Waiting for pwr_button to release, retry %d.', retry)
Todd Broch31c82502011-08-29 08:14:39 -0700153 retry += 1
154 time.sleep(Servo.SHORT_DELAY)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700155
156
157 def lid_open(self):
158 """Simulate opening the lid."""
Craig Harrison48997262011-06-27 14:31:10 -0700159 self.set_nocheck('lid_open', 'yes')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700160
161
162 def lid_close(self):
Craig Harrison48997262011-06-27 14:31:10 -0700163 """Simulate closing the lid.
164
165 Waits 6 seconds to ensure the device is fully asleep before returning.
166 """
167 self.set_nocheck('lid_open', 'no')
Chrome Bot9a1137d2011-07-19 14:35:00 -0700168 time.sleep(Servo.SLEEP_DELAY)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700169
170
Todd Broch9753bd42012-03-21 10:15:08 -0700171 def _press_and_release_keys(self, m1, m2,
172 press_secs=SERVO_SEND_SIGNAL_DELAY):
Todd Broch9dfc3a82011-11-01 08:09:28 -0700173 """Simulate button presses."""
Todd Broch9753bd42012-03-21 10:15:08 -0700174 # set keys to none
175 (m2_a1, m2_a0) = self.KEY_MATRIX['m2']['none']
176 (m1_a1, m1_a0) = self.KEY_MATRIX['m1']['none']
177 self.set_nocheck('kbd_m2_a0', m2_a0)
178 self.set_nocheck('kbd_m2_a1', m2_a1)
179 self.set_nocheck('kbd_m1_a0', m1_a0)
180 self.set_nocheck('kbd_m1_a1', m1_a1)
Todd Broch9dfc3a82011-11-01 08:09:28 -0700181
Todd Broch9753bd42012-03-21 10:15:08 -0700182 (m2_a1, m2_a0) = self.KEY_MATRIX['m2'][m2]
183 (m1_a1, m1_a0) = self.KEY_MATRIX['m1'][m1]
Todd Broch9dfc3a82011-11-01 08:09:28 -0700184 self.set_nocheck('kbd_en', 'on')
Todd Broch9753bd42012-03-21 10:15:08 -0700185 self.set_nocheck('kbd_m2_a0', m2_a0)
186 self.set_nocheck('kbd_m2_a1', m2_a1)
187 self.set_nocheck('kbd_m1_a0', m1_a0)
188 self.set_nocheck('kbd_m1_a1', m1_a1)
Todd Broch9dfc3a82011-11-01 08:09:28 -0700189 time.sleep(press_secs)
190 self.set_nocheck('kbd_en', 'off')
191
192
Chrome Bot9a1137d2011-07-19 14:35:00 -0700193 def ctrl_d(self):
194 """Simulate Ctrl-d simultaneous button presses."""
Todd Broch9dfc3a82011-11-01 08:09:28 -0700195 self._press_and_release_keys('d', 'ctrl')
196
197
Todd Broch9753bd42012-03-21 10:15:08 -0700198 def ctrl_enter(self):
199 """Simulate Ctrl-enter simultaneous button presses."""
200 self._press_and_release_keys('enter', 'ctrl')
201
202
Todd Broch9dfc3a82011-11-01 08:09:28 -0700203 def d_key(self):
204 """Simulate Enter key button press."""
205 self._press_and_release_keys('d', 'none')
206
207
208 def ctrl_key(self):
209 """Simulate Enter key button press."""
210 self._press_and_release_keys('none', 'ctrl')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700211
212
Chrome Bot9a1137d2011-07-19 14:35:00 -0700213 def enter_key(self):
214 """Simulate Enter key button press."""
Todd Broch9dfc3a82011-11-01 08:09:28 -0700215 self._press_and_release_keys('enter', 'none')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700216
217
Chrome Bot9a1137d2011-07-19 14:35:00 -0700218 def refresh_key(self):
219 """Simulate Refresh key (F3) button press."""
Todd Broch9dfc3a82011-11-01 08:09:28 -0700220 self._press_and_release_keys('none', 'refresh')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700221
222
Chrome Bot9a1137d2011-07-19 14:35:00 -0700223 def imaginary_key(self):
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700224 """Simulate imaginary key button press.
225
226 Maps to a key that doesn't physically exist.
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700227 """
Todd Broch9dfc3a82011-11-01 08:09:28 -0700228 self._press_and_release_keys('none', 'unused')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700229
230
Craig Harrison6b36b122011-06-28 17:58:43 -0700231 def enable_recovery_mode(self):
232 """Enable recovery mode on device."""
233 self.set('rec_mode', 'on')
234
235
236 def disable_recovery_mode(self):
237 """Disable recovery mode on device."""
238 self.set('rec_mode', 'off')
239
240
241 def enable_development_mode(self):
242 """Enable development mode on device."""
243 self.set('dev_mode', 'on')
244
245
246 def disable_development_mode(self):
247 """Disable development mode on device."""
248 self.set('dev_mode', 'off')
249
Chris Sosa8ee1d592011-08-14 16:50:31 -0700250 def enable_usb_hub(self, host=False):
Craig Harrison86b1a572011-08-12 11:26:52 -0700251 """Enable Servo's USB/ethernet hub.
252
Chris Sosa8ee1d592011-08-14 16:50:31 -0700253 This is equivalent to plugging in the USB devices attached to Servo to
254 the host (if |host| is True) or dut (if |host| is False).
255 For host=False, requires that the USB out on the servo board is
256 connected to a USB in port on the target device. Servo's USB ports are
257 labeled DUT_HUB_USB1 and DUT_HUB_USB2. Servo's ethernet port is also
258 connected to this hub. Servo's USB port DUT_HUB_IN is the output of the
259 hub.
Craig Harrison86b1a572011-08-12 11:26:52 -0700260 """
261 self.set('dut_hub_pwren', 'on')
Chris Sosa8ee1d592011-08-14 16:50:31 -0700262 if host:
Todd Broch9753bd42012-03-21 10:15:08 -0700263 self.set('usb_mux_oe1', 'on')
264 self.set('usb_mux_sel1', 'servo_sees_usbkey')
Chris Sosa8ee1d592011-08-14 16:50:31 -0700265 else:
Todd Broch9753bd42012-03-21 10:15:08 -0700266 self.set('dut_hub_sel', 'dut_sees_hub')
Chris Sosa8ee1d592011-08-14 16:50:31 -0700267
Craig Harrison86b1a572011-08-12 11:26:52 -0700268 self.set('dut_hub_on', 'yes')
269
270
271 def disable_usb_hub(self):
272 """Disable Servo's USB/ethernet hub.
273
274 This is equivalent to unplugging the USB devices attached to Servo.
275 """
276 self.set('dut_hub_on', 'no')
277
278
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700279 def boot_devmode(self):
280 """Boot a dev-mode device that is powered off."""
Tom Wai-Hong Tam23869102012-01-17 15:41:30 +0800281 self.power_short_press()
Craig Harrison48997262011-06-27 14:31:10 -0700282 self.pass_devmode()
283
284
285 def pass_devmode(self):
286 """Pass through boot screens in dev-mode."""
Chrome Bot9a1137d2011-07-19 14:35:00 -0700287 time.sleep(Servo.BOOT_DELAY)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700288 self.ctrl_d()
Chrome Bot9a1137d2011-07-19 14:35:00 -0700289 time.sleep(Servo.BOOT_DELAY)
Craig Harrison48997262011-06-27 14:31:10 -0700290
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700291
Craig Harrison6b36b122011-06-28 17:58:43 -0700292 def cold_reset(self):
293 """Perform a cold reset of the EC.
294
Chris Sosa8ee1d592011-08-14 16:50:31 -0700295 Has the side effect of shutting off the device. Device is guaranteed
296 to be off at the end of this call.
Craig Harrison6b36b122011-06-28 17:58:43 -0700297 """
298 self.set('cold_reset', 'on')
Chrome Bot9a1137d2011-07-19 14:35:00 -0700299 time.sleep(Servo.SERVO_SEND_SIGNAL_DELAY)
Craig Harrison6b36b122011-06-28 17:58:43 -0700300
301
302 def warm_reset(self):
303 """Perform a warm reset of the device.
304
305 Has the side effect of restarting the device.
306 """
307 self.set('warm_reset', 'on')
Chrome Bot9a1137d2011-07-19 14:35:00 -0700308 time.sleep(Servo.SERVO_SEND_SIGNAL_DELAY)
Craig Harrison6b36b122011-06-28 17:58:43 -0700309 self.set('warm_reset', 'off')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700310
311
Todd Brochefe72cb2012-07-11 19:58:53 -0700312 def _get_xmlrpclib_exception(self, xmlexc):
313 """Get meaningful exception string from xmlrpc.
314
315 Args:
316 xmlexc: xmlrpclib.Fault object
317
318 xmlrpclib.Fault.faultString has the following format:
319
320 <type 'exception type'>:'actual error message'
321
322 Parse and return the real exception from the servod side instead of the
323 less meaningful one like,
324 <Fault 1: "<type 'exceptions.AttributeError'>:'tca6416' object has no
325 attribute 'hw_driver'">
326
327 Returns:
328 string of underlying exception raised in servod.
329 """
330 return re.sub('^.*>:', '', xmlexc.faultString)
331
332
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700333 def get(self, gpio_name):
334 """Get the value of a gpio from Servod."""
335 assert gpio_name
Todd Brochefe72cb2012-07-11 19:58:53 -0700336 try:
337 return self._server.get(gpio_name)
338 except xmlrpclib.Fault as e:
339 err_msg = "Getting '%s' :: %s" % \
340 (gpio_name, self._get_xmlrpclib_exception(e))
341 raise error.TestFail(err_msg)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700342
343
344 def set(self, gpio_name, gpio_value):
345 """Set and check the value of a gpio using Servod."""
Chrome Bot9a1137d2011-07-19 14:35:00 -0700346 self.set_nocheck(gpio_name, gpio_value)
Todd Brochcf7c6652012-02-24 13:03:59 -0800347 retry_count = Servo.GET_RETRY_MAX
348 while gpio_value != self.get(gpio_name) and retry_count:
349 logging.warn("%s != %s, retry %d", gpio_name, gpio_value,
350 retry_count)
351 retry_count -= 1
352 time.sleep(Servo.SHORT_DELAY)
353 if not retry_count:
354 assert gpio_value == self.get(gpio_name), \
355 'Servo failed to set %s to %s' % (gpio_name, gpio_value)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700356
357
358 def set_nocheck(self, gpio_name, gpio_value):
359 """Set the value of a gpio using Servod."""
360 assert gpio_name and gpio_value
Todd Broch9753bd42012-03-21 10:15:08 -0700361 logging.info('Setting %s to %s', gpio_name, gpio_value)
Todd Brochefe72cb2012-07-11 19:58:53 -0700362 try:
363 self._server.set(gpio_name, gpio_value)
364 except xmlrpclib.Fault as e:
365 err_msg = "Setting '%s' to '%s' :: %s" % \
366 (gpio_name, gpio_value, self._get_xmlrpclib_exception(e))
367 raise error.TestFail(err_msg)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700368
369
Jon Salzc88e5b62011-11-30 14:38:54 +0800370 # TODO(waihong) It may fail if multiple servo's are connected to the same
371 # host. Should look for a better way, like the USB serial name, to identify
372 # the USB device.
Simran Basi741b5d42012-05-18 11:27:15 -0700373 # TODO(sbasi) Remove this code from autoserv once firmware tests have been
374 # updated.
Jon Salzc88e5b62011-11-30 14:38:54 +0800375 def probe_host_usb_dev(self):
376 """Probe the USB disk device plugged-in the servo from the host side.
377
378 It tries to switch the USB mux to make the host unable to see the
379 USB disk and compares the result difference.
380
381 This only works if the servo is attached to the local host.
382
383 Returns:
384 A string of USB disk path, like '/dev/sdb', or None if not existed.
385 """
386 cmd = 'ls /dev/sd[a-z]'
387 original_value = self.get('usb_mux_sel1')
388
389 # Make the host unable to see the USB disk.
390 if original_value != 'dut_sees_usbkey':
391 self.set('usb_mux_sel1', 'dut_sees_usbkey')
392 time.sleep(self.USB_DETECTION_DELAY)
393 no_usb_set = set(utils.system_output(cmd, ignore_status=True).split())
394
395 # Make the host able to see the USB disk.
396 self.set('usb_mux_sel1', 'servo_sees_usbkey')
397 time.sleep(self.USB_DETECTION_DELAY)
398 has_usb_set = set(utils.system_output(cmd, ignore_status=True).split())
399
400 # Back to its original value.
401 if original_value != 'servo_sees_usbkey':
402 self.set('usb_mux_sel1', original_value)
403 time.sleep(self.USB_DETECTION_DELAY)
404
405 diff_set = has_usb_set - no_usb_set
406 if len(diff_set) == 1:
407 return diff_set.pop()
408 else:
409 return None
410
411
Simran Basi741b5d42012-05-18 11:27:15 -0700412 def install_recovery_image(self, image_path=None,
413 wait_timeout=RECOVERY_INSTALL_DELAY,
414 make_image_noninteractive=False,
415 host=None):
Jon Salzc88e5b62011-11-30 14:38:54 +0800416 """Install the recovery image specied by the path onto the DUT.
417
418 This method uses google recovery mode to install a recovery image
419 onto a DUT through the use of a USB stick that is mounted on a servo
Tom Wai-Hong Tama07115e2012-01-09 12:27:01 +0800420 board specified by the usb_dev. If no image path is specified
Jon Salzc88e5b62011-11-30 14:38:54 +0800421 we use the recovery image already on the usb image.
422
423 Args:
424 image_path: Path on the host to the recovery image.
Gilad Arnold9df73de2012-03-14 09:35:08 -0700425 wait_timeout: How long to wait for completion; default is
426 determined by a constant.
Simran Basi741b5d42012-05-18 11:27:15 -0700427 make_image_noninteractive: Make the recovery image noninteractive,
428 therefore the DUT will reboot
429 automatically after installation.
430 host: Host object for the DUT that the installation process is
431 running on. If provided, will wait to see if the host is back
432 up after starting recovery mode.
Jon Salzc88e5b62011-11-30 14:38:54 +0800433 """
Gilad Arnold9df73de2012-03-14 09:35:08 -0700434 # Turn the device off. This should happen before USB key detection, to
435 # prevent a recovery destined DUT from sensing the USB key due to the
436 # autodetection procedure.
437 self.power_long_press()
438
Jon Salzc88e5b62011-11-30 14:38:54 +0800439 # Set up Servo's usb mux.
440 self.set('prtctl4_pwren', 'on')
441 self.enable_usb_hub(host=True)
Tom Wai-Hong Tama07115e2012-01-09 12:27:01 +0800442 if image_path:
Simran Basi741b5d42012-05-18 11:27:15 -0700443 logging.info('Searching for usb device')
444 if not self._server.download_image_to_usb(image_path):
445 logging.error('Failed to transfer requested image to USB. '
446 'Please take a look at Servo Logs.')
447 raise error.AutotestError('Download image to usb failed.')
448 if make_image_noninteractive:
449 logging.info('Making image noninteractive')
450 if not self._server.make_image_noninteractive():
451 logging.error('Failed to make image noninteractive. '
452 'Please take a look at Servo Logs.')
Jon Salzc88e5b62011-11-30 14:38:54 +0800453
454 # Boot in recovery mode.
455 try:
Jon Salzc88e5b62011-11-30 14:38:54 +0800456 self.enable_recovery_mode()
Tom Wai-Hong Tam23869102012-01-17 15:41:30 +0800457 self.power_short_press()
Jon Salzc88e5b62011-11-30 14:38:54 +0800458 time.sleep(Servo.RECOVERY_BOOT_DELAY)
Tom Wai-Hong Tam922ed052012-01-09 12:27:52 +0800459 self.set('usb_mux_sel1', 'dut_sees_usbkey')
Jon Salzc88e5b62011-11-30 14:38:54 +0800460 self.disable_recovery_mode()
461
Simran Basi741b5d42012-05-18 11:27:15 -0700462 if host:
Jon Salzc88e5b62011-11-30 14:38:54 +0800463 logging.info('Running the recovery process on the DUT. '
Simran Basi741b5d42012-05-18 11:27:15 -0700464 'Will wait up to %d seconds for recovery to '
465 'complete.', wait_timeout)
466 start_time = time.time()
467 # Wait for the host to come up.
468 if host.wait_up(timeout=wait_timeout):
469 logging.info('Recovery process completed successfully in '
470 '%d seconds.', time.time() - start_time)
471 else:
472 logger.error('Host failed to come back up in the allotted '
473 'time: %d seconds.', wait_timeout)
Jon Salzc88e5b62011-11-30 14:38:54 +0800474 logging.info('Removing the usb key from the DUT.')
475 self.disable_usb_hub()
Jon Salzc88e5b62011-11-30 14:38:54 +0800476 except:
477 # In case anything went wrong we want to make sure to do a clean
478 # reset.
479 self.disable_recovery_mode()
480 self.warm_reset()
481 raise
482
483
Craig Harrison6b36b122011-06-28 17:58:43 -0700484 def _init_seq_cold_reset_devmode(self):
485 """Cold reset, init device, and boot in dev-mode."""
486 self.cold_reset()
487 self._init_seq()
488 self.set('dev_mode', 'on')
489 self.boot_devmode()
490
491
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700492 def _init_seq(self):
493 """Initiate starting state for servo."""
Todd Broch9753bd42012-03-21 10:15:08 -0700494 # TODO(tbroch) This is only a servo V1 control. Need to add ability in
495 # servod to easily identify version so I can make this conditional not
496 # try and fail quietly
497 try:
498 self.set('tx_dir', 'input')
499 except:
500 logging.warning("Failed to set tx_dir. This is ok if not servo V1")
501
502
Todd Broch6ec29432011-12-19 14:32:02 -0800503 # TODO(tbroch) Investigate method to determine DUT's type so we can
504 # conditionally set lid if applicable
505 self.set_nocheck('lid_open', 'yes')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700506 self.set('rec_mode', 'off')
507
508
Todd Brochf24d2782011-08-19 10:55:41 -0700509 def _connect_servod(self, servo_host, servo_port):
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700510 """Connect to the Servod process with XMLRPC.
511
512 Args:
513 servo_port: Port the Servod process is listening on.
514 """
Todd Brochf24d2782011-08-19 10:55:41 -0700515 remote = 'http://%s:%s' % (servo_host, servo_port)
Todd Broch96d83aa2011-08-29 14:37:38 -0700516 self._server = xmlrpclib.ServerProxy(remote)
Todd Brochf24d2782011-08-19 10:55:41 -0700517 try:
518 self._server.echo("ping-test")
Todd Broch96d83aa2011-08-29 14:37:38 -0700519 except:
520 logging.error('Connection to servod failed')
Todd Brochf24d2782011-08-19 10:55:41 -0700521 raise