Home | History | Annotate | Download | only in firmware_ECBattery
      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 
      5 import logging
      6 import re
      7 
      8 from autotest_lib.client.common_lib import error
      9 from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
     10 
     11 class firmware_ECBattery(FirmwareTest):
     12     """
     13     Servo based EC thermal battery status report test.
     14     """
     15     version = 1
     16 
     17     # Battery status path in sysfs
     18     BATTERY_STATUS = '/sys/class/power_supply/%s/status'
     19 
     20     # Battery voltage reading path in sysfs
     21     BATTERY_VOLTAGE_READING = '/sys/class/power_supply/%s/voltage_now'
     22 
     23     # Battery current reading path in sysfs
     24     BATTERY_CURRENT_READING = '/sys/class/power_supply/%s/current_now'
     25 
     26     # Maximum allowed error of voltage reading in mV
     27     VOLTAGE_MV_ERROR_MARGIN = 300
     28 
     29     # Maximum allowed error of current reading in mA
     30     CURRENT_MA_ERROR_MARGIN = 300
     31 
     32     # Maximum allowed battery temperature in C
     33     BATTERY_TEMP_UPPER_BOUND = 70
     34 
     35     # Minimum allowed battery temperature in C
     36     BATTERY_TEMP_LOWER_BOUND = 0
     37 
     38 
     39     def initialize(self, host, cmdline_args):
     40         super(firmware_ECBattery, self).initialize(host, cmdline_args)
     41         # Only run in normal mode
     42         self.switcher.setup_mode('normal')
     43         self.ec.send_command("chan 0")
     44 
     45 
     46     def cleanup(self):
     47         self.ec.send_command("chan 0xffffffff")
     48         super(firmware_ECBattery, self).cleanup()
     49 
     50 
     51     def _get_battery_path(self):
     52         """Get battery path in sysfs."""
     53         match = self.faft_client.system.run_shell_command_get_output(
     54                 'grep -iH --color=no "Battery" /sys/class/power_supply/*/type')
     55         name = re.search("/sys/class/power_supply/([^/]+)/",
     56                          match[0]).group(1)
     57         logging.info("Battery name is %s", name)
     58         self._battery_status = self.BATTERY_STATUS % name
     59         self._battery_voltage = self.BATTERY_VOLTAGE_READING % name
     60         self._battery_current = self.BATTERY_CURRENT_READING % name
     61 
     62 
     63     def _check_voltage_match(self):
     64         """Check if voltage reading from kernel and servo match.
     65 
     66         Raises:
     67           error.TestFail: Raised when the two reading mismatch by more than
     68             VOLTAGE_MV_ERROR_MARGIN mV.
     69         """
     70         servo_reading = int(self.servo.get('ppvar_vbat_mv'))
     71         # Kernel gives voltage value in uV. Convert to mV here.
     72         kernel_reading = int(
     73             self.faft_client.system.run_shell_command_get_output(
     74                 'cat %s' % self._battery_voltage)[0]) / 1000
     75         logging.info("Voltage reading from servo: %dmV", servo_reading)
     76         logging.info("Voltage reading from kernel: %dmV", kernel_reading)
     77         if abs(servo_reading - kernel_reading) > self.VOLTAGE_MV_ERROR_MARGIN:
     78             raise error.TestFail(
     79                     "Voltage reading from servo (%dmV) and kernel (%dmV) "
     80                     "mismatch." % (servo_reading, kernel_reading))
     81 
     82 
     83     def _check_current_match(self):
     84         """Check if current reading from kernel and servo match.
     85 
     86         Raises:
     87           error.TestFail: Raised when the two reading mismatch by more than
     88             CURRENT_MA_ERROR_MARGIN mA.
     89         """
     90         # The signs of the current values from servo and kernel are not
     91         # consistent across different devices. So we pick the absolute values.
     92         # TODO(victoryang (at] chromium.org): Investigate the sign issue.
     93         servo_reading = abs(int(self.servo.get('ppvar_vbat_ma')))
     94         # Kernel gives current value in uA. Convert to mA here.
     95         kernel_reading = abs(
     96             int(self.faft_client.system.run_shell_command_get_output(
     97                 'cat %s' % self._battery_current)[0])) / 1000
     98         logging.info("Current reading from servo: %dmA", servo_reading)
     99         logging.info("Current reading from kernel: %dmA", kernel_reading)
    100         if abs(servo_reading - kernel_reading) > self.CURRENT_MA_ERROR_MARGIN:
    101             raise error.TestFail(
    102                     "Current reading from servo (%dmA) and kernel (%dmA) "
    103                     "mismatch." % (servo_reading, kernel_reading))
    104 
    105 
    106     def _check_temperature(self):
    107         """Check if battery temperature is reasonable.
    108 
    109         Raises:
    110           error.TestFail: Raised when battery tempearture is higher than
    111             BATTERY_TEMP_UPPER_BOUND or lower than BATTERY_TEMP_LOWER_BOUND.
    112         """
    113         battery_temp = float(self.ec.send_command_get_output("battery",
    114                 ["Temp:.+\(([0-9\.]+) C\)"])[0][1])
    115         logging.info("Battery temperature is %f C", battery_temp)
    116         if (battery_temp > self.BATTERY_TEMP_UPPER_BOUND or
    117             battery_temp < self.BATTERY_TEMP_LOWER_BOUND):
    118             raise error.TestFail("Abnormal battery temperature, %.2f C." %
    119                                  battery_temp)
    120 
    121 
    122     def run_once(self):
    123         if not self.check_ec_capability(['battery']):
    124             raise error.TestNAError("Nothing needs to be tested on this device")
    125 
    126         self._get_battery_path()
    127 
    128         logging.info("Checking battery current reading...")
    129         self._check_current_match()
    130 
    131         logging.info("Checking battery voltage reading...")
    132         self._check_voltage_match()
    133 
    134         logging.info("Checking battery temperature...")
    135         self._check_temperature()
    136