cros_ec_python.commands.memmap

These functions are used to get the values of the memory-mapped data.

They aren't actually commands that are sent to the EC (usually), but rather data that is read from the EC. This is why they aren't mixed in with the other commands.

  1"""
  2These functions are used to get the values of the memory-mapped data.
  3
  4They aren't actually commands that are sent to the EC (usually), but rather data that is read from the EC.
  5This is why they aren't mixed in with the other commands.
  6"""
  7
  8
  9import struct
 10from ..baseclass import CrosEcClass
 11from ..constants.COMMON import *
 12from ..constants.MEMMAP import *
 13
 14
 15def get_temps(ec: CrosEcClass, adjust: int | float = -273) -> list[int | float]:
 16    """
 17    Get the temperature of all temp sensors.
 18    :param ec: The CrOS_EC object.
 19    :param adjust: The adjustment to apply to the temperature. Default is -273 to convert from Kelvin to Celsius.
 20    :return: A list of temperatures.
 21    """
 22    version = int(ec.memmap(EC_MEMMAP_THERMAL_VERSION, 1)[0])
 23    if not version:
 24        # No temp sensors supported
 25        return []
 26
 27    ret = []
 28    if version >= 1:
 29        resp = ec.memmap(EC_MEMMAP_TEMP_SENSOR, EC_TEMP_SENSOR_ENTRIES)
 30        temps = struct.unpack(f"<{EC_TEMP_SENSOR_ENTRIES}B", resp)
 31        ret += [temp + EC_TEMP_SENSOR_OFFSET + adjust for temp in temps if temp < 0xFC]
 32
 33    if version >= 2:
 34        resp = ec.memmap(EC_MEMMAP_TEMP_SENSOR_B, EC_TEMP_SENSOR_B_ENTRIES)
 35        temps = struct.unpack(f"<{EC_TEMP_SENSOR_B_ENTRIES}B", resp)
 36        ret += [temp + EC_TEMP_SENSOR_OFFSET + adjust for temp in temps if temp < 0xFC]
 37
 38    return ret
 39
 40
 41def get_fans(ec: CrosEcClass) -> list[int | None]:
 42    """
 43    Get the speed of all fans.
 44    :param ec: The CrOS_EC object.
 45    :return: A list of fan speeds. None if the fan has stalled.
 46    """
 47    version = int(ec.memmap(EC_MEMMAP_THERMAL_VERSION, 1)[0])
 48    if not version:
 49        # No fans supported
 50        return []
 51
 52    resp = ec.memmap(EC_MEMMAP_FAN, EC_FAN_SPEED_ENTRIES * 2)  # 2 bytes per fan
 53    fans = struct.unpack(f"<{EC_FAN_SPEED_ENTRIES}H", resp)
 54    return [None if fan is EC_FAN_SPEED_STALLED else fan for fan in fans if fan < EC_FAN_SPEED_NOT_PRESENT]
 55
 56
 57def get_switches(ec: CrosEcClass) -> dict[str, bool]:
 58    """
 59    Get the state of the switches.
 60    :param ec: The CrOS_EC object.
 61    :return: The state of the switches.
 62    """
 63    version = int(ec.memmap(EC_MEMMAP_SWITCHES_VERSION, 1)[0])
 64    if not version:
 65        # No switches supported
 66        return {}
 67
 68    resp = ec.memmap(EC_MEMMAP_SWITCHES, 1)[0]
 69    return {
 70        "lid_open": bool(resp & EC_SWITCH_LID_OPEN),
 71        "power_button_pressed": bool(resp & EC_SWITCH_POWER_BUTTON_PRESSED),
 72        "write_protect_disabled": bool(resp & EC_SWITCH_WRITE_PROTECT_DISABLED),
 73        "dedicated_recovery": bool(resp & EC_SWITCH_DEDICATED_RECOVERY)
 74    }
 75
 76
 77def get_battery_values(ec: CrosEcClass) -> dict[str, int | bool | str]:
 78    """
 79    Get the values of the battery.
 80    :param ec: The CrOS_EC object.
 81    :return: The state of the battery.
 82    """
 83    version = int(ec.memmap(EC_MEMMAP_BATTERY_VERSION, 1)[0])
 84    if not version:
 85        # No battery supported
 86        return {}
 87
 88    resp = ec.memmap(EC_MEMMAP_BATT_VOLT, EC_MEMMAP_ALS - EC_MEMMAP_BATT_VOLT)
 89    data = struct.unpack("<IIIBBBxIIII8s8s8s8s", resp)
 90    return {
 91        "volt": data[0],
 92        "rate": data[1],
 93        "capacity": data[2],
 94        "ac_present": bool(data[3] & EC_BATT_FLAG_AC_PRESENT),
 95        "batt_present": bool(data[3] & EC_BATT_FLAG_BATT_PRESENT),
 96        "discharging": bool(data[3] & EC_BATT_FLAG_DISCHARGING),
 97        "charging": bool(data[3] & EC_BATT_FLAG_CHARGING),
 98        "level_critical": bool(data[3] & EC_BATT_FLAG_LEVEL_CRITICAL),
 99        "invalid_data": bool(data[3] & EC_BATT_FLAG_INVALID_DATA),
100        "count": data[4],
101        "index": data[5],
102        "design_capacity": data[6],
103        "design_voltage": data[7],
104        "last_full_charge_capacity": data[8],
105        "cycle_count": data[9],
106        "manufacturer": data[10].decode("utf-8").rstrip("\x00"),
107        "model": data[11].decode("utf-8").rstrip("\x00"),
108        "serial": data[12].decode("utf-8").rstrip("\x00"),
109        "type": data[13].decode("utf-8").rstrip("\x00")
110    }
111
112
113def get_als(ec: CrosEcClass) -> list[int]:
114    """
115    Get the current value from all Ambient Light Sensors.
116    :param ec: The CrOS_EC object.
117    :return: A list of ALS values. May be 0 if the sensor is not present.
118    """
119    resp = ec.memmap(EC_MEMMAP_ALS, EC_ALS_ENTRIES * 2)  # 2 bytes per sensor
120    als = struct.unpack(f"<{EC_ALS_ENTRIES}H", resp)
121    return [val for val in als]
122
123
124def get_accel(ec: CrosEcClass) -> list[int]:
125    """
126    Get the current value from all accelerometers.
127    :param ec: The CrOS_EC object.
128    :return: A list of accelerometer values. May be 0 if the sensor is not present.
129    """
130    EC_ACC_ENTRIES: Final = 3
131    resp = ec.memmap(EC_MEMMAP_ACC_DATA, EC_ACC_ENTRIES * 2)  # 2 bytes per sensor
132    accel = struct.unpack(f"<{EC_ACC_ENTRIES}H", resp)
133    return [val for val in accel]
def get_temps( ec: cros_ec_python.baseclass.CrosEcClass, adjust: int | float = -273) -> list[int | float]:
16def get_temps(ec: CrosEcClass, adjust: int | float = -273) -> list[int | float]:
17    """
18    Get the temperature of all temp sensors.
19    :param ec: The CrOS_EC object.
20    :param adjust: The adjustment to apply to the temperature. Default is -273 to convert from Kelvin to Celsius.
21    :return: A list of temperatures.
22    """
23    version = int(ec.memmap(EC_MEMMAP_THERMAL_VERSION, 1)[0])
24    if not version:
25        # No temp sensors supported
26        return []
27
28    ret = []
29    if version >= 1:
30        resp = ec.memmap(EC_MEMMAP_TEMP_SENSOR, EC_TEMP_SENSOR_ENTRIES)
31        temps = struct.unpack(f"<{EC_TEMP_SENSOR_ENTRIES}B", resp)
32        ret += [temp + EC_TEMP_SENSOR_OFFSET + adjust for temp in temps if temp < 0xFC]
33
34    if version >= 2:
35        resp = ec.memmap(EC_MEMMAP_TEMP_SENSOR_B, EC_TEMP_SENSOR_B_ENTRIES)
36        temps = struct.unpack(f"<{EC_TEMP_SENSOR_B_ENTRIES}B", resp)
37        ret += [temp + EC_TEMP_SENSOR_OFFSET + adjust for temp in temps if temp < 0xFC]
38
39    return ret

