cros_ec_python.commands.general

General / test commands

  1"""
  2General / test commands
  3"""
  4
  5from typing import Final, Literal
  6import struct
  7from ..baseclass import CrosEcClass
  8from ..constants.COMMON import *
  9from ..exceptions import ECError
 10
 11EC_CMD_PROTO_VERSION: Final = 0x0000
 12
 13
 14def proto_version(ec: CrosEcClass) -> UInt32:
 15    """
 16    Get protocol version, used to deal with non-backward compatible protocol changes.
 17    :param ec: The CrOS_EC object.
 18    :return: The protocol version as a uint32.
 19    """
 20    resp = ec.command(0, EC_CMD_PROTO_VERSION, 0, 4)
 21    return struct.unpack("<I", resp)[0]
 22
 23
 24EC_CMD_HELLO: Final = 0x0001
 25
 26
 27def hello(ec: CrosEcClass, in_data: UInt32) -> UInt32:
 28    """
 29    Hello.  This is a simple command to test the EC is responsive to commands.
 30    :param ec: The CrOS_EC object.
 31    :param in_data: Pass anything here. Max value is 0xFFFFFFFF (uint32).
 32    :return: Output will be in_data + 0x01020304.
 33    """
 34    data = struct.pack("<I", in_data)
 35    resp = ec.command(0, EC_CMD_HELLO, len(data), 4, data)
 36    return struct.unpack("<I", resp)[0]
 37
 38
 39EC_CMD_GET_VERSION: Final = 0x0002
 40
 41
 42def get_version(ec: CrosEcClass, version: Literal[0, 1] = 0) -> dict[str, str | int]:
 43    """
 44    Get version number
 45    :param ec: The CrOS_EC object.
 46    :param version: The command version to use. Default is 0.
 47    :return: The EC version as strings, and the RW status.
 48    """
 49    match version:
 50        case 0:
 51            resp = ec.command(version, EC_CMD_GET_VERSION, 0, 32 + 32 + 32 + 4)
 52            unpacked = struct.unpack("<32s32s32sI", resp)
 53            return {
 54                "version_string_ro": unpacked[0].decode("utf-8").rstrip("\x00"),
 55                "version_string_rw": unpacked[1].decode("utf-8").rstrip("\x00"),
 56                "reserved": unpacked[2].decode("utf-8").rstrip("\x00"),
 57                "current_image": unpacked[3]
 58            }
 59        case 1:
 60            resp = ec.command(version, EC_CMD_GET_VERSION, 0, 32 + 32 + 32 + 4 + 32)
 61            unpacked = struct.unpack("<32s32s32sI32s", resp)
 62            return {
 63                "version_string_ro": unpacked[0].decode("utf-8").rstrip("\x00"),
 64                "version_string_rw": unpacked[1].decode("utf-8").rstrip("\x00"),
 65                "cros_fwid_ro": unpacked[2].decode("utf-8").rstrip("\x00"),
 66                "current_image": unpacked[3],
 67                "crod_fwid_rw": unpacked[4].decode("utf-8").rstrip("\x00")
 68            }
 69        case _:
 70            raise NotImplementedError
 71
 72
 73# Read test - OBSOLETE
 74EC_CMD_READ_TEST: Final = 0x0003
 75
 76EC_CMD_GET_BUILD_INFO: Final = 0x0004
 77
 78
 79def get_build_info(ec: CrosEcClass) -> str:
 80    """
 81    Get build information
 82    :param ec: The CrOS_EC object.
 83    :return: The build info as a string.
 84    """
 85    # 0xEC is the max command size on some platforms
 86    resp = ec.command(0, EC_CMD_GET_BUILD_INFO, 0, 0xEC, warn=False)
 87    return resp.decode("utf-8").rstrip("\x00")
 88
 89
 90EC_CMD_GET_CHIP_INFO: Final = 0x0005
 91
 92
 93def get_chip_info(ec: CrosEcClass) -> dict[str, str]:
 94    """
 95    Get chip info
 96    :param ec: The CrOS_EC object.
 97    :return: The chip vendor, name, and revision as strings.
 98    """
 99    resp = ec.command(0, EC_CMD_GET_CHIP_INFO, 0, 32 + 32 + 32)
