8
from ncd_usb import set_relay
10
log = logging.getLogger()
11
logging.basicConfig(level=logging.INFO)
14
class DeviceError(Exception):
18
def _reimage_from_fastboot(serial):
19
#Starting from fastboot mode, put a known-good image on the device
20
log.info("Flashing the last stable image")
21
subprocess.check_output(['ubuntu-device-flash', '--serial', serial,
22
'--channel', 'ubuntu-touch/stable',
23
'--bootstrap', '--password', 'ubuntuci'])
24
return _wait_for_device(serial, 600)
27
def _wait_for_device(serial, timeout=120):
28
# Wait for the device to come up to a good/booted state
29
log.info("Waiting for the device to become available")
31
subprocess.check_call(['timeout', str(timeout), 'adb', '-s',
32
serial, 'wait-for-device'])
34
log.error("Timed out waiting for reboot. Recover device manually")
36
dev_state = device_info.get_state(serial)
37
if dev_state != 'device':
38
raise DeviceError("Device in state: {0}, still not available after "
39
"{1} seconds".format(dev_state, timeout))
41
log.info("Device is now available")
45
def _wait_for_fastboot(serial, timeout=120):
51
while waited < timeout:
52
state = device_info.get_state(serial)
53
if state == 'fastboot':
58
state = device_info.get_state(serial)
59
if state == 'fastboot':
61
log.error("Timed out waiting for fastboot. Recover device manually")
62
raise DeviceError("Device in state: {0}, still not available after "
63
"{1} seconds".format(state, timeout))
66
def _mako_to_bootloader(urlbase, bank, power=1, volume=2):
68
This just works on mako for certain, but that's all we have connected
69
right now. After this runs, the device should be in the bootloader
71
log.info("Forcing the device to enter the bootloader")
72
#Power off the device from any state
73
set_relay(urlbase, bank, power, 1)
75
set_relay(urlbase, bank, power, 0)
78
set_relay(urlbase, bank, volume, 1)
79
set_relay(urlbase, bank, power, 1)
81
set_relay(urlbase, bank, volume, 0)
82
set_relay(urlbase, bank, power, 0)
85
def _full_recovery(device_name):
86
#we only support mako at the moment
87
(url, bank, power, volume) = device_info.get_power(device_name)
88
if None in (url, bank, power, volume):
89
#This device does not have information about relays
90
raise DeviceError("Full recovery not possible with this device")
91
_mako_to_bootloader(url, bank, power, volume)
92
serial = device_info.get_serial(device_name)
93
_wait_for_fastboot(serial)
94
_reimage_from_fastboot(serial)
96
_check_adb_shell(serial)
98
# The device looks like it's available, but not responding
99
raise DeviceError("Could not fully recover {}".format(device_name))
103
def _check_adb_shell(serial):
104
# Run a quick command in adb to see if the device is responding
105
subprocess.check_call(['timeout', '10', 'adb', '-s',
106
serial, 'shell', 'pwd'])
111
serial = device_info.get_serial(device)
112
except AttributeError:
113
log.error("No device found for '{}'".format(device))
115
state = device_info.get_state(serial)
116
if state in ('device', 'recovery'):
118
_check_adb_shell(serial)
120
# The device looks like it's available, but not responding
121
return _full_recovery(device)
122
#The device can proceed with testing
124
if state == 'fastboot':
125
#The device is in fastboot right now, we need it booted first
126
_reimage_from_fastboot(serial)
128
_check_adb_shell(serial)
130
# The device looks like it's available, but not responding
131
return _full_recovery(device)
132
if state in ('unknown', 'disconnected'):
133
#The device is in an unknown state, we need full recovery
134
return _full_recovery(device)
135
#In theory, we should never get here, but....
136
raise DeviceError("Device '{}' is in an unknown state!".format(device))
139
if __name__ == '__main__':
143
except AttributeError:
144
#This is what we'll get if it's an unknown device, raise for
145
#everything else so we get better debugging information