blob: e6de6a9ff7204b5d672244a94c0d4bd72c9aef20 [file] [log] [blame]
# 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.faft_classes import FAFTSequence
def delayed(seconds):
def decorator(f):
def wrapper(*args, **kargs):
t = Timer(seconds, f, args, kargs)
t.start()
return wrapper
return decorator
class firmware_ECLidSwitch(FAFTSequence):
"""
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 wake by lid switch including kernel
# shutdown time
LONG_WAKE_DELAY = 25
SHORT_WAKE_DELAY = 15
def initialize(self, host, cmdline_args):
super(firmware_ECLidSwitch, self).initialize(host, cmdline_args)
# Only run in normal mode
self.setup_dev_mode(False)
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()
@delayed(LONG_WAKE_DELAY)
def long_delayed_wake(self):
"""Delay for LONG_WAKE_DELAY and then wake DUT with lid switch."""
self._wake_by_lid_switch()
@delayed(SHORT_WAKE_DELAY)
def short_delayed_wake(self):
"""Delay for SHORT_WAKE_DELAY and then wake DUT with lid switch."""
self._wake_by_lid_switch()
def shutdown_and_wake(self, wake_func):
"""Software shutdown and delay. Then wake by lid switch.
Args:
wake_func: Delayed function to wake DUT.
"""
self.faft_client.system.run_shell_command('shutdown -P now')
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 if lid open/close send power button keycode.
Returns:
True if no power button keycode is captured. Otherwise, False.
"""
cmd = 'showkey | grep "keycode 116" | wc -l'
self._open_lid()
self.delayed_close_lid()
lines = self.faft_client.system.run_shell_command_get_output(cmd)
if int(lines[0].strip()) != 0:
logging.error("Captured power button keycode on lid close.")
self._open_lid()
return False
self.delayed_open_lid()
lines = self.faft_client.system.run_shell_command_get_output(cmd)
if int(lines[0].strip()) != 0:
logging.error("Captured power button keycode on lid close.")
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 dutring 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):
if not self.check_ec_capability(['lid']):
raise error.TestNAError("Nothing needs to be tested on this device")
self.register_faft_sequence((
{ # Step 1, shutdown and long delayed wake
'reboot_action': (self.shutdown_and_wake,
self.long_delayed_wake),
},
{ # Step 2, shutdown and short delayed wake
'reboot_action': (self.shutdown_and_wake,
self.short_delayed_wake),
},
{ # Step 3, check keycode and backlight
'state_checker': self.check_keycode_and_backlight
}
))
self.run_faft_sequence()