100    unpacked = struct.unpack("<32s32s32s", resp)
101    return {
102        "vendor": unpacked[0].decode("utf-8").rstrip("\x00"),
103        "name": unpacked[1].decode("utf-8").rstrip("\x00"),
104        "revision": unpacked[2].decode("utf-8").rstrip("\x00")
105    }
106
107
108EC_CMD_GET_BOARD_VERSION: Final = 0x0006
109
110
111def get_board_version(ec: CrosEcClass) -> UInt16:
112    """
113    Get board HW version
114    :param ec: The CrOS_EC object.
115    :return: The board version as a uint16.
116    """
117    resp = ec.command(0, EC_CMD_GET_BOARD_VERSION, 0, 2)
118    return struct.unpack("<H", resp)[0]
119
120
121# use the CrOS_EC.memmap method instead
122EC_CMD_READ_MEMMAP: Final = 0x0007
123
124EC_CMD_GET_CMD_VERSIONS: Final = 0x0008
125
126
127def get_cmd_versions(ec: CrosEcClass, cmd: UInt8 | UInt16, version: Literal[0, 1] | None = None) -> UInt32 | None:
128    """
129    Read versions supported for a command.
130    :param ec: The CrOS_EC object.
131    :param cmd: The command to get the supported versions of.
132    :param version: The command version to use. Default is guess. 0 supports 8 bit commands, 1 supports 16 bit commands.
133    :return: The supported versions as a bitmask. Bit 0 is version 0, bit 1 is version 1, etc. None if the command is not supported.
134    """
135    if version is None:
136        version = int(cmd > 0xFF)
137    try:
138        match version:
139            case 0:
140                resp = ec.command(version, EC_CMD_GET_CMD_VERSIONS, 1, 4, struct.pack("<B", cmd))
141                return struct.unpack("<I", resp)[0]
142            case 1:
143                resp = ec.command(version, EC_CMD_GET_CMD_VERSIONS, 2, 4, struct.pack("<H", cmd))
144                return struct.unpack("<I", resp)[0]
145            case _:
146                raise NotImplementedError
147    except ECError as e:
148        # EC_CMD_GET_CMD_VERSIONS throws EC_RES_INVALID_PARAM if the command is not supported
149        # Catch this and return None
150        if e.status == EcStatus.EC_RES_INVALID_PARAM.value:
151            return None
152        # Otherwise, raise the exception
153        raise e
154
155
156EC_CMD_GET_COMMS_STATUS: Final = 0x0009
157
158EC_CMD_TEST_PROTOCOL: Final = 0x000A
159
160
161def test_protocol(ec: CrosEcClass, result: UInt32, ret_len: UInt32, buf: bytes, in_size: Int32 | None = None) -> bytes:
162    """
163    Fake a variety of responses, purely for testing purposes.
164    :param ec: The CrOS_EC object.
165    :param result: Result for the EC to return.
166    :param ret_len: Length of return data.
167    :param buf: Data to return. Max length is 32 bytes.
168    :param in_size: Max number of bytes to accept from the EC. None to use ret_len.
169    :return: The data returned.
170    """
171    data = struct.pack("<II", result, ret_len) + buf
172    resp = ec.command(0, EC_CMD_TEST_PROTOCOL, len(data), in_size or ret_len, data)
173    return resp
174
175
176EC_CMD_GET_PROTOCOL_INFO: Final = 0x000B
177
178
179def get_protocol_info(ec: CrosEcClass) -> dict[str, int]:
180    """
181    Get protocol info
182    :param ec: The CrOS_EC object.
183    :return: The protocol info as a dictionary.
184    """
185    resp = ec.command(0, EC_CMD_GET_PROTOCOL_INFO, 0, 12)
186    unpacked = struct.unpack("<IHHI", resp)
187    return {
188        "protocol_versions": unpacked[0],
189        "max_request_packet_size": unpacked[1],
190        "max_response_packet_size": unpacked[2],
191        "flags": unpacked[3]
192    }
EC_CMD_PROTO_VERSION: Final = 0
def proto_version(ec: cros_ec_python.baseclass.CrosEcClass) -> int:
15def proto_version(ec: CrosEcClass) -> UInt32:
16    """
17    Get protocol version, used to deal with non-backward compatible protocol changes.
18    :param ec: The CrOS_EC object.
19    :return: The protocol version as a uint32.
20    """
21    resp = ec.command(0, EC_CMD_PROTO_VERSION, 0, 4)
22    return struct.unpack("<I", resp)[0]

Get protocol version, used to deal with non-backward compatible protocol changes.

Parameters
  • ec: The CrOS_EC object.
Returns

The protocol version as a uint32.

