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