Home | History | Annotate | Download | only in kernel_CrosECSysfsAccel
      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 
      6 import logging, os
      7 import math
      8 from autotest_lib.client.bin import utils, test
      9 from autotest_lib.client.common_lib import error
     10 
     11 
     12 class 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