Home | History | Annotate | Download | only in firmware_ECUsbPorts
      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 
      5 import logging
      6 
      7 from autotest_lib.client.common_lib import error
      8 from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
      9 
     10 
     11 class firmware_ECUsbPorts(FirmwareTest):
     12     """
     13     Servo based EC USB port control test.
     14     """
     15     version = 1
     16 
     17 
     18     # Delay for remote shell command call to return
     19     RPC_DELAY = 1
     20 
     21     # Delay between turning off and on USB ports
     22     REBOOT_DELAY = 6
     23 
     24     # Timeout range for waiting system to shutdown
     25     SHUTDOWN_TIMEOUT = 10
     26 
     27     # USB charge modes, copied from ec/include/usb_charge.h
     28     USB_CHARGE_MODE_DISABLED       = 0
     29     USB_CHARGE_MODE_SDP2           = 1
     30     USB_CHARGE_MODE_CDP            = 2
     31     USB_CHARGE_MODE_DCP_SHORT      = 3
     32     USB_CHARGE_MODE_ENABLED        = 4
     33 
     34     def initialize(self, host, cmdline_args):
     35         super(firmware_ECUsbPorts, self).initialize(host, cmdline_args)
     36         # Only run in normal mode
     37         self.switcher.setup_mode('normal')
     38         self.ec.send_command("chan 0")
     39 
     40 
     41     def cleanup(self):
     42         try:
     43             self.ec.send_command("chan 0xffffffff")
     44         except Exception as e:
     45             logging.error("Caught exception: %s", str(e))
     46         super(firmware_ECUsbPorts, self).cleanup()
     47 
     48 
     49     def fake_reboot_by_usb_mode_change(self):
     50         """
     51         Turn off USB ports and also kill FAFT client so that this acts like a
     52         reboot. If USB ports cannot be turned off or on, reboot step would
     53         fail.
     54         """
     55         for_all_ports_cmd = ('id=0; while [ $id -lt %d ];' +
     56                              'do ectool usbchargemode "$id" %d;' +
     57                              'id=$((id+1)); sleep 0.5; done')
     58         # Port disable - same for smart and dumb ports.
     59         ports_off_cmd = for_all_ports_cmd % (self._port_count,
     60                                              self.USB_CHARGE_MODE_DISABLED)
     61         # Port enable - different command based on smart/dumb port.
     62         port_enable_param = (self.USB_CHARGE_MODE_SDP2
     63             if self._smart_usb_charge else self.USB_CHARGE_MODE_ENABLED)
     64         ports_on_cmd = for_all_ports_cmd % (self._port_count, port_enable_param)
     65         cmd = ("(sleep %d; %s; sleep %d; %s)&" %
     66                 (self.RPC_DELAY, ports_off_cmd,
     67                  self.REBOOT_DELAY,
     68                  ports_on_cmd))
     69         self.faft_client.system.run_shell_command(cmd)
     70         self.faft_client.disconnect()
     71 
     72 
     73     def get_port_count(self):
     74         """
     75         Get the number of USB ports by checking the number of GPIO named
     76         USB*_ENABLE.
     77         """
     78         cnt = 0
     79         limit = 10
     80         while limit > 0:
     81             try:
     82                 gpio_name = "USB%d_ENABLE" % (cnt + 1)
     83                 self.ec.send_command_get_output(
     84                         "gpioget %s" % gpio_name,
     85                         ["[01].\s*%s" % gpio_name])
     86                 cnt = cnt + 1
     87                 limit = limit - 1
     88             except error.TestFail:
     89                 logging.info("Found %d USB ports", cnt)
     90                 return cnt
     91 
     92         # Limit reached. Probably something went wrong.
     93         raise error.TestFail("Unexpected error while trying to determine " +
     94                              "number of USB ports")
     95 
     96 
     97     def wait_port_disabled(self, port_count, timeout):
     98         """
     99         Wait for all USB ports to be disabled.
    100 
    101         Args:
    102           @param port_count: Number of USB ports.
    103           @param timeout: Timeout range.
    104         """
    105         logging.info('Waiting for %d USB ports to be disabled.', port_count)
    106         while timeout > 0:
    107             try:
    108                 timeout = timeout - 1
    109                 for idx in xrange(1, port_count+1):
    110                     gpio_name = "USB%d_ENABLE" % idx
    111                     self.ec.send_command_get_output(
    112                             "gpioget %s" % gpio_name,
    113                             ["0.\s*%s" % gpio_name])
    114                 return True
    115             except error.TestFail:
    116                 # USB ports not disabled. Retry.
    117                 pass
    118         return False
    119 
    120 
    121     def check_power_off_mode(self):
    122         """Shutdown the system and check USB ports are disabled."""
    123         self._failed = False
    124         self.faft_client.system.run_shell_command("shutdown -P now")
    125         self.switcher.wait_for_client_offline()
    126         if not self.wait_port_disabled(self._port_count, self.SHUTDOWN_TIMEOUT):
    127             logging.info("Fails to wait for USB port disabled")
    128             self._failed = True
    129         self.servo.power_short_press()
    130 
    131 
    132     def check_failure(self):
    133         """Returns true if failure has been encountered."""
    134         return not self._failed
    135 
    136 
    137     def run_once(self):
    138         if not self.check_ec_capability(['usb']):
    139             raise error.TestNAError("Nothing needs to be tested on this device")
    140 
    141         self._smart_usb_charge = (
    142             'smart_usb_charge' in self.faft_config.ec_capability)
    143         self._port_count = self.get_port_count()
    144 
    145         logging.info("Turn off all USB ports and then turn them on again.")
    146         self.switcher.mode_aware_reboot(
    147                 'custom', self.fake_reboot_by_usb_mode_change)
    148 
    149         logging.info("Check USB ports are disabled when powered off.")
    150         self.switcher.mode_aware_reboot('custom', self.check_power_off_mode)
    151 
    152         logging.info("Check if failure occurred.")
    153         self.check_state(self.check_failure)
    154