From fa3c17aa4a11829d543cb7c0eaa752b72fed2051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 16 Dec 2018 17:04:44 +0100 Subject: [PATCH] module/battery: use libudev to monitor for battery changes This allows us to detect plug/unplug events immediately, instead of having to wait for the next poll event. Unfortunately, capacity changes do not appear to generate events :( --- CMakeLists.txt | 4 ++++ modules/battery/battery.c | 47 +++++++++++++++++++++++++++++++++------ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 11ea46e..48b7a48 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ pkg_check_modules(CAIRO REQUIRED cairo cairo-xcb) # Core pkg_check_modules(YAML REQUIRED yaml-0.1) # Core (configuration) pkg_check_modules(JSON REQUIRED json-c) # Module/i3 +pkg_check_modules(UDEV REQUIRED libudev) # Module/battery add_executable(f00bar bar.c bar.h @@ -47,6 +48,7 @@ target_compile_options(f00bar PRIVATE ${CAIRO_CFLAGS_OTHER} ${YAML_CFLAGS_OTHER} ${JSON_CFLAGS_OTHER} + ${UDEV_CFLAGS_OTHER} ) target_include_directories(f00bar PRIVATE @@ -54,6 +56,7 @@ target_include_directories(f00bar PRIVATE ${CAIRO_INCLUDE_DIRS} ${YAML_INCLUDE_DIRS} ${JSON_INCLUDE_DIRS} + ${UDEV_INCLUDE_DIRS} ) target_link_libraries(f00bar @@ -62,4 +65,5 @@ target_link_libraries(f00bar ${CAIRO_LIBRARIES} ${YAML_LIBRARIES} ${JSON_LIBRARIES} + ${UDEV_LIBRARIES} ) diff --git a/modules/battery/battery.c b/modules/battery/battery.c index ad62164..f6b9675 100644 --- a/modules/battery/battery.c +++ b/modules/battery/battery.c @@ -11,6 +11,8 @@ #include #include +#include + #include "../../bar.h" enum state { STATE_FULL, STATE_CHARGING, STATE_DISCHARGING }; @@ -183,7 +185,41 @@ run(struct module_run_context *ctx) int power_fd = openat(base_dir_fd, "power_now", O_RDONLY); assert(power_fd != -1); - do { + struct udev *udev = udev_new(); + assert(udev != NULL); + + struct udev_monitor *mon = udev_monitor_new_from_netlink(udev, "udev"); + assert(mon != NULL); + + int r = udev_monitor_filter_add_match_subsystem_devtype(mon, "power_supply", NULL); + assert(r == 0); + r = udev_monitor_enable_receiving(mon); + assert(r == 0); + + 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); + bool is_us = strcmp(udev_device_get_sysname(dev), m->battery) == 0; + + udev_device_unref(dev); + + if (!is_us) + continue; + } + } else + first = false; + const char *status = readline_from_fd(status_fd); if (strcmp(status, "Full") == 0) m->state = STATE_FULL; @@ -207,13 +243,10 @@ run(struct module_run_context *ctx) // m->capacity, m->energy, m->power); bar->refresh(bar); + } - struct pollfd fds[] = {{.fd = ctx->abort_fd, .events = POLLIN}}; - poll(fds, 1, m->poll_interval * 1000); - - if (fds[0].revents & POLLIN) - break; - } while (true); + udev_monitor_unref(mon); + udev_unref(udev); close(power_fd); close(energy_fd);