Get the temperature of all temp sensors.

Parameters
  • ec: The CrOS_EC object.
  • adjust: The adjustment to apply to the temperature. Default is -273 to convert from Kelvin to Celsius.
Returns

A list of temperatures.

def get_fans(ec: cros_ec_python.baseclass.CrosEcClass) -> list[int | None]:
42def get_fans(ec: CrosEcClass) -> list[int | None]:
43    """
44    Get the speed of all fans.
45    :param ec: The CrOS_EC object.
46    :return: A list of fan speeds. None if the fan has stalled.
47    """
48    version = int(ec.memmap(EC_MEMMAP_THERMAL_VERSION, 1)[0])
49    if not version:
50        # No fans supported
51        return []
52
53    resp = ec.memmap(EC_MEMMAP_FAN, EC_FAN_SPEED_ENTRIES * 2)  # 2 bytes per fan
54    fans = struct.unpack(f"<{EC_FAN_SPEED_ENTRIES}H", resp)
55    return [None if fan is EC_FAN_SPEED_STALLED else fan for fan in fans if fan < EC_FAN_SPEED_NOT_PRESENT]

Get the speed of all fans.

Parameters
  • ec: The CrOS_EC object.
Returns

A list of fan speeds. None if the fan has stalled.

def get_switches(ec: cros_ec_python.baseclass.CrosEcClass) -> dict[str, bool]:
58def get_switches(ec: CrosEcClass) -> dict[str, bool]:
59    """
60    Get the state of the switches.
61    :param ec: The CrOS_EC object.
62    :return: The state of the switches.
63    """
64    version = int(ec.memmap(EC_MEMMAP_SWITCHES_VERSION, 1)[0])
65    if not version:
66        # No switches supported
67        return {}
68
69    resp = ec.memmap(EC_MEMMAP_SWITCHES, 1)[0]
70    return {
71        "lid_open": bool(resp & EC_SWITCH_LID_OPEN),
72        "power_button_pressed": bool(resp & EC_SWITCH_POWER_BUTTON_PRESSED),
73        "write_protect_disabled": bool(resp & EC_SWITCH_WRITE_PROTECT_DISABLED),
74        "dedicated_recovery": bool(resp & EC_SWITCH_DEDICATED_RECOVERY)
75    }

