• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2017 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
5import logging
6import time
7from threading import Timer
8
9from autotest_lib.client.bin.input import linux_input
10from autotest_lib.client.common_lib import error
11from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
12
13
14class firmware_BaseECKeyboard(FirmwareTest):
15    """Servo-based BaseEC keyboard test.
16
17    The base should be connected to the servo v4 board through an extra
18    micro-servo. It talks to the base EC to emulate key-press.
19    """
20    version = 1
21
22    # Delay to ensure client is ready to read the key press.
23    KEY_PRESS_DELAY = 2
24
25    # Delay to wait until the UI starts.
26    START_UI_DELAY = 1
27
28    # Delay to wait until developer console is open.
29    DEV_CONSOLE_DELAY = 2
30
31
32    def initialize(self, host, cmdline_args):
33        super(firmware_BaseECKeyboard, self).initialize(host, cmdline_args)
34        # Don't require USB disk
35        self.setup_usbkey(usbkey=False)
36        # Only run in normal mode
37        self.switcher.setup_mode('normal')
38
39
40    def cleanup(self):
41        # Restart UI anyway, in case the test failed in the middle
42        try:
43            self.faft_client.system.run_shell_command('start ui | true')
44        except Exception as e:
45            logging.error("Caught exception: %s", str(e))
46        super(firmware_BaseECKeyboard, self).cleanup()
47
48
49    def _base_keyboard_checker(self, press_action):
50        """Press key and check from DUT.
51
52        Args:
53          press_action: A callable that would press the keys when called.
54
55        Returns:
56          True if passed; or False if failed.
57        """
58        # Stop UI so that key presses don't go to Chrome.
59        self.faft_client.system.run_shell_command('stop ui')
60
61        # Start a thread to perform the key-press action
62        Timer(self.KEY_PRESS_DELAY, press_action).start()
63
64        # Invoke client side script to monitor keystrokes.
65        # The codes are linux input event codes.
66        # The order doesn't matter.
67        result = self.faft_client.system.check_keys([
68                linux_input.KEY_ENTER,
69                linux_input.KEY_LEFTCTRL,
70                linux_input.KEY_D])
71
72        # Turn UI back on
73        self.faft_client.system.run_shell_command('start ui')
74        time.sleep(self.START_UI_DELAY)
75
76        return result
77
78
79    def keyboard_checker(self):
80        """Press 'd', Ctrl, ENTER by servo and check from DUT."""
81
82        def keypress(): # pylint:disable=missing-docstring
83            self.servo.enter_key()
84            self.servo.ctrl_d()
85
86        return self._base_keyboard_checker(keypress)
87
88
89    def switch_tty2(self):
90        """Switch to tty2 console."""
91        self.base_ec.key_down('<ctrl_l>')
92        self.base_ec.key_down('<alt_l>')
93        self.base_ec.key_down('<f2>')
94        self.base_ec.key_up('<f2>')
95        self.base_ec.key_up('<alt_l>')
96        self.base_ec.key_up('<ctrl_l>')
97        time.sleep(self.DEV_CONSOLE_DELAY)
98
99
100    def reboot_by_keyboard(self):
101        """Reboot DUT by keyboard.
102
103        Simulate key press sequence to log into console and then issue reboot
104        command.
105        """
106        # Assume that DUT runs a test image, which has tty2 console and root
107        # access.
108        self.switch_tty2()
109        self.base_ec.send_key_string('root<enter>')
110        self.base_ec.send_key_string('test0000<enter>')
111        self.base_ec.send_key_string('reboot<enter>')
112
113
114    def run_once(self):
115        """Runs a single iteration of the test."""
116        if not self.base_ec:
117            raise error.TestError('The base not found on servo. Wrong setup?')
118
119        logging.info('Testing keypress by servo...')
120        self.check_state(self.keyboard_checker)
121
122        logging.info('Use key press simulation to issue reboot command...')
123        self.switcher.mode_aware_reboot('custom', self.reboot_by_keyboard)
124