blob: 59693219fdfadca0f0ad4e3ebad8c2f9ba0bda99 [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."""
117 self.power_key(Servo.LONG_DELAY)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700118
119
120 def power_normal_press(self):
Chrome Bot9a1137d2011-07-19 14:35:00 -0700121 """Simulate a normal power button press."""
122 self.power_key()
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700123
124
125 def power_short_press(self):
Chrome Bot9a1137d2011-07-19 14:35:00 -0700126 """Simulate a short power button press."""
127 self.power_key(Servo.SHORT_DELAY)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700128
129
Chrome Bot9a1137d2011-07-19 14:35:00 -0700130 def power_key(self, secs=NORMAL_TRANSITION_DELAY):
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700131 """Simulate a power button press.
132
133 Args:
134 secs: Time in seconds to simulate the keypress.
135 """
Craig Harrison6b36b122011-06-28 17:58:43 -0700136 self.set_nocheck('pwr_button', 'press')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700137 time.sleep(secs)
Todd Broch31c82502011-08-29 08:14:39 -0700138 self.set_nocheck('pwr_button', 'release')
139 # TODO(tbroch) Different systems have different release times on the
140 # power button that this loop addresses. Longer term we may want to
141 # make this delay platform specific.
142 retry = 1
143 while True:
144 value = self.get('pwr_button')
145 if value == 'release' or retry > Servo.RELEASE_RETRY_MAX:
146 break
Todd Broch9753bd42012-03-21 10:15:08 -0700147 logging.info('Waiting for pwr_button to release, retry %d.', retry)
Todd Broch31c82502011-08-29 08:14:39 -0700148 retry += 1
149 time.sleep(Servo.SHORT_DELAY)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700150
151
152 def lid_open(self):
153 """Simulate opening the lid."""
Craig Harrison48997262011-06-27 14:31:10 -0700154 self.set_nocheck('lid_open', 'yes')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700155
156
157 def lid_close(self):
Craig Harrison48997262011-06-27 14:31:10 -0700158 """Simulate closing the lid.
159
160 Waits 6 seconds to ensure the device is fully asleep before returning.
161 """
162 self.set_nocheck('lid_open', 'no')
Chrome Bot9a1137d2011-07-19 14:35:00 -0700163 time.sleep(Servo.SLEEP_DELAY)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700164
165
Todd Broch9753bd42012-03-21 10:15:08 -0700166 def _press_and_release_keys(self, m1, m2,
167 press_secs=SERVO_SEND_SIGNAL_DELAY):
Todd Broch9dfc3a82011-11-01 08:09:28 -0700168 """Simulate button presses."""
Todd Broch9753bd42012-03-21 10:15:08 -0700169 # set keys to none
170 (m2_a1, m2_a0) = self.KEY_MATRIX['m2']['none']
171 (m1_a1, m1_a0) = self.KEY_MATRIX['m1']['none']
172 self.set_nocheck('kbd_m2_a0', m2_a0)
173 self.set_nocheck('kbd_m2_a1', m2_a1)
174 self.set_nocheck('kbd_m1_a0', m1_a0)
175 self.set_nocheck('kbd_m1_a1', m1_a1)
Todd Broch9dfc3a82011-11-01 08:09:28 -0700176
Todd Broch9753bd42012-03-21 10:15:08 -0700177 (m2_a1, m2_a0) = self.KEY_MATRIX['m2'][m2]
178 (m1_a1, m1_a0) = self.KEY_MATRIX['m1'][m1]
Todd Broch9dfc3a82011-11-01 08:09:28 -0700179 self.set_nocheck('kbd_en', 'on')
Todd Broch9753bd42012-03-21 10:15:08 -0700180 self.set_nocheck('kbd_m2_a0', m2_a0)
181 self.set_nocheck('kbd_m2_a1', m2_a1)
182 self.set_nocheck('kbd_m1_a0', m1_a0)
183 self.set_nocheck('kbd_m1_a1', m1_a1)
Todd Broch9dfc3a82011-11-01 08:09:28 -0700184 time.sleep(press_secs)
185 self.set_nocheck('kbd_en', 'off')
186
187
Chrome Bot9a1137d2011-07-19 14:35:00 -0700188 def ctrl_d(self):
189 """Simulate Ctrl-d simultaneous button presses."""
Todd Broch9dfc3a82011-11-01 08:09:28 -0700190 self._press_and_release_keys('d', 'ctrl')
191
192
Todd Broch9753bd42012-03-21 10:15:08 -0700193 def ctrl_enter(self):
194 """Simulate Ctrl-enter simultaneous button presses."""
195 self._press_and_release_keys('enter', 'ctrl')
196
197
Todd Broch9dfc3a82011-11-01 08:09:28 -0700198 def d_key(self):
199 """Simulate Enter key button press."""
200 self._press_and_release_keys('d', 'none')
201
202
203 def ctrl_key(self):
204 """Simulate Enter key button press."""
205 self._press_and_release_keys('none', 'ctrl')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700206
207
Chrome Bot9a1137d2011-07-19 14:35:00 -0700208 def enter_key(self):
209 """Simulate Enter key button press."""
Todd Broch9dfc3a82011-11-01 08:09:28 -0700210 self._press_and_release_keys('enter', 'none')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700211
212
Chrome Bot9a1137d2011-07-19 14:35:00 -0700213 def refresh_key(self):
214 """Simulate Refresh key (F3) button press."""
Todd Broch9dfc3a82011-11-01 08:09:28 -0700215 self._press_and_release_keys('none', 'refresh')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700216
217
Chrome Bot9a1137d2011-07-19 14:35:00 -0700218 def imaginary_key(self):
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700219 """Simulate imaginary key button press.
220
221 Maps to a key that doesn't physically exist.
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700222 """
Todd Broch9dfc3a82011-11-01 08:09:28 -0700223 self._press_and_release_keys('none', 'unused')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700224
225
Craig Harrison6b36b122011-06-28 17:58:43 -0700226 def enable_recovery_mode(self):
227 """Enable recovery mode on device."""
228 self.set('rec_mode', 'on')
229
230
231 def disable_recovery_mode(self):
232 """Disable recovery mode on device."""
233 self.set('rec_mode', 'off')
234
235
236 def enable_development_mode(self):
237 """Enable development mode on device."""
238 self.set('dev_mode', 'on')
239
240
241 def disable_development_mode(self):
242 """Disable development mode on device."""
243 self.set('dev_mode', 'off')
244
Chris Sosa8ee1d592011-08-14 16:50:31 -0700245 def enable_usb_hub(self, host=False):
Craig Harrison86b1a572011-08-12 11:26:52 -0700246 """Enable Servo's USB/ethernet hub.
247
Chris Sosa8ee1d592011-08-14 16:50:31 -0700248 This is equivalent to plugging in the USB devices attached to Servo to
249 the host (if |host| is True) or dut (if |host| is False).
250 For host=False, requires that the USB out on the servo board is
251 connected to a USB in port on the target device. Servo's USB ports are
252 labeled DUT_HUB_USB1 and DUT_HUB_USB2. Servo's ethernet port is also
253 connected to this hub. Servo's USB port DUT_HUB_IN is the output of the
254 hub.
Craig Harrison86b1a572011-08-12 11:26:52 -0700255 """
256 self.set('dut_hub_pwren', 'on')
Chris Sosa8ee1d592011-08-14 16:50:31 -0700257 if host:
Todd Broch9753bd42012-03-21 10:15:08 -0700258 self.set('usb_mux_oe1', 'on')
259 self.set('usb_mux_sel1', 'servo_sees_usbkey')
Chris Sosa8ee1d592011-08-14 16:50:31 -0700260 else:
Todd Broch9753bd42012-03-21 10:15:08 -0700261 self.set('dut_hub_sel', 'dut_sees_hub')
Chris Sosa8ee1d592011-08-14 16:50:31 -0700262
Craig Harrison86b1a572011-08-12 11:26:52 -0700263 self.set('dut_hub_on', 'yes')
264
265
266 def disable_usb_hub(self):
267 """Disable Servo's USB/ethernet hub.
268
269 This is equivalent to unplugging the USB devices attached to Servo.
270 """
271 self.set('dut_hub_on', 'no')
272
273
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700274 def boot_devmode(self):
275 """Boot a dev-mode device that is powered off."""
Tom Wai-Hong Tam23869102012-01-17 15:41:30 +0800276 self.power_short_press()
Craig Harrison48997262011-06-27 14:31:10 -0700277 self.pass_devmode()
278
279
280 def pass_devmode(self):
281 """Pass through boot screens in dev-mode."""
Chrome Bot9a1137d2011-07-19 14:35:00 -0700282 time.sleep(Servo.BOOT_DELAY)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700283 self.ctrl_d()
Chrome Bot9a1137d2011-07-19 14:35:00 -0700284 time.sleep(Servo.BOOT_DELAY)
Craig Harrison48997262011-06-27 14:31:10 -0700285
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700286
Craig Harrison6b36b122011-06-28 17:58:43 -0700287 def cold_reset(self):
288 """Perform a cold reset of the EC.
289
Chris Sosa8ee1d592011-08-14 16:50:31 -0700290 Has the side effect of shutting off the device. Device is guaranteed
291 to be off at the end of this call.
Craig Harrison6b36b122011-06-28 17:58:43 -0700292 """
293 self.set('cold_reset', 'on')
Chrome Bot9a1137d2011-07-19 14:35:00 -0700294 time.sleep(Servo.SERVO_SEND_SIGNAL_DELAY)
Craig Harrison6b36b122011-06-28 17:58:43 -0700295
296
297 def warm_reset(self):
298 """Perform a warm reset of the device.
299
300 Has the side effect of restarting the device.
301 """
302 self.set('warm_reset', 'on')
Chrome Bot9a1137d2011-07-19 14:35:00 -0700303 time.sleep(Servo.SERVO_SEND_SIGNAL_DELAY)
Craig Harrison6b36b122011-06-28 17:58:43 -0700304 self.set('warm_reset', 'off')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700305
306
Todd Brochefe72cb2012-07-11 19:58:53 -0700307 def _get_xmlrpclib_exception(self, xmlexc):
308 """Get meaningful exception string from xmlrpc.
309
310 Args:
311 xmlexc: xmlrpclib.Fault object
312
313 xmlrpclib.Fault.faultString has the following format:
314
315 <type 'exception type'>:'actual error message'
316
317 Parse and return the real exception from the servod side instead of the
318 less meaningful one like,
319 <Fault 1: "<type 'exceptions.AttributeError'>:'tca6416' object has no
320 attribute 'hw_driver'">
321
322 Returns:
323 string of underlying exception raised in servod.
324 """
325 return re.sub('^.*>:', '', xmlexc.faultString)
326
327
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700328 def get(self, gpio_name):
329 """Get the value of a gpio from Servod."""
330 assert gpio_name
Todd Brochefe72cb2012-07-11 19:58:53 -0700331 try:
332 return self._server.get(gpio_name)
333 except xmlrpclib.Fault as e:
334 err_msg = "Getting '%s' :: %s" % \
335 (gpio_name, self._get_xmlrpclib_exception(e))
336 raise error.TestFail(err_msg)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700337
338
339 def set(self, gpio_name, gpio_value):
340 """Set and check the value of a gpio using Servod."""
Chrome Bot9a1137d2011-07-19 14:35:00 -0700341 self.set_nocheck(gpio_name, gpio_value)
Todd Brochcf7c6652012-02-24 13:03:59 -0800342 retry_count = Servo.GET_RETRY_MAX
343 while gpio_value != self.get(gpio_name) and retry_count:
344 logging.warn("%s != %s, retry %d", gpio_name, gpio_value,
345 retry_count)
346 retry_count -= 1
347 time.sleep(Servo.SHORT_DELAY)
348 if not retry_count:
349 assert gpio_value == self.get(gpio_name), \
350 'Servo failed to set %s to %s' % (gpio_name, gpio_value)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700351
352
353 def set_nocheck(self, gpio_name, gpio_value):
354 """Set the value of a gpio using Servod."""
355 assert gpio_name and gpio_value
Todd Broch9753bd42012-03-21 10:15:08 -0700356 logging.info('Setting %s to %s', gpio_name, gpio_value)
Todd Brochefe72cb2012-07-11 19:58:53 -0700357 try:
358 self._server.set(gpio_name, gpio_value)
359 except xmlrpclib.Fault as e:
360 err_msg = "Setting '%s' to '%s' :: %s" % \
361 (gpio_name, gpio_value, self._get_xmlrpclib_exception(e))
362 raise error.TestFail(err_msg)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700363
364
Jon Salzc88e5b62011-11-30 14:38:54 +0800365 # TODO(waihong) It may fail if multiple servo's are connected to the same
366 # host. Should look for a better way, like the USB serial name, to identify
367 # the USB device.
Simran Basi741b5d42012-05-18 11:27:15 -0700368 # TODO(sbasi) Remove this code from autoserv once firmware tests have been
369 # updated.
Jon Salzc88e5b62011-11-30 14:38:54 +0800370 def probe_host_usb_dev(self):
371 """Probe the USB disk device plugged-in the servo from the host side.
372
373 It tries to switch the USB mux to make the host unable to see the
374 USB disk and compares the result difference.
375
376 This only works if the servo is attached to the local host.
377
378 Returns:
379 A string of USB disk path, like '/dev/sdb', or None if not existed.
380 """
381 cmd = 'ls /dev/sd[a-z]'
382 original_value = self.get('usb_mux_sel1')
383
384 # Make the host unable to see the USB disk.
385 if original_value != 'dut_sees_usbkey':
386 self.set('usb_mux_sel1', 'dut_sees_usbkey')
387 time.sleep(self.USB_DETECTION_DELAY)
388 no_usb_set = set(utils.system_output(cmd, ignore_status=True).split())
389
390 # Make the host able to see the USB disk.
391 self.set('usb_mux_sel1', 'servo_sees_usbkey')
392 time.sleep(self.USB_DETECTION_DELAY)
393 has_usb_set = set(utils.system_output(cmd, ignore_status=True).split())
394
395 # Back to its original value.
396 if original_value != 'servo_sees_usbkey':
397 self.set('usb_mux_sel1', original_value)
398 time.sleep(self.USB_DETECTION_DELAY)
399
400 diff_set = has_usb_set - no_usb_set
401 if len(diff_set) == 1:
402 return diff_set.pop()
403 else:
404 return None
405
406
Simran Basi741b5d42012-05-18 11:27:15 -0700407 def install_recovery_image(self, image_path=None,
408 wait_timeout=RECOVERY_INSTALL_DELAY,
409 make_image_noninteractive=False,
410 host=None):
Jon Salzc88e5b62011-11-30 14:38:54 +0800411 """Install the recovery image specied by the path onto the DUT.
412
413 This method uses google recovery mode to install a recovery image
414 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 +0800415 board specified by the usb_dev. If no image path is specified
Jon Salzc88e5b62011-11-30 14:38:54 +0800416 we use the recovery image already on the usb image.
417
418 Args:
419 image_path: Path on the host to the recovery image.
Gilad Arnold9df73de2012-03-14 09:35:08 -0700420 wait_timeout: How long to wait for completion; default is
421 determined by a constant.
Simran Basi741b5d42012-05-18 11:27:15 -0700422 make_image_noninteractive: Make the recovery image noninteractive,
423 therefore the DUT will reboot
424 automatically after installation.
425 host: Host object for the DUT that the installation process is
426 running on. If provided, will wait to see if the host is back
427 up after starting recovery mode.
Jon Salzc88e5b62011-11-30 14:38:54 +0800428 """
Gilad Arnold9df73de2012-03-14 09:35:08 -0700429 # Turn the device off. This should happen before USB key detection, to
430 # prevent a recovery destined DUT from sensing the USB key due to the
431 # autodetection procedure.
432 self.power_long_press()
433
Jon Salzc88e5b62011-11-30 14:38:54 +0800434 # Set up Servo's usb mux.
435 self.set('prtctl4_pwren', 'on')
436 self.enable_usb_hub(host=True)
Tom Wai-Hong Tama07115e2012-01-09 12:27:01 +0800437 if image_path:
Simran Basi741b5d42012-05-18 11:27:15 -0700438 logging.info('Searching for usb device')
439 if not self._server.download_image_to_usb(image_path):
440 logging.error('Failed to transfer requested image to USB. '
441 'Please take a look at Servo Logs.')
442 raise error.AutotestError('Download image to usb failed.')
443 if make_image_noninteractive:
444 logging.info('Making image noninteractive')
445 if not self._server.make_image_noninteractive():
446 logging.error('Failed to make image noninteractive. '
447 'Please take a look at Servo Logs.')
Jon Salzc88e5b62011-11-30 14:38:54 +0800448
449 # Boot in recovery mode.
450 try:
Jon Salzc88e5b62011-11-30 14:38:54 +0800451 self.enable_recovery_mode()
Tom Wai-Hong Tam23869102012-01-17 15:41:30 +0800452 self.power_short_press()
Jon Salzc88e5b62011-11-30 14:38:54 +0800453 time.sleep(Servo.RECOVERY_BOOT_DELAY)
Tom Wai-Hong Tam922ed052012-01-09 12:27:52 +0800454 self.set('usb_mux_sel1', 'dut_sees_usbkey')
Jon Salzc88e5b62011-11-30 14:38:54 +0800455 self.disable_recovery_mode()
456
Simran Basi741b5d42012-05-18 11:27:15 -0700457 if host:
Jon Salzc88e5b62011-11-30 14:38:54 +0800458 logging.info('Running the recovery process on the DUT. '
Simran Basi741b5d42012-05-18 11:27:15 -0700459 'Will wait up to %d seconds for recovery to '
460 'complete.', wait_timeout)
461 start_time = time.time()
462 # Wait for the host to come up.
463 if host.wait_up(timeout=wait_timeout):
464 logging.info('Recovery process completed successfully in '
465 '%d seconds.', time.time() - start_time)
466 else:
467 logger.error('Host failed to come back up in the allotted '
468 'time: %d seconds.', wait_timeout)
Jon Salzc88e5b62011-11-30 14:38:54 +0800469 logging.info('Removing the usb key from the DUT.')
470 self.disable_usb_hub()
Jon Salzc88e5b62011-11-30 14:38:54 +0800471 except:
472 # In case anything went wrong we want to make sure to do a clean
473 # reset.
474 self.disable_recovery_mode()
475 self.warm_reset()
476 raise
477
478
Craig Harrison6b36b122011-06-28 17:58:43 -0700479 def _init_seq_cold_reset_devmode(self):
480 """Cold reset, init device, and boot in dev-mode."""
481 self.cold_reset()
482 self._init_seq()
483 self.set('dev_mode', 'on')
484 self.boot_devmode()
485
486
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700487 def _init_seq(self):
488 """Initiate starting state for servo."""
Todd Broch9753bd42012-03-21 10:15:08 -0700489 # TODO(tbroch) This is only a servo V1 control. Need to add ability in
490 # servod to easily identify version so I can make this conditional not
491 # try and fail quietly
492 try:
493 self.set('tx_dir', 'input')
494 except:
495 logging.warning("Failed to set tx_dir. This is ok if not servo V1")
496
497
Todd Broch6ec29432011-12-19 14:32:02 -0800498 # TODO(tbroch) Investigate method to determine DUT's type so we can
499 # conditionally set lid if applicable
500 self.set_nocheck('lid_open', 'yes')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700501 self.set('rec_mode', 'off')
502
503
Todd Brochf24d2782011-08-19 10:55:41 -0700504 def _connect_servod(self, servo_host, servo_port):
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700505 """Connect to the Servod process with XMLRPC.
506
507 Args:
508 servo_port: Port the Servod process is listening on.
509 """
Todd Brochf24d2782011-08-19 10:55:41 -0700510 remote = 'http://%s:%s' % (servo_host, servo_port)
Todd Broch96d83aa2011-08-29 14:37:38 -0700511 self._server = xmlrpclib.ServerProxy(remote)
Todd Brochf24d2782011-08-19 10:55:41 -0700512 try:
513 self._server.echo("ping-test")
Todd Broch96d83aa2011-08-29 14:37:38 -0700514 except:
515 logging.error('Connection to servod failed')
Todd Brochf24d2782011-08-19 10:55:41 -0700516 raise