blob: 6e86bc101b9d6f014c17a7ef72c19c9771809b8d [file] [log] [blame]
Board API
=========
If you need to implement test behavior in a board-specific way, use or
extend :py:class:`cros.factory.system.board.Board`. This class
provides board-specific functionality, e.g.:
- forcing device charge state
- observing on-board sensors such as temperature sensors
- querying the EC (embedded controller)
- directly reading/writing values over the I2C bus
Obtaining a Board object
------------------------
To obtain a :py:class:`cros.factory.system.board.Board` object for the
device under test, use the following function:
.. py:module:: cros.factory.system
.. autofunction:: GetBoard
.. _board-api-extending:
Extending the Board class
-------------------------
The :py:class:`cros.factory.board.chromeos_board.ChromeOSBoard` class
is the default implementation of :py:class:`cros.factory.system.board.Board`,
but you may find that you need to customize or override certain functionality
for your project. To do so:
#. Define a new subclass of :py:class:`cros.factory.system.board.Board`
in the :py:mod:`cros.factory.board` package. In general, for a board
named :samp:`{xxx}`, you will add a
file :samp:`private-overlays/overlay-{xxx}-private/chromeos-base/chromeos-factory-board/files/py/board/{xxx}_board.py`
containing the following::
import factory_common # pylint: disable=W0611
from cros.factory.board.chromeos_board import ChromeOSBoard
from cros.factory.system.board import Board, BoardException
class XxxBoard(ChromeOSBoard):
# ... implement/override methods here ...
Generally, your class should be derived from the
:py:class:`cros.factory.board.chromeos_board.ChromeOSBoard` class, but if your
device has no EC or a standard EC, you may wish to directly subclass
:py:class:`cros.factory.system.board.Board`.
#. Specify that your implementation should be used. To do this, in
:samp:`private-overlays/overlay-{board}-private/chromeos-base/chromeos-factory-board/files/board/board_setup_factory.sh`,
add a line like the following::
export CROS_FACTORY_BOARD_CLASS="cros.factory.board.xxx_board.XxxBoard"
Adding new methods to the Board class
-------------------------------------
If you need to perform some system operation in a highly CrOS-specific
or board-specific way, you may need to add a new method to the
:py:class:`cros.factory.system.board.Board` class.
Let's say that you're working on a cool new CrOS device ("mintyfresh")
with a built-in air freshener, and you need to write a test for this
game-changing new component. Consider the following questions:
- **Is there a standard way of controlling the air freshener component
in a way that should work for all present and future devices?** (For
example, you can activate and deactivate the component by writing
``1`` or ``0`` to ``/sys/module/airfreshener/active``, or calling a
user-level program ``airfreshenerctl enable``.)
In this case there is no reason to add a method to
:py:class:`cros.factory.system.board.Board`, since no one will ever
need to override it. Simply add a new function
``SetAirFreshenerActive(active)`` to one of the utility modules in
:py:mod:`cros.factory.util`; or if the component is better
encapsulated perhaps a new wrapper class
:py:class:`cros.factory.system.air_freshener.AirFreshener`.
- **Is there a mostly standard way of controlling the air freshener
across CrOS devices, but that might be different for certain
devices?** (For instance, you can call ``ectool airfreshener 1`` to
enable the air freshener, but CrOS devices with a non-standard EC
may need to implement this differently.)
In this case, add an abstract method to
:py:class:`cros.factory.system.board.Board` and a default
implementation in
:py:class:`cros.factory.board.chromeos_board.ChromeOSBoard`; it will
work for "standard" devices but can be overridden as necessary.
- **Is the functionality totally one-off for your device?** (For instance,
you need to control the device via a hard-coded register on the I2C bus.)
If so, add an abstract method to
:py:class:`cros.factory.system.board.Board` and provide the
implementation directly in your
:py:class:`cros.factory.board.MintyFreshBoard` class. Don't provide
an implementation in
:py:class:`cros.factory.board.chromeos_board.ChromeOSBoard`, since
it wouldn't be useful on other boards anyway.
- **Is the functionality confidential?**
If so, simply implement your functionality in
:py:class:`cros.factory.board.MintyFreshBoard`. Once the device is
launched, add a method to
:py:class:`cros.factory.system.board.Board` and move your
implementation to
:py:class:`cros.factory.board.chromeos_board.ChromeOSBoard` so it
can be re-used for future devices.
API Documentation
-----------------
.. py:module:: cros.factory.system.board
.. autoclass:: Board
:members:
.. py:module:: cros.factory.board.chromeos_board
.. autoclass:: ChromeOSBoard