1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from threading import Timer
import logging
import re
import time
from autotest_lib.client.common_lib import error
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
def delayed(seconds): # pylint:disable=missing-docstring
def decorator(f): # pylint:disable=missing-docstring
def wrapper(*args, **kargs): # pylint:disable=missing-docstring
t = Timer(seconds, f, args, kargs)
t.start()
return wrapper
return decorator
class firmware_ECLidSwitch(FirmwareTest):
"""
Servo based EC lid switch test.
"""
version = 1
# Delay between closing and opening the lid
LID_DELAY = 1
# Delay to allow FAFT client receive command
RPC_DELAY = 2
# Delay between shutdown and wakeup by lid switch
WAKE_DELAY = 10
def initialize(self, host, cmdline_args):
super(firmware_ECLidSwitch, self).initialize(host, cmdline_args)
# Only run in normal mode
self.switcher.setup_mode('normal')
def _open_lid(self):
"""Open lid by servo."""
self.servo.set('lid_open', 'yes')
def _close_lid(self):
"""Close lid by servo."""
self.servo.set('lid_open', 'no')
@delayed(RPC_DELAY)
def delayed_open_lid(self):
"""Delay by RPC_DELAY and then open lid by servo."""
self._open_lid()
@delayed(RPC_DELAY)
def delayed_close_lid(self):
"""Delay by RPC_DELAY and then close lid by servo."""
self._close_lid()
def _wake_by_lid_switch(self):
"""Wake DUT with lid switch."""
self._close_lid()
time.sleep(self.LID_DELAY)
self._open_lid()
def delayed_wake(self):
"""
Confirm the device is in G3, wait for WAKE_DELAY, and then wake DUT
with lid switch.
"""
self.check_shutdown_power_state(self.POWER_STATE_G3, pwr_retries=10)
time.sleep(self.WAKE_DELAY)
self._wake_by_lid_switch()
def immediate_wake(self):
"""Confirm the device is in G3 and then wake DUT with lid switch."""
self.check_shutdown_power_state(self.POWER_STATE_G3, pwr_retries=10)
self._wake_by_lid_switch()
def shutdown_and_wake(self, shutdown_func, wake_func):
"""Software shutdown and wake.
Args:
shutdown_func: Function to shut down DUT.
wake_func: Delayed function to wake DUT.
"""
shutdown_func()
wake_func()
def _get_keyboard_backlight(self):
"""Get keyboard backlight brightness.
Returns:
Backlight brightness percentage 0~100. If it is disabled, 0 is
returned.
"""
cmd = 'ectool pwmgetkblight'
pattern_percent = re.compile(
'Current keyboard backlight percent: (\d*)')
pattern_disable = re.compile('Keyboard backlight disabled.')
lines = self.faft_client.system.run_shell_command_get_output(cmd)
for line in lines:
matched_percent = pattern_percent.match(line)
if matched_percent is not None:
return int(matched_percent.group(1))
matched_disable = pattern_disable.match(line)
if matched_disable is not None:
return 0
raise error.TestError('Cannot get keyboard backlight status.')
def _set_keyboard_backlight(self, value):
"""Set keyboard backlight brightness.
Args:
value: Backlight brightness percentage 0~100.
"""
cmd = 'ectool pwmsetkblight %d' % value
self.faft_client.system.run_shell_command(cmd)
def check_keycode(self):
"""Check that lid open/close do not send power button keycode.
Returns:
True if no power button keycode is captured. Otherwise, False.
"""
# Don't check the keycode if we don't have a keyboard.
if not self.check_ec_capability(['keyboard'], suppress_warning=True):
return True
self._open_lid()
self.delayed_close_lid()
if self.faft_client.system.check_keys([]) < 0:
return False
self.delayed_open_lid()
if self.faft_client.system.check_keys([]) < 0:
return False
return True
def check_backlight(self):
"""Check if lid open/close controls keyboard backlight as expected.
Returns:
True if keyboard backlight is turned off when lid close and on when
lid open.
"""
if not self.check_ec_capability(['kblight'], suppress_warning=True):
return True
ok = True
original_value = self._get_keyboard_backlight()
self._set_keyboard_backlight(100)
self._close_lid()
if self._get_keyboard_backlight() != 0:
logging.error("Keyboard backlight still on when lid close.")
ok = False
self._open_lid()
if self._get_keyboard_backlight() == 0:
logging.error("Keyboard backlight still off when lid open.")
ok = False
self._set_keyboard_backlight(original_value)
return ok
def check_keycode_and_backlight(self):
"""
Disable powerd to prevent DUT shutting down during test. Then check
if lid switch event controls keycode and backlight as we expected.
"""
ok = True
logging.info("Stopping powerd")
self.faft_client.system.run_shell_command('stop powerd')
if not self.check_keycode():
logging.error("check_keycode failed.")
ok = False
if not self.check_backlight():
logging.error("check_backlight failed.")
ok = False
logging.info("Restarting powerd")
self.faft_client.system.run_shell_command('start powerd')
return ok
def run_once(self):
"""Runs a single iteration of the test."""
if not self.check_ec_capability(['lid']):
raise error.TestNAError("Nothing needs to be tested on this device")
logging.info("Shut down and then wake up DUT after a delay.")
self.switcher.mode_aware_reboot(
'custom',
lambda:self.shutdown_and_wake(
shutdown_func=self.run_shutdown_cmd,
wake_func=self.delayed_wake))
logging.info("Shut down and then wake up DUT immediately.")
self.switcher.mode_aware_reboot(
'custom',
lambda:self.shutdown_and_wake(
shutdown_func=self.run_shutdown_cmd,
wake_func=self.immediate_wake))
logging.info("Close and then open the lid when not logged in.")
self.switcher.mode_aware_reboot(
'custom',
lambda:self.shutdown_and_wake(
shutdown_func=self._close_lid,
wake_func=self.immediate_wake))
logging.info("Check keycode and backlight.")
self.check_state(self.check_keycode_and_backlight)
|