EC_CMD_HELLO: Final = 1
def hello(ec: cros_ec_python.baseclass.CrosEcClass, in_data: int) -> int:
28def hello(ec: CrosEcClass, in_data: UInt32) -> UInt32:
29    """
30    Hello.  This is a simple command to test the EC is responsive to commands.
31    :param ec: The CrOS_EC object.
32    :param in_data: Pass anything here. Max value is 0xFFFFFFFF (uint32).
33    :return: Output will be in_data + 0x01020304.
34    """
35    data = struct.pack("<I", in_data)
36    resp = ec.command(0, EC_CMD_HELLO, len(data), 4, data)
37    return struct.unpack("<I", resp)[0]

Hello. This is a simple command to test the EC is responsive to commands.

Parameters
  • ec: The CrOS_EC object.
  • in_data: Pass anything here. Max value is 0xFFFFFFFF (uint32).
Returns

Output will be in_data + 0x01020304.

EC_CMD_GET_VERSION: Final = 2
def get_version( ec: cros_ec_python.baseclass.CrosEcClass, version: Literal[0, 1] = 0) -> dict[str, str | int]:
43def get_version(ec: CrosEcClass, version: Literal[0, 1] = 0) -> dict[str, str | int]:
44    """
45    Get version number
46    :param ec: The CrOS_EC object.
47    :param version: The command version to use. Default is 0.
48    :return: The EC version as strings, and the RW status.
49    """
50    match version:
51        case 0:
52            resp = ec.command(version, EC_CMD_GET_VERSION, 0, 32 + 32 + 32 + 4)
53            unpacked = struct.unpack("<32s32s32sI", resp)
54            return {
55                "version_string_ro": unpacked[0].decode("utf-8").rstrip("\x00"),
56                "version_string_rw": unpacked[1].decode("utf-8").rstrip("\x00"),
57                "reserved": unpacked[2].decode("utf-8").rstrip("\x00"),
58                "current_image": unpacked[3]
59            }
60        case 1:
61            resp = ec.command(version, EC_CMD_GET_VERSION, 0, 32 + 32 + 32 + 4 + 32)
62            unpacked = struct.unpack("<32s32s32sI32s", resp)
63            return {
64                "version_string_ro": unpacked[0].decode("utf-8").rstrip("\x00"),
65                "version_string_rw": unpacked[1].decode("utf-8").rstrip("\x00"),
66                "cros_fwid_ro": unpacked[2].decode("utf-8").rstrip("\x00"),
67                "current_image": unpacked[3],
68                "crod_fwid_rw": unpacked[4].decode("utf-8").rstrip("\x00")
69            }
70        case _:
71            raise NotImplementedError

Get version number

Parameters
  • ec: The CrOS_EC object.
  • version: The command version to use. Default is 0.
Returns

The EC version as strings, and the RW status.

EC_CMD_READ_TEST: Final = 3
EC_CMD_GET_BUILD_INFO: Final = 4
def get_build_info(ec: cros_ec_python.baseclass.CrosEcClass) -> str:
80def get_build_info(ec: CrosEcClass) -> str:
81    """
82    Get build information
83    :param ec: The CrOS_EC object.
84    :return: The build info as a string.
85    """
86    # 0xEC is the max command size on some platforms
87    resp = ec.command(0, EC_CMD_GET_BUILD_INFO, 0, 0xEC, warn=False)
88    return resp.decode("utf-8").rstrip("\x00")

Get build information

Parameters
  • ec: The CrOS_EC object.
Returns

The build info as a string.

EC_CMD_GET_CHIP_INFO: Final = 5
def get_chip_info(ec: cros_ec_python.baseclass.CrosEcClass) -> dict[str, str]:
 94def get_chip_info(ec: CrosEcClass) -> dict[str, str]:
 95    """
 96    Get chip info
 97    :param ec: The CrOS_EC object.
 98    :return: The chip vendor, name, and revision as strings.
 99    """
100    resp = ec.command(0, EC_CMD_GET_CHIP_INFO, 0, 32 + 32 + 32)
101    unpacked = struct.unpack("<32s32s32s", resp)
102    return {
103        "vendor": unpacked[0].decode("utf-8").rstrip("\x00"),
104        "name": unpacked[1].decode("utf-8").rstrip("\x00"),
105        "revision": unpacked[2].decode("utf-8").rstrip("\x00")
106    }

Get chip info

Parameters
  • ec: The CrOS_EC object.
Returns

The chip vendor, name, and revision as strings.

EC_CMD_GET_BOARD_VERSION: Final = 6
def get_board_version(ec: cros_ec_python.baseclass.CrosEcClass) -> int:
112def get_board_version(ec: CrosEcClass) -> UInt16:
113    """
114    Get board HW version
115    :param ec: The CrOS_EC object.
116    :return: The board version as a uint16.
117    """
118    resp = ec.command(0, EC_CMD_GET_BOARD_VERSION, 0, 2)
119    return struct.unpack("<H", resp)[0]

