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
5import logging, os
6
7from autotest_lib.client.common_lib import error, autotemp, site_utils
8from autotest_lib.server import autotest, hosts
9from autotest_lib.server import test, utils
10
11bored_now = """
12[  _____             ____  _               _  ]
13[ |_   _|__   ___   / ___|| | _____      _| | ]
14[  | |/ _ \ / _ \  \___ \| |/ _ \ \ /\ / /| | ]
15[  | | (_) | (_) |  ___) | | (_) \ V  V / |_| ]
16[  |_|\___/ \___/  |____/|_|\___/ \_/\_/  (_) ]
17[                                             ]
18[ The device didn't wake up - either the HID device isn't working or  ]
19[ the chromebook just didn't wake up: Either way, wake the chromebook ]
20[ so we can finish the test, or we'll be sitting here for a while...  ]
21"""
22
23press_button_banner = """
24[     _   _   _             _   _              ]
25[    / \ | |_| |_ ___ _ __ | |_(_) ___  _ __   ]
26[   / _ \| __| __/ _ \ '_ \| __| |/ _ \| '_ \  ]
27[  / ___ \ |_| ||  __/ | | | |_| | (_) | | | | ]
28[ /_/   \_\__|\__\___|_| |_|\__|_|\___/|_| |_| ]
29[                                              ]
30[ Press the power, sleep or other suitable button on your USB HID Device ]
31[ NOTE: NOT on the Chromebook itself - on the USB Keyboard/Remote/etc    ]
32[ Then press Return or Enter here so we can proceed with the test        ]
33"""
34
35
36class platform_USBHIDWake(test.test):
37    version = 1
38
39    def suspend(self):
40        self._client.run("(echo mem > /sys/power/state &)")
41
42
43    def check_dependencies(self):
44        if not utils.system('which openvt', ignore_status=True) == 0:
45            raise error.TestError('openvt missing (see control file)')
46        if not utils.system('sudo true', ignore_status=True) == 0:
47            raise error.TestError('Insufficient privileges: cannot sudo')
48
49
50    def prompt(self, banner=">>>>>>>>>>> Achtung! <<<<<<<<<<<"):
51        """prompt the user with the supplied banner,
52        then wait for them to press enter
53
54        @param banner: A [possibly multi-line] banner prompt to display
55        """
56        temp = autotemp.tempfile(unique_id='vtprompt', text=True)
57        os.write(temp.fd, banner)
58        pcmd = ("sudo openvt -s -w -- " +
59                "sh -c 'clear && cat %s && read -p \"READY> \" REPLY &&" +
60                " echo $REPLY'") % temp.name
61        utils.system(pcmd)
62        temp.clean()
63
64
65    def wait_for_host(self, host=None, timeout=30):
66        '''Wait for the DUT to come back up, with a timeout
67
68        @param host: ip address or hostname of DUT
69        @param timeout: maximum time in seconds to wait
70
71        Returns True if the host comes up in time, False otherwise'''
72        return site_utils.ping(host, deadline=timeout) == 0
73
74
75    def have_hid_device(self):
76        """Return True is a USB HID device is present, False otherwise"""
77        cmd = 'grep "^03$" /sys/bus/usb/devices/[0-9]*/[0-9]*/bInterfaceClass'
78        rval = self._client.run(cmd, ignore_status=True)
79        return rval.exit_status == 0
80
81
82    def run_once(self, client_ip):
83        """Check to see if a DUT at the given address wakes from suspend
84        on USB HID events
85
86        @param client_ip: ip address (string) at which the DUT may be found"""
87        self.check_dependencies()
88        if not client_ip:
89            raise error.TestError('Must have test client IP address')
90        self._client = hosts.create_host(client_ip)
91        if not self.have_hid_device():
92            raise error.TestError('No HID devices found, please attach one')
93        self.suspend()
94        self.prompt(banner=press_button_banner)
95        if not self.wait_for_host(host=client_ip, timeout=10):
96            self.prompt(banner=bored_now)
97            raise error.TestFail('DUT did not wake up on HID event')
98