Home | History | Annotate | Download | only in firmware_BaseECKeyboard
      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 
      5 import logging
      6 import time
      7 from threading import Timer
      8 
      9 from autotest_lib.client.bin.input import linux_input
     10 from autotest_lib.client.common_lib import error
     11 from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
     12 
     13 
     14 class 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():
     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         if not self.base_ec:
    116             raise error.TestError('The base not found on servo. Wrong setup?')
    117 
    118         logging.info('Testing keypress by servo...')
    119         self.check_state(self.keyboard_checker)
    120 
    121         logging.info('Use key press simulation to issue reboot command...')
    122         self.switcher.mode_aware_reboot('custom', self.reboot_by_keyboard)
    123