• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2014 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
6import logging, os
7import math
8from autotest_lib.client.bin import utils, test
9from autotest_lib.client.common_lib import error
10
11
12class kernel_CrosECSysfsAccel(test.test):
13    '''Make sure the EC sysfs accel interface provides meaningful output'''
14    version = 1
15
16
17    # For EC accelerometer, define the number of counts in 1G, and the number
18    # of counts that the magnitude of each sensor is allowed to be off from a
19    # magnitude of 1G. These values are not sensor dependent, they are based
20    # on the EC sysfs interface, which specifies number of counts in 1G.
21    _ACCEL_1G = 1024
22    _ACCEL_MAG_VALID_OFFSET = 250
23
24
25    sysfs_accel_search_path = '/sys/bus/iio/devices'
26    sysfs_accel_path = ''
27
28
29    def _read_sysfs_accel_file(self, filename):
30        """
31        Read the contents of the given accel sysfs file or fail
32
33        @param filename Name of the file within the accel sysfs interface
34        directory
35        """
36        fullpath = os.path.join(self.sysfs_accel_path, filename)
37
38        try:
39            content = utils.read_file(fullpath)
40        except Exception as err:
41            raise error.TestFail('sysfs file problem: %s' % err)
42        return content
43
44
45    def _find_sysfs_accel_dir(self):
46        """
47        Return the sysfs directory for accessing EC accels
48        """
49        for _, dirs, _ in os.walk(self.sysfs_accel_search_path):
50            for d in dirs:
51                namepath = os.path.join(self.sysfs_accel_search_path, d, 'name')
52
53                try:
54                    content = utils.read_file(namepath)
55                except IOError as err:
56                    # errno 2 is code for file does not exist, which is ok
57                    # here, just continue on to next directory. Any other
58                    # error is a problem, raise an error.
59                    if (err.errno == 2):
60                        continue
61                    raise error.TestFail('IOError %d while searching for accel'
62                                         'sysfs dir in %s', err.errno, namepath)
63
64                # Correct directory has a file called 'name' with contents
65                # 'cros-ec-accel'
66                if content.strip() == 'cros-ec-accel':
67                    return os.path.join(self.sysfs_accel_search_path, d)
68
69        raise error.TestFail('No sysfs interface to EC accels (cros-ec-accel)')
70
71
72    def _verify_accel_data(self, name):
73        """
74        Verify one of the EC accelerometers through the sysfs interface.
75        """
76        x = int(self._read_sysfs_accel_file('in_accel_x_' + name + '_raw'))
77        y = int(self._read_sysfs_accel_file('in_accel_y_' + name + '_raw'))
78        z = int(self._read_sysfs_accel_file('in_accel_z_' + name + '_raw'))
79        mag = math.sqrt(x*x + y*y + z*z)
80
81        # Accel data is out of range if magnitude is not close to 1G.
82        # Note, this means test will fail on the moon.
83        if (abs(mag - self._ACCEL_1G) <= self._ACCEL_MAG_VALID_OFFSET):
84            logging.info("%s accel passed. Magnitude is %d.", name, mag)
85        else:
86            logging.info("%s accel bad data. Magnitude is %d, expected "
87                         "%d +/-%d. Raw data is x:%d, y:%d, z:%d.", name,
88                         mag, self._ACCEL_1G, self._ACCEL_MAG_VALID_OFFSET,
89                         x, y, z)
90            raise error.TestFail("Accel magnitude out of range.")
91
92
93    def run_once(self):
94        """
95        Check for accelerometers, and if present, check data is valid
96        """
97        # First make sure that the motion sensors are active. If this
98        # check fails it means the EC motion sense task is not running and
99        # therefore not updating acceleration values in shared memory.
100        active = utils.system_output('ectool motionsense active')
101        if active == "0":
102            raise error.TestFail("Motion sensing is inactive")
103
104        # Find the iio sysfs directory for EC accels
105        self.sysfs_accel_path = self._find_sysfs_accel_dir()
106        logging.info("EC accelerometers found at %s", self.sysfs_accel_path)
107
108        # Get all accelerometer data
109        accel_info = utils.system_output('ectool motionsense')
110        info = accel_info.splitlines()
111
112        # If the base accelerometer is present, then verify data
113        if 'None' not in info[1]:
114            self._verify_accel_data('base')
115
116        # If the lid accelerometer is present, then verify data
117        if 'None' not in info[2]:
118            self._verify_accel_data('lid')
119