module/battery: error handling during initialization

This commit is contained in:
Daniel Eklöf 2018-12-19 20:54:36 +01:00
parent ffaec546f5
commit 7e95862e12

View file

@ -26,6 +26,7 @@ struct private {
char *battery; char *battery;
char *manufacturer; char *manufacturer;
char *model; char *model;
long energy_full_design;
long energy_full; long energy_full;
enum state state; enum state state;
@ -132,20 +133,22 @@ readint_from_fd(int fd)
} }
static int static int
run(struct module_run_context *ctx) initialize(struct private *m)
{ {
const struct bar *bar = ctx->module->bar;
struct private *m = ctx->module->private;
int pw_fd = open("/sys/class/power_supply", O_RDONLY); int pw_fd = open("/sys/class/power_supply", O_RDONLY);
assert(pw_fd != -1); if (pw_fd == -1)
return -1;
int base_dir_fd = openat(pw_fd, m->battery, O_RDONLY); int base_dir_fd = openat(pw_fd, m->battery, O_RDONLY);
assert(base_dir_fd != -1); close(pw_fd);
if (base_dir_fd == -1)
return -1;
{ {
int fd = openat(base_dir_fd, "manufacturer", O_RDONLY); int fd = openat(base_dir_fd, "manufacturer", O_RDONLY);
assert(fd != -1); if (fd == -1)
goto err;
m->manufacturer = strdup(readline_from_fd(fd)); m->manufacturer = strdup(readline_from_fd(fd));
close(fd); close(fd);
@ -153,77 +156,43 @@ run(struct module_run_context *ctx)
{ {
int fd = openat(base_dir_fd, "model_name", O_RDONLY); int fd = openat(base_dir_fd, "model_name", O_RDONLY);
assert(fd != -1); if (fd == -1)
goto err;
m->model = strdup(readline_from_fd(fd)); m->model = strdup(readline_from_fd(fd));
close(fd); close(fd);
} }
long energy_full_design = 0;
{ {
int fd = openat(base_dir_fd, "energy_full_design", O_RDONLY); int fd = openat(base_dir_fd, "energy_full_design", O_RDONLY);
assert(fd != -1); if (fd == -1)
goto err;
energy_full_design = readint_from_fd(fd); m->energy_full_design = readint_from_fd(fd);
close(fd); close(fd);
} }
{ {
int fd = openat(base_dir_fd, "energy_full", O_RDONLY); int fd = openat(base_dir_fd, "energy_full", O_RDONLY);
assert(fd != -1); if (fd == -1)
goto err;
m->energy_full = readint_from_fd(fd); m->energy_full = readint_from_fd(fd);
close(fd); close(fd);
} }
LOG_INFO("%s: %s %s (at %.1f%% of original capacity)", return base_dir_fd;
m->battery, m->manufacturer, m->model,
100.0 * m->energy_full / energy_full_design);
int status_fd = openat(base_dir_fd, "status", O_RDONLY); err:
assert(status_fd != -1); close(base_dir_fd);
return -1;
}
int capacity_fd = openat(base_dir_fd, "capacity", O_RDONLY); static void
assert(capacity_fd != -1); update_status(struct module *mod, int capacity_fd, int energy_fd, int power_fd,
int status_fd)
int energy_fd = openat(base_dir_fd, "energy_now", O_RDONLY); {
assert(energy_fd != -1); struct private *m = mod->private;
int power_fd = openat(base_dir_fd, "power_now", O_RDONLY);
assert(power_fd != -1);
struct udev *udev = udev_new();
struct udev_monitor *mon = udev_monitor_new_from_netlink(udev, "udev");
udev_monitor_filter_add_match_subsystem_devtype(mon, "power_supply", NULL);
udev_monitor_enable_receiving(mon);
module_signal_ready(ctx);
bool first = true;
while (true) {
if (!first) {
struct pollfd fds[] = {
{.fd = ctx->abort_fd, .events = POLLIN},
{.fd = udev_monitor_get_fd(mon), .events = POLLIN},
};
poll(fds, 2, m->poll_interval * 1000);
if (fds[0].revents & POLLIN)
break;
if (fds[1].revents & POLLIN) {
struct udev_device *dev = udev_monitor_receive_device(mon);
const char *sysname = udev_device_get_sysname(dev);
bool is_us = strcmp(sysname, m->battery) == 0;
udev_device_unref(dev);
if (!is_us)
continue;
}
} else
first = false;
long capacity = readint_from_fd(capacity_fd); long capacity = readint_from_fd(capacity_fd);
long energy = readint_from_fd(energy_fd); long energy = readint_from_fd(energy_fd);
@ -249,26 +218,94 @@ run(struct module_run_context *ctx)
LOG_DBG("capacity: %ld, energy: %ld, power: %ld", LOG_DBG("capacity: %ld, energy: %ld, power: %ld",
capacity, energy, power); capacity, energy, power);
mtx_lock(&ctx->module->lock); mtx_lock(&mod->lock);
m->state = state; m->state = state;
m->capacity = capacity; m->capacity = capacity;
m->energy = energy; m->energy = energy;
m->power = power; m->power = power;
mtx_unlock(&ctx->module->lock); mtx_unlock(&mod->lock);
}
static int
run(struct module_run_context *ctx)
{
const struct bar *bar = ctx->module->bar;
struct private *m = ctx->module->private;
int base_dir_fd = initialize(m);
if (base_dir_fd == -1) {
module_signal_ready(ctx);
return -1;
}
LOG_INFO("%s: %s %s (at %.1f%% of original capacity)",
m->battery, m->manufacturer, m->model,
100.0 * m->energy_full / m->energy_full_design);
int ret = -1;
int status_fd = openat(base_dir_fd, "status", O_RDONLY);
int capacity_fd = openat(base_dir_fd, "capacity", O_RDONLY);
int energy_fd = openat(base_dir_fd, "energy_now", O_RDONLY);
int power_fd = openat(base_dir_fd, "power_now", O_RDONLY);
struct udev *udev = udev_new();
struct udev_monitor *mon = udev_monitor_new_from_netlink(udev, "udev");
if (status_fd == -1 || capacity_fd == -1 || energy_fd == -1 ||
power_fd == -1 || udev == NULL || mon == NULL)
{
module_signal_ready(ctx);
goto out;
}
udev_monitor_filter_add_match_subsystem_devtype(mon, "power_supply", NULL);
udev_monitor_enable_receiving(mon);
update_status(ctx->module, capacity_fd, energy_fd, power_fd, status_fd);
module_signal_ready(ctx);
while (true) {
struct pollfd fds[] = {
{.fd = ctx->abort_fd, .events = POLLIN},
{.fd = udev_monitor_get_fd(mon), .events = POLLIN},
};
poll(fds, 2, m->poll_interval * 1000);
if (fds[0].revents & POLLIN)
break;
if (fds[1].revents & POLLIN) {
struct udev_device *dev = udev_monitor_receive_device(mon);
const char *sysname = udev_device_get_sysname(dev);
bool is_us = strcmp(sysname, m->battery) == 0;
udev_device_unref(dev);
if (!is_us)
continue;
}
update_status(ctx->module, capacity_fd, energy_fd, power_fd, status_fd);
bar->refresh(bar); bar->refresh(bar);
} }
out:
if (mon != NULL)
udev_monitor_unref(mon); udev_monitor_unref(mon);
if (udev != NULL)
udev_unref(udev); udev_unref(udev);
if (power_fd != -1)
close(power_fd); close(power_fd);
if (energy_fd != -1)
close(energy_fd); close(energy_fd);
if (capacity_fd != -1)
close(capacity_fd); close(capacity_fd);
if (status_fd != -1)
close(status_fd); close(status_fd);
close(base_dir_fd); close(base_dir_fd);
close(pw_fd); return ret;
return 0;
} }
struct module * struct module *