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