Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
cerebro1 committed Aug 10, 2022
1 parent b342425 commit 3ebd75d
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 0 deletions.
92 changes: 92 additions & 0 deletions src/shared/sleep-config.c
Expand Up @@ -41,10 +41,14 @@
#include "string-util.h"
#include "strv.h"
#include "time-util.h"
#include "unaligned.h"


#define BATTERY_LOW_CAPACITY_LEVEL 5
#define DISCHARGE_RATE_FILEPATH "/var/lib/systemd/sleep/battery_discharge_percentage_rate_per_hour"
#define BATTERY_DISCHARGE_RATE_HASH_KEY SD_ID128_MAKE(5f,9a,20,18,38,76,46,07,8d,36,58,0b,bb,c4,e0,63)
#define SYS_ENTRY_RAW_FILE_TYPE1 "/sys/firmware/dmi/entries/1-0/raw"
#define POWER_SUPPLY_DIRPATH "/sys/class/power_supply"

static void *CAPACITY_TO_PTR(int capacity) {
assert(capacity >= 0);
Expand All @@ -59,6 +63,12 @@ static int PTR_TO_CAPACITY(void *p) {
return capacity;
}

enum {
SMBIOS_WAKEUP_BIT_SET,
SMBIOS_WAKEUP_BIT_UNSET,
SMBIOS_WAKEUP_BIT_UNKNOWN,
};

int parse_sleep_config(SleepConfig **ret_sleep_config) {
_cleanup_(free_sleep_configp) SleepConfig *sc = NULL;
int allow_suspend = -1, allow_hibernate = -1,
Expand Down Expand Up @@ -526,6 +536,88 @@ int get_total_suspend_interval(Hashmap *last_capacity, usec_t *ret) {
return 0;
}

static int read_power_supply_battery_alarm_file(const char *alarm_filepath, int *ret) {
_cleanup_free_ char *batterytrippoint = NULL;
int battery_alarm, r;

r = read_one_line_file(alarm_filepath, &batterytrippoint);
if (r < 0)
return r;

r = safe_atoi(batterytrippoint, &battery_alarm);
if (r < 0)
return r;

*ret = battery_alarm;

return 0;
}

bool battery_trip_point_alarm_exists(void) {
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
sd_device *dev;
int r;

r = battery_enumerator_new(&e);
if (r < 0)
return log_debug_errno(r, "Failed to initialize battery enumerator: %m");

FOREACH_DEVICE(e, dev) {
const char *battery_name, *alarm_filepath;
int battery_alarm;

r = sd_device_get_property_value(dev, "POWER_SUPPLY_NAME", &battery_name);
if (r < 0) {
log_device_debug_errno(dev, r, "Failed to read battery name, ignoring: %m");
continue;
}

alarm_filepath = path_join(POWER_SUPPLY_DIRPATH, battery_name, "alarm");
r = read_power_supply_battery_alarm_file(alarm_filepath, &battery_alarm);
if (r < 0) {
log_device_debug_errno(dev, r, "Failed to read battery alarm from %s, ignoring: %m", alarm_filepath);
continue;
}
if (battery_alarm <= 0)
return false;
}

return true;
}

/* Get wakeup-type from dmi tables */
int get_dmi_wakeup_type(char *ret) {
_cleanup_free_ char *s = NULL;
char offset_char;
size_t readsize;
int offset_int, r;

/* implementation via dmi/entries */
r = read_full_virtual_file(SYS_ENTRY_RAW_FILE_TYPE1, &s, &readsize);
if (r < 0) {
log_debug_errno(r, "Unable to read %s, ignoring: %m", SYS_ENTRY_RAW_FILE_TYPE1);
return SMBIOS_WAKEUP_BIT_UNKNOWN;
}
if (readsize < 25 || s[1] < 25) {
log_debug("Only read %zu bytes from %s (expected 24)", readsize, SYS_ENTRY_RAW_FILE_TYPE1);
return SMBIOS_WAKEUP_BIT_UNKNOWN;
}

offset_char = s[24];
if (offset_char) {
log_debug("DMI BIOS System Information indicates wakeup type bit is set.");

r = safe_atoi(&offset_char, &offset_int);
if (r < 0)
return log_debug_errno(r, "Failed to parse wakeup type offset value: %m");

*ret = offset_int;
return SMBIOS_WAKEUP_BIT_SET;
}
log_debug("DMI BIOS System Information does not indicate wakeup type bit is set.");
return SMBIOS_WAKEUP_BIT_UNSET;
}

int can_sleep_state(char **types) {
_cleanup_free_ char *text = NULL;
int r;
Expand Down
4 changes: 4 additions & 0 deletions src/shared/sleep-config.h
Expand Up @@ -4,6 +4,7 @@
#include <linux/fiemap.h>

#include "hashmap.h"
#include "sd-device.h"
#include "time-util.h"

typedef enum SleepOperation {
Expand Down Expand Up @@ -65,6 +66,9 @@ int estimate_battery_discharge_rate_per_hour(
Hashmap *current_capacity,
usec_t before_timestamp,
usec_t after_timestamp);
int get_dmi_wakeup_type(char *ret);

bool battery_trip_point_alarm_exists(void);

const char* sleep_operation_to_string(SleepOperation s) _const_;
SleepOperation sleep_operation_from_string(const char *s) _pure_;
13 changes: 13 additions & 0 deletions src/sleep/sleep.c
Expand Up @@ -35,6 +35,12 @@
#include "time-util.h"
#include "util.h"

enum {
SMBIOS_WAKEUP_BIT_SET,
SMBIOS_WAKEUP_BIT_UNSET,
SMBIOS_WAKEUP_BIT_UNKNOWN,
};

static SleepOperation arg_operation = _SLEEP_OPERATION_INVALID;

static int write_hibernate_location_info(const HibernateLocation *hibernate_location) {
Expand Down Expand Up @@ -264,10 +270,16 @@ static int execute(

static int execute_s2h(const SleepConfig *sleep_config) {
_cleanup_hashmap_free_ Hashmap *last_capacity = NULL, *current_capacity = NULL;
char *wakeup_type_byte = NULL;
int r;

assert(sleep_config);

r = get_dmi_wakeup_type(wakeup_type_byte);
log_debug("bit returned is %s", wakeup_type_byte);
if (PTR_TO_INT(wakeup_type_byte) == 3)
log_debug("wakeup type is apm timer");

while (battery_is_low() == 0) {
_cleanup_close_ int tfd = -1;
struct itimerspec ts = {};
Expand Down Expand Up @@ -332,6 +344,7 @@ static int execute_s2h(const SleepConfig *sleep_config) {
} else
log_debug("System woke up too early to estimate discharge rate");


if (!woken_by_timer)
/* Return as manual wakeup done. This also will return in case battery was charged during suspension */
return 0;
Expand Down

0 comments on commit 3ebd75d

Please sign in to comment.