• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5import logging, time
6
7from autotest_lib.server import autotest, test
8from autotest_lib.client.common_lib import error
9
10_SUSPEND_TIME = 60
11_SUSPEND_TIMEOUT = 30
12
13class 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