Get board HW version

Parameters
  • ec: The CrOS_EC object.
Returns

The board version as a uint16.

EC_CMD_READ_MEMMAP: Final = 7
EC_CMD_GET_CMD_VERSIONS: Final = 8
def get_cmd_versions( ec: cros_ec_python.baseclass.CrosEcClass, cmd: int, version: Optional[Literal[0, 1]] = None) -> int | None:
128def get_cmd_versions(ec: CrosEcClass, cmd: UInt8 | UInt16, version: Literal[0, 1] | None = None) -> UInt32 | None:
129    """
130    Read versions supported for a command.
131    :param ec: The CrOS_EC object.
132    :param cmd: The command to get the supported versions of.
133    :param version: The command version to use. Default is guess. 0 supports 8 bit commands, 1 supports 16 bit commands.
134    :return: The supported versions as a bitmask. Bit 0 is version 0, bit 1 is version 1, etc. None if the command is not supported.
135    """
136    if version is None:
137        version = int(cmd > 0xFF)
138    try:
139        match version:
140            case 0:
141                resp = ec.command(version, EC_CMD_GET_CMD_VERSIONS, 1, 4, struct.pack("<B", cmd))
142                return struct.unpack("<I", resp)[0]
143            case 1:
144                resp = ec.command(version, EC_CMD_GET_CMD_VERSIONS, 2, 4, struct.pack("<H", cmd))
145                return struct.unpack("<I", resp)[0]
146            case _:
147                raise NotImplementedError
148    except ECError as e:
149        # EC_CMD_GET_CMD_VERSIONS throws EC_RES_INVALID_PARAM if the command is not supported
150        # Catch this and return None
151        if e.status == EcStatus.EC_RES_INVALID_PARAM.value:
152            return None
153        # Otherwise, raise the exception
154        raise e

Read versions supported for a command.

Parameters
  • ec: The CrOS_EC object.
  • cmd: The command to get the supported versions of.
  • version: The command version to use. Default is guess. 0 supports 8 bit commands, 1 supports 16 bit commands.
Returns

The supported versions as a bitmask. Bit 0 is version 0, bit 1 is version 1, etc. None if the command is not supported.

EC_CMD_GET_COMMS_STATUS: Final = 9
EC_CMD_TEST_PROTOCOL: Final = 10
def test_protocol( ec: cros_ec_python.baseclass.CrosEcClass, result: int, ret_len: int, buf: bytes, in_size: int | None = None) -> bytes:
162def test_protocol(ec: CrosEcClass, result: UInt32, ret_len: UInt32, buf: bytes, in_size: Int32 | None = None) -> bytes:
163    """
164    Fake a variety of responses, purely for testing purposes.
165    :param ec: The CrOS_EC object.
166    :param result: Result for the EC to return.
167    :param ret_len: Length of return data.
168    :param buf: Data to return. Max length is 32 bytes.
169    :param in_size: Max number of bytes to accept from the EC. None to use ret_len.
170    :return: The data returned.
171    """
172    data = struct.pack("<II", result, ret_len) + buf
173    resp = ec.command(0, EC_CMD_TEST_PROTOCOL, len(data), in_size or ret_len, data)
174    return resp

Fake a variety of responses, purely for testing purposes.

Parameters
  • ec: The CrOS_EC object.
  • result: Result for the EC to return.
  • ret_len: Length of return data.
  • buf: Data to return. Max length is 32 bytes.
  • in_size: Max number of bytes to accept from the EC. None to use ret_len.
Returns

The data returned.

EC_CMD_GET_PROTOCOL_INFO: Final = 11
def get_protocol_info(ec: cros_ec_python.baseclass.CrosEcClass) -> dict[str, int]:
180def get_protocol_info(ec: CrosEcClass) -> dict[str, int]:
181    """
182    Get protocol info
183    :param ec: The CrOS_EC object.
184    :return: The protocol info as a dictionary.
185    """
186    resp = ec.command(0, EC_CMD_GET_PROTOCOL_INFO, 0, 12)
187    unpacked = struct.unpack("<IHHI", resp)
188    return {
189        "protocol_versions": unpacked[0],
190        "max_request_packet_size": unpacked[1],
191        "max_response_packet_size": unpacked[2],
192        "flags": unpacked[3]
193    }

Get protocol info

Parameters
  • ec: The CrOS_EC object.
Returns

The protocol info as a dictionary.