Get the state of the switches.

Parameters
  • ec: The CrOS_EC object.
Returns

The state of the switches.

def get_battery_values(ec: cros_ec_python.baseclass.CrosEcClass) -> dict[str, int | bool | str]:
 78def get_battery_values(ec: CrosEcClass) -> dict[str, int | bool | str]:
 79    """
 80    Get the values of the battery.
 81    :param ec: The CrOS_EC object.
 82    :return: The state of the battery.
 83    """
 84    version = int(ec.memmap(EC_MEMMAP_BATTERY_VERSION, 1)[0])
 85    if not version:
 86        # No battery supported
 87        return {}
 88
 89    resp = ec.memmap(EC_MEMMAP_BATT_VOLT, EC_MEMMAP_ALS - EC_MEMMAP_BATT_VOLT)
 90    data = struct.unpack("<IIIBBBxIIII8s8s8s8s", resp)
 91    return {
 92        "volt": data[0],
 93        "rate": data[1],
 94        "capacity": data[2],
 95        "ac_present": bool(data[3] & EC_BATT_FLAG_AC_PRESENT),
 96        "batt_present": bool(data[3] & EC_BATT_FLAG_BATT_PRESENT),
 97        "discharging": bool(data[3] & EC_BATT_FLAG_DISCHARGING),
 98        "charging": bool(data[3] & EC_BATT_FLAG_CHARGING),
 99        "level_critical": bool(data[3] & EC_BATT_FLAG_LEVEL_CRITICAL),
100        "invalid_data": bool(data[3] & EC_BATT_FLAG_INVALID_DATA),
101        "count": data[4],
102        "index": data[5],
103        "design_capacity": data[6],
104        "design_voltage": data[7],
105        "last_full_charge_capacity": data[8],
106        "cycle_count": data[9],
107        "manufacturer": data[10].decode("utf-8").rstrip("\x00"),
108        "model": data[11].decode("utf-8").rstrip("\x00"),
109        "serial": data[12].decode("utf-8").rstrip("\x00"),
110        "type": data[13].decode("utf-8").rstrip("\x00")
111    }

Get the values of the battery.

Parameters
  • ec: The CrOS_EC object.
Returns

The state of the battery.

def get_als(ec: cros_ec_python.baseclass.CrosEcClass) -> list[int]:
114def get_als(ec: CrosEcClass) -> list[int]:
115    """
116    Get the current value from all Ambient Light Sensors.
117    :param ec: The CrOS_EC object.
118    :return: A list of ALS values. May be 0 if the sensor is not present.
119    """
120    resp = ec.memmap(EC_MEMMAP_ALS, EC_ALS_ENTRIES * 2)  # 2 bytes per sensor
121    als = struct.unpack(f"<{EC_ALS_ENTRIES}H", resp)
122    return [val for val in als]

Get the current value from all Ambient Light Sensors.

Parameters
  • ec: The CrOS_EC object.
Returns

A list of ALS values. May be 0 if the sensor is not present.

def get_accel(ec: cros_ec_python.baseclass.CrosEcClass) -> list[int]:
125def get_accel(ec: CrosEcClass) -> list[int]:
126    """
127    Get the current value from all accelerometers.
128    :param ec: The CrOS_EC object.
129    :return: A list of accelerometer values. May be 0 if the sensor is not present.
130    """
131    EC_ACC_ENTRIES: Final = 3
132    resp = ec.memmap(EC_MEMMAP_ACC_DATA, EC_ACC_ENTRIES * 2)  # 2 bytes per sensor
133    accel = struct.unpack(f"<{EC_ACC_ENTRIES}H", resp)
134    return [val for val in accel]

Get the current value from all accelerometers.

Parameters
  • ec: The CrOS_EC object.
Returns

A list of accelerometer values. May be 0 if the sensor is not present.