Home | History | Annotate | Download | only in power_USBHotplugInSuspend
      1 # Copyright (c) 2013 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, time
      6 
      7 from autotest_lib.server import autotest, test
      8 from autotest_lib.client.common_lib import error
      9 
     10 _SUSPEND_TIME = 60
     11 _SUSPEND_TIMEOUT = 30
     12 
     13 class power_USBHotplugInSuspend(test.test):
     14     version = 1
     15 
     16     def _switch_usbkey_power(self, on):
     17         """
     18         Turn on/off the power to the USB key.
     19 
     20         @param on True to turn on, false otherwise.
     21         """
     22         if on:
     23             self._host.servo.set('prtctl4_pwren', 'on')
     24         else:
     25             self._host.servo.set('prtctl4_pwren', 'off')
     26         time.sleep(self._host.servo.USB_POWEROFF_DELAY)
     27 
     28     def _get_usb_devices(self):
     29         """
     30         Get the USB device attached to the client.
     31 
     32         Parses output from lsusb and returns the set of device IDs.
     33         """
     34         try:
     35             lines = self._host.run('lsusb').stdout.strip().split('\n')
     36         except:
     37             raise error.TestError('Failed to get list of USB devices.')
     38         devices = set(line.split()[5] for line in lines)
     39         logging.info('USB Devices: %s' % (",".join(devices)))
     40         return devices
     41 
     42     def _suspend_client(self):
     43         """
     44         Start the client test power_KernelSuspend to suspend the client and
     45         do not wait for it to finish.
     46         """
     47         client_at = autotest.Autotest(self._host)
     48         # TODO(scottz): Add server side support to sys_power: crosbug.com/38115
     49         client_at.run_test('power_KernelSuspend', background=True,
     50                            seconds=_SUSPEND_TIME)
     51 
     52     def _suspend_and_hotplug(self, insert):
     53         """
     54         Suspend the client and add/remove the USB key.  This assumes that a
     55         USB key is plugged into the servo and is facing the DUT.
     56 
     57         @param insert True to test insertion during suspend, False to test
     58                       removal.
     59         """
     60         # Initialize the USB key and get the set of USB devices before
     61         # suspending.
     62         self._switch_usbkey_power(not insert)
     63         before_suspend = self._get_usb_devices()
     64 
     65         # Suspend the client and wait for it to go down before powering on/off
     66         # the usb key.
     67         self._suspend_client()
     68         if not self._host.ping_wait_down(_SUSPEND_TIMEOUT):
     69             raise error.TestError('Client failed to suspend.')
     70         self._switch_usbkey_power(insert)
     71 
     72         # Wait for the client to come back up (suspend time + some slack time).
     73         # TODO(beeps): Combine the two timeouts in wait_up after
     74         # crbug.com/221785 is resolved.
     75         time.sleep(_SUSPEND_TIME)
     76         if not self._host.wait_up(self._host.RESUME_TIMEOUT):
     77             raise error.TestError('Client failed to resume.')
     78 
     79         # Get the set of devices plugged in and make sure the change was
     80         # detected.
     81         after_suspend = self._get_usb_devices()
     82         diff = after_suspend ^ before_suspend
     83         if not diff:
     84             raise error.TestFail('No USB changes detected after resuming.')
     85 
     86         # Finally, make sure hotplug still works after resuming by switching
     87         # the USB key's power once more.
     88         self._switch_usbkey_power(not insert)
     89         after_hotplug = self._get_usb_devices()
     90         diff = after_hotplug ^ after_suspend
     91         if not diff:
     92             raise error.TestFail('No USB changes detected after hotplugging.')
     93 
     94     def cleanup(self):
     95         """
     96         Reset the USB key to its initial state.
     97         """
     98         self._host.servo.switch_usbkey(self._init_usbkey_direction)
     99         self._switch_usbkey_power(self._init_usbkey_power == 'on')
    100         super(power_USBHotplugInSuspend, self).cleanup()
    101 
    102     def run_once(self, host):
    103         """
    104         Tests adding and removing a USB device while the client is suspended.
    105         """
    106         self._host = host
    107         self._init_usbkey_power = self._host.servo.get('prtctl4_pwren')
    108         self._init_usbkey_direction = self._host.servo.get_usbkey_direction()
    109 
    110         # Make sure the USB key is facing the DUT and is actually present.
    111         self._host.servo.switch_usbkey('dut')
    112         self._switch_usbkey_power(False)
    113         before_insert = self._get_usb_devices()
    114         self._switch_usbkey_power(True)
    115         after_insert = self._get_usb_devices()
    116         diff = after_insert - before_insert
    117         logging.info('Inserted USB device(s): %s' % (",".join(diff)))
    118         if not diff:
    119             raise error.TestError('No new USB devices detected. Is a USB key '
    120                                   'plugged into the servo?')
    121 
    122         logging.info('Testing insertion during suspend.')
    123         self._suspend_and_hotplug(True)
    124         logging.info('Testing removal during suspend.')
    125         self._suspend_and_hotplug(